Recommended Posts

This problem is driving me absolutely insane.
I'm sure i'm just being stupid.
The screenshot demonstrates some examples
http://img299.imageshack.us/my.php?image=examplecollisions.jpg
This is for a top down 2d space game.
I don't want to do anything complex, there is NO rotation. i just want the player to bounce off the tiles, but i can't seem to work out the code to do it.
I can detect the collisions and get a list of all the tiles the player has collided with.
I just can't work out how to provide the correct response vector
If anyone got any resources you could recommend to look, or help to share, i've tried google and found nothing covering AABB-AABB collision response.

Share this post

Link to post

Share on other sites

The basic algorithm would be to test each tile against the player, one by one, and move the player away from intersecting tiles by the amount of intersection.

However, in example 1 and 3 and 4, you would have multiple contacts, and that would not give you clean response if you try to do it the straight forward way.

If you take example 3, where the player is resting on a bunch of horizontal tiles, you know that the only way for the player is going up. For each tile intersected, the left and right sides are occupied by another tile, therefore those sides should be ignored for response. Only up and down can give you a valid response plane.

in the code, the 'mtd' (minimum translation distance) is the vector of intersection between two boxes (and for box vs sphere). In general, the mtd provides you with the direction and amount of intersection occuring, and you can push your player by that vector to stop him intersecting with a tile.

would need to be changed slightly to ignore sides that cannot be used for response. But in general, the same principle should be valid for your purpose, and the player should be moved out of the intersections nice and smooth.

// found right side intersection smaller than previous found mtdif((mtdlength < 0.0f) || (dx0 <= mtdlength)) {// if we are on the right side of the tile, // and the right side isn't blocked,// set MTD to right vector.if((tileSides & tileSideRight) && (dx0 < dx1)) { mtd = Vector(dx0, 0); mtdlength = dx0; } }

// found left side intersection smaller than previous found mtdif((mtdlength < 0.0f) || (dx1 <= mtdlength)) {// if we are on the left side of the tile, // and the left side isn't blocked// set MTD to left vector.if((dx1 < dx0) && (tileSides & tileSideLeft)) { mtd = Vector(-dx1, 0); mtdlength = dx1; } }

// found top side intersection smaller than previous found mtdif((mtdlength < 0.0f) || (dy0 <= mtdlength)) {// if we are on the top side of the tile, // and the top side tile isn't blocked// set MTD to top vector.if((dy0 < dy1) && (tileSides & tileSideTop)) { mtd = Vector(0, dy0); mtdlength = dy0; } }

To find the collision plane, you can use the 'mtd' vector as your plane normal. If you intersect on the left of the tile, the collison plane normal would basically point to the left, same as the mtd vector.

However there is a simpler solution. When you check for intersections and modify the player position, you end up with a final player position that is different from where he would be if there was no collision.

// if we had a collision, // the player position is not where we wanted to be // so bounce against a virtual plane if(dcoll > 1.0f) // arbitrary tolerance, start bouncing if we've been pushed by at least one pixel away. { // normalise collision plane normal ncoll /= dcoll;