Hello and welcome to my first tutorial! I am going to try and make this a multi-part guide for 2D sprite animations that will start with a fully functioning 2D sprite animation library and finish with an editor to create animations and save them to XML using the IntermediateSerializer.

The system I will go over in this guide is an amalgamation of my favorite features and functionality from various animation tutorials and game programming books that I have read over the years. The system will support any style of sprite sheets that you can think of!

NOTE : This tutorial assumes you know how to create projects in Visual Studio and also add files and XNA content in the solution explorer (including SpriteFonts).

Lets set up our projects. Create a new Windows Game Project in Visual Studio and name it whatever you like (I will name mine AnimationProject). Add a Windows Game Library to the your Game Project called AnimationLibrary. Don’t forget to add a reference to the AnimationLibrary in your Game Project!

Once you have the project set up we will need to add a couple of class files to the AnimationLibrary project called “KeyFrame” and “Animation“. These two classes will define exactly what an animation is and how it functions. I will post the classes and go over what each variable and method will be used for.

The purpose of this class is to define what a frame is in our animations. Our Animation class will manage a list of these objects. The reason we create a class to hold the source rectangle instead of just adding a List<Rectangle> field to the animation class is that we can easily add some cool functionality to a KeyFrame. For example, you have an animation of your character drawing back his sword and swinging. If you want to play a “slashing” sound effect right when the sword is swung you could add a field (int, string, enum) to the KeyFrame class that holds data for a sound effect. When the Animation class encounters a key frame it will check if that variable is initialized and if so tell your game to play the specified sound. This is a great and easy way to make smooth timings for things in your game. You could also give the KeyFrame class a Vector2 value to define its origin. This can be useful if you have frames of different sizes in the same animation.

There is a lot going on in here that we need to go over. We will start with the fields.

[string name] This is used to identify the specific animation for various functions in this system
[bool shouldLoop] Lets us know if the animation is supposed to play in a loop.
[bool isComplete] Tells us if the animation has reached the last KeyFrame.
[float framesPerSecond] the number of KeyFrames we want to display to the screen in a second.
[float timePerFrame] This is the amount of time that needs to pass before we can switch to the next KeyFrame.
[float totalElapsedTime] acts as a timer that we compare to timePerFrame to see if we need to switch to the next KeyFrame.
[int currentFrame] stores the current frame to render and update.
[List<KeyFrame> frames] holds all the KeyFrames in this animation
[string transitionKey] used to switch to another animation when completed (only for non-looping animations)

The properties will reveal most of the private fields. We have one property, CurntKeyFrame, that acts as a utility property for easy access to the current frame. Time to go over the methods.

The Reset() method is used when changing to a new Animation. It makes sure the animation starts fresh by resetting some variables.

We start by updating our timer (totalElapsedTime) and setting the current KeyFrame.

if (totalElapsedTime >= timePerFrame)

Now we check if totalElapsedTime is greater than the timePerFrame value that we get from framesPerSecond. If totalElapsedTime is greater than timePerFrame we know enough time has passed to switch to the next frame… but first we need to check a few things.

Check if this KeyFrame is the last frame in our animation, and if so we will see if this animation should loop back to the beginning. If this animation does not loop we will set the isComplete flag to true. If all else fails we know that we still have some frames left to cycle through so we update the currentFrame and reset out timer so we can go through the process all over again in the next frame of our game.

We can now add a class to the Game Project we created called AnimatedEntity. Here is the class in its entirety. I will step through all of the fields and methods.

The first field is a Dictionary<string, Animation> that will hold all the Animation objects this entity will use. The string value we pass in as the Key will be the name field we gave our animation class. The next is an Animation field to hold a reference to the currently playing animation. The rest of the fields will be passed to the SpriteBatch object we use to draw the entity.

The AnimatedEntity LoadContent methods are used to load or set our sprite sheet texture. AddAnimation is a helper method to add animations to the entity. We check to see if the Dictionary contains the key (name) of the animation we want to add and if not we are safe to add it. The PlayAnimation class is how we tell the entity what animation to update. We pass in the name of the animation we want to play and do a few checks to make sure its safe to switch animations. If we pass the tests we will set the new animation and call the Reset method to be sure it plays fresh. Next in line is the Update method. In this method we handle the logic for updating our currently playing animation and transitions. We first check if the currentAnimation field is null and if not we can start updating it. We set our origin to the center of our source rectangle contained in currentAnimation.CurntKeyFrame. Now we call the Animations Update method to begin cycling through all of the KeyFrames. If the animations IsComplete flag is true we know that it doesn’t loop so we can check if the transitionKey has a value and switch to that animation. This lets us have an animation that is only meant to transition into others. For example (this is a mouthful) if we want our player to go from an “idle” animation to a “start running” animation and finally into a “running loop” animation we would only have to pass the name given to the “running loop” animation into the “start running” animations constructor. When we set the entity to “start running“ from “idle” it will automatically switch to the running loop on the last frame of the “start running” animation. Last but not least we have the Draw method. This does what you would expect. We give it a SpriteBatch object and call spriteBatch.Draw passing the sprite sheet texture, position, the source of the current KeyFrame and the rest of the drawing related fields.

That is it! You should now have a functioning system that updates and draws spriteSheet based animation with some nifty features. To preview the system in action add this texture http://flic.kr/p/dZW96E (Which I take no credit in creating) to your XNA Game Content and a SpriteFont of your choice.