Discussion:
Scaling the hitbox/rect of a sprite
Skorpio
2014-05-22 10:47:19 UTC
Permalink
Hi everybody,

How can you scale the hitbox of a sprite? I tried self.rect =
self.rect.inflate(-85, -20) and that scaled the rect correctly (to the
center of the rect), but the game still takes the upper left corner of the
rect as the blit position for the image/surface. That means the rect covers
only the upper left part of the sprite, so that the left half of the sprite
image can be hit and the right half can't be hit.

Regards,
Skorpio



--
View this message in context: http://pygame-users.25799.x6.nabble.com/pygame-Scaling-the-hitbox-rect-of-a-sprite-tp1227.html
Sent from the pygame-users mailing list archive at Nabble.com.
Sam Bull
2014-05-22 12:39:20 UTC
Permalink
Post by Skorpio
How can you scale the hitbox of a sprite? I tried self.rect =
self.rect.inflate(-85, -20) and that scaled the rect correctly (to the
center of the rect), but the game still takes the upper left corner of the
rect as the blit position for the image/surface. That means the rect covers
only the upper left part of the sprite, so that the left half of the sprite
image can be hit and the right half can't be hit.
I'm not sure why you would use the hitbox as your blit position, if the
hitbox is a different size to the sprite.

I'd probably keep the rect for the sprite, and then when doing
hittesting, just do hit_test(self.rect.inflate(-85, -20)) or something
(never actually storing the scaled rect).
Skorpio
2014-05-22 13:08:59 UTC
Permalink
I don't blit the sprites at the rect/hitbox, Pygame does that. The sprites
are in a pygame.sprite.Group and when I call sprite_group.draw(screen) and
if the rects are scaled, their images get still blitted at the top left
corner of the rect. I'm using pygame.sprite.spritecollide() for the
collision detection.

Is there a way to give a sprite a additional hitbox?



--
View this message in context: http://pygame-users.25799.x6.nabble.com/pygame-Scaling-the-hitbox-rect-of-a-sprite-tp1227p1231.html
Sent from the pygame-users mailing list archive at Nabble.com.
Jeffrey Kleykamp
2014-05-22 14:29:48 UTC
Permalink
Using spritecollide(sprite, group, dokill, collided = None) you can specify
a collided function. They have one built in for a constant ratio
pygame.sprite.collide_rect_ratio().
You can also specify your own function. If you do that you can specify a
different variable of your sprite to be your collision rect.
Eg.
my_func = lambda left, right: pygame.sprite.collide_rect(left.scaled_rect,
right.scaled_rect)
spritecollide(sprite, group, dokill, collided = my_func)

Jeff
Post by Skorpio
I don't blit the sprites at the rect/hitbox, Pygame does that. The sprites
are in a pygame.sprite.Group and when I call sprite_group.draw(screen) and
if the rects are scaled, their images get still blitted at the top left
corner of the rect. I'm using pygame.sprite.spritecollide() for the
collision detection.
Is there a way to give a sprite a additional hitbox?
--
http://pygame-users.25799.x6.nabble.com/pygame-Scaling-the-hitbox-rect-of-a-sprite-tp1227p1231.html
Sent from the pygame-users mailing list archive at Nabble.com.
--
Jeffrey Kleykamp
Jake b
2014-05-22 16:30:21 UTC
Permalink
To preserve the center:


pos = self.rect.center
self.rect = self.rect.inflate(-85, -20)
self.rect.center = pos
Post by Skorpio
Hi everybody,
How can you scale the hitbox of a sprite? I tried self.rect =
self.rect.inflate(-85, -20) and that scaled the rect correctly (to the
center of the rect), but the game still takes the upper left corner of the
rect as the blit position for the image/surface. That means the rect covers
only the upper left part of the sprite, so that the left half of the sprite
image can be hit and the right half can't be hit.
Regards,
Skorpio
--
http://pygame-users.25799.x6.nabble.com/pygame-Scaling-the-hitbox-rect-of-a-sprite-tp1227.html
Sent from the pygame-users mailing list archive at Nabble.com.
--
Jake
Christopher Night
2014-05-22 17:57:16 UTC
Permalink
You don't need to do that. rect.inflate already preserves the center. The
question is more about how to use a separate rect for hitbox than you do
for blitting.
Post by Jake b
pos = self.rect.center
self.rect = self.rect.inflate(-85, -20)
self.rect.center = pos
Post by Skorpio
Hi everybody,
How can you scale the hitbox of a sprite? I tried self.rect =
self.rect.inflate(-85, -20) and that scaled the rect correctly (to the
center of the rect), but the game still takes the upper left corner of the
rect as the blit position for the image/surface. That means the rect covers
only the upper left part of the sprite, so that the left half of the sprite
image can be hit and the right half can't be hit.
Regards,
Skorpio
--
http://pygame-users.25799.x6.nabble.com/pygame-Scaling-the-hitbox-rect-of-a-sprite-tp1227.html
Sent from the pygame-users mailing list archive at Nabble.com.
--
Jake
Skorpio
2014-05-23 14:02:45 UTC
Permalink
Thanks for the help everybody, but it still doesn't work.

I've tried these functions as collided values (as Jeffrey Kleykamp
suggested):

pygame.sprite.collide_rect() takes only sprites as values and then uses
their rects. That means I can't use the sprite's scaled "hitbox" attribute,
otherwise I get this error: AttributeError: 'pygame.Rect' object has no
attribute 'rect'
And if I do sprite.rect = sprite.hitbox, the image gets blitted at the top
left corner again.

pygame.Rect.colliderect() doesn't work.

pygame.sprite.collide_rect_ratio() works as intended but causes a huge
performance drop, so it's not useable for me. I have quite a lot of sprites
on the screen (sometimes over 100).

Christopher Night is right. It would be a lot easier for me, if Pygame
sprites had an additional (optional) hitbox rect.

Maybe I should rewrite my collision detection passage and just use
pygame.Rect.colliderect() instead of pygame.sprite.spritecollide().



--
View this message in context: http://pygame-users.25799.x6.nabble.com/pygame-Scaling-the-hitbox-rect-of-a-sprite-tp1227p1237.html
Sent from the pygame-users mailing list archive at Nabble.com.
Jeffrey Kleykamp
2014-05-23 14:23:54 UTC
Permalink
Oops, my code was wrong, it should be,
my_collide_rect = lambda a, b: a.hitbox.colliderect(b.hitbox)

You want to use the colliderect function of the Rect module to test if they
collide.
http://www.pygame.org/docs/ref/rect.html#pygame.Rect.colliderect

Jeffrey
Post by Skorpio
Thanks for the help everybody, but it still doesn't work.
I've tried these functions as collided values (as Jeffrey Kleykamp
pygame.sprite.collide_rect() takes only sprites as values and then uses
their rects. That means I can't use the sprite's scaled "hitbox" attribute,
otherwise I get this error: AttributeError: 'pygame.Rect' object has no
attribute 'rect'
And if I do sprite.rect = sprite.hitbox, the image gets blitted at the top
left corner again.
pygame.Rect.colliderect() doesn't work.
pygame.sprite.collide_rect_ratio() works as intended but causes a huge
performance drop, so it's not useable for me. I have quite a lot of sprites
on the screen (sometimes over 100).
Christopher Night is right. It would be a lot easier for me, if Pygame
sprites had an additional (optional) hitbox rect.
Maybe I should rewrite my collision detection passage and just use
pygame.Rect.colliderect() instead of pygame.sprite.spritecollide().
--
http://pygame-users.25799.x6.nabble.com/pygame-Scaling-the-hitbox-rect-of-a-sprite-tp1227p1237.html
Sent from the pygame-users mailing list archive at Nabble.com.
--
Jeffrey Kleykamp
bw
2014-05-23 15:26:44 UTC
Permalink
Example attached. This might get you going.

Gumm
Post by Skorpio
Thanks for the help everybody, but it still doesn't work.
I've tried these functions as collided values (as Jeffrey Kleykamp
pygame.sprite.collide_rect() takes only sprites as values and then uses
their rects. That means I can't use the sprite's scaled "hitbox" attribute,
otherwise I get this error: AttributeError: 'pygame.Rect' object has no
attribute 'rect'
And if I do sprite.rect = sprite.hitbox, the image gets blitted at the top
left corner again.
pygame.Rect.colliderect() doesn't work.
pygame.sprite.collide_rect_ratio() works as intended but causes a huge
performance drop, so it's not useable for me. I have quite a lot of sprites
on the screen (sometimes over 100).
Christopher Night is right. It would be a lot easier for me, if Pygame
sprites had an additional (optional) hitbox rect.
Maybe I should rewrite my collision detection passage and just use
pygame.Rect.colliderect() instead of pygame.sprite.spritecollide().
--
View this message in context: http://pygame-users.25799.x6.nabble.com/pygame-Scaling-the-hitbox-rect-of-a-sprite-tp1227p1237.html
Sent from the pygame-users mailing list archive at Nabble.com.
Skorpio
2014-05-23 16:42:27 UTC
Permalink
Thanks guys, your solutions work fine. I didn't realize that the collided
callback function automatically gets the two sprites as input.



--
View this message in context: http://pygame-users.25799.x6.nabble.com/pygame-Scaling-the-hitbox-rect-of-a-sprite-tp1227p1242.html
Sent from the pygame-users mailing list archive at Nabble.com.

Loading...