devxlogo

Introducing XNA Game Studio Express

Introducing XNA Game Studio Express

f you have ever dreamed of being a game developer (honestly, who among us has not toyed with the idea at least a little?), this is your time in the sun. With the release of XNA Game Studio Express in December of 2006, Microsoft has begun a steady march on a mission to change the game development industry.

Microsoft released XNA Game Studio Express as a beta in early August 2006, followed up with a second beta a few months later in November, and then officially released version 1.0 in December of 2006 to much excitement in the game development community. The initial audience to embrace XNA Game Studio Express has been game development hobbyists and small independent game shops, but it is clear that the game development community as a whole has its eye on XNA Game Studio Express?not only where it’s going, but also where it’s taking the game industry.

After a quick introduction of XNA Game Studio Express, this article shows you how to use it to create a simple 2D example game.

It’s Good to Be Free!
One of the most attractive features of XNA Game Studio Express is its price. Everything you need to make a game with XNA Game Studio Express is…free! Developers who want to use XNA Game Studio Express also use C# Express, giving them the power and speed of developing with managed code in a free development environment. The only costs to game developer hopefuls are the art and sound assets, which in many cases they can find for free, or create with free tools. It is pretty hard to argue with a price like that.

Even if you can afford XNA Game Studio Express, you must make sure that your computer can actually handle developing with it. Hardware requirements primarily consist of not having an older video card. You need a Direct3D 9.0 video card capable of at least Shader Model 1.1. You can purchase cards that meet this minimum requirement fairly inexpensively from most major computer electronic retailers. Some people with older laptops might have to jump this hurdle, but most users won’t have trouble meeting the minimum requirements.

What does XNA stand for? It’s a recursive acronym that stands for “XNA’s Not Acronymed.”

Getting Started
Getting started with XNA Game Studio Express starts with learning C#. While you don’t need to be a C# expert to learn to use XNA Game Studio Express, you will need to have a basic understanding of the syntax and the initial concepts of object-oriented programming.

If you are fairly familiar with C# and you have some experience with DirectX development, you may wonder where the tutorial and sample code are that show how to set up a graphic device and display that first black screen. Talking to the graphics device and getting a good blank slate is always a good first step in a game project. This was quite an arduous task with DirectX, particularly for newcomers.

To help prevent that frustration with XNA Game Studio Express, here’s a walk-through of that initial “first game” project to get you started, with slow and detailed steps so you won’t spend an entire evening getting through this first game development step.

Making That First Game Project
Here’s the process in a nutshell:

  1. Launch XNA Game Studio Express. You’ll see the familiar C# Express development environment. XNA Game Studio Express is basically that standard environment, with some extra XNA Framework goodies thrown in.
  2. Click the File menu and select New Project.
  3. Select the “Windows Game” project template.
  4. Give your new game a name and click OK.
  5. Run your game.

Yes, that’s it! If you were greeted by a beautiful cornflower blue screen (it’s the new black), then congratulations! The rest of the night is now yours to spend writing game logic rather than setting up communications with a graphics device.

You have just experienced a small part of the power of XNA Game Studio Express. To be fair, it is true that once you had established a communication with a graphics device with DirectX, you could have created your own “Windows Game” template?but the point of using XNA Game Studio Express is that you didn’t have to. Installing XNA Game Studio Express also installs a Windows Game template that lets new game developers get up and running quickly without all the confusion.

The Game Loop
Another great example of this kind of “out-of-the-gate” mentality in XNA Game Studio Express is the game loop. Traditional game development has always involved a great deal of thought and philosophical debate on how to construct and use a game loop. Many people put a lot of time into this, and new game developers often get lost just trying to wade through the many and differing discussions. New game developers just want to get started on their game, but getting started on a game loop can cause confusion.

With XNA Game Studio Express, game loops are no longer a research topic or a stumbling block for new game developers. When you create a new XNA Game Studio Express game, the game loop is already there?beneath the surface. Instead of developing the loop, game developers can immediately begin putting game logic into the pre-existing Update method and display logic into the Draw method. These methods are not only created automatically when you begin a new XNA Game Studio Express game, but they are called automatically by the hidden game loop and fire continuously during the life of the game. Developers can now begin actual game development instead of trying to figure out how to create an efficient game loop correctly.

The Content Pipeline
Since XNA Game Studio Express makes creating a new game project simple, and it takes care of creating an efficient game loop, what’s next on the list of XNA Game Studio Express features that lowers the learning curve for new game developers? That would be the content pipeline. This feature of XNA Game Studio Express aids game developers in getting content into their games. Whether that content consists of models, backgrounds, textures, sprite sheets, music, sound effects, or XML files, Microsoft’s content pipeline makes loading content a little easier and a bit more uniform.

Along with loading content, the content pipeline also makes it easier to distribute your games. The built-in content pipeline converts all your content pipeline-loaded assets to XNA binary files (XNB) files. XNB is a new file extension specific to XNA Game Studio Express. You ship the XNB files instead of your assets with your executable when you finally release your game. The content pipeline and the XNB files not only help keep track of your assets, but help protect them as well, because (at least right now) there are no tools that can extract them from the XNB file format back into the original asset files.

Player Input
Now that you’ve seen an overview of how to load game content into your games in XNA Game Studio Express, it might be nice to have a way of getting some user input to control that content. For that, Microsoft has given game developers the very intuitive and extremely easy to use Keyboard, Mouse, and Gamepad objects along with corresponding “state” objects to gather information about those devices.

For example, suppose you want to know if a user has pressed the Escape key. You could do it like this:

   if (Keyboard.GetState().IsKeyDown(      Keys.Escape) == true)   {      this.Exit();   }

The Keyboard object is already a part of XNA Game Studio Express, so developers do not need to create or initialize it. The Keyboard object just waits, ready to be used if needed. Getting information about mouse or gamepad devices is just as simple using the Mouse and Gamepad objects. In other words, gathering user input using XNA Game Studio Express is a snap.

Game Components
You represent game components as GameComponent classes that you can add to your main game class. Each GameComponent class has its own Update and Draw methods that are automatically called from the main game loop. This creates the potential for powerful plug-and-play opportunities in your game design. While the XNA community has not seen many generic pluggable game components appear yet, some early examples that calculate and display frames per second have appeared. As game developers get used to developing game components, adding rich game functionality to your game may become as easy as dropping in the appropriate GameComponent classes.

Yeah, I Made That
I’ve covered some of the basic features that showcase the power of XNA Game Studio Express, but I have not yet mentioned one of the most powerful and coolest features of the framework. The feature that has generated the most buzz and has some of the highest wow factor is that you can play games you develop with XNA Game Studio Express on your Xbox 360. This feature, while cool, does come with a price. In order to play your creations on the Xbox 360, you need a membership to the Microsoft Creators Club, which runs around $99 for a year membership. Try to develop for any other console at that price! No other company has given the general public this kind of officially supported access for development on a console before, so this feature has great potential to start some changes in game development.

Getting Help
I wrote this article to give you an overview of XNA Game Studio Express and a brief glimpse of its power. As you begin to play with XNA Game Studio Express yourself, I am sure that you will have questions. Since I cannot possibly hope to answer all of your questions here (or even in a series of articles), I’ll point you to the Microsoft’s Creator’s Club site to get your questions answered.

The Creators Club site is not only a great place to grab some Microsoft XNA Game Studio Express content such as new starter kits and samples, but it also has some of the most active support forums I have ever seen. You’ll find support from XNA community members, but even more importantly, the extremely helpful and knowledgeable XNA Game Studio Express developers at Microsoft also monitor the forums. If you post a question, you are sure to get an answer, often within hours, if not minutes, of your initial post.

The community around XNA Game Studio Express has been amazing and helpful right from the very beginning. I’d be neglectful if I do not at this point mention some of the great sites, resources, and games provided by the XNA Game Studio Express community (see sidebar, Community).

“The” Competition
With all of this power in XNA Game Studio Express and an active and growing community, how do you go about increasing the XNA Game Studio Express fever? You hold a game development competition and make the grand prize so attractive that game developers around the world from hobbyists to indies to professional houses want a shot at it. Microsoft has done that with their Dream Build Play competition. With a $10,000 grand prize and the potential for an Xbox LIVE Arcade publishing contract, this competition has most of the community working feverishly to get their game ideas completed and coded in time.

Now that you have learned a little about XNA Game Studio Express and the XNA Framework, let me show you how to make a game!

Editor’s Note: This article was first published in the September/October 2007 issue of CoDe Magazine, and is reprinted here by permission.

Drive Fast and Avoid the Oncoming Obstacles
In 1981, back when Microsoft was first getting started, IBM contracted with the company to develop the BASIC programming language for the new IBM PC computer. At that time, Bill Gates co-wrote a game to help demonstrate the abilities of the IBM PC and the new BASIC programming language. This game was DONKEY.BAS.

Today the torch has been passed, and I’ll show you how to create a clone of that simple game and its basic game play using XNA Game Studio Express. I’ll call the game “Drive Fast and Avoid Oncoming Obstacles,” which is very similar to DONKEY.BAS and will consist of, you guessed it, a car driving fast along a road and avoiding obstacles. (That name could almost be a design document!)

I’ll start by listing some of the other design elements of the game.

  • The only movement players can make is to switch their car between lanes by pressing the Spacebar key.
  • Obstacles scroll down through the screen in one of two lanes and the player must change lanes to avoid hitting the obstacles.
  • The game tracks the number of obstacles a player has successfully passed. The more obstacles the player successfully avoids, the faster the car will go.
  • Colliding with an obstacle ends the game. At that point, players must make a choice between playing again or exiting the game.

That is some pretty simple game play, I know, but XNA Game Studio Express makes this game pretty simple to put together too.

Creating the New Game Project
To begin, create a new Windows Game Project. Launch XNA Game Studio Express and then select New Project from the File menu.

?
Figure 1: Creating a new game based on an XNA Game Studio Express template.

In the New Project window, select the “Windows Game” template (see Figure 1) and then give the project a name and designate a save location. Name the game “Drive Fast and Avoid Oncoming Obstacles” so that Visual Studio names the project appropriately.

Build the project. If you get an error, then your video card may not meet the minimum requirements for XNA Game Studio Express. Visit the XNA FAQ on MSDN for a complete list of the minimum requirements. If you believe your video card does meet those requirements and you get an error, then try heading over to the Game Developer forums and ask for some help. The forums are quite active and it is likely someone will be able to help you fairly quickly.

Adding the Road Image
Now that you have the game set up correctly, here’s how to add your first image to the project. This “road” image will scroll vertically through the screen?but for now, just work on getting the image added to the project so you can display it.

?
Figure 2: Adding the road image to the game project.

To add an image to the game project, right-click on the project name and select Add ? Existing Item, which opens the Add Existing Item dialog box. The dialog defaults to show only “Visual C# Files,” which means you will not see any images until you change this filter. To use the Content Pipeline to manage your images, select Content Pipeline Files from the “Files of type:” combo box. Now you should be able to navigate to your image. Select the image and then click the Add button. With the image added to your game project, you now need to display it (see Figure 2).

Drawing the Road Image
So far you’ve created the game project and added the image, so now let’s finally write some code to draw that image on the screen. To start you’ll add two new objects to the main game class (Game1.cs by default). These two objects will store the image and draw the image to the screen:

   private SpriteBatch mSpriteBatch;   private Texture2D mRoad;

You use SpriteBatch, an XNA Framework object, to draw images to the screen. Texture2D, another XNA Framework object, is used to store an image. You’ll use both of these objects frequently when creating 2D games with XNA, so learning to use them and all they can do becomes very important.

With the objects declared you now need to initialize and use them. To initialize the objects you’ll add some code to the LoadGraphicsContent method. You may have noticed that there were already some additional objects added to the top of your game class and that your class is already populated with methods. XNA Game Studio creates these objects and methods automatically when you create a project using the Windows Game template. By adding code to these methods you begin to fill in the skeleton of the framework that will be your game.

Add the following code to the LoadGraphicsContent method within the if block that you’ll find pre-created within that method:

   if (loadAllContent)   {      mSpriteBatch = new          SpriteBatch(graphics.GraphicsDevice);      mRoad = content.Load("Road");   }

The preceding code initializes the SpriteBatch object and then loads the road image from disk and stores it in the Texture2D object. That is fairly straightforward, right?

With the objects initialized and loaded you can draw the road image to the screen by adding some code to the Draw method. That’s pretty intuitive isn’t it? The Draw method is another one of those base methods created automatically when you began a new Windows Game project, and it’s where you stick your drawing logic.

Go to the Draw method in the code, and begin by making the “screen wipe” color a little better match for the road image. To do this change the pre-existing line of code that clears the screen with the CornflowerBlue color to the code below:

   graphics.GraphicsDevice.Clear(Color.SaddleBrown);

The CornflowerBlue color just doesn’t look as good with the road image as the SaddleBrown color does.

Next, add the following code to the Draw method:

   mSpriteBatch.Begin();   mSpriteBatch.Draw(mRoad, new Vector2(0,0),      Color.White);   mSpriteBatch.End();

This code tells the SpriteBatch object that you are ready to begin drawing things to the screen. To draw the road image, pass in the screen position?in this case start drawing it in the upper left corner (0,0). The Color.White parameter that you pass in to the SpriteBatch’s Draw method tells the object that you do not want to apply any tint to the image.

?
Figure 3: Drawing the road image to the screen.

Finally, tell the SpriteBatch object that you’re finished drawing using mSpriteBatch.End(). Your road image is ready for its big debut.

Stop and do a quick build just to make sure you have coded things correctly and that the road image displays as it should. After you build and run the game, you should see a screen similar to Figure 3.

Now that you can display the road image you can begin working on some code to start scrolling the road.

Scrolling the Road
To get the road image to scroll you’ll need to add some new objects to the class. Insert this code snippet toward the top where you added the SpriteBatch and Texture2D objects:

   private float mVelocityY;   private int[] mRoadY = new int[3];

The mRoadY integer array will keep track of a “chain” of road images that continually move down through the screen to simulate movement on the road. The mVelocityY float will keep track of the velocity of the road in the Y direction, so you can control how fast the road should move. You’ll start the game with mVelocityY set to a constant value, but that will change as the game progresses to increase the difficulty.

Now, create a new method called StartGame in the Game1.cs class to initialize the various tracking objects to their starting positions. StartGame will also restart the game when appropriate. Here’s the code:

   protected void StartGame()   {      mRoadY[0] = 0;      mRoadY[1] = mRoadY[0] + -mRoad.Height + 2;      mRoadY[2] = mRoadY[1] + -mRoad.Height + 2;      mVelocityY = 0.3F;   }

You call the StartGame method to initialize all the objects whenever the game starts or restarts. To do that add a call to the Initialize method you’ll find in the game class. It is important to call StartGame after the base.Initialize() method has fired so you can be sure the Texture object has already been created (mRoad), because you’ll need its Height property to properly position the road images.

Add the following code to the Initialize method after base.Initialize().

   StartGame();

The next task is to create a method that scrolls the road.

Add the following ScrollRoad method to Game1.cs:

   private void ScrollRoad(GameTime theTime)   {      //Loop the road      for (int aIndex = 0; aIndex < mRoadY.Length; aIndex++)      {         if (mRoadY[aIndex] >=            this.Window.ClientBounds.Height)         {            int aLastRoadIndex = aIndex;            for (int aCounter = 0; aCounter <               mRoadY.Length; aCounter++)            {               if (mRoadY[aCounter] < mRoadY[aLastRoadIndex])               {                  aLastRoadIndex = aCounter;               }            }            mRoadY[aIndex] = mRoadY[aLastRoadIndex] -                mRoad.Height + 2;         }      }         //Move the road      for (int aIndex = 0; aIndex < mRoadY.Length; aIndex++)      {                      mRoadY[aIndex] += (int)(mVelocityY *             theTime.ElapsedGameTime.TotalMilliseconds);      }   }

You want to call this method every time the game updates so add the following line of code to the Update method of the game class:

   ScrollRoad(gameTime);

The only thing remaining to get this road scrolling is to loop through and draw each road image to the screen. You'll use the same texture for each image, but you'll draw it at a different Y location on the screen. To do that, remove the lines of code you initially used to draw the road image to the screen, and add the following code to the Draw method instead:

   mSpriteBatch.Begin();   for (int aIndex = 0; aIndex < mRoadY.Length; aIndex++)   {      mSpriteBatch.Draw(mRoad,          new Vector2(0, mRoadY[aIndex]), Color.White);   }   mSpriteBatch.End();

Add the Car Image
Now you'll add the car image (see Figure 4) to the project in exactly the same way you added the road image, and then add a new Texture2D object to the class to store the car image.

?
Figure 4: Adding the car image to the game project.

Add the following code to the beginning of the Game1.cs class:

   private Texture2D mCar;   private Rectangle mCarPosition;

You saw the Texture2D object before when you added the road image, and once again you'll use it to store an image. The Rectangle object is an XNA Framework object used to store a rectangular shape with positioning and size information. In this game the mCarPosition rectangle keeps track of where the car is and how big the car should be.

You need to add code to initialize these new objects. Add the following line of code to the StartGame method to initialize the position object.

   mCarPosition = new Rectangle(280, 440,      (int)(mCar.Width * 0.2f),      (int)(mCar.Height * 0.2f));

Next, initialize the Texture2D object by loading the car image from disk, and storing it in the object using the following code. Add the code line to the LoadGraphicsContent method, where you added code earlier to load the road image:

   mCar = content.Load("Car");

With the car positioned and the image loaded, you can now draw the image to make sure you have it all set up properly. When drawing 2D images with SpriteBatch, it is important to draw your images back to front. For example, if you draw the car first, and then draw the road, the road image will be drawn over the car image and the player will never see it.

Add the following line of code to the Draw method, making sure the road image gets drawn before the car image:

   mSpriteBatch.Draw(mCar, mCarPosition, Color.White);
?
Figure 5: Drawing the car image to the screen.

Build and run your game project to make sure you added the drawing code for the car correctly. You should see a little red car zooming along the road as shown in Figure 5.

Now you can start capturing user input to move the car.

Getting User Input: Keyboard
To gather user input from the keyboard you must add some new class-level objects to the game. Add the following code to the beginning of the Game1.cs class:

   private KeyboardState mPreviousKeyboardState;   private int mMoveCarX;

The KeyboardState object is part of the XNA Framework; you use it to store the state of the keyboard. You can query which keys are pressed?or not being pressed?at any given point in time. The KeyboardState object stores the previous keyboard state, so (for example) you can check to see if a key that the user is currently pressing was pressed last time you checked the state. This allows you to do things such as enforce a rule that users must release a key before repeating some action. In this case you want the car to change lanes every time the user presses the spacebar, but you don't want to continually switch lanes while the user holds the spacebar down. That is where the mPreviousKeyboardSate KeyboardState object comes into play.

The second object, the mMoveCarX integer defined above, stores how far to move the car in the X direction. You'll use this value to move the car back and forth between the lanes. You start by initializing mMoveCarX in the StartGame method using the following line:

   mMoveCarX = 160;

Now you'll add code to the Update method to check user input and move the car accordingly. You want the car to switch lanes only when users press the spacebar and you want to make sure they have released the spacebar before moving the car again. Add the following lines of code to the Update method:

   KeyboardState aCurrentKeyboardState =      Keyboard.GetState();   if (aCurrentKeyboardState.IsKeyDown(      Keys.Escape) == true)   {      this.Exit();   }   if (aCurrentKeyboardState.IsKeyDown(      Keys.Space) == true &&      mPreviousKeyboardState.IsKeyDown(      Keys.Space) == false)   {      mCarPosition.X += mMoveCarX;      mMoveCarX *= -1;   }   mPreviousKeyboardState = aCurrentKeyboardState;

This code starts off by collecting information about the current keyboard state. Next, it checks to see whether the user has pressed the Escape key, which indicates that the user wants to exit the game. If not, the code then checks to see whether the spacebar has been pressed, and if so, that it was not pressed continuously since the last check (this prevents the user from holding it down to repeatedly switch lanes). If that's true, the code moves the car between the lanes by changing its current X position.

The last line stores the current keyboard state in the mPreviousKeyboardState object for use the next time the Update method fires.

Build the project again and run it. Now, when you press the spacebar, the car should move between the lanes as it zooms along the scrolling road.

Getting the User Input: Xbox 360 Controller
If you intend to deliver your games to the Xbox 360, you need to support the Xbox gamepad instead of the keyboard. Fortunately, they're similar. You can easily add gamepad support to your game for any wired Xbox 360 (or wireless with the appropriate dongle adapter) controller. Both will plug into a USB port on your computer. The XNA Framework provides built-in support for the Xbox 360 gamepad.

To gather gamepad input, you need to add some more class-level objects to the game. Add the following code to the beginning of the Game1.cs class:

   private GamePadState mPreviousGamePadState;

The GamePadState object is built into the XNA Framework. It lets you store the gamepad state. You use it similarly to the KeyboardState object. You just need to check whether the user has pressed and released a button on the gamepad. Again, you do that in the Update method. Because you may not know whether a user is running the game on a computer or on the Xbox, enhance the code that checks to see whether the Escape key has been pressed so it also checks to see if a user pressed the Back button on the gamepad. In either case, exit the game.

   KeyboardState aCurrentKeyboardState =      Keyboard.GetState();   GamePadState aCurrentGamePadState =      GamePad.GetState(PlayerIndex.One);   if (aCurrentKeyboardState.IsKeyDown(      Keys.Escape) == true ||       aCurrentGamePadState.Buttons.Back ==       ButtonState.Pressed)   {      this.Exit();   }   

The code next checks to see if the user has pressed the "X" button on the controller; if so, it moves the car. Note that the check process is very similar to the way you checked the spacebar previously.

      if       ((aCurrentKeyboardState.IsKeyDown(Keys.Space)       == true &&       mPreviousKeyboardState.IsKeyDown(Keys.Space)       == false) || (aCurrentGamePadState.Buttons.X        == ButtonState.Pressed &&        mPreviousGamePadState.Buttons.X ==        ButtonState.Released))   {       mCarPosition.X += mMoveCarX;       mMoveCarX *= -1;   }   mPreviousKeyboardState = aCurrentKeyboardState;   mPreviousGamePadState = aCurrentGamePadState;

Finally, the code stores the current gamepad state in the mPreviousGamePadState object for use the next time Update gets called.

Go ahead and build the project. You should be able to use your Xbox 360 controller or the computer keyboard to move the car between the lanes and exit the game.

Add the Hazard Image
With the road scrolling and the car successfully changing lanes, you can add an obstacle that the car must avoid. Start this next stage in the development of your game by adding the hazard image (see Figure 6) to the project. Follow the same technique as before.

?
Figure 6: Adding the hazard image to the game project.

After you've added the image, add a Texture2D object to store it in. Write the following code in the beginning of the Game1.cs class:

   private Texture2D mHazard;   private Rectangle mHazardPosition;

The Rectangle object will hold the size and current position of the hazard on the screen.

You need to initialize the hazard position, so add the following code to the StartGame method to set the initial size and starting position for the hazard:

   mHazardPosition = new Rectangle(275, 0,      (int)(mHazard.Width * 0.4f),      (int)(mHazard.Height * 0.4f));

Load the image from disk and into the Texture2D object in the the LoadGraphicsContent method:

   mHazard = content.Load("Hazard");

Finally, you need to draw the hazard image to the screen. Add the following code to the Draw method.

   mSpriteBatch.Draw(mHazard, mHazardPosition,      Color.White);
?
Figure 7: Drawing the hazard image to the screen.

Place this code before the SpriteBatch.End() line, but after the road and car have been drawn. Remember that the order in which you draw objects is important.

Now build the project and verify that your code draws the hazard image to the screen properly (see Figure 7).

The image should appear in the upper left lane. It probably looks a little funny because it's not moving as the road scrolls. You'll fix that next.

Move the Hazard
Hazards should scroll down through the screen on the road. As they exit the bottom of the screen they should reappear randomly in the right or left lane, repeating the process. To introduce this randomness, you first need to define a Random object at the top of the Game1.cs class:

   private Random mRandom = new Random();

It's generally best to make only one Random object, and then use it throughout the entire game. This helps ensure that random number generation is as random as possible. Initializing multiple random objects often leads to the same numbers being generated, especially if the random objects were created on similar ticks.

Seeing hazards jump into view is disorienting; it would be better if they glide into the screen more smoothly. To do that, you need to change the initial starting position of the hazard so it starts just off-screen, and then scrolls down into the screen.

Change the following line of code in the StartGame method to look like this.

   mHazardPosition = new Rectangle(275,       -mHazard.Height,       (int)(mHazard.Width * 0.4f),       (int)(mHazard.Height * 0.4f));

Now, create a method to move the hazard down through the screen. The technique is similar to scrolling the road.

Add the following UpdateHazard method to your Game1.cs class.

   private void UpdateHazard(GameTime theTime)   {      mHazardPosition.Y += (int)(mVelocityY *          theTime.ElapsedGameTime.TotalMilliseconds);      if (mHazardPosition.Y >         this.Window.ClientBounds.Height)      {         mHazardPosition.X = 275;         if (mRandom.Next(1, 3) == 2)         {            mHazardPosition.X = 440;         }         mHazardPosition.Y = -mHazard.Height;      }   }

This code moves the hazard down the screen. It then checks to make sure the hazard has not scrolled off the screen entirely. If the hazard has moved past the screen boundary, then players can no longer see the hazard. When that occurs, the code uses the Random object to randomly pick a lane for the hazard to appear in and then changes the hazard's position to be just off the top of the screen in that lane.

You also need to add a call to UpdateHazard in the Update method. Add the following line of code to Update just after the ScrollRoad method call.

   UpdateHazard(gameTime);

Now build the project again to make sure you've done everything correctly. When you run the game, you should see the hazards scrolling down the screen one after the other, appearing randomly in one lane or another.

You might think you're done at this point. Unfortunately, your car can currently drive right through the hazard. You'll correct that in just a bit. The game also needs to keep score. This game simply tracks the number of hazards that the car has passed successfully.

Counting Hazards Passed
The XNA Framework provides a nice way to display text in a game. To begin the process, you need to add a new item to your project. So right-click on your project and choose Add New Item from the context menu. In the Add New Item dialog box (see Figure 8), select the SpriteFont object. Name it myFont and click Add.

?
Figure 8: Adding the sprite font to the game project.

?
Figure 9: Modifying the sprite font XML file.

That adds a new SpriteFont object to your project, which is basically an XML file that provides some information about a system font that you want to use in your game. You'll need to edit that information to indicate which font to use as well as the size and style of the font. Edit the SpriteFont XML file as shown in Figure 9.

To show the count (score) onscreen, add two new objects to the top of the Game1.cs class:

   private int mHazardsPassed;   private SpriteFont mFont;

The mHazardsPassed integer keeps track of how many hazards a player has passed successfully. The SpriteFont object lets you to load a font into the game, which you can use to write text to the screen.

The code snippet below initializes the number of hazards passed in the StartGame method. That way, every time the user starts or restarts the game, the number of hazards passed resets to 0. Add the following line of code to the StartGame method:

   mHazardsPassed = 0;

Next, load the font into the SpriteFont object in the LoadGraphicsContent method using this code:

   mFont = content.Load("myFont");

Every time a hazard scrolls off-screen (meaning the player successfully passed it), you need to increment the mHazardsPassed counter. To do that you'll enhance the UpdateHazard method. You'll also increase the velocity every time the player successfully passes a hazard just to add an extra level of complexity to the game.

Add the following code to the UpdateHazard method within the if block that checks to see if the hazard has exited the viewing area:

   mHazardsPassed += 1;   mVelocityY += 0.1F;

Finally, this snippet displays the number of hazards the player has passed. Add the following code to the Draw method:

   mSpriteBatch.DrawString(mFont,       "Hazards: " + mHazardsPassed.ToString(),    new Vector2(5, 25), Color.White, 0, new      Vector2(0, 0),       1.0f, SpriteEffects.None, 0);
?
Figure 10: Drawing the text to the screen.

Build the game and check your handiwork. As the hazards scroll off the screen, you should see the number in the upper left of the window display the number of hazards (and increase) as shown in Figure 10.

You're almost ready to start making it a little harder to run right over the hazards, but first there's one more concept to add to the game. When working on a game, you reach a point where you realize that?depending on what's going on?you need to display certain things at certain times, but not at others. This brings me to the topic of game state.

Game State
Game state, in its simplest form, is just a way of keeping track of what state your game is in. Complex games may have many states, but this game has only two states: Running and Crash. You'll create an enum to define the various states the game can be in, and an object to indicate which state the game currently is in at the top of the Game1.cs class.

   private enum State   {       Running,       Crash   }   private State mCurrentState;

When the game starts you initialize the current state to Running in the StartGame method.

   mCurrentState = State.Running;

Next, enhance the Update method to respond to the various states. Using the state information, you'll update certain things only when the game is running:

   KeyboardState aCurrentKeyboardState =      Keyboard.GetState();   GamePadState aCurrentGamePadState =      GamePad.GetState(PlayerIndex.One);   if (aCurrentKeyboardState.IsKeyDown(Keys.Escape)      == true ||       aCurrentGamePadState.Buttons.Back ==       ButtonState.Pressed)   {      this.Exit();   }   switch (mCurrentState)   {      case State.Running:      {         If ((aCurrentKeyboardState.IsKeyDown(Keys.Space) == true &&             mPreviousKeyboardState.IsKeyDown(Keys.Space) == false) ||             (aCurrentGamePadState.Buttons.X == ButtonState.Pressed &&             mPreviousGamePadState.Buttons.X == ButtonState.Released))         {            mCarPosition.X += mMoveCarX;            mMoveCarX *= -1;         }         ScrollRoad(gameTime);         UpdateHazard(gameTime);         break;      }      case State.Crash:      {         break;      }   }   mPreviousKeyboardState = aCurrentKeyboardState;   mPreviousGamePadState = aCurrentGamePadState;

Basically, the preceding code wraps the existing code in the Update method in a switch block when the current state is Running. The Keyboard state remains outside of the block, but was shown for context.

Currently, the game doesn't do anything when a crash occurs; in fact, there is no way to detect a crash. You'll change that in the next section, but first, quickly build the game just to make sure everything still runs as it should with the newly added game state code.

Collision Detection: Game Over
Without collision detection, the game is pretty easy to play. Luckily, adding simple collision detection into the game is fairly easy as well. The XNA Framework Rectangle objects contain functionality that let you check whether they're intersecting another Rectangle object. You'll use this functionality and add it to the Update method to check whether a hazard has collided with the car. When a collision does occur, you switch the current game state to Crash.

After a crash occurs, the game will be over?but you need a way to allow the user to play the game again or exit, and you should probably tell them how to do that.

Go ahead and add the following code to the Update method. This code replaces the existing UpdateHazard call.

   if (mHazardPosition.Intersects(mCarPosition) == false)   {      UpdateHazard(gameTime);   }   else   {      mCurrentState = State.Crash;   }

This code checks for a collision by using the Rectangle object's Intersects method. When a collision is detected, the current state of the game changes to Crash to reflect this.

You also want to add the following lines of code within the Crash case of the switch block in the Update method.

   if (aCurrentKeyboardState.IsKeyDown(Keys.Enter) == true ||       aCurrentGamePadState.Buttons.Start == ButtonState.Pressed)   {      StartGame();   }

This code checks to see whether the user has pressed Enter or the Start button. Pressing either causes a call to the StartGame method, which restarts the game.

Now that the code responds to game state in the Update method, you need to do the same in the Draw method.

Add the following code just after the line of code that draws the current number of hazards that the car has passed.

   if (mCurrentState == State.Crash)   {      mSpriteBatch.DrawString(mFont, "Crash!",          new Vector2(5, 200), Color.White, 0,          new Vector2(0, 0), 1.0f,          SpriteEffects.None, 0);      mSpriteBatch.DrawString(mFont,          "'Enter' to play again.",         new Vector2(5, 230),         Color.White, 0, new Vector2(0, 0), 1.0f,         SpriteEffects.None, 0);      mSpriteBatch.DrawString(mFont,          "'Escape' to exit.",         new Vector2(5, 260),         Color.White, 0, new Vector2(0, 0), 1.0f,         SpriteEffects.None, 0);   }
?
Figure 11: Running the final build of the game project.

This code displays some informational text to the player?but only if the current state of the game is Crash. Players then know how to exit the game or replay.

That's it. Now you can build the project for the last time and play the game (see Figure 11).

You should now have a functional game. Sure, you can make some enhancements to make it a little prettier, a bit more challenging and more interesting, but I'll leave that to your very capable minds.

XNA Game Studio Express is a perfect fit for a game developer. With a small learning curve, low (or no) cost, a thriving community, and excellent support from Microsoft, if you are interested in giving game development a shot, this is your chance. By making it intuitive and easier to get a game started and developers developing quicker, Microsoft has opened the floodgates for creativity and risktaking in game development. I'm excited to see what the community does with this and just where XNA game development might take the future of gaming.

In April 2006 Microsoft refreshed XNA Game Studio Express and included even more features, building font support into XNA Game Studio Express and making it easier to share game projects without packaging up the source code. I expect that Microsoft will continue to add features and enhancements to XNA Game Studio Express, and I expect the XNA team will continue to solicit feedback in the forums for problems and ask for enhancement requests and set priorities.

Useful Links
Along with the Creators Club (which is basically the central XNA hang-out site), I suggest you check out several prominent XNA sites run by what most would consider the grandfathers of the XNA community. Here are some of my favorites:

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist