Thursday, October 16, 2008

XNA Part 8 - Simple Collisions

Most games that have any kind of movement need to detect object collision. There are many levels of object collision (as I am learning) that we can detect, but to start, we will look at simple rectangular collisions.

Here is the basic idea: First take 2 objects of type Rectangle which is defined this way

Rectangle a = new Rectangle(10, 10, 100, 100);

where we pass the X and Y coords of the top left corner of the rectangle and then the width and height of the rectangle. Then we create another one

Rectangle b = new Rectangle(20, 15, 100, 100);

Now we can call a member of the Rectangle class called Intersects() that will return a bool to tell us if if the 2 rectangles intersect.

So in this case since a and b do intersect,

a.Intersects(b)

would return true. We can use this type of information to help us out. In determining our game logic and behavior.

Here is an idea I came up with for putting this type of functionality into our GameObject Class. We can implement an Intersects method for our GameObject class that takes a GameObject as a parameter and then do our determining there. Here is the code for a simple GameObject

class GameObject
{
public Texture2D sprite;
public Vector2 position;

public GameObject(Texture2D inSprite,float x, float y)
{
sprite = inSprite;
position = new Vector2(x, y);
}

public Rectangle Bounds
{
get
{
return new Rectangle((int)position.X,
(int)position.Y,
sprite.Width,
sprite.Height);

}
}

public bool Intersects(GameObject b)
{
return Bounds.Intersects(b.Bounds);
}
}

We will hold only the texture and the position for now and we set them both in our constructor. Then we add a read only property called Bounds. This dynamically returns a Rectangle object that has been derived from the position vector and the size of the texture. Then in our Intersects() method we will ask our class for it's bounds and then see if it intersects with the bounds of our GameObject b. That way, we can later run code that looks like this.


GameObject a = new GameObject(Content.Load("test"), 10, 10);
GameObject b = new GameObject(Content.Load("test"), 300, 300);
if(a.Intersects(b)){
//Do something here
}

Now of course in this example, both GameObjects are hard coded to a location, so we would want to add code somewhere to get one of these puppies moving. So in our Update method I will add

a.position.X += 1.0f;
a.position.Y += 1.0f;

and flesh out my Draw method with

if(a.Intersects(b)){
graphics.GraphicsDevice.Clear(Color.Red);
} else {
graphics.GraphicsDevice.Clear(Color.Green);
}
spriteBatch.Begin();
spriteBatch.Draw(a.sprite, a.position, Color.White);
spriteBatch.Draw(b.sprite, b.position, Color.Blue);
spriteBatch.End();

So in the end, if a and b intersect, the background is cleared with red otherwise it is green.

This method works great when our Game Objects are rectangles, but if you recall, we are using PNG images which support transparency, so even the transparent part of your GameObjects would cause a collision since we don't care what is drawn in our GameObject we are just checking the bounds. Next we will be taking a closer look at our image to see if, pixel by pixel, we have collisions.

No comments: