2D collision resolution: works on each axis individually, but not with both combined

My collision detection method is solid and detects box to box collision every time. Then comes the resolve part which I'm struggling with quite a bit. It works perfectly when I'm manipulating the x-axis and y-axis of the player (tile) but only happens to work when I move on any given axis individually. If I try to move on both axis then the whole thing breaks down and starts acting weird.

I'm trying to implement gravity. And so I keep a constant down force on my player tile. This is when I realized that when I'm applying force on both axis (because gravity is constantly applying force on the y-axis) and moving the player tile right or left on the same time my collision resolve method breaks down.

My collision is working great while moving along each axis individually. Here's the result:

How can I approach collision resolution in order to avoid this type of result?

I'm currently predicting the position the player will be at, then I'm checking every single collideable tile at that position. If I detect a collision, I move the player back along the axis the collision was detected in.

This is my current code with collisions working well on a single axis at a time:

void Tile_Player::Move(double delta, G3::Tile_Map *map)
{
int xvel = (this->xDirection * (G3::TILE_STEP * (delta/1000)));
int yvel = (this->yDirection * (G3::TILE_STEP * (delta/1000)));

G3::xy_pos predictedPos;
predictedPos.x = this->tile_location.x; predictedPos.y = this->tile_location.y;

predictedPos.x += xvel;
predictedPos.y += yvel;

bool collision_status = false;

for (int i=0; i< map->GetTotalTileCount(); i++)
{
G3::Tile *tempTile = map->GetTileAt(i);
if (this != tempTile)
{
bool coll_bool;
coll_bool =  this->CheckCollision(predictedPos, tempTile->GetTilePos());
if (coll_bool)
{
//check collision on the left
if (this->xDirection == -1)
{
predictedPos.x = tempTile->GetTilePos().x+G3::TILE_SIZE+0.1;
}
//check collision on the right
if (this->xDirection == 1)
{
predictedPos.x = tempTile->GetTilePos().x-G3::TILE_SIZE-0.1;
}
//check collision on bottom(ground)
if (this->yDirection == -1)
{
predictedPos.y = tempTile->GetTilePos().y+G3::TILE_SIZE+0.1;
}
//check collision on top
if (this->yDirection == 1)
{
predictedPos.y = tempTile->GetTilePos().y-G3::TILE_SIZE-0.1;
}

}
}
}

this->tile_location.x = predictedPos.x;
this->tile_location.y = predictedPos.y;

this->xDirection = 0;
this->yDirection = 0;
}

• where are you adding gravity? adding velocity due to gravity to the predicted position before the collision detection should probably work fine if your CheckCollision function is working as expected. – gordonk Jun 17 '13 at 13:14
• I guess when we have a duplicate of a too localized question, maybe it wasn't too localized. gamedev.stackexchange.com/questions/35080/… – MichaelHouse Jun 17 '13 at 13:17
• i could add up: int this->yDirection = -1; at the very beginning of my function and i would have a constant "force" pulling me down. But then if i try to move right or left i would be applying two "forces" at once and hence my collision resolution breaks down. – apoiat Jun 17 '13 at 13:51
• i would then integrate states like is_ground=true if i have a top collision and is_ground=false if i have no collisions whatsoever but havent managed to work it out so far. Its possible im messing the logic behind it. – apoiat Jun 17 '13 at 13:53
• @Byte56: the question as it stands is too localized (debug his code), but it could be cleared up to be about general practice and math independent of a specific implementation. Especially as addressing this singular bug isn't going to fix any of the larger problems in his approach to platformer physics, this just isn't super useful in general as stated. – Sean Middleditch Jun 17 '13 at 17:44