When Things Collide, We Detect!

Starting off 2008 with some collision detection! Now that we’ve slowly learned how to work with XNA framework, we’re getting very close to knowing most of what we need to build an actual playable - and maybe even a fun - game. Let’s get right to it then: What is collision detection?

Collision detection is one of the methods you can use to detect if two objects in your game collide. Why would you want to do that? Let’s say you have a very simple game where the player controls a ship that shoots missiles. You have enemies that fly around and you shoot at them. How will you know when your missiles hit an enemy? That’s where collision detection comes into play. You want to detect when two objects - missiles and enemy ship - collide together.

How does collision detection work? Here’s the “theory” behind it. Check out this diagram here:

image

See how we have two rectangles? Obj 1 and Obj 2. Right now they have not collided together, right? Let’s see what happens when they do collide:

image

See that? The rectangles have collided and we can see that due to the intersection that happened between them. This is how you can detect if two rectangles have collided together: if they intersect together.

So how do that apply to a game? What you need to do is specify a rectangle for every object in your game that contains that object. Such a rectangle is called a BoundingRectangle. As objects in the world move around, you check for collisions at every Update call to see if the rectangles intersect, if they do, you got a hit!

Visual example:

image

See how we have a virtual rectangle drawn around each texture in the game? They are not actually rendered of course, just defined in the code and kept around for collision detection. If these two creatures actually collide, the rectangles are going to intersect and we get a hit.

Show me the code!

Let’s have a quick look at how this would work in code. We’ll have a very simple scenario where you have an enemy and a missile that is aimed at them. We want to know when the missile hits the enemy so that we can render an explosion or something cool.

First we see what data structures we need to create:

 

   1: Texture2D enemy;
   2: Texture2D missile;
   3:
   4: Rectangle enemyBR;
   5: Rectangle missileBR;
   6:
   7: Vector2 enemyPosition;
   8: Vector2 missilePosition;
  • Lines 1 & 2: Simple declaration of the enemy and missile textures we’ll use.
  • Lines 4 & 5: These are the two Bounding Rectangles we’ll use for collision detection. One for the enemy and one for the missile. We use the Rectangle structure from XNA framework for this.
  • Lines 7 & 8: Two Vector2 objects that we’ll use to track the position of the enemy and missile in the world.

Next we initialize everything, I did that in my LoadContent method:

 

   1: protected override void LoadContent()
   2: {
   3:     spriteBatch = new SpriteBatch(GraphicsDevice);
   4:     enemy = Content.Load<Texture2D>(“enemy”);
   5:     missile = Content.Load<Texture2D>(“missile”);
   6:
   7:     // Init positions
   8:     enemyPosition = new Vector2(10, 10);
   9:     missilePosition = new Vector2(70, 70);
  10:
  11:     // Init Bounding Rectangles
  12:     enemyBR = new Rectangle((int)enemyPosition.X,(int)enemyPosition.Y,
  13:                                 enemy.Width, enemy.Height);
  14:     missileBR = new Rectangle((int)missilePosition.X, (int)missilePosition.Y,
  15:                                 missile.Width, missile.Height);
  16: }
  • Lines 8 & 9: Nothing new here, just initializing the positions of the enemy and missile in our world. I just put whatever values in there, they are not really accurate ;)
  • Lines 12-15: We initialize the Bounding Rectangles. The constructor for the Rectangle struct takes a position in X,Y and a Width and Height values. I use the initial positions of each object for the X,Y and the Width and Height of the texture for the rest. Very simple.

Finally, we go to the Update method:

 

   1: protected override void Update(GameTime gameTime)
   2: {
   3:     // Allows the game to exit
   4:     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
   5:         this.Exit();
   6:
   7:     // Move stuff around based on input or whatever
   8:     // I removed that part of the code for simplicity
   9:
  10:     // Make sure to sync the Bounding Rectangles with the current position
  11:     // of the contained object
  12:     enemyBR.X = (int)enemyPosition.X;
  13:     enemyBR.Y = (int)enemyPosition.Y;
  14:
  15:     missileBR.X = (int)missilePosition.X;
  16:     missileBR.Y = (int)missilePosition.Y;
  17:
  18:     // Now check if they collide or not
  19:     if (enemyBR.Intersects(missileBR))
  20:     {
  21:         // We got a HIT! Do something!     
  22:     }
  23:
  24:     base.Update(gameTime);
  25: }
  • Lines 12-16: As we moved the sprites around the screen based on user input or whatever, we have to make sure we synchronize the Bounding Rectangles as well! They won’t move on their own. So at every update, I make sure to update the X,Y values for the Rectangles.
  • Lines 19-22: This is where the magic happens! We use the Intersects method in the Rectangle struct to see if the enemy rectangle intersects the missile rectangle. If they do, then we know we got a hit!!

That’s it! How easy was that eh? What’s even cooler is that these same concepts pretty much work the same in 3D graphics. But we’re getting ahead of ourselves, we’ll get there soon.

Tips & Tricks

Some food for thought:

As you probably figured out by now, it’ll be easier if you create a container object for your objects in the world that has all the data needed by that object. So things like the texture that represents it, the position in the world, the bounding rectangle, etc. This way you can have everything self update in a more automatic and contained way. Manually updating the bounding rectangles like the code above is not the most efficient way to do things.

When you initialize your bounding rectangles, you don’t have to make them the exact size of the texture like I did above. Actually, most games like to make them smaller so that a collision happens when the two objects rendered are overlapping more than in my example. This way you use the rectangle to mark the “hit-able” part of the image which for a ship might be the power core or something.

Another REALLY cool use of bounding rectangles is to mark areas in the world where you want to know if something enters or exits it. For instance, let’s say you have your ship moving left and right along the X-axis at the bottom of the screen. How do you make sure it doesn’t move off the screen edge? You can keep checking the x-value of the ship against x = 0 (left side) and x = screen width (right side) and make sure you don’t move it beyond those points. OR… you can put small bounding boxes at the right and left of the screen and check for intersections.

Tip conclusion: Bounding rectangles can be used to detect when objects hit areas of the screen! Use that to achieve things such as event triggers or movement restrictions.

Last tip… hmm… I got nothing for you… I just don’t want to end on a “Tip Conclusion” since it kinda looked ugly ;) Maybe you guys have some more tips to share!

Tips from you guys! (Keep them coming!)

From KaBaL: Don’t forget, you can use more then one Bounding Box for a single object (sprite) that way you can get better detail for irregular shaped objects (ship’s nose, wings, tail)

Thanks for reading! I'd love to hear your thoughts, feel free to leave a comment below. Don't forget to subscribe to my RSS Feed!

2 Responses to “When Things Collide, We Detect!”

  1. KaBaL Says:

    Don’t forget, you can use more then one Bounding Box for a single object (sprite) that way you can get better detail for irregular shaped objects (ship’s nose, wings, tail)

  2. nazeeh Says:

    Thanks KaBaL :) That’s a good one. I put it as part of the post. Keep’em coming :)

Leave a Reply

The page's WebCounter count says that you are visitor number Visitor Counter by Digits
FireStats icon Powered by FireStats