0

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?

  • 1
    A [mcve] would make it easier for people to help you. You might also try using the [rect.inflate()](https://www.pygame.org/docs/ref/rect.html#pygame.Rect.inflate) function, this will resize the rect, but retain its centre (as much as possible). – import random Oct 29 '18 at 01:41
  • can you tell me how to use this function? I didn't really understand it from the documentation. I don't want to shrink the rect from each side equally, I would prefer if I could customize the size of the rect – MOHAMED IBRAHIM Student Oct 29 '18 at 01:47
  • try something like: `self.rect = self.rect.inflate(-20, -10)` to shrink your rect size by twenty pixels in width and ten in height. – import random Oct 29 '18 at 01:50
  • For example, I want to make the sides and top shorter, but not the bottom. How could I achieve that? – MOHAMED IBRAHIM Student Oct 29 '18 at 01:51
  • It sounds like you can't use a rectangle for your collision detection if the top and bottom dimensions aren't equal. Also, you can use `rect.inflate_ip(-20, -10)` to change the size "in place". – import random Oct 29 '18 at 01:53
  • what does "in place" mean? How much of a difference would it make if I used inflate_ip as opposed to inflate? – MOHAMED IBRAHIM Student Oct 29 '18 at 01:54
  • "in place" means that the object value will change, so an additional assignment is not required. The code `self.rect.inflate_ip(...)` should have the same outcome as `self.rect = self.rect.inflate(...)`. It's analogous to using `var += 1` instead of `var = var + 1`. – import random Oct 29 '18 at 01:57
  • There's a [comprehensive answer here](https://gamedev.stackexchange.com/a/30870/121785) that describes approaches for non-rectangular collision that should be useful for you. – import random Oct 29 '18 at 01:59
  • Okay, but if I try shrinking the height, it will look like the player's feet is inside of the floor. That's why I would want to shrink from the top only. Is there any other way I could possibly fix this? – MOHAMED IBRAHIM Student Oct 29 '18 at 02:00
  • Perhaps you need to resize your rect and the move it 'down' by adjusting the y coordinate of the rect, e.g. `self.rect.y += 10` – import random Oct 29 '18 at 02:02
  • wouldn't that also move the image down with it? – MOHAMED IBRAHIM Student Oct 29 '18 at 02:07
  • Is there a way i could *resize it without retaining the center?* – MOHAMED IBRAHIM Student Oct 29 '18 at 02:11
  • Many of your follow-up questions can be answered quickly by yourself if you try out the suggestions. Without a proper sample of your running code, it's difficult for us to answer your questions accurately. Are you using a pygame Sprite object for your player or are you doing something different? Please read [How to Ask](https://stackoverflow.com/questions/how-to-ask). – import random Oct 29 '18 at 03:22

1 Answers1

1

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.

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