bzar
A Commando
Box2d forums seem to be down, and I couldn't find any mention about this anywhere, so I'm posting here.
I'm making a game with python|pygame|pybox2d. The game involves a player jumping on platforms. The platforms can be either dynamic or static. The decision on whether the player can jump is determined by collisions reported by box2d. If the player collides with a subclass of Platform and the collision normal vector is in a predefined range, the object is added to "new platform collisions" set, which is added to "current platform collisions" set when the game world updates. If on the other hand the player stops colliding with a platform, the platform is first searched from the new collisions and then from old collisions. If the platform resides in one of them it is removed from the set (but only one set). This complex procedure is to determine all the platforms with what the player has collided or still collides with in a certain frame. Yes it's quite complex, but taking into account how box2d works, it seems to be the only reliable way.
Now to the point. If a dynamic object (player) collides with a static object (wall), the player is bounced off the wall during the same box2d world update. However, if the other object is also dynamic (a dynamic box for example), both objects are actually affected the next frame!
Let me give an example. Say the player is falling straight down (positive y axis being up) and hits an object on the third frame from T=0. in the following example the leftmost column represents the frame index (T), the middle column is the player's linear velocity if the other object is static, the rightmost column the same as the middle one but with a dynamic object (the actual values are arbituary).
0 (0,-1.0) (0,-1.0)
1 (0,-1.1) (0,-1.1)
2 (0,-1.4) (0,-1.4)
3 (0,0.7) (0,-1.4) # the player hits the floor
4 (0,0.6) (0,0.7)
If I implement jumping by applying an impulse to the player, and the player jumps the moment he hits the floor, he'll jump normally, if the floor is static, but won't jump a pixel if it's dynamic, because the downward motion nullifies the impulse. This can worked around by setting the players linear y velocity to zero before applying the impulse, but thats not too pretty.
Even with this fix there's another problem. If the player is rotating, it should affect which way the player will jump. If the player is moving right in the air and rotating wildly counterclockwise, shouldn't he jump left when he touches ground? Well, he won't if it's a dynamic object, because also the effect of the rotating movement is calculated the next frame. So he jumps right without any regard to the rotating movement until he hits a static object. I could delay handling all collisions by one frame, but then collisions lasting only one frame would never count. This would mean that the player sometimes just wouldn't jump. That's not a good thing for playability.
My current (ugly) solution is to use not one but two sets for the new platform collisions. One for the static platforms and another for the dynamic ones. The static platforms take effect immediately, so you can jump off those one-frame-collisions. The dynamic platform collisions however are delayed by one frame.
Is this a bug in box2d or pybox2d? Is there a standard way to cope with it?
I'm making a game with python|pygame|pybox2d. The game involves a player jumping on platforms. The platforms can be either dynamic or static. The decision on whether the player can jump is determined by collisions reported by box2d. If the player collides with a subclass of Platform and the collision normal vector is in a predefined range, the object is added to "new platform collisions" set, which is added to "current platform collisions" set when the game world updates. If on the other hand the player stops colliding with a platform, the platform is first searched from the new collisions and then from old collisions. If the platform resides in one of them it is removed from the set (but only one set). This complex procedure is to determine all the platforms with what the player has collided or still collides with in a certain frame. Yes it's quite complex, but taking into account how box2d works, it seems to be the only reliable way.
Now to the point. If a dynamic object (player) collides with a static object (wall), the player is bounced off the wall during the same box2d world update. However, if the other object is also dynamic (a dynamic box for example), both objects are actually affected the next frame!
Let me give an example. Say the player is falling straight down (positive y axis being up) and hits an object on the third frame from T=0. in the following example the leftmost column represents the frame index (T), the middle column is the player's linear velocity if the other object is static, the rightmost column the same as the middle one but with a dynamic object (the actual values are arbituary).
0 (0,-1.0) (0,-1.0)
1 (0,-1.1) (0,-1.1)
2 (0,-1.4) (0,-1.4)
3 (0,0.7) (0,-1.4) # the player hits the floor
4 (0,0.6) (0,0.7)
If I implement jumping by applying an impulse to the player, and the player jumps the moment he hits the floor, he'll jump normally, if the floor is static, but won't jump a pixel if it's dynamic, because the downward motion nullifies the impulse. This can worked around by setting the players linear y velocity to zero before applying the impulse, but thats not too pretty.
Even with this fix there's another problem. If the player is rotating, it should affect which way the player will jump. If the player is moving right in the air and rotating wildly counterclockwise, shouldn't he jump left when he touches ground? Well, he won't if it's a dynamic object, because also the effect of the rotating movement is calculated the next frame. So he jumps right without any regard to the rotating movement until he hits a static object. I could delay handling all collisions by one frame, but then collisions lasting only one frame would never count. This would mean that the player sometimes just wouldn't jump. That's not a good thing for playability.
My current (ugly) solution is to use not one but two sets for the new platform collisions. One for the static platforms and another for the dynamic ones. The static platforms take effect immediately, so you can jump off those one-frame-collisions. The dynamic platform collisions however are delayed by one frame.
Is this a bug in box2d or pybox2d? Is there a standard way to cope with it?