Collision Jitter

Introduction

Bouncing collision is a common behavior which has been implemented in the earliest of games including the ball bouncing off paddles and walls in Pong, the ball bouncing off of blocks in Breakout, and the fireballs bouncing off of terrain in Super Mario Bros. http://www.ordiworld.com/jargon/fig/pong.gif http://www.consoleclassix.com/info_img/Breakout_2600_ScreenShot2.jpg http://img67.photobucket.com/albums/v205/LBoogie82583/Screenshots/SMB1.jpg While this behavior appeared early in video games it can present some challenges. Collision jitter is one of these challenges which often appears when first implementing bouncing collision behavior. This article discusses what collision jitter is and common solutions.

Simple Bouncing Collision Example

The first step to understanding collision jitter is to understand bouncing collision code. I will use a simple ball vs. axis aligned rectangle example and ignore the possibility of the ball hitting the corners. I will assume that I have a method which returns the side on which the collision has occurred.

if(ball.CollideAgainst(rectangle))
{
   // This is not a FlatRedBall call, but I'll pretend it is for simplicity
   Side side = ball.SideOn(rectangle);
   if(sideOn == Side.Right || sideOn == Side.Left)
   {
       // Collided on the left or right side so invert the XVelocity.
       ball.XVelocity *= -1;
   }

   if(sideOn == Side.Top || Side.Bottom)
   {
       // Collided on the top or bottom side so invert the YVelocity.
       ball.YVelcity *= -1;
   }
}

This code seems like it should work but it is possible that it will result in collision jitter especially if the game is not running at a fixed frame rate.

What Causes Collision Jitter

Solutions for Collision Jitter

The most obvious solution to collision jitter is to have a constant frame rate. While the default FlatRedBall XNA template does provide a constant frame rate which reduces the likelihood that this will occur, it is not a 100% solution. Due to floating point inaccuracies it is still possible to trigger a collision.

Repositioning After Collision

if(ball.CollideAgainst(rectangle))
{
   // This is not a FlatRedBall call, but I'll pretend it is for simplicity
   Side side = ball.SideOn(rectangle);
   if(sideOn == Side.Right)
   {
       ball.X = rectangle.X - rectangle.ScaleX - ball.Radius;
       ball.XVelocity *= -1;
   }

   if(sideOn == Side.Left)
   {
       ball.X = rectangle.X + rectangle.ScaleX + ball.Radius;
       ball.XVelocity *= -1;
   }

   if(sideOn == Side.Top)
   { 
       ball.Y = rectangle.Y - rectangle.ScaleY - ball.Radius;
       ball.YVelcity *= -1;
   }

   if(sideOn == Side.Bottom)
   {
       ball.Y = rectangle.Y + rectangle.ScaleY + ball.Radius;
       ball.YVelcity *= -1;
   }
}

Selectively Inverting Velocity

if(ball.CollideAgainst(rectangle))
{
   // This is not a FlatRedBall call, but I'll pretend it is for simplicity
   Side side = ball.SideOn(rectangle);
   if(sideOn == Side.Right)
   {
       ball.XVelocity = -1 * System.Math.Abs(ball.XVelocity);
   }

   if(sideOn == Side.Left)
   {
       ball.XVelocity = System.Math.Abs(ball.XVelocity);
   }

   if(sideOn == Side.Top)
   { 
       ball.YVelcity = -1 * System.Math.Abs(ball.YVelocity);
   }

   if(sideOn == Side.Bottom)
   {
       ball.YVelcity = System.Math.Abs(ball.YVelocity);
   }
}

Last updated