University of the West of England, Bristol

Department of Computer Science and Creative Technologies


C# XNA Worksheet 4 - Sprite Sheets and Animation

C# 2010 - XNA Version 4


Learning Aims

This worksheet shows you how to handle a sprite sheet containing multiple images. This is useful for simple forms of sprite animation where the program cycles between different images from the sprite sheet.

When you've completed this worksheet, you should be able to:

To get the most out of this worksheet you should do the following:


If You Get Interrupted

If you are unable to finish any of these worksheets in one go, then this is what you should do to make sure that you can resume it from the point you finished, without having to start from scratch:


Practical Steps- What You Have to Do

Before Starting

This worksheet assumes that you've already completed worksheets 1, 2 and 3, building on the knowledge that you have previously acquired.

Getting Started

  1. Make sure you have the image file named "BalloonSpriteSheet.png". This is available in WorksheetAssets which you have probably already downloaded for the previous worksheets. (Download WorksheetAssets.zip)
  2. Start XNA Game Studio and create a NEW Windows Game project. You should name the project SpriteFrameProject

Load the Sprite Sheet into the Content Section

The sprite sheet is loaded into the project just like any other Texture2D image:

  1. Load the sprite sheet image "BalloonSpriteSheet.png" into the Content section of the solution explorer
  2. At the top of the Game1.cs file, declare a field: Texture2D spriteSheet;
  3. In the LoadContent() method, load the sprite file into the spriteSheet field.

Selecting an Image from the Sprite Sheet

The complete sprite sheet looks like this:

There are five images of a balloon, in various stages of inflation, and three images of it exploding. Each image is exactly 120x120 pixels, with the whole sprite sheet being 960 (120x8) pixels wide. We will call the first image Frame 0 and the final image Frame 7.

To draw any particular object from the sprite sheet, we need to put an invisible rectangle around it. For example, to draw Frame 4, we need to define this rectangle:

The starting X position of the rectangle within the sprite sheet is given by the frame number * the image width. In this case, the frame number is 4 (starting from 0!) and the image width is 120. The starting Y position of the rectangle is 0. The rectangle width and height are both 120. We can use this information to create a C# Rectangle object:

  
  Rectangle source = new Rectangle(4*120, 0, 120, 120);	// Frame 4  

We can also set up a screen location for the sprite image:

  Vector2 position = new Vector2(400, 300);

We pass the source Rectangle and screen position to the spriteBatch.Draw() method like this:

  spriteBatch.Draw(spriteSheet, position, source, Color.White);

Let's put it all together to create a simple program:

  1. Put the following statements inside the Draw() method:
      spriteBatch.Begin();
      Vector2 position = new Vector2(400, 300);
      Rectangle source = new Rectangle(4*120, 0, 120, 120);
      spriteBatch.Draw(spriteSheet, position, source, Color.White);
      spriteBatch.End();
    
  2. Run the program and confirm that Frame 4 appears on the screen.
  3. Add a new field to the Game1.cs file, just after the Texture2D definition of spriteSheet:
      int frame = 0;
    
  4. Modify the Rectangle definition in the Draw() method to replace 4 by frame:
      Rectangle source = new Rectangle(frame*120, 0, 120, 120);
    
  5. Run the program several times, changing the value you assign into frame each time. You should see a different image drawn each time.

Setting the Sprite Origin

The somewhat basic version of spriteBatch.Draw() is acceptable for this simple case, but as we've seen in earlier worksheets we would really like to have the ability to support a sprite origin, rotation and scaling. Fortunately there's an alternative version we can use:

  spriteBatch.Draw(spriteSheet, position, source, colour, 
      rotation, spriteOrigin, scale, spriteEffects, zPosition);

For this particular sprite sheet, all the images can use the same origin value of 60, 60 - which approximately the centre of each balloon image.

  1. Add the following statement to the Draw() method, so that it is before the spriteBatch.Draw() statement:
      Vector2 origin = new Vector2(60, 60);
    
  2. Modify the spriteBatch.Draw() statement that you put in earlier to choose the version (overload) shown above, with source, origin, rotation, etc.
  3. Run the program several times, changing the value of frame each time and confirming that the correct image frame is displayed with each change.

Getting Animated

We will now expand the program so that it shows simple animation by moving from frame to frame at some fixed rate.

An obvious way to do this is to add 1 to frame on each update, however this will cause the animation to run too quickly. Try it for yourself and see.

We need to slow down the animation, so that we only update frame once every 20 (say) updates. To do this, we need to add an extra field to the Game1.cs file:

  int updateCount = 0;

Within the Update() method, we can now increment (add 1) to this counter. When the counter value reaches or exceeds 20 we can then add 1 to frame and reset updateCount to zero. In this way, we will slow down the animation.

  1. Add the updateCount field to the Game1.cs file. Since it's a field it needs to go near the declaration of spriteSheet.
  2. Put the following code within the Update() method:
      // TODO: Add your update logic here
      updateCount++;
      if (updateCount >= 20)
      {
        frame++;
        updateCount = 0;
      }
    
  3. Get the program working and see what happens.
  4. Modify the program so that the animation stops when it reaches Frame 4. The game should continue to show the deflated balloon when this happens.

On Your Own

Use what you've learned so far to modify the project so that:

When you've got this working then try this:


Tidying Up When You've Finished

When you've finished all the steps above, you need to close down Game Studio Express as follows:


Return to home page