Question

I have a simple rectangle-tile collision scheme set up, and it works beautifully.

The only problem is when you start falling off of a ledge. Your speed reaches the point where the change in Y/X each frame is large enough for you to clip into solid objects and glitch about.

Basically my setup is as follows:

To start with, the player's position has its velocity added to it, so the player is now at the place he would be next frame if no collisions happen. The list below is just a single function, checkIntersectTiles(Vector2 maskPos);

  1. Calculate tiles around the character to check.
  2. Loop through tiles, including those inside the bounding tiles.
  3. Check the player's collision rectangle against each of these tiles.
  4. If there's an intersection, move the largest offending axis out of the tile, then set that axis velocity to 0.
  5. Continue checks.

When you clip into the ground, you jitter around inside, as my algorithm attempts to move you outside the tile that is most colliding with you.

My solution: Check each position from the player's pos, to the player's pos + velocity. I'm stuck on that bit.

Can anyone give me a hand?

Was it helpful?

Solution

I assume that your code to move the player out of the colliding tile does so in a single step. So if the player collides with a tile you determine that the penetration depth is 5 in the Y direction you immediately adjust the player Y position by -5.

As you suggest, check the player position at each step. So if the Y velocity is 5 then you can adjust the players Y position by 1, check for collision and then repeat 4 more times. See later for calculations handling time stepping. The following is just some basic pseudo code and just in the Y direction.

player.Y += vel;
if (player.CheckCollisions())
{
  // handle collision
}

Becomes

for (int i = 0; i < vel; ++i)
{
  player.Y += 1;
  if (player.CheckCollisions())
  {
    // handle collision
    break;
  }
}

That is the simple version if you are not adjusting for ellaped time. If you are, then you rather perform smaller time steps

So

player.Y += vel * elapsedTime;
if (player.CheckCollisions())
{
  // handle collision
}

Becomes

float currentTimeStep = 0;
Position startY = player.Y;
while (currentTimeStep < elapsedTime)
{
  currentTimeStep = Math.Min(currentTimeStep + stepDelta, elapsedTime); // You need to tune the stepDelta
  player.Y = startY + vel * currentTimeStep;
  if (player.CheckCollisions())
  {
    // handle collision
    break;
  }      
}

In the above you will need to tune the time step delta to ensure that you balance performance with accuracy. You might event consider calculating the delta dynamically each frame to ensure that the adjustment is close to 1 pixel.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top