This question already has an answer here:
-
How do I center a surface (subsurface) around a rectangle? (scaled sprite hitbox / collision rect)
1 answer
Another problem I've recently tried tackling was adjusting the size of the player's hitbox. Here's how I tried changing the hit-box (Rect's) size:
self.pseudo_rect = self.image.get_rect() # This is the rect from the player's image to use as a reference
self.rect = pygame.Rect((self.pseudo_rect.x,self.pseudo_rect.y), (self.pseudo_rect.width,self.pseudo_rect.height)) # This is where I used the above values to make a rect with the dimensions I want
What I've discovered after testing this was that only the width and height would change when an amount is added/subtracted from it, not the x or y values. I'm not exactly sure where to go from here. Can you tell me if there's something that I'm doing wrong, or even if there is a betterr/simpler solution to this?
Pygame already offers some solutions for this.
If you use pygame's collision handling, (e.g. pygame.sprite.spritecollide
, pygame.sprite.groupcollide
or pygame.sprite.spritecollideany
), note that you can use a callback function used to calculate if two sprites are colliding (the collided
argument).
The default that is used is pygame.sprite.collide_rect
, but in your case, you should take a look at pygame.sprite.collide_rect_ratio
:
pygame.sprite.collide_rect_ratio()
Collision detection between two sprites, using rects scaled to a ratio.
collide_rect_ratio(ratio) -> collided_callable
A callable class that checks for collisions between two sprites, using a scaled version of the sprites rects.
Is created with a ratio, the instance is then intended to be passed as a collided callback function to the *collide functions.
A ratio is a floating point number - 1.0 is the same size, 2.0 is twice as big, and 0.5 is half the size.
Here's how collide_rect_ratio
is implemented.
Of course you can write such a callback function yourself if you need some custom behaviour.
So maybe you want to change the function to check if a sprite has a pseudo_rect
attribute, and then use this instead of the rect
attribute.
Then, in your sprite classes, you could do something like this:
self.rect = self.image.get_rect()
self.pseudo_rect = self.rect.inflate(5, 5)
if you want to give a sprite a bigger hitbox (don't forget to set pseudo_rect's center
attribute to rect.center
everything you change rect
).
Another way could be to give your sprites a collision_ration
attribute and use it in the collision function, if set.