Jump to content
  • Advertisement
Sign in to follow this  
sheep19

An SDL_Animation class!

This topic is 2547 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have looked a bit in the past for an SDL Animation class. However, I didn't find one, so I made my own to use it my own games. Here it is, you can use it as well:

SDL_Animation.h
#ifndef __MIN_SDL_ANIMATION_H__
#define __MIN_SDL_ANIMATION_H__

/*
* SDL_Animation class - by Minas Mina
* Version: 1.0
* Last Updated: 25/11/2011
* Contact: minas_mina1990[AT]hotmail.co.uk
*/

#include <SDL.h>

class SDL_Animation
{
enum {STARTED, PAUSED, STOPPED};

public:
enum { FORWARD = 0, REVERSE = 2, LOOP = 4 };

SDL_Animation(int _frameCount, float _fps = 1.0f);
~SDL_Animation();

// adds a surface to a frame. frame must be < frameCount
void AddSurface(SDL_Surface *s, int frame);

// draw on a surface. if not parameters are given, draws on the screen
void Draw(int x, int y, SDL_Surface *target = SDL_GetVideoSurface());

// update animation. dt is in seconds
void Update(float dt);

// gets fps
float FPS() const;

// sets fps
void FPS(float val);

void Start();
void Pause();
void Stop();

bool IsStarted() const;
bool IsPaused() const;
bool IsStopped() const;

int Mode() const;
void Mode(int flags);

int CurrentFrame() const;
void CurrentFrame(int _frame);

int Frames() const;

// returns the width of the surface (each one), -1 if no surfaces have been added yet
int Width() const;
int Height() const;

private:
// copy constructor and assignment operator disabled
SDL_Animation(const SDL_Animation &);
SDL_Animation & operator = (const SDL_Animation &);

SDL_Surface **img; // array of SDL_Surface pointers

int frameCount; // how many frames this animation constists of
int currentFrame; // the current frame

int state; // STARTED, PAUSED or STOPPED
int mode;

float fps;
float t; // time passed since last frame
};

// gets fps
inline float SDL_Animation::FPS() const { return fps; }

// sets fps. if val is negative, nothing is done
inline void SDL_Animation::FPS(float val)
{
if( val >= 0 )
fps = val;
}

inline void SDL_Animation::Start()
{
state = STARTED;
t = 0.0f;
}

// pauses the animation
inline void SDL_Animation::Pause() { state = PAUSED; }

// stops the animation
inline void SDL_Animation::Stop()
{
state = STOPPED;
currentFrame = 0;
}

inline bool SDL_Animation::IsStarted() const { return state == STARTED; }
inline bool SDL_Animation::IsPaused() const { return state == PAUSED; }
inline bool SDL_Animation::IsStopped() const { return state == STOPPED; }

// returns mode
inline int SDL_Animation::Mode() const { return mode; }

// sets mode
inline void SDL_Animation::Mode(int flags) { mode = flags; }

// returns the current frame
inline int SDL_Animation::CurrentFrame() const { return currentFrame; }

// sets the current frame
inline void SDL_Animation::CurrentFrame(int _frame) { currentFrame = _frame; }

// returns number of frames
inline int SDL_Animation::Frames() const { return frameCount; }

// returns the width of the surface (each one), -1 on error
inline int SDL_Animation::Width() const { return (img[0] ? img[0]->w : -1); }
inline int SDL_Animation::Height() const { return (img[0] ? img[0]->h : -1); }

#endif


source file
#include "SDL_Animation.h"

#include <cstdio>
#include <stdexcept>

using namespace std;

SDL_Animation::SDL_Animation(int _frameCount, float _fps) : frameCount(_frameCount), currentFrame(0), fps(_fps), t(0.0f), state(STOPPED),
mode(FORWARD)
{
try
{
img = new SDL_Surface* [frameCount];
memset(img, NULL, sizeof(SDL_Surface*) * frameCount);

#ifdef _DEBUG
fprintf(stderr, "SDL_Animation::SDL_Animation : memory allocation successful.");
fflush(stderr);
#endif
}
catch(bad_alloc &ba)
{
#ifdef _DEBUG
fprintf(stderr, "SDL_Animation::SDL_Animation : array memory allocation failed.");
fflush(stderr);
exit(-1);
#endif
throw ba;
}
}


SDL_Animation::~SDL_Animation()
{
// free the surfaces
for(int i = 0; i < frameCount; ++i)
SDL_FreeSurface(img);

// delete the array
delete img;
}

void SDL_Animation::AddSurface(SDL_Surface *s, int frame)
{
if( !s || !img || frame >= frameCount || frame < 0 )
{
#ifdef _DEBUG
if( !s )
fprintf(stderr, "%s\n", "SDL_Animation::AddSurface : surface passed as argument is NULL");
if( !img )
fprintf(stderr, "%s\n", "SDL_Animation::AddSurface : image array is NULL");
if( frame >= frameCount || frame < 0 )
fprintf(stderr, "%s\n", "SDL_Animation::AddSurface : invalid value for \"frame\". Correct values are 0 <= frame <= FrameCount() - 1");
fflush(stderr);
exit(-1);
#endif
return;
}

++s->refcount;
img[frame] = s;
}

// draw on a surface. if not parameters are given, draws on the screen
void SDL_Animation::Draw(int x, int y, SDL_Surface *target)
{
if( !target )
{
#ifdef _DEBUG
if( !target )
fprintf(stderr, "%s\n", "SDL_Animation::Draw : surface passed as argument is NULL");
if( !img )
fprintf(stderr, "%s\n", "SDL_Animation::Draw : image array is NULL");
fflush(stderr);
exit(-1);
#endif
return;
}

SDL_Rect r = {x, y};

SDL_BlitSurface(img[currentFrame], NULL, target, &r);
}

void SDL_Animation::Update(float dt)
{
if( state != STARTED )
return;

t += dt;

while( t >= 1/fps )
{
// FORWARD
if( mode == FORWARD )
{
if( currentFrame + 1 < frameCount )
{
++currentFrame;
t -= 1/fps;
}
else
state = STOPPED;
}
// REVERSE
else if( mode == REVERSE )
{
if( currentFrame - 1 >= 0 )
{
--currentFrame;
t = 0.0f;
}
else
state = STOPPED;
}
// FORWARD | LOOP
else if( mode == (FORWARD | LOOP) )
{
++currentFrame;
t -= 1/fps;
if( currentFrame == frameCount )
currentFrame = 0;
}
// REVERSE | LOOP
else if( mode == (REVERSE | LOOP) )
{
--currentFrame;
t = 0.0f;
if( currentFrame < 0 )
currentFrame = frameCount - 1;
}
}
}


How to use:

First, you have to load the surfaces you are going to use. This class library does not support sprite sheets for now, so you each frame must be in a separate file.
Let's say that my animation consists of 3 frames, "anim_0.png", "anim_1.png" and "anim_2.png"

First you need to load the images.
SDL_Surface *frames[3];
frames[0] = IMG_Load("anim_0.png");
frames[1] = IMG_Load("anim_1.png");
frames[2] = IMG_Load("anim_2.png");

Now, you need to create your animation.
SDL_Animation *animation = new SDL_Animation(3, 1.0f); // 3 frames, 1.0f frames/second

We use the AddSurface member function to tell the animation about its frames.
animation->AddSurface(frames[0], 0);
animation->AddSurface(frames[1], 1);
animation->AddSurface(frames[2], 2);

Now we are ready to draw! Drawing is done using the Draw member function!
// draw on a surface. if not parameters are given, draws on the screen
void Draw(int x, int y, SDL_Surface *target = SDL_GetVideoSurface());


The animation needs to updated every frame, using the update member function:
// update animation. dt is in seconds
void Update(float dt);


Ok, now we need to free the frames we have allocated.
for(int i = 0; i < 3; ++i)
SDL_FreeSurface(frames);


Thank you :)

I have not documented the library very well, so please read the source code to understand it (I have written comments inside).

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!