Sign in to follow this  
c-gibson-s

sprite animation

Recommended Posts

how would i go about making an animation for sprites? i understand the animation is basically a lot of frames of the sprite in differing positions (duh), but how do i get them to do that, then insert them into my game? im doing it in SDL... gibson thanks!

Share this post


Link to post
Share on other sites
ok, first make the animation like this:
frame 1 picture frame 2 picture ...
then, to switch what frame you are blitting, change the source rectangle's x value to match what frame you are on
put all this in a callback function for a timer, I haven't figured out how to do that yet :)

Share this post


Link to post
Share on other sites
once you have all the frames, its pretty easy. lets say your animation is 2 frames, of a person walking...

SDL_Surface *walk_1;
SDL_Surface *walk_2;

better yet, stick them in an array.

SDL_Surface *walking_frames[2];

now, lets say you have a function call blit_img() which took a surface to blit and the coordinates to blit it to. you just switch up which surface you send this function... you could do this:


static int counter = 0;
if(character_is_walking)
{
blit_img(walking_frames[cntr],x_pos,y_pos);
cntr++;

if(cntr >= total_frames)
cntr = 0;
}


do you see whats done here? you just flip which frame to play... this is very basic, though. this switches the image each frame, where you should do it based on time. just use SDL_GetTicks() to get the time, and increment cntr based on that. of course, a vector would be best for this situation if you know how to use them, since you dont have to track how many frames you have, plus they are much nicer in general. i would strongly recommend to learn vectors before doing an animation system (they are easy to learn...)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
yeah i know how to do like walking or somthing similar, i was wondering about a full blown, say, attack animation, where there are up to 20 frames. could i use the SDL_GetTicks() and just have the animations in the array blit in the order of the Tick and also write a simple calculation for xy positioning?

if that is the way to do it, is that the most efficient way to?

thanks again!

Share this post


Link to post
Share on other sites
well, there really isn't a "most efficient" way of doing it, but one way is to create of vector of a list/vector of frames, and have some way of determining the starting index of each action (which contains x amount of frames), and then yes, like you said, just use SDL_GetTicks() and blit another image when enough time has passed.
for other image formats [besides .bmps], look into the sdl_image library :
http://www.libsdl.org/projects/SDL_image/

Share this post


Link to post
Share on other sites
Picking up on Graveyard Filla's code, I'm getting the idea of blitting the surface every time a new frame is called. I can get implement SDL_GetTicks() on my own from there. But how would you load the images from the array? This is all I can think off the top of my head right now:

SDL_Surface *walking_frames[1];
walking_frames[1] = SDL_LoadBMP("frame1.bmp");

That seems too slow, loading them from the disk on every frame. There must be a better way I'm not aware of.

Share this post


Link to post
Share on other sites
If you are feeling more serious about it, i suggest when you get your hard coded animation running, try out saving animation in XLM files and use a parser to parse it and take frame sets out of it, this will make life easy for one time work.

I am using it and also Raymond Jacobs of Ethereal Darkness is using XML for saving animation sets for his upcoming Morning's Wrath.

Well don't try unless you got something running and up!

Share this post


Link to post
Share on other sites
classes are an amazing thing:

here is my SDL animation class that i made for a game a while ago...

animation.h

//ANIMATION CLASS FOR SPRITE



#include "cSDL.h"
#pragma once
//AnimationState Struct////////////////
typedef struct
{
int CurrentFrame;
int XCellPosition;
int YCellPosition;
int frames;
unsigned int AnimationSpeed;
} AnimationState;
///////////////////////////////////////

//ANIMATION STATE ENUM/////////////////
enum SPECIAL_ANIM_STATE
{
MOVEDOWN = 0,
MOVEUP,
MOVELEFT,
MOVERIGHT,
};
///////////////////////////////////////

//ANIMATION CLASS//////////////////////
class cAnimation
{
public:
//Constructor and Destructor
cAnimation();
~cAnimation();

//Cell co-ordinates//////////
int myXCell;

//Animation Properties///////
int AnimationSpeed;
Uint32 LastFrameTime;


Uint32 ChangeBackTime;
bool animTimer;
int lastAnim;

//Directional Facing/////////
int move_right;
int move_left;
int move_up;
int move_down;

//Special
int get_hit;

/////////////////////////////
AnimationState* AnimationStates;
int AnimationStateCount;
int CurrentAnimationState;


//Simple Advance frame
void AdvanceFrame();

//Starts Animation Ticker
void StartAnimTicker();

void SetAnimationWithTime(int animation, Uint32 time);
};
///////////////////////////////////////


and here is the animatoin.cpp


//CANIMATION IMPLEMENTATION

//INCLUDE
#include "cAnimation.h"

//CONSTRUCTORS//////////////////
cAnimation::cAnimation()
{
AnimationStates = NULL;
CurrentAnimationState = 0;
myXCell = 0;
move_up = 0;
move_down = 0;
move_left = 0;
move_right = 0;
animTimer = false;

};
cAnimation::~cAnimation()
{
delete AnimationStates;
AnimationStateCount = 0;
}
;
////////////////////////////////


//Starts animation ticker///////
void cAnimation::StartAnimTicker()
{
LastFrameTime = SDL_GetTicks();
}
////////////////////////////////


//Advance Frame/////////////////
void cAnimation::AdvanceFrame()
{
//Gets current time
Uint32 current = SDL_GetTicks();

//Tests for next frame
if(current - LastFrameTime >= AnimationStates[CurrentAnimationState].AnimationSpeed)
{
//Resets Frame time
LastFrameTime = current;

//Tests and calculates multiple frame skips
if((current - LastFrameTime) / AnimationStates[CurrentAnimationState].AnimationSpeed > 1)
myXCell += int((current - LastFrameTime) / AnimationStates[CurrentAnimationState].AnimationSpeed);
else
{
//Advances Frame
myXCell++;
}
if(myXCell >= AnimationStates[CurrentAnimationState].frames)
myXCell = 0;
}

if(SDL_GetTicks() >= ChangeBackTime && animTimer)
{
animTimer = false;
CurrentAnimationState = lastAnim;
}
}
////////////////////////////////

void cAnimation::SetAnimationWithTime(int animation, Uint32 time)
{
lastAnim = CurrentAnimationState;
this->CurrentAnimationState = animation;
ChangeBackTime = SDL_GetTicks() + time;
animTimer = true;
}


hope looking over that stuff helps. i havent used this code in a while so i kinda dont even know what it does. this is designed as a "has a" class for object sprites. the animation class i believe just takes care of texture rect coordinates, and switching the frame based on passed time (SDL_GetTicks()).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Anonymous Poster
yeah i know how to do like walking or somthing similar, i was wondering about a full blown, say, attack animation, where there are up to 20 frames. could i use the SDL_GetTicks() and just have the animations in the array blit in the order of the Tick and also write a simple calculation for xy positioning?

if that is the way to do it, is that the most efficient way to?

thanks again!


Better yet, loading one image as a sprite set instead of many little ones. Then just look up the coordinates of each sprite in your favorite graphics editing program and note them down. You can then 'plug' these numbers in the appropriate (int) values for the blit_img function. You should probably store these numbers as another vector or array.


Share this post


Link to post
Share on other sites
So suppose I have a sprite set bitmap where all the sprites are in a row, and each is 20-25 pixels wide. I would want the portion in view to change in order to create the illusion of motion (think of a zoetrope).


int i=0;
int xpos[5] {0, 20, 45, 65, 90};

// x, y = where the sprite on the screen is at the moment
// as i changes, a different image would be seen from the sprite set

while (key_is_pressed) {
Blit_img(sprite, x, y, 20, 30, (int)xpos[i], 0);
i++;
if (i >= 5) {i = 0;}

// 33 milliseconds for 30 fps

SDL_Delay(33);
}


I just got this out of my head since I can't test it right now. But if someone can tell me if this will work on their programs let me know. Also tell me if I'm missing something.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this