How to dynamically generate shapes in Pygame?

Viewed 305

I'm trying to generate multiple rectangles which translate across the screen with varying distance of separation between any two consecutive rectangles.

Here's the snippet of the code-

win = pygame.display.set_mode((500, 500)) #canvas size is 500x500

width = 40
height = 60
x = 500 - width
y = 500 - height
vel = 5

state = True
while(state):
   pygame.time.delay(50)
   x -= vel
   pygame.draw.rect(win, (0, 0, 255), (x, y, width, height))
   pygame.display.update()

#I have not included the pygame exit code

Now, how do I go about this, without making the rectangles disappear everytime I try to generate a new one?

2 Answers

Create a list of rectangles:

rect_list = []

When you want to add a new rectangle, the append an new pygame.Rect object to the list:

rect_list.append(pygame.Rect(x, y, width, height))

Change the location of the rectangle and draw the rectangles in a loop, in the main application loop:

state = True
while state:
    # [...]

    for rect_obj in rect_list:
        rect_obj.x -= vel
        pygame.draw.rect(win, (0, 0, 255), rect_obj)

    # [...]

This answer is derived off Rabbid76's answer, but with a slight modification that allows each individual rect to have it's own vel speed and color:

class rectangle:
# You can add as many new values as you like, just be wary about changing the other magic methods
    def __init__(top, left, width, height, vel, color=(0, 0, 255)):
        self.vel = vel
        self.pos = (top, left)
        self.size = (width, height)
        self.rect = self.pos + self.size

    def __iter__(self):
        return self.rect

    def __getitem__(self, key):
        if type(key)!=int:
            raise TypeError('invalid key!')
        return self.rect[key]

    def __len__(self):
        return len(self.rect)

    def __reversed__(self):
        return reversed(self.rect)

    def update_rect(self): # This should be called every time you make an adjustment to pos or size
        self.rect = self.pos+self.size

    def move(self, x, y):
        self.pos[0] += x
        self.pos[1] += y
        self.update_rect

    def resize(self, width, height):
        self.size = (width, height)
        self.update_rect

Now, you store a list of instances:

rect_list = []
rect_list.append(rectangle(top, left, width, height, vel, color)) # You can call this as many times as you want

of these classes instead of a list of pygame.Rects, and when it comes time to draw it, the magic methods will come into play, and magically make it a pygame.Rect object:

for rect in rect_list:
    rect.move(x=-rect.vel, y=0) # Move it negative x
    pygame.draw.rect(win, rect.color, pygame.Rect(rect)) # Draw it.
Related