Days 19 & 20: Collision Detection 2.0 – Which side was hit?

29 Oct

If you check out my last blog post, you see the game I did for the BaconGameJam last weekend. I’m still working on improving the game as I want to release it on the Windows Store and maybe port it to Windows Phone 8.

One issue I had was with the current collision detection. All I did was to check, whether the ball hits a tile or not. If the ball hit a tile, i inverted the Y-Velocity. This works great and is OK as long as the ball hits the tile on the top or bottom. If the ball hits a tile on the side, the Y-Velocity should stay the same and the X-Velocity should invert.

This is how I’ve created the detection:

  1. Check if the BoundingBoxes of the objects Intersect – otherwise there is no need to further check for collision.
  2. As the tile is a rectangle, I know its edges which i define as: yTileMax, yTileMin and xTileMax, xTileMin.
  3. I calculate the distance from the center of the ball (Position) to all the edges of the rectangle (tile).
  4. If the distance from the ball to xTile is smaller than the distance from the ball to the yTile, the ball hit the tile on the side.

I had to draw this on a piece of paper to understand it myself 🙂

Check out the code, this should make it a lot clearer:


public static int CollideSide(SpriteObject ball, SpriteObject obj2)
 {
 // 0 : No Hit
 // 1 : Hit on Side
 // 2 : Hit on bottom/top

if (ball.BoundingBox.Intersects(obj2.BoundingBox))
 {
 float ballSize = ball.SpriteTexture.Width / 2 * ball.ScaleX;
 float obj2Size = obj2.SpriteTexture.Width / 2 * obj2.ScaleX;

// Tile Hight
 float tileHight = obj2.SpriteTexture.Height * obj2.ScaleY;
 float tileWidth = obj2.SpriteTexture.Width * obj2.ScaleX;

float yTileMin = obj2.PositionY - (tileHight / 2);
 float yTileMax = obj2.PositionY + (tileHight / 2);

float xTileMin = obj2.PositionX - (tileWidth / 2);
 float xTileMax = obj2.PositionX + (tileWidth / 2);

float yDistMax = System.Math.Abs(yTileMax - ball.PositionY);
 float yDistMin = System.Math.Abs(yTileMin - ball.PositionY);
 float yDist = System.Math.Min(yDistMax, yDistMin);

float xDistMax = System.Math.Abs(xTileMax - ball.PositionX);
 float xDistMin = System.Math.Abs(xTileMin - ball.PositionX);
 float xDist = System.Math.Min(xDistMax, xDistMin);

if (yDist < xDist)
 {
 return 2;
 }
 else
 {
 return 1;
 }

}
 return 0;
 }

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: