I am developing an action platformer in Python, with Pygame. That said, my question is a general one about collision resolution strategies.
I use an axis-aligned bounding box for the purposes of collision detection. The bounding box changes sizes depending on the sprite's action and the frame of the action's animation.
When I update my sprite's position, I first update the y-coordinate, check for and resolve collision in the y-direction, then do the same for the x-coordinate. When I resolve collision, I simply move the bounding rect's sides to align flush with the appropriate walls.
Because the bounding rect changes sizes throughout my animations, I am noticing buggy behavior in certain situations when the frame moves from a smaller one to a larger one. The change of frame results in the sprite intersecting a wall and his position is resolved such that he falls off the map.
Here is a diagram illustrating the problem:
It doesn't matter whether I resolve in the x-direction or the y-direction first. They result in reciprocal buggy behavior when the next frame is wider or taller, respectively.
My question concerns general collision resolution strategies for axis-aligned bounding boxes that change size and shape. What are the best algorithms for collision resolution that avoid this issue?
Here are some of the functions and values I have access to:
- colliderect -- tests if two rectangles collide
- collidepoint -- boolean that tests if a point collides with a rectangle
- rect.topleft, rect.topright, rect.bottomleft, rect.bottomright, rect.center, rect.centerx, rect.centery -- various points on the rectangles
- rect.left, rect.right, rect.top, rect.bottom -- values for the sides of the rects
- various vectors
- in short, the usual stuff
Apologies if this question is a dupe. I imagine it is a pretty common one, though I couldn't find anything that helped me specifically.
Answer
In brief there are two ways of doing this. Both are relatively fast and simple to run.
Method 1
If the AABB (axis aligned bounding box) changes every frame because of animations, then you can simply wait until after the sprite has been moved and the next frame of the animation has played before resolving the collisions
def MainLoop():
#Update the position
rect.center = rect.center + velocity
#I don't know how you are doing your animations, but play the next frame here
Animate.PlayNextFrame()
#Now you want to check for collisions as normal now that everything has moved in the frame we can check for collisions once
CheckCollisions()
This means that the collision detection occurs only once animation and the movement has occurred. This prevents the need to do collision detection more than once per frame and takes the animation into account.
Method 2
Make a dummy aabb for collision detection that follows the main character which has a fixed size. This will occasionally result in some minor intersection between the character and the wall but in most cases it looks fine.
This is also relatively easy to implement and very fast to run.
No comments:
Post a Comment