# Tile-based 2D collision detection problems

I'm trying to follow this tutorial http://www.tonypa.pri.ee/tbw/tut05.html to implement real-time collisions in a tile-based world.

I find the center coordinates of my entities thanks to these properties:

public float CenterX
{
get { return X + Width / 2f; }
set { X = value - Width / 2f; }
}
public float CenterY
{
get { return Y + Height / 2f; }
set { Y = value - Height / 2f; }
}


Then in my update method, in the player class, which is called every frame, I have this code:

public override void Update()
{
base.Update();

int downY = (int)Math.Floor((CenterY + Height / 2f - 1) / 16f);
int upY = (int)Math.Floor((CenterY - Height / 2f) / 16f);
int leftX =     (int)Math.Floor((CenterX + Speed * NextX - Width / 2f) / 16f);
int rightX = (int)Math.Floor((CenterX + Speed * NextX + Width / 2f - 1) / 16f);

bool upleft = Game.CurrentMap[leftX, upY] != 1;
bool downleft = Game.CurrentMap[leftX, downY] != 1;
bool upright = Game.CurrentMap[rightX, upY] != 1;
bool downright = Game.CurrentMap[rightX, downY] != 1;

if(NextX == 1)
{
if (upright && downright)
CenterX += Speed;
else
CenterX = (Game.GetCellX(CenterX) + 1)*16 - Width / 2f;
}
}


downY, upY, leftX and rightX should respectively find the lowest Y position, the highest Y position, the leftmost X position and the rightmost X position. I add + Speed * NextX because in the tutorial the getMyCorners function is called with these parameters:

getMyCorners (ob.x+ob.speed*dirx, ob.y, ob);


The GetCellX and GetCellY methods:

public int GetCellX(float mX)
{
return (int)Math.Floor(mX / SGame.Camera.TileSize);
}
public int GetCellY(float mY)
{
return (int)Math.Floor(mY / SGame.Camera.TileSize);
}


The problem is that the player "flickers" while hitting a wall, and the corner detection doesn't even work correctly since it can overlap walls that only hit one of the corners. I do not understand what is wrong. In the tutorial the ob.x and ob.y fields should be the same as my CenterX and CenterY properties, and the ob.width and ob.height should be the same as Width / 2f and Height / 2f. However it still doesn't work.

• Are you testing the collision once the player is on that spot and boucing it back if it collides or are you testing if the next move is a collision? – kyndigs Feb 11 '11 at 14:37
• I would recommend adding a key press check in that update function that will break the current process when you press the key. Then hit the key when the player is "flickering" and walk through the debugger. (pay attention to what is happening to the numbers) Try to find out what is happening to the numbers when it flickers. – Michael Coleman Feb 12 '11 at 13:29

A couple of suggestions, although I'm not sure they will fix the problem as I don't have full code to run and debug.

In this code:

if(NextX == 1)
{
if (upright && downright)
CenterX += Speed;
else
CenterX = (Game.GetCellX(CenterX) + 1)*16 - Width / 2f;
}


the else statement is moving the object even though the object should not be moving.
I guess you are trying to make the object flush against the wall but maybe the calculation is incorrect.
If you comment out the else statement, does the object still flicker?

The calculation does look a bit suspicious as it subtracts (Width / 2f) and then the CenterX set operator does the same subtraction again.

Another thing I'd like to point, just to help the clarity of the code, is that you made the properties for CenterX calculate the value back and forth, but the code is still littered with the same calculation over and over again.
This might well be part of the problem. Either way, I'd suggest making a few more properties and settling on one standard for all of them. For example, make the Center be the property stored and calculate the others from it:

public float CenterX
{
get { return X; }
set { X; }
}

public float LeftX
{
get { return CenterX - Width / 2f; }
set { CenterX = value + Width / 2f; }
}

public float RightX
{
get { return CenterX + Width / 2f; }
set { CenterX = value - Width / 2f; }
}