1

In the code below I add a center and before it a top and a left attribute to the self.rect (this is only for learning and understanding pygame behavior). When I add the top attribute it seems that the top will be overwritten by the center, but having a left before center comes changes the x position of the block. Can any one explain why the left doesn't get overwritten by center?

import pygame
pygame.init()


screen=pygame.display.set_mode((500,500))

class Block(pygame.sprite.Sprite):

    def __init__(self):
        super(Block, self).__init__()
        self.image=pygame.Surface((50,50))
        self.image.fill((0,0,200))
        self.rect=self.image.get_rect(top=400,center=(0,0)) 
        #this will obviously be overwritten by center, but not the following, why?
        #self.rect=self.image.get_rect(left=400,center=(0,0))

b=Block()
blockGrp=pygame.sprite.Group()
blockGrp.add(b)
print blockGrp

while 1:
    pygame.time.wait(50)
    for e in pygame.event.get():
        if e.type==pygame.QUIT:
            pygame.quit()

    blockGrp.draw(screen)

    pygame.display.flip()
sloth
  • 99,095
  • 21
  • 171
  • 219

1 Answers1

2

The keywords you use when you call the get_rect function are, in the end, passed as a dict to the function.

The Rect class* then iterates over this dict and calls the appropriate setter function.

Now note that the order of the items in the dict is not the same order you used when creating that dict.

For example, try running the following code in your python interpreter:

>>> {"top": 400, "center": (0, 0)}
{'top': 400, 'center': (0, 0)}
>>> {"left": 400, "center": (0, 0)}
{'center': (0, 0), 'left': 400}
>>>

As you can see, when you use ...get_rect(left=400,center=(0,0)), a dict like {'center': (0, 0), 'left': 400} is created (this is an implementation detail that may change depending on the python interpreter you use).

So, first center will be set, then left will be set.

Now if you use ...get_rect(top=400,center=(0,0)), a dict like {'top': 400, 'center': (0, 0)} will be generated, and top will be set first, then center will be set.

For more information about how dict works internally, look at this great answer.


That being said, if you want to set multiple attributes that collide with each other, (like top and center e.g.), you should call the setter manually, e.g.

self.rect = self.image.get_rect(center=(0,0)) 
self.rect.top = 400

* it's not really a Rect class, since it's implemented in C, so it's a C function that does the work in the end.

Community
  • 1
  • 1
sloth
  • 99,095
  • 21
  • 171
  • 219