# Character jittering with this tile based collision code

I have been trying to get my collision code working for hours now but with every resource I have tried my character still jitters. First I tried using the platformer sample but my character still jittered up and down really quickly, even when standing still. Then I took to these forums and found this post and I used his code and eventually found out that in order for his to work you have to:

1. Move the character's position along the x-axis only.
2. Check if the character collided with something along the x-axis

Then do the same thing for the y axis. In other words, the character could only move one direction at a time and with my game there are a lot of different forces, velocities, accelerations, et cetera. all pulling on the target at once and this kind of solution didn't really work.

I heavily simplified the code in the sample and ended up with this:

Rectangle playerBounds = GetPlayerBounds(motion.Position.X, motion.Position.Y, characterWidth, characterHeight);

// Get the player's bounding rectangle and find neighboring tiles.
Rectangle bounds = playerBounds;
int leftTile = (int)Math.Floor((float)bounds.Left / TileSize);
int rightTile = (int)Math.Ceiling(((float)bounds.Right / TileSize)) - 1;
int topTile = (int)Math.Floor((float)bounds.Top / TileSize);
int bottomTile = (int)Math.Ceiling(((float)bounds.Bottom / TileSize)) - 1;

for (int y = topTile; y <= bottomTile; ++y) // For each potentially colliding tile,
{
for (int x = leftTile; x <= rightTile; ++x)
{
Tile collision = stage.CustomLayer.GetTile(x, y);

if (collision.Value == Tile.CollisionTile)
{
Vector2 depth = Extensions.GetIntersectionDepth(bounds, collision.Bounds); // Determine collision depth (with direction) and magnitude.

if (depth != Vector2.Zero)
{
if (Math.Abs(depth.Y) < Math.Abs(depth.X)) // Resolve the collision along the shallow axis.
{
motion.Position = new Vector2(motion.Position.X, motion.Position.Y + depth.Y); // Resolve the collision along the Y axis.
}
else // Ignore platforms.
{
motion.Position = new Vector2(motion.Position.X + depth.X, motion.Position.Y); // Resolve the collision along the X axis.
}

bounds = playerBounds; // Perform further collisions with the new bounds.
}
}
}
}


The code produces the jittering effect as well. I have debugged it for hours and I think I found the cause but I do not know how to fix it.

For example, if the character's Y position is 500 and is found to be colliding with a tile with a depth of 5 pixels, he will be pushed to Y position 495. At this time, though, the loop will continue based off of old topTile and bottomTile values and he may still be found to be colliding with those tiles, and will be pushed up to Y position of 490. Next time this function is called though when the character has moved back down to Y position of 495 due to gravity, he won't be colliding because of different initial topTile and bottomTile values and will continue moving downwards.

I believe this is what causes the jittering effect but I do not understand why it is happening to me. As far as I know, I am using the same algorithm as everyone else and their code doesn't produce any jittering. All my tiles are of equal size (32x32) and I am using the same GetIntersectionDepth method found in the platformer sample.

Thanks to anyone who can help me solve this problem.

• Switching bounds = playerBounds; to bounds = GetPlayerBounds(motion.Position.X, motion.Position.Y, characterWidth, characterHeight); solved the problem. Thank you. Commented Mar 13, 2012 at 19:55
• That's good. I'll copy the comments to the answer section and delete them. Commented Mar 13, 2012 at 19:57
• Also, I am still interested in your solution. I see the disadvantages of the one I have posted now. However, I have performance concerns with your solution. Wouldn't the checking collision method have to be called twice for all objects in the game? Seems like that could be an issue. Commented Mar 13, 2012 at 19:57
• Indeed it's slower, but unfortunately I have yet to find another way to handle tile based collisions that doesn't start giving problems in some cases. I'd be happy to learn about a more proper solution! But it has to work in every direction and against every wall - think oldschool Zelda type of collision, not platformer. Commented Mar 13, 2012 at 20:05
• Hmm, alright. Well I definitely prefer a proper working solution that's somewhat slower to one that is buggy and faster! I'm going to go and try your solution once more. I doubt collision testing is really going to be the bottleneck regardless. Thanks for all your help. Commented Mar 13, 2012 at 20:11

As for the jittering problem, I remember I had it too and the solution for me was by doing Math.Round on the player position after applying velocity (I did it before handling collisions, but I'm not sure if order matters). You can see that on my example, line 66, and if I remember correctly it was also present in the original sample in the Update method or something. From your code snippet I can't see if you're already doing it or not, but I recommend it to prevent jittering at certain speeds.
Other than that suggestion, there's something wrong with your code. In particular, since Rectangle is a value type, not a reference type, when you do bounds=playerBounds after moving the player, you're not really pointing to the new bounds of the player. It's still the old value. You need to call GetPlayerBounds() again to recalculate the new bounds for the player.