Archived

This topic is now archived and is closed to further replies.

krez

collision response (2D, per-pixel)

Recommended Posts

i am working on a 2D platformer game, but i am stuck on a point. i basically have a matrix of bits representing the collidable portions of each sprite, which are [bitwise] ANDed together when the bounding box check indicates it is necessary. this accurately detects collisions, but i do not know how to move the sprites to an appropriate position when a collision results. for example, say the character sprite is falling fast (from a high spot, i use fairly realistic gravity) and collides with a floor/platform tile. depending on framerate, the speed, and tons of other stuff, the character sprite may only overlap the floor by one pixel, so it would have to be "pushed up" one pixel. but, it might "sink in" a dozen pixels, and have to be raised even more. i thought up a few solutions, but i cannot decide between them, and someone else might have a better idea: 1) move the movable sprite (character, as the floor/platform is stationary) a pixel or two back in the direction it came from, and do the collision tests again. the problem with this is if the sprites overlap a lot, there will be many collision tests before it is moved far back enough, and this might lag the game. 2) store yet another matrix of "how deep into the sprite" a pixel is, and move them by this value. the problem here is that i would need multiple matrices of these values, for motion in different directions, and i am not certain that it would be accurate anyway. 3) calculate the size of the overlap based on the bounding boxes, and move them apart by a fraction of this amount (1/2 maybe?) before trying the collision tests again. the problem with this is that some sprites would give funky results (i.e. sprites that have something "collidable" sticking out would give a larger "push back" motion than is actually appropriate). 4) have the collision detection count the number of pixels overlapped (colliding), and use this number to scale the "push back" motion before the re-testing. the problem here is that, again, strangly shaped sprites might give funky results. i would just implement all of these and see which works best, but that would be a waste of time IMO. so, does anyone have any suggestions or ideas? thanks! --- krez (krez@optonline.net)

Share this post


Link to post
Share on other sites
What I do is this:

Assume m_speed is the number of units this thing can move this game tick.

for (intc=0; c<m_speed; c++)
{
moveOneUnit();
if(checkCollision())
{
blowUp();
}
}

It boils down to this: don't just move the thing x number of pixels/inches/whatever. Move it one unit at a time and check for collision.

I hope that makes some sense.

Sabbac


[edited by - sabbac on September 2, 2003 10:35:33 PM]

Share this post


Link to post
Share on other sites
I think what he''s saying is move your object by time, not by pixels. When you move an object by time, it is a lot easier to project when a collision will occur or if it already has occurred and the object has moved deeper into the collision.

You can move your object one unit per measure of time (say, a unit every 10 milliseconds). Using this method, you can project exactly where the object was 10 or 50 milliseconds ago, or where it will be x milliseconds in the future. That way, you can detect when the actual collision occurred, and process it accordingly.

Share this post


Link to post
Share on other sites
i see what you are saying now... i am already moving the sprites by time, so the frame rate doesn''t affect the game speed.

but, i am not using simple geometric collision. the bounding boxen are checked, but then (if they collide) a pixel-perfect collision is done. i don''t see any way to project or calculate whether or not the pixels overlap, except for doing the whole comparison of sprites again for each step.

then again, i just realized that even a sprite moving 120 pixels/second would only move 2 pixels per frame (at 60fps), so it wouldn''t be as much overhead as i originally thought to just do the tests again. i will try to implement this and stop worrying until it actually causes a problem i guess.

if anyone else has anything to say, i''d love to hear it

Share this post


Link to post
Share on other sites