Sprite Sheets in Xna: The Basics

When designing 2D games, many of has have the annoying habit of being born out of the Flash age. We want to be able to have a drawing of something and animate, just like we did in Flash! However, this is obviously not possible in XNA since XNA is not a enriched content creation platform but instead a library for the creation of games. There is, however, an alternative that we might find more familiar, and these are Sprite Sheets.

Sprite Sheets are a fairly basic and clever concept. Essentially the idea is to use a single image containing each ‘frame’ of your animation and the run through each frame in a sequential order, like a flip book. The difference is we need to section off which frame we want to show.

Lets start with an example of a Sprite Sheet:
(Also with an apology for the horrendous thieving of these images, if you own them, tell me so I can appropriately thank you for your contribution, or change the images if you so wish)

As we can see I have my character (my beloved Gohan of DBZ fame) and the different poses I want him to strike. The first three images are him walking North, the next three East, next three South and final three West. For this tutorial I am concentrating on a 4 directional movement scheme (North, South, East, West) which means when the character eventually moves they will move only perpendicular to the axes (no diagonal). If anyone wishes I will extend this to 8 directions.

I think now is probably the appropriate time to mention that I chose a straight line for my animations because I’m lazy, but you can use multiple rows if you so wish, it just takes a little extra code to provide jumping down to the next animation row. Also, its important to note that when creating (or stealing) your sprite sheet you need to know exactly how big each ‘frame’ is and each ‘frame’ needs to be of equal size.

Now we can consider our problem. We want to achieve the following logic:

  • Starting with the first ‘frame’, flip through each ‘frame’ until the end is reached then return to the beginning
  • Have some sort of timer so we can actually see the animation created else the sprite will flip through so fast we wont be able to see it
  • Only render individual ‘frames’ of my sprite and not the whole thing

So from our requirements we can start to flesh out some variable we will probably need:

//A Timer variable
float timer = 0f;
//The interval (100 milliseconds)
float interval = 100f;
//Current frame holder (start at 1)
int currentFrame = 1;
//Width of a single sprite image, not the whole Sprite Sheet
int spriteWidth = 25;
//Height of a single sprite image, not the whole Sprite Sheet
int spriteHeight = 35;

So lets just walk through those.

First we have timer, simple enough, a variable to store how much time has elapsed.

The interval, this essentially is used to choose how fast or slow we go through our animation. I chose 100 milliseconds because I like how smooth it looks with my sprite sheet.

CurrentFrame, stores which frame we are currently on.

SpriteWidth and SpriteHeight store the size of a single ‘frame’ in pixels.

The final thing we need is some way to only show one frame instead of the whole sheet. Luckily XNA provides us with a very easy way to do this, using the rectangle class. We need to draw a rectangle around the current frame that will ‘frame out’ the rest of the sheet. This rectangle is used by the SpriteBatch in one of its overloaded methods to define the ‘viewable’ portion of a sprite. We can therefore define a rectangle as follows:

sourceRect = new Rectangle(currentFrame * spriteWidth, 0, spriteWidth, spriteHeight);

What this does is sets the coordinate of the top left corner of the rectangle by multiplying the width of a frame by the current frame it is on (with 0 representing the Y-Coordinate). The next two parameters specify the width and height of the rectangle. The multiplication works as a linear shift, moving the rectangle by the frames width across the sheet.

Then to flip through the animation we simply we need increase out timer per frame, check if its greater than the interval and if it is move to the next frame, like this:

//Increase the timer by the number of milliseconds since update was last called
timer += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
 
//Check the timer is more than the chosen interval
if (timer > interval)
    {
        //Show the next frame
        currentFrame++;
        //Reset the timer
        timer = 0f;
    }
//If we are on the last frame, reset back to the one before the first frame (because currentFrame++ is called next so the next frame will be 1!)
if (currentFrame == 12)
    {
         currentFrame = 0;
    }

Increasing the timer is adding the amount of time elapsed by the game since the last call of the update function.

Now if you run my source code you should see everything I mentioned above. See my next couple of tutorials dealing with Keyboard movement and auto movement if you want your sprite to do more than pointlessly flick though its animations!


Source is Here

Please note that the source is compiled for windows, and is also compiled for XNA 4.0! You will also need Visual Studio 2010

14 thoughts on “Sprite Sheets in Xna: The Basics

  1. Just starting XNA 3.1 in my game design class, and I have to say your tutorials on your site are the best I’ve seen by far at explaining everything I need.

    You mentioned you would do an 8-directional tutorial if someone asked….well, I am asking now heh

    Thx for everything and keep it up.

  2. This was exceptionally helpful to get the basic understanding on animation and can really be expanded on. Thanks!

    Just a note: Make sure your dimensions are correctly set! I had this issue and took me a bit of time to figure it out.

    =D

  3. This is the most blunt tutorial on single loop animation sprite sheeting I’ve seen. Makes perfect sense to me mate so THANKS and I think I’m going to try to build on your method possibly and add in custom animations so I can go to different points in a sprite sheet.
    (If I do I will be sure to let you know!)

  4. Thanks a lot for this tutorial! I noticed your XNA tutorials end during December 2008, did you just stop writing tutorials, or did you stop learning XNA?

  5. Very nice post. Thanks!

    One note, instead of if(currentFrame == 12) you can have currentFrame = currentFrame%12 and that will reset you back to 0 when you hit 12.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>