Wednesday, September 25, 2013

Hitboxes and you!

Pygame, you did a bad thing.  With sprites, if one wants to position them, they manipulate the rect property.

What do you mean that isn't a bad design move!  Ok, if that was all it was it wouldn't be an issue... except that the rect property is also used in hit detection... and that the sprite image always, and I mean always is redrawn on the top left hand corner of this rect, wherever the rectangle controlling the sprite is located.  Anyone that has ever played or made a bullet-hell shooter can tell you that is a terrible idea.

So, when I set the rect property to allow for things like the sprite of Arianna to nudge up against the wall, well, bad things happen.


Now, fellow reader, do not despair, for I was able to find a reasonable workaround.

First, I made a new property simply known as hitbox.  The hitbox was shaped to my liking.

Next, I had to rewrite the function that checked for collisions.  Before it looked like this:

    def checkCollision (self,sprite):
        level_bumps = spritecollide(sprite,self.sprites,False)
        for items in level_bumps:
            items.onCollision(sprite)



It was using the native function that came with pygame to check for collisions between sprites.  Course, both rely on the sprite's rect property to work, which I am no longer using for collision detection with moving characters like the PC or enemies.

Course, the native function relied on a function that pygame Rectangle objects have: colliderect().  So, I rewrote the function thusly:

    def checkCollision (self,sprite):
        for item in self.sprites:
            if sprite.hitbox.colliderect(item):
                item.onCollision(sprite)


So that the onCollision function would be called right when the one sprite was seen to be in contact with another.

Finally, it would be simply making sure that the hitbox moved with the rest of the sprite.  I put that in the update function, where the last line reads:

self.hitbox.center = self.rect.center

At present that simply means that the hitbox is centered on the sprite.  I could change that later, which I probably will.

The result?


No comments:

Post a Comment