SDL Animation
SDL Tutorials January 29th, 2008The 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)














January 29th, 2008 at 11:06 pm
Very nice work, this helped me alot with a game im working on I couldnt quite get my animations working perfectly until reading this, thanks again.
January 30th, 2008 at 8:23 pm
Very nice post, helped alot with game development. Quite simple and easy to follow.
Keep up the nice work! =]
January 31st, 2008 at 3:00 pm
I’m going to visit your site till I will find new tutorial! Great work
February 28th, 2008 at 12:05 am
Linux source: http://gaten.homelinux.net/sdltuts/sdl_animation.tar.gz
March 3rd, 2008 at 12:51 pm
I might be tired but have you covered how to make background of images transparent? It can be done in just 1 or 2 lines of code
March 3rd, 2008 at 1:20 pm
I sure did! It’s on the Tic Tac Toe tutorial page. But, as always, feel free to add code here as well for people to find. Some people like to look and leave, often missing what they came for.
March 29th, 2008 at 12:17 am
Nice tutorial, gratz.
April 7th, 2008 at 6:04 am
Nice tutorials Tim, but i have a problem here… Yoshi is up and animated but i cant close the screen anymore… any ideas??
April 7th, 2008 at 6:58 am
It’s probably because you aren’t grabbing the SDL_QUIT event. If you are using the CEvent class in CApp, then you have to simply overload the OnExit function in CApp. And then set Running = false. Look at the Events tutorial to see what I mean.
April 7th, 2008 at 8:33 am
Yeah i’ve done that. It only happens after i instantiate a CAnimation object, its fine otherwise.
Where exactly are you putting CAnimation Anim_Yoshi; ? In the public section of CApp?
April 7th, 2008 at 8:35 am
Yes, either in the public or private of CApp.h. Have you tried looking at the download files?
April 7th, 2008 at 10:02 am
Ok, it closes now…
Only thing i could find was in the parameters for main() i had int main(int argc, char**argv)
instead of int main(int argc, char** argv) Many thanks
April 12th, 2008 at 10:19 am
don’t work
April 12th, 2008 at 10:22 am
Oskar, what are you referring to?
May 8th, 2008 at 3:57 pm
When animating this i found yoshi to be a bit stilted at some point. It seems the final frame was not being shown. I changed
“MaxFrames - 1″ to “MaxFrames” of the final IF statement to fiz this.
It problem seems to be from moving
CurrentFrame += FrameInc;
above the IF block, to fix the earlier bug you noted.
On the last iteration of the animation we set the frame to 7 but before leaving the function to animate, we enter into the final IF statement and set CurrentFrame to 0; therefore, never displaying the 7th frame.
Also, unless something else is being done, i don’t think we need to worry about MaxFrame = 0 since even a still image has 1 frame to display.
May 16th, 2008 at 10:57 am
You’re right PAW, and I feel a little bad for knowing the bug was there and not fixing it yet. The correct condition for checking the bounds is: CurrentFrame >= MaxFrames, not CurrentFrame >= MaxFrames - 1. This tutorial has had the most bugs yet… ~sigh~
I’m not sure what you meant by the MaxFrame = 0.
May 20th, 2008 at 7:10 pm
I was just referring to the bug fix you added from Alexander Mangel for CAnimation::OnAnimate involving the placement of CurrentFrame += FrameInc;.
He noted a problem where currentFrame is set to 1 if MaxFrames = 0.
Whilst i don’t mean to be picky, i was just noting that this bug shouldn’t really occur (where MaxFrame=0) because every image has at minimum of 1 frame, meaning [MaxFrame >= 1] for any displayed image. Logically A MaxFrame = 0 doesn’t make sense. No big deal, just the bug fix seemed interesting since i think the conditions should never occur.
June 3rd, 2008 at 9:37 pm
Alexander Mangel’s fix is needed not because you could set MaxFrame = 0(that’s silly), but because never displaying CurrentFrame = 0.
June 4th, 2008 at 6:50 am
Kronen, You’re right. The thing also is that if you have an entity that doesn’t animate, you shouldn’t have to set MaxFrames to 1 or even touch it. And since the constructor sets it to 0, the code should take it into consideration.
June 19th, 2008 at 11:08 pm
Hi. Um. I’m in trouble here. I’ve got
“undefined reference to CAnimation::OnAnimate()” in the OnLoop function where I put “Anim_Yoshi.OnAnimate();”
“undefined reference to CAnimation::GetCurrentFrame()” in the OnRender function where I put “CSurface::OnDraw(Surf_Display, Surf_Test, 290, 220, 0, Anim_Yoshi.GetCurrentFrame() * 64, 64, 64);”
and
“undefined reference to CAnimation::CAnimation()” at the very beginning of CApp.cpp when CApp::CApp() is declared. Twice, that one.
I’m not sure what I’m doing wrong. As far as I can tell CAnimation.cpp is properly including CAnimation.h, CAnimation.h is properly #ifndef/#define-ing CANIMATION_H and including , and CApp.h is including CAnimation.h
Based on all that, any idea where I managed to goof up?
-Albert
June 20th, 2008 at 6:50 am
Hi Albert,
It’s hard to tell what is going on exactly, though I know what the issue is. Could you send over some code that I could look at?
Thanks.
June 20th, 2008 at 9:54 am
I sent you an email with the code attached.
Thanks again.
-Albert
June 28th, 2008 at 3:11 pm
I had the same problem as Albert. Turns out I had forgotten to check the Debug and Release boxes when I created the CAnimation.cpp and .h-files.
You can change this by right-clicking on the files in Code::Blocks, selecting Properties and then the Build-tab! Just check the boxes in the white field, and it should work if you have the same problem.
July 23rd, 2008 at 8:28 pm
gaten website says forbidden? any other mirros