The last tutorial we took our chance at making a Tic-Tac-Toe game. Hopefully most of you were successful in getting it to work. If not, don’t fret, you’ll get the hang of all of this eventually.
In this tutorial we are going to take our hand at SDL Animation. As before, we’ll be building on top of the previous SDL lessons (but not including the Tic Tac Toe one). So lets get started.
We’ll be creating a new class to handle Animation, and in the next tutorial we will create a class to handle Entities. Please keep in mind that these two things are seperate, and while I know they could be one class, I don’t wish to take that approach. So please hold back your criticism.
Create two new files (I am sure you are seeing a pattern now, hopefully), called CAnimation.h and CAnimation.cpp. Eventually, our CEntity class will inherit this class, but for now we’ll be testing through an object we create later. And before we get started add the include directive within CApp.h (before #include “CEvent.h” is just fine).
Now open up CAnimation.h and lets start coding. Add the following basic class structure to your file.
#define _CANIMATION_H_
#include <SDL.h>
class CAnimation {
private:
int CurrentFrame;
int FrameInc;
private:
int FrameRate; //Milliseconds
long OldTime;
public:
int MaxFrames;
bool Oscillate;
public:
CAnimation();
void OnAnimate();
public:
void SetFrameRate(int Rate);
void SetCurrentFrame(int Frame);
int GetCurrentFrame();
};
#endif
Now, open up CAnimation.cpp and add this code:
CAnimation::CAnimation() {
CurrentFrame = 0;
MaxFrames = 0;
FrameInc = 1;
FrameRate = 100; //Milliseconds
OldTime = 0;
Oscillate = false;
}
void CAnimation::OnAnimate() {
if(OldTime + FrameRate > SDL_GetTicks()) {
return;
}
OldTime = SDL_GetTicks();
CurrentFrame += FrameInc;
if(Oscillate) {
if(FrameInc > 0) {
if(CurrentFrame >= MaxFrames – 1) {
FrameInc = -FrameInc;
}
}else{
if(CurrentFrame <= 0) {
FrameInc = -FrameInc;
}
}
}else{
if(CurrentFrame >= MaxFrames – 1) {
CurrentFrame = 0;
}
}
}
void CAnimation::SetFrameRate(int Rate) {
FrameRate = Rate;
}
void CAnimation::SetCurrentFrame(int Frame) {
if(Frame < 0 || Frame >= MaxFrames) return;
CurrentFrame = Frame;
}
int CAnimation::GetCurrentFrame() {
return CurrentFrame;
}
Some explanation on what this class is all about now. There is one basic element of animation that we need to handle, that is the current frame of the animation. Take the Yoshi image below for example (we’ll be using him in this tutorial). You’ll notice we have 8 frames of Yoshi on one image. Each frame would then be labeled 0, 1, 2 from Top to Bottom.

Remember the second tutorial where we create a function to draw part of an image? Well, if we take that function in conjunction with the frame of the animation, voila!
So the first variable I want you to see is CurrentFrame. This is the current frame of the animation that we are going to draw on the screen. Whatever value it has, will determine what part of the surface we will draw to the screen. So, when we call our draw function, we would do something like this:
Since our Yoshi is really 64 x 64 pixels, that’s the width and height we will grab, and is also how we grab the frame. Look at the image below for an illustration.

When the CurrentFrame increases by 1, we jump down 64 pixels (the height of Yoshi’s frame), and draw that frame.
The other part of this class is that we need to know how many frames this animation is, thus the MaxFrames. The last vital part to know is how many frames per second, or rather, how fast this animation is going to display. In order to determine that we find use this bit of code found in the OnAnimate function.
return;
}
By taking the Old Time in milliseconds plus the desired frame rate, we can check it against how long the SDL has been running. So, for example, we just started our program. SDL_GetTicks is 0, and OldTime is 0. Our desired frame rate is 1 frame per second. So FrameRate = 1000 (milliseconds). So, is 0 + 1000 greater than 0? No, thus we will skip over the function and wait. But once 0 + 1000 is less than SDL_GetTicks, that must mean 1 second has passed. So we increment the frame, and then reset OldTime to the current time, and start over.
The next interesting tid bit is Oscillate and FrameInc. Not that I wanted to confuse anyone by adding this, but I feel it’s necessary for certain things later on. Basically, when the Oscillate flag is true, the animation will increase frames, and then decrease frames. If we had an animation with 10 frames, it would do something like this:
0 1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1 2 …
You see, it goes up to 9, and then decreases back down to 0, and so on. There are some interesting uses for this, but we’ll get into that in other lessons. So how does this work? Take a look at the OnAnimate function.
if(OldTime + FrameRate > SDL_GetTicks()) {
return;
}
OldTime = SDL_GetTicks();
CurrentFrame += FrameInc;
if(Oscillate) {
if(FrameInc > 0) {
if(CurrentFrame >= MaxFrames – 1) {
FrameInc = -FrameInc;
}
}else{
if(CurrentFrame <= 0) {
FrameInc = -FrameInc;
}
}
}else{
if(CurrentFrame >= MaxFrames – 1) {
CurrentFrame = 0;
}
}
}
We already know what the OldTime and such do, but what about the rest? For now, look at the else statement of the Oscillate if statement. You’ll notice we’re simply checking if the CurrentFrame has exceeded the Max Frames. If it has, reset back to 0. Pretty simple. Then below that, outside of the block, we increase to the next frame.
Now, the more confusing part is the Oscillate if statement. This is where the FrameInc variable comes in. Basically, the FrameInc is set to 1 or -1, depending on how we are increasing or decreasing the frames. Remember, Oscillating causes the frames to go from 0 to 9 back to 0. So if the FrameInc is greater than 0, we are increasing the frames, otherwise we are decreasing frames. The innermost if statements basically inverse the FrameInc if we reached the end of 0, or MaxFrames.
Now that that is all taken care of, lets put this class into action. Create a new CAnimation object within CApp.h:
Now, lets set the MaxFrames, add this to CApp_OnInit:
If you want to see your animation Oscillate, set this:
Okay, now to make our animation loop, add this to CApp_OnLoop:
Now, the last thing, to make it actually animate; add this to CApp_OnRender:
Now try compiling, and watch your Yoshi workout! Make sure you replace the myimage.bmp with the Yoshi image.
SDL Animation – Tutorial Files:
Win32: Zip, Rar
Linux: Tar (Thanks Gaten)
Did you like this tutorial/blog post? Feel free to donate to keep more comin', and have more contests.
im totally stumped here i get an error ‘\stray226′ in program
That is a problem with the character encoding, just delete the ‘-’ in the line and write ‘-’ again.
I was having problems with visual studio 2010
in the function:
void CAnimation::OnAnimate()
it was saying that the lines needed a “)” :
CurrentFrame >= MaxFrames – 1
problem was, (if anybody else had it). When you copy and paste the code from the webpage the minus(-) is something else so just delete it from those two lines then type it manually. That should take care of it
Hey, thanks a bunch for these tutorials. One question: Since, CurrentFrame is incremented before the if statements, shouldn’t they read “if(current_frame_ > max_frames_)” and “if(current_frame_ < 0)" (no 'or equal to'). I think the way it is in the tutorial prevents the last frame from being rendered.
Thanks!
Sorry, I meant to type “if(CurrentFrame > MaxFrames – 1)” and “if(CurrentFrame < 0)".
Love the tutorial —
Is there a reason for making the Animation a separate class and not an extension of the Surface class, or of a Sprite class or something?
Perhaps you address that later…
This is because the animation class is not concerned with animating a surface only, it could also be used to animate 3d models (as an example).
Why to use “Oscillate” when you can just set it to 0 and start over again? I can’t notice why would it be useful.
See my reply below. An example where oscillate might be useful is a bouncing ball animation. The ball on the floor would be frame 0, and the ball in the air would be the last frame, and if you oscillate, it animates and makes it look like the ball is bouncing.
Great tutorial Tim, it’s making this very easy!
Just wanted to add that the animation sequence for the Yoshi’s seem to work better 0->7, 0->7 repeated rather then 0->7->0.
Just under If (FrameInc > 0) if (CurrentFrame >= MaxFrames-1)
simply just take out the FrameInc=-FrameInc; and put CurrentFrame = 0; hope this is makes sense. Thanks again Tim Awesome tutorial!
You are correct, I was simply demonstrating what oscillate does.
Jordan,
What sort of problems are you having? All you should have to do is change the framerate with SetFrameRate().
Hey Tim, was wondering if you could go over how to animate at a different frame rate, e.g, an attack animation. I’ve been trying to get it work for the past few days, but haven’t been able to make any progress.
Callum,
The problem is that C++ only has one way to inherit another class, so yes, it can seem as if we are saying “CApp is a CEvent.” Other languages have fixed this problem by introducing abstract classes, and interfaces. So, keeping this in mind, CApp is really inheriting “characteristics” of an Event listener, in other words, CApp can be an object that can listen. It’s not that CApp “is” a CEvent, rather, CApp “behaves” like CEvent. If you want to be a purist with your code, then what you do is a create a CAppListener class (which inherits CEvent), and then create a CAppListener object in your CApp. You can then check the listener in your CApp for events.
Update:
I want to further clarify by stating that CEvent behaves much more like an interface than anything else, it simply lays out the methods. It does contain one method though with code, which would disqualify it from being a true interface. (Which you could always make a static method somewhere like CEventManager::OnEvent(CEvent* Instance) ). In that sense, the “Class is a SuperClass” would no longer apply. For example, the String class in Java extends “Object”, and implements “Serializable”, “Comparable”, and “CharSequence.” Would this apply: “String is a Serializable?” No, but “String behaves like Serializable” or “String can be Serializable” makes sense.
Heya Tim, another fantastic tutorial.
I was wondering about the basic structure of the program so far…and I can’t get my head around why CApp must inherit CEvent? At college we have the words “Inheritance means IS A” tattoo’d into our brains. To me this doesn’t seem the case? CApp is a CEvent?
If I were to re-write it so CApp has a CEvent member, could I get similar results? My main problem would be with the pure virtual functions…I can’t over write them if I dont use inheritance?
What do you think? Any feedback would be fab.
Thanks again for the tutorials!