Animated Textures

In my last post, we talked about textures in general and how to use them. This post will talk about a fun and important aspect of using textures in 2D games: Animation. Say you have a 2D game and you have Wizard character that the player controls and it can cast a spell. It would be boring if the wizard did not have any cool animation to indicate that he is casting a spell. This is where animation comes handy! We can use animation to make a 2D image appear to be alive and have motion.

So how do you create such an animation? First you need to have the actual animation designed. I found a free-to-use animated GIF on the web that I will use for this post:

Doing_magic

As you can see from the image, it’s a simple animation of a wizard using a wand. We want to take this wizard and use him in our game and have this animation be available.

So how do we do that? Every animation is made up of what’s called “Frames”. That means that the animation is actually a series of images each showing one step of the animation. For this one, you have the following 3 frames that make up the animation:

Doing_magic

It should be clear now how the animation works, right? It’s 3 frames that you display one after the other with a long enough delay in between to make it look good. So let’s see how we can get this animation to work in a game we build.

Create the animation into a horizontal strip

First thing you need to do is create the animation you want somehow. One way I tend to do it is by either finding animated gifs on the web that are “free” to use, or built them on my own. I can’t go into how to build them now since that’s outside the scope of this post. But basically, you need to build something like the second image up there. A horizontal strip that has all the frames of the image on it.

The image strip that contains your frames should have a correct size though! Every frame should be exactly the same width as the others. So if you have 3 frames in your strip, the width of the strip should be 3 x Width of one frame. You’ll see why later.

If you have an animated Gif like mine here, you can use this really cool tool I found on the web to convert it to a strip: Bitstrip.

Bitstrip is a simple tool that can convert animated GIF to a horizontal strip. To do that, fire up the tool, it has a very simple UI:

image

Click on “Browse to GIF file” button and find your GIF file.

Click on “Horizontal” button to see what the horizontal strip would look like.

With the Horizontal view open, click on “Save output as” and save the output file somewhere on your machine. It will be a .bmp file that looks like this:

image

What is all that pink???? Nothing to worry about! That’s the color the tool uses to indicate that this should be transparent. Fortunately, that is the same color that a lot of tools (and XNA Game Studio) use to indicate transparency. This technique is called Color Keying (you can read about more about it on Wikipedia).

Animating the texture in code

So now that we have the final texture we’ll use, it’s time to figure out how to animate it using code. Let’s examine what we’ll need to do:

  1. Need to figure out how many frames we have (nothing to figure out, we know from the image we created)
  2. Figure out the width of a single frame. Easy. Frame Width = Total Width of strip / number of frames.
  3. We need to render frame 1, then wait for sometime, then render frame 2, wait for sometime, etc until we reach the end of the frames. We can then loop back again to frame #1.

I happen to have a class that I wrote that specifically does what we listed just now. I call it: AnimatedTexture. Here’s the code:

 

   1: class AnimatedTexture
   2: {
   3:     private Texture2D aniTex;
   4:     private int CurrentFrame = 0;
   5:     private int numberOfFrames = 0;
   6:     private int msBetweenFrames = 0;
   7:
   8:     private Rectangle rect;
   9:
  10:     private int width = 0;
  11:     private int height = 0;
  12:
  13:     float timer = 0;
  14:
  15:     public AnimatedTexture(Texture2D texture, int numFrames, int msBetweenFrames)
  16:     {
  17:         this.aniTex = texture;
  18:         this.numberOfFrames = numFrames;
  19:         this.msBetweenFrames = msBetweenFrames;
  20:
  21:         this.width = texture.Width / numberOfFrames;
  22:         this.height = texture.Height;
  23:
  24:         // Init rectangle
  25:         rect.X = 0;
  26:         rect.Y = 0;
  27:         rect.Width = width;
  28:         rect.Height = height;
  29:     }
  30:
  31:     public void Update(GameTime gametime)
  32:     {
  33:         timer += gametime.ElapsedGameTime.Milliseconds;
  34:
  35:         if (timer >= msBetweenFrames)
  36:         {
  37:             timer = 0;
  38:
  39:             if (CurrentFrame++ == numberOfFrames - 1)
  40:                 CurrentFrame = 0;
  41:
  42:             rect.X = CurrentFrame * width;
  43:             rect.Y = 0;
  44:         }
  45:     }
  46:
  47:     public void Render(SpriteBatch sb, Vector2 position, Color color)
  48:     {
  49:         sb.Draw(aniTex, position, rect, color, 0, Vector2.Zero, 2.0f, SpriteEffects.None, 0);
  50:     }
  51:
  52: }

Let’s have a closer look at the code:

Lines 3-13: Local variables that we will use

Line 15: This is the constructor of the class. It takes the following arguments:

  • Texture2D texture: This is the strip we prepared. Load it up using the Content pipeline and pass it here.
  • int numFrames: This is the number of frames in the strip. User provided.
  • int msBetweenFrames: This is how many milliseconds should we wait between frames. The lower, the faster the animation.

Lines 21,22: Here we calculate the width and height of a single frame. Simple.

Lines 25-28: We initialize a rectangle to contain the first frame in the strip. We will use this in the rendering.

Lines 31-44: This is the Update method for the class. This method calculates the values in our Rectangle to move it to contain the next frame when it’s time. Time is calculated via the GameTime object so that we can tell when to move on to the next frame. We wait for a total number of msBetweenFrames milliseconds before moving on to the next frame. Simple math.

Lines 47-50: This is the Render method. Here we use a SpriteBatch object the user passes in along with a position and color to draw the current Rectangle from the texture. SpriteBatch has an overload that lets you specify a region in the texture to draw rather than the entire thing. This is why we’ve been calculating a rectangle for each frame in the Update method. We only draw the content of this rectangle each time.

Using the code in your game

Using the AnimatedTexture class we just created in our game is very easy.

Create a member variable in your Game1.cs file, in the Game1 class:

AnimatedTexture aniTex;

Load a texture in it in the LoadContentMethod:

 

   1: protected override void LoadContent()
   2: {
   3:     spriteBatch = new SpriteBatch(GraphicsDevice);
   4:     aniTex = new AnimatedTexture(Content.Load<Texture2D>(“doing_magic”), 3, 80);
   5: }

I used 80 ms as the in-between frames delay. It seemed to look fine.

Make sure to call the Update method for the AnimatedTexture in the Update method:

 

   1: protected override void Update(GameTime gameTime)
   2: {
   3:     // Allows the game to exit
   4:     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
   5:         this.Exit();
   6:
   7:     aniTex.Update(gameTime);
   8:
   9:     base.Update(gameTime);
  10: }

Finally, call the Render method in the Draw method:

 

   1: protected override void Draw(GameTime gameTime)
   2: {
   3:     graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
   4:
   5:     spriteBatch.Begin();
   6:     aniTex.Render(spriteBatch, Vector2.Zero, Color.White);
   7:     spriteBatch.End();
   8:
   9:     base.Draw(gameTime);
  10: }

There you go! It’s done :) Hit F5 and you should see a cool animation running. You can move it around by adding movement code just like you would for a normal texture. Just change the position argument in the Render method for AnimatedTexture.

Have fun!

Thanks for reading! I'd love to hear your thoughts, feel free to leave a comment below. Don't forget to subscribe to my RSS Feed!

9 Responses to “Animated Textures”

  1. errolian Says:

    Thanks for these blog posts, they are always of great interest to read.

  2. nazeeh Says:

    Thanks a lot Errolian :) I am glad you’re finding them useful and worth your time to read! I appreciate the feedback.

    Nazeeh

  3. radioact1ve Says:

    Just wanted to say thanks for these “tutorials”. They’re excellent! Keep up the sense of humor as well.

  4. RickettsZ22 Says:

    Thanks alot for all of these tuts, i think they are really really helpful but i am having trouble with this tutorial I can’t seem to get it to work i keep getting an error code for the aniTex, so i didn’t know if you could help me thanks.

  5. nazeeh Says:

    Of course I would love to help. Why don’t you explain to me what you were doing and maybe copy/paste the error you got as well. Let’s work this out!

  6. Himayat Says:

    Thanks a lot, Man. Now I can finally working on my 2d game.

  7. Kamal Says:

    I did not follow your tutorial exactly but I used it to change frames on a spritesheet when a particular event is triggered so I have left out the time component. Some questions came up while I was doing that.

    First, shouldn’t

    rect.X = CurrentFrame * width;

    really be

    rect.X = CurrentFrame + width;

    ? The original is multiplying by 0 so it will not work.

    Second, shouldn’t there be a

    CurrentFrame += rect.X;

    ? Or does the

    if (CurrentFrame++ == numberOfFrames - 1)

    make my questions look silly? Hmm… now that I have said it I think it does since the CurrentFrame++ (adding 1 to CurrentFrame) will get triggered each call.

    I guess I will make the comment anyway since it may be useful to someone and I did write all this stuff and don’t want to see it go to waste. :) BTW, I am new to programming and XNA so be kind. :)

  8. nazeeh Says:

    Hey Kamal :)

    Sorry for the late reply.

    Nah…the code is correct. Here’s how it works:

    You have a long horizontal image that has all the frames of the animation, right? Each frame is X pixels in width, so the entire image is X * Frames in pixels. So to be able to tell at which pixel a frame starts, we multiply the number of the frame by the width of the pixels. For instance, if my frames are each 10 pixels long and I have 5 of them, the image is 5 * 10 = 50 pixels wide. Frame 1 (which would be index 0 since we start from 0 all the way to 4) would be:

    Frame #0 * 10 = 0

    First frame starts at pixel 0! Correct!

    Frame #1 (which is second frame) starts at 1 * 10 = 10

    Second frame starts at pixel 10!

    see how it works? That is why we multiply.

    Hope that helps! Enjoy XNA!!

  9. Kamal Says:

    Hi Nazeeh, thanks for the clarification, I got it working with the adding the frame width to the counter but I realize that can be confusing. Your way is definitely better.

Leave a Reply

The page's WebCounter count says that you are visitor number Visitor Counter by Digits
FireStats icon Powered by FireStats