Ioannis Panagopoulos blog

Tutorials on HTML5, Javascript, WinRT and .NET

XNA Game Development (First Steps)

by Ioannis Panagopoulos

Welcome to a short introduction in game Development using the XNA Framework!

Let's start with the basics by examining how different is Windows programming to XNA Game programming. As we know, windows programming is "event driven". This means that our logic resides in event handlers that get called when a resource or a Control needs to tell us that something happened. So our program is nothing more than a loop that awaits for events to happen and a bunch of event handlers that respond to those events.

Game programming is different. Game programming is real-time and thus cannot afford to be lazy by waiting for some event to happen to actually do something useful. Therefore, game software cannot be event driven but rather operate on a polling basis. This means that our game will again be executing a loop (the typical game loop as it is called) and whenever the programmer likes, he/she will be asking resources about their status and whether something happened that needs attention. So the logic in games does not reside in event handlers but happens within the loop and knowing what happens in resources is in our hands to ask and discover.

A typical game loop consists of the steps shown in the following image:

 

 

The magic happens in the light-blue shaded area which is the loop that gets the user's input (e.g. polls the keyboard for a pressed key), calculates the positions of all the game actors on the screen, tests whether certain gameplay related criteria have been met (e.g. a collision occurred and the gamer should loose a life) and provides feedback to the gamer in the form of sound, control vibration or of course graphics.

The typical game loop in XNA is realized by the following methods where the "Get User Input", "Calculate" and "Test Criteria" parts happen within the Update() methods and the visual feedback happens in the Draw() method.

 

 

So lets implement our first program in XNA. First you need to download and install XNA Game Studio. Then start a new Visual Studio project and select to create a Windows Game. Now you will notice that the template has created several files in the project with most important the Game1.cs file that contains the game loop and the Content folder that will contain all the resources. We right-click the Content folder, click on "Add/Existing Item..." and locate the two image files we need (Ivan.png and SeaBottom.png). The two images are added to the project under the Contents folder and if you see their properties you will notice that they have been given an "Asset Name" , "Ivan" and "SeaBottom" respectively. Those are the names that will be used for referencing those resources within the game.

So what do we want to do? We want to load our resources and then draw them on screen. Therefore we need to put some code in the LoadContent() method (to load them), code in the UnloadContent() method (to free the resources when no longer needed), We do not need to alter the Update() method since we just want to draw the two images, so we will just add some drawing code to Draw(). So here is goes:

private Texture2D _ivan;
private Texture2D _backImage;
private Vector2 _ivanPosition;

public Game1()
{
    _graphics = new GraphicsDeviceManager(this);   
    _graphics.PreferredBackBufferWidth = 800;
    _graphics.PreferredBackBufferHeight = 600;
    Window.Title = "CrazyIvan Ver. 1.0 - DevDays 2009,Athens - Giannis Panagopoulos";
    _ivanPosition = new Vector2(400, 300);
    Content.RootDirectory = "Content";
}

 

protected override void LoadContent()
{
    _ivan = Content.Load<Texture2D>("Ivan");
    _backImage = Content.Load<Texture2D>("SeaBottom");
    spriteBatch = new SpriteBatch(GraphicsDevice);
}

 

protected override void UnloadContent()
{
    _ivan.Dispose();
    _backImage.Dispose();
}

 

 

In the beginning we set the size of the window, set the title and initialize the position of the Ivan (that is the position that image Ivan.png will be drawn).

Then we define two Texture2D objects that will hold the background image (SeaBottom) and the Ivan image (Ivan) respectively. In LoadContent() we load the images and initialize the textures and in the UnloadContent() we Dispose the textures. Pretty easy right?

Now in the Draw() method we draw the textures. Note that we have available a spriteBatch object created for us automatically by the framework which we will use to draw whatever we like. All drawing should be happening within spriteBatch.Begin() and spriteBatch.End() method:

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);
    spriteBatch.Begin();
    spriteBatch.Draw(_backImage, new Vector2(0f, 0f), Color.White);
    spriteBatch.Draw(_ivan, _ivanPosition, Color.White);
    spriteBatch.End();
    base.Draw(gameTime);
}

 We draw the background image at postion 0,0 and Ivan at the position defined by the Vector2D _ivanPosition object.

So now how can we make Ivan to move based on the arrow key pressed? This should happen in update. So we need to check whether a key was pressed and if so, we need to alter Ivan's position accordingly. This can be realized as follows:

protected override void Update(GameTime gameTime)
{
    KeyboardState KeyState = Keyboard.GetState();
    if (KeyState.IsKeyDown(Keys.Up))
        _ivanPosition = new Vector2(_ivanPosition.X, _ivanPosition.Y - 1);
    if (KeyState.IsKeyDown(Keys.Down))
        _ivanPosition = new Vector2(_ivanPosition.X, _ivanPosition.Y + 1);
    if (KeyState.IsKeyDown(Keys.Left))
        _ivanPosition = new Vector2(_ivanPosition.X-1, _ivanPosition.Y);
    if (KeyState.IsKeyDown(Keys.Right))
        _ivanPosition = new Vector2(_ivanPosition.X+1, _ivanPosition.Y);
              
    base.Update(gameTime);
}

 On the other hand if we want Ivan to follow the mouse we need to implement our Update() method as follows:

protected override void Update(GameTime gameTime)
{
   
    MouseState MState = Mouse.GetState();
    Vector2 MouseVector = new Vector2(MState.X, MState.Y);
    Vector2 IvanToMouseVector = -(_ivanPosition - MouseVector);
    IvanToMouseVector.Normalize();

 

    _ivanPosition += 4*IvanToMouseVector;
   
    base.Update(gameTime);
}

 

Compile and run the project with the two alternatives to check them out. Remember that XNA repeatedly calls your two methods (Update and Draw) and it never waits for any event.

You can download the whole project here.

In the next post we will discuss about the typical architecture of an XNA game that enables us to harness the complexity involved in having to deal with a lot of sprites in the game scene and also may help a team of developers partition the work that needs to be done.

  

kick it on DotNetKicks.com

Shout it

blog comments powered by Disqus
hire me