Re-visiting my Animation Class [Not Solved]

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

Re-visiting my Animation Class [Not Solved]

Post by superLED »

Hello! I'm currently working on my animation class, and I've come across some problems while trying to make it more flexible.
I am using SDL, but I guess that's not much of relevance on this topic.

What i've used to do so far, is to have an SDL_Rect to each "animation" (one SDL_Rect for "idle", one for "walkingLeft", and so on), as an array to hold 4 frames (4 frames for each state).
And to set them up, I've done something like this:

Code: Select all

walkingRight[0].x = 0;
walkingRight[0].y = 0;
walkingRight[0].w = width;
walkingRight[0].h = height;

walkingRight[1].x = width;
...
walkingLeft[0].x = something
This can become very tedious. And I'm not quite sure how I can loop all these either to do the work for me.

So, I want to be able, in it's init function, to specify how many states I want for my characters. With a function like "void Anim::init(int numberOfStates, int numberOfFrames);"
And then the animation class should be able to handle all this by itself, with no fixed number of states and frames.

To sum it up: What I need help with, or be guided to, is to make my animation class a little more flexible, so I'm not stuck to the hardcoded states and frames.
In contrast of how my animation class is working now: I am limited to 4 frames (I can add more, but then I'd need to continue hardcoding it), limited to 4 states (the same as frames).

Here is some copy-paste of some of my animation class (my most horryfying class):

Anim.h

Code: Select all

class Anim : public Graph
{
protected:
	int frame, status;
	int frameCount, frameMax;

	SDL_Rect clipsUp[4];
	SDL_Rect clipsDown[4];
	SDL_Rect clipsLeft[4];
	SDL_Rect clipsRight[4];

public:
	Anim();
	~Anim();

	void setClips();

	// Setters
	void setFrame(int myFrame);

	// Getters
	SDL_Rect getClipsUp();
	SDL_Rect getClipsDown();
	SDL_Rect getClipsLeft();
	SDL_Rect getClipsRight();
};
Anim.cpp

Code: Select all

Anim::Anim() {
	frame = 0;
	status = 0;
	frameCount = 0;
	frameMax = 10;
}

Anim::~Anim() {
	//
}

void Anim::setClips() {
	// DOWN

	// #1 frame
    clipsRight[ 0 ].x = 0;
    clipsRight[ 0 ].y = 0;
    clipsRight[ 0 ].w = width;
    clipsRight[ 0 ].h = height;
    
	// #2 frame
    clipsRight[ 1 ].x = width;
    clipsRight[ 1 ].y = 0;
    clipsRight[ 1 ].w = width;
    clipsRight[ 1 ].h = height;
    
	// #3 frame
    clipsRight[ 2 ].x = width * 2;
    clipsRight[ 2 ].y = 0;
    clipsRight[ 2 ].w = width;
    clipsRight[ 2 ].h = height;
    
	// #4 frame
    clipsRight[ 3 ].x = width * 3;
    clipsRight[ 3 ].y = 0;
    clipsRight[ 3 ].w = width;
    clipsRight[ 3 ].h = height;
    
	//UP

	// #1 frame
    clipsLeft[ 0 ].x = 0;
    clipsLeft[ 0 ].y = height;
    clipsLeft[ 0 ].w = width;
    clipsLeft[ 0 ].h = height;
    
	// #2 frame
    clipsLeft[ 1 ].x = width;
    clipsLeft[ 1 ].y = height;
    clipsLeft[ 1 ].w = width;
    clipsLeft[ 1 ].h = height;
    
	// #3 frame
    clipsLeft[ 2 ].x = width * 2;
    clipsLeft[ 2 ].y = height;
    clipsLeft[ 2 ].w = width;
    clipsLeft[ 2 ].h = height;
    
	// #4 frame
    clipsLeft[ 3 ].x = width * 3;
    clipsLeft[ 3 ].y = height;
    clipsLeft[ 3 ].w = width;
    clipsLeft[ 3 ].h = height;

	// LEFT
	
	// #1 frame
    clipsDown[ 0 ].x = 0;
    clipsDown[ 0 ].y = height * 2;
    clipsDown[ 0 ].w = width;
    clipsDown[ 0 ].h = height * 2;
    
	// #2 frame
    clipsDown[ 1 ].x = width;
    clipsDown[ 1 ].y = height * 2;
    clipsDown[ 1 ].w = width;
    clipsDown[ 1 ].h = height * 2;
    
	// #3 frame
    clipsDown[ 2 ].x = width * 2;
    clipsDown[ 2 ].y = height * 2;
    clipsDown[ 2 ].w = width;
    clipsDown[ 2 ].h = height * 2;
    
	// #4 frame
    clipsDown[ 3 ].x = width * 3;
    clipsDown[ 3 ].y = height * 2;
    clipsDown[ 3 ].w = width;
    clipsDown[ 3 ].h = height * 2;
    
	// RIGHT

	// #1 frame
    clipsUp[ 0 ].x = 0;
    clipsUp[ 0 ].y = height * 3;
    clipsUp[ 0 ].w = width;
    clipsUp[ 0 ].h = height * 3;
    
	// #2 frame
    clipsUp[ 1 ].x = width;
    clipsUp[ 1 ].y = height * 3;
    clipsUp[ 1 ].w = width;
    clipsUp[ 1 ].h = height * 3;
    
	// #3 frame
    clipsUp[ 2 ].x = width * 2;
    clipsUp[ 2 ].y = height * 3;
    clipsUp[ 2 ].w = width;
    clipsUp[ 2 ].h = height * 3;
    
	// #4 frame
    clipsUp[ 3 ].x = width * 3;
    clipsUp[ 3 ].y = height * 3;
    clipsUp[ 3 ].w = width;
    clipsUp[ 3 ].h = height * 3;
}

void Anim::setFrame(int myFrame) {
	frame = myFrame;
}

SDL_Rect Anim::getClipsUp() {
	return clipsUp[frame];
}

SDL_Rect Anim::getClipsDown() {
	return clipsDown[frame];
}

SDL_Rect Anim::getClipsLeft() {
	return clipsLeft[frame];
}

SDL_Rect Anim::getClipsRight() {
	return clipsRight[frame];
}
User avatar
LeonBlade
Chaos Rift Demigod
Chaos Rift Demigod
Posts: 1314
Joined: Thu Jan 22, 2009 12:22 am
Current Project: Trying to make my first engine in C++ using OGL
Favorite Gaming Platforms: PS3
Programming Language of Choice: C++
Location: Blossvale, NY

Re: Re-visiting my Animation Class [Not Solved]

Post by LeonBlade »

Hello,

Instead of making an array of frames, you can just keep an integer for your current frame instead and just move the frame accordingly.

Code: Select all

if(oldTime + frameRate > SDL_GetTicks())
	return;

oldTime = SDL_GetTicks();
currentFrame += frameIncrease;
    
// if you want to oscillate back (used in player animations)
if (oscillate)
{
	if (frameIncrease > 0) 
	{
		if (currentFrame >= maxFrames - 1)
			frameIncrease = -frameIncrease;
	}
	else
	{
		if (currentFrame <= 0)
			frameIncrease = -frameIncrease;
	}
}
else 
{
	if (currentFrame >= maxFrames - 1)
		currentFrame = 0;
}
And this is how I render

Code: Select all

frameRect.x = this->animationControl.GetCurrentFrame() * TILE_SIZE;
frameRect.y = facing * TILE_SIZE;
frameRect.w = TILE_SIZE;
frameRect.h = TILE_SIZE;
There's no place like ~/
like80ninjas
Chaos Rift Regular
Chaos Rift Regular
Posts: 101
Joined: Thu Dec 09, 2010 2:13 am

Re: Re-visiting my Animation Class [Not Solved]

Post by like80ninjas »

In my 2D engine(s), I use a few values,

int image_index
float image_speed;
float speed_index;

so I add image_speed to speed_index every step, and then set the int image_index = float image_speed, which drops the decimal from the value(you will get a warning for this).

with this image_speed integer, I use it as my index in my array of rects (frames),

DrawImageClipped( x, y, WalkAnimation[image_index] ); Or whatever your draw code looks like.

also, once speed_index is greater than your max number of frames, set it to 0.0, so it will loop, giving you animation.

the image_speed can be 1.0 to 0.0 with lower values producing slower animations and 1.0 animating at your frame rate.

Code: Select all

if (speed_index > max_frames)
    speed_index = 0.0f;

speed_index += image_speed;
image_index = speed_index;
//Then set your image_index as the frame in your animation (array of rects)
As for actually putting the frame arrays together, I make sure my sprite sheets are nice and orderly ( like all 64x64 images lined up side by side ) and then use a for loop to set them up automatically.

If you want to have them done "for" you, then I think that's the easiest way. Just make a function that sets up the array of rects to what it should be

Code: Select all

for (int i =0; i<number_of_animations; i++)
{
    for (int r = 0; r<number_of_frames_per_animations; r++)
    {
        Player_anims[i][r].x = r*w;
        Player_anims[i][r].y = i*h;
        Player_anims[i][r].w = r*w + w;
        Player_anims[i][r].h = i*h + h;
    }
}
Something like that will set it up to where you can have Player_anims[r], where i is the animation, and r is its frames.
***Note that the code above assumes your images have one line per animation.

Then you can just remember which "i" index is which animation, or set up constants or enums for the numbers so you can reference with names.

I'm no programming whiz, but that's how I do it in my games, and it's worked with no problems so far, so help this helps.
User avatar
bnpph
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 75
Joined: Thu Mar 10, 2011 12:30 pm

Re: Re-visiting my Animation Class [Not Solved]

Post by bnpph »

I don't fully understand your question, but here is a quick thing that might be what you're looking for:

Code: Select all

class AnimationManager {
  public:
    struct Animation {
      unsigned int numFrames;
      SDL_Rect* frames;
    };
  private:
    unsigned int animationStackPtr;
    unsigned int numAnimations;
    Animation* animations;
  public:
    Animation() : animations(NULL), animationStackPtr(0) {}
    Animation(unsigned int numAnimations) : {
    animationStackPtr(0)
      animations = new Animation[numAnimations];
    }
    ~Animation() {
      if(animations) {
        for(unsigned int i = 0; i < animationStackPtr; ++i)
          delete[] animations[i].frames;
        delete[] animations;
      }
    }
    
    Animation* addAnimation(unsigned int numFrames) {
      animations[animationStackPtr].numFrames = numFrames;
      animations[animationStackPtr].frames = new SDL_Rect[numFrames];
      return &animations[animationStackPtr];
    }
};
Have not tested or compiled.
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

Re: Re-visiting my Animation Class [Not Solved]

Post by superLED »

Many interesting solutions. I will test them out as soon as I get home!
I am sure all of your suggestions will come in handy. Thanks a lot!

I will post an update to tell you all how it worked out.
User avatar
MadPumpkin
Chaos Rift Maniac
Chaos Rift Maniac
Posts: 484
Joined: Fri Feb 13, 2009 4:48 pm
Current Project: Octopia
Favorite Gaming Platforms: PS1-3, Genesis, Dreamcast, SNES, PC
Programming Language of Choice: C/++,Java,Py,LUA,XML
Location: C:\\United States of America\Utah\West Valley City\Neighborhood\House\Computer Desk

Re: Re-visiting my Animation Class [Not Solved]

Post by MadPumpkin »

I (personally) would go with LeonBlade's, it's closest to what I use. The others seem fine though, so which ever looks prettiest to you. I was going to post mine but changed my mind once I read LeonBlade's code.
While Jesus equipped with angels, the Devil's equipped with cops
For God so loved the world that he blessed the thugs with rock
Image
Image
Image
Post Reply