Making a 2D XNA Game - When Cods Collide Part 1
To make the most use of this and its subsequent post, you should download the XNA 2D Collision detection sample and look over both the code and documentation in Game Studio 2.0. This post was written with the game.cs file open, so may as well read it in the same vein...the blog post is meant to help you decipher the sample even if you've never seen C# before.
Frankly, before I set about the write this post, I had never written in C# either. But the powerful awesomeness of the rectangle collision sample, combined with my almost-too-colloquial-to-be-accurate blogging, will set you on the road to making your own 2D collision game. I have no doubt that experienced programmers will be bored or appalled by all this, so if that's you, you can always move on to anything blogged by Shawn Hargreaves. And ya, after having these epiphanies with our sample, I did make an XNA game called "When Cods Collide."
Introduction
In my desire to do more with my bouncing cod code, I went on to read the XNA 2D Collision detection sample. I figured colliding cods would be even more amusing.
Then I realized that, while I can readily stuff in my own images and pretend I coded something :P, I needed to get clear on some concepts before I proceeded. Because on my way to actually finding that tutorial, I got lost in a larger MSDN world I didn’t understand. I figured if you, like me, had no C# experience before, you would need a roadmap to this sample and how to change it. So think of this series of blog posts as newbie commentary on the rectangle collision sample and its tutorial. If I dissect it in enough detail, the way I came to understand it – hopefully you too will understand it well enough to adapt that sample to make your own XNA 2D game....and read more about C# and the ways to make more complex XNA games.
Where do I begin…..
As with any coding project, breaking the overall task of the program up and setting its boundaries will help me attack how to code it.
1) Am I staying in 2D? Yes. Knowing that I am staying in 2D means I know what mathematics will drive my game logic. Also, it helps me know what graphics resources and their formats are what will be used in this game.
2) Will I change the visuals of the original sample? Yes. Let’s change out images. Substitute cods for the people. Also, add martini glasses for the falling arrows.
3) Change the motion of this game. Yes, something should happen when a cod hits a martini. Some sort of rapture... But also, can I change the way the cods and the martinis move in the first place?
4) Will I change the overall rules of the game? Yes. I want the goal not to be avoiding collision, but embracing collision. The cod WANTS the martini.
So as I dissect the rectangle collision sample I will be looking at a few things:
- What is actually happening in the sample
- How to adapt the code so that I can use new graphics
- How to adapt the code so I can change how the player moves around the screen
- How to adapt the code so that I can change the rules of the game
What dimension are we in?
First off, I want to make my cods and martinis collide in two-dimensional space. If you need a more mundane metaphor, think of it as sliding a piece of colored paper across a white kitchen counter top – that is what I mean by 2D.
(Why do I want the cods to collide in 2D? Because I’m a noob, that’s why. I don’t want to mess with all those other Z coordinates right now. )
Being in 2D means we are using vector math. If like me you haven’t had vector math for a while, let’s go back to the kitchen table with a colored paper circle cutout. That circle cutout I am moving around, represents a point on the plane of the kitchen table. It has a horizontal location (x) and a vertical location (y) as it moves around on top of the table.
Unlike the x and y discussions you had in algebra class long ago, where 0,0 was in the lower left of your graph paper, for game screens 0,0 is actually the upper left.
We use a Vector2d class, or unit of code, to hold the location information for the cods and the falling martinis. I’ll talk more about vector2d classes later. But now I need to talk about what those cods and martinis really are.
Sprites are not imaginary creatures, they just represent abstract things
So we all know the difference between gaming and the reality of the game code. One looks like Halo3 and lots of fragging – the other looks like The Matrix, with tons of obscure symbols and math equations falling on your head.
When I talk about moving a cod (or a person in the rectangle sample) around the game screen, I’m really talking about two things: its sprite, or the 2d representation of what it looks like ( asset files and code that create visual effects when the sprite is created on the screen), and the code objects that contain the location points and the game logic that determines what happens to the cod.
In the beauty vs. brains dichotomy, the sprite is primarily beauty – the class or object is the brains. The image files and effects that make up a sprite, show you the status of what’s happening to the game class or object. A lot more can be happening under that shiny surface than appears on the screen.
The other thing to keep in mind as we talk about sprites is that they don’t actually “move” the way that movies aren’t actually moving pictures. Movie film is represented by thousands of frames, each showing an incremental change in the image, say of a running horse. Projecting these images of a running horse past our eyes fast enough, we think the horse moves across the movie screen.
The same thing happens with rectangle sample’s player-controlled Person sprite, or my future game, the player's cod. In the code, I will have the computer continually draw and redraw the screen to fool the player (and myself) such that when I run the code, it appears that something is actually moving.
There are some handy diagrams of sprites and how they are made/move on MSDN. (I’ll be covering some of this in the blog post, but for completeness you want to refer this page. https://msdn2.microsoft.com/en-us/library/bb203919.aspx)
But as I use code to move my sprites around the way I want, I also want to know how to make the sprite look like what I want.
Basic components of a sprite:
- Source image files, known as textures – they should be bitmaps or .png files so you don’t get weird artifacts from compression
- Code that controls how the sprite itself gets drawn (effects, whether it is rotated, does it slip “behind” another sprite)
- Code that controls how the sprite behaves (game logic, classes, etc)
How do we “move” sprites in this dimension?
In order to have the computer move sprites around as a response to your code, you need to use a SpriteBatch object in your game code to make that happen. This is a unit of C# code that is already part of the XNA Framework, a unit also known as a class. Because it is part of the XNA Framework already, you can just use it without any extra setup.
The specific lines of code that sets us up to get a SpriteBatch class for your use (called “spriteBatch” with a small s) , is repeated below.
// The images will be drawn with this SpriteBatch
SpriteBatch spriteBatch;
The code that actually creates your specific instance of that SpriteBatch class is here:
// Create a sprite batch to draw those textures
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
}
Think of an object or class in programming as a giant bucket. Inside the bucket, you have statements (functions, subroutines, whatever) that make stuff happen TO the bucket (grow a handle, turn red, empty the contents, fill with fried chicken, spin clockwise, etc). What actually happens to the bucket and stuff in it, depends on whether your program calls that particular method (“bucket.empty”, “bucket.spin”).
One of the biggest things in a SpriteBatch class’s little life, aside from its Begin and End methods that actually define its little life inside your game program, is this one called Draw. In the tutorial, an example of calling the Draw method is:
spriteBatch.Draw(personTexture, personPosition, Color.White);
{The official MSDN explainer for the SpriteBatch Draw method is here: https://msdn2.microsoft.com/en-us/library/microsoft.xna.framework.graphics.spritebatch.draw.aspx
Loading the content
Ok, so I’ve shown you how a sprite gets drawn. But I haven’t talked about how I control what a sprite looks like. Mostly, I wanted to get you down the garden path without having your eyes cross from the abstraction. Here goes from ground level to top:
· Texture = Image file or bitmap resource that assists you in making your sprite.
· Texture2d – this is a class that knows where the texture’s image file is, and makes it available to your game code for manipulation.
· SpriteBatch class, the code which actually can draw sprites and make then dance for you*
* Literally speaking, our developer education dude Matt wants me to tell you there is no such method called SpriteBatch.dance and frankly, it makes him ill. Don’t go there, he says.
To get an image file referenced from a sprite, you have to use aTexture2D object to hold the bitmap information and then you reference that Texture2D object in your code. In our collision sample, personTexture is a Texture2D object.
How did it get associated with the little bitmap of the person? In the LoadContent portion of the game program:
protected override void LoadContent()
{
// Load textures
blockTexture = Content.Load<Texture2D>("Block");
personTexture = Content.Load<Texture2D>("Person");
// Create a sprite batch to draw those textures
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
}
Get back to the drawing
Let’s look in the sample at the small sequence our little spriteBatch goes through. As you are looking at the code in game.cs you will see the double slashes. These //’s denote comments in C#. I’ve added comments here in addition to the original sample comments.
//This gets the another class, GraphicsDevice, ready to draw some sprites.
spriteBatch.Begin();
// Draw person
// Note how it follows the syntax of SpriteBatch.Draw Method (Texture2D, Vector2, Color)
spriteBatch.Draw(personTexture, personPosition, Color.White);
// Draw blocks
// This contains a couple of concepts we get to talk about
//namely “for each”, “vector2,” and handling of positions
foreach (Vector2 blockPosition in blockPositions)
spriteBatch.Draw(blockTexture, blockPosition, Color.White);
//This closes down the spriteBatch class
spriteBatch.End();
Think of an object or class in programming as a giant bucket. Inside the bucket, you have statements (functions, subroutines, whatever) that make stuff happen TO the bucket (grow a handle, turn red, empty the contents, fill with fried chicken, spin clockwise, etc). What actually happens to the bucket and stuff in it, depends on whether your program calls that particular METHOD (“bucket.empty”, “bucket.spin”).
One of the biggest things in a SpriteBatch class’s little life, aside from Begin and End methods that define its little life, is this one called Draw. In the tutorial, an example of this is:
spriteBatch.Draw(personTexture, personPosition, Color.White);
Following the syntax of SpriteBatch.Draw Method (Texture2D, Vector2, Color)
as referenced on MSDN here. ( https://msdn2.microsoft.com/en-us/library/bb196415.aspx).
Above, we’ve passed 3 values to the Draw method – the Texture2D class that holds the Person image file, the initial starting position of the Person, and the tint color. Color.White (which actually means no tinting.)
The starting position of the person is contained by the Vector2 class, with X and Y values. That’s what vector2 does for you – it’s the bucket that contains the location information for the sprite.
I’ve walked you through the part of the code and tutorial gets you to a certain point where your Person is now showing up. Next, the sample tutorial starts talking about the falling blocks, player input, and the nuts and bolts of collision. I’ll tackle those in the next post.
Comments
- Anonymous
February 10, 2008
To make the most use of this and its previous post , you should download the XNA 2D Collision detection - Anonymous
February 11, 2008
You've been kicked (a good thing) - Trackback from GameDevKicks.com - Anonymous
February 13, 2008
The comment has been removed - Anonymous
February 15, 2008
I work in the same team area as the venerable Besty Aoki does. It's fun, because most of the time she