Sign in to follow this  
Nate Hale

Thoughs on sprite animation organization

Recommended Posts

Hey, everyone. I've been reading topics here a lot over the years, but don't post much. Recently, I've started programming my own sprite-based platformer using the old NES Mega Man games as a model to work and learn from. Going through some of the sprite sheets I found online, I noticed that each animation has a different number of frames. The run cycle, for instance, is only about 4 frames and the jump is 1. After a lot of deliberation and some experimentation programming, I decided on a system that lends itself to a lot of flexibility but isn't as organized as I would like. basically it looks like this. A frame object contains coordinate information of the location and size of the frame on the master sprite sheet. An animation object contains a vector of these frame objects and each sprite contains a vector of animation objects. So if I wanted to access a frame in a run cycle, I could make the call as follows: spriteObject.vectorOfAnimations.at(animationNumber).vectorOfFrames.at(frameNumber); where animationNumber and frameNumber are integers like 2. I'm curious on your opinions and thoughts about this system. I'm considering using arrays to be more efficient with access time, but my main concern is loosing track off all this coordinate information and the confusingly lengthy calls. I could write a function making it easier to interpret by assigning specific indexes in the animation vector an enumeration like "RUN" so I could call spriteObject.animate(RUN), but the underlying structures remain the same and this is further building on top of an already confusing system. Does anyone have a simpler approach that won't limit the number of frames and animations a sprite can have?

Share this post


Link to post
Share on other sites
I usually push this out to a text file. Something like (I'm being extra-verbose):
run_animation file: mega-man.png x: 0 y: 0 w: 128 h: 128 cell_w: 32 cell_h: 32
jump_animation file: mega-man.png x: 0 y: 128 w: 128 h: 32 frames: 4

Then you'd have something like an animation definition class which would parse that up, find a reference to the image in memory, and store it. Your actual animation can then get the image it needs and the relevant frame data.

I wouldn't bother with some complicated abstract array system like you've built. Keeping your objects simple is good and besides, you may want your sprite sheets to have a bit of non-uniformity.

Share this post


Link to post
Share on other sites
Your idea to import coordinate information is good actually; I'll probably want to do that before I finish the project, but even if I predefine it in a file, I'd still have to structure the frame objects into an organized animation system UNLESS I perform I/O every time I want to access a frame.

Opening and parsing an entire file to find my a specific frame FOR EACH sprite is not something I want to do. After I read the information into my code, I still need to structure it somehow and that's the trouble I'm having.

The simplest solution I've been able to think of is to create several subclasses from sprite like FlyingEnemy or Hero or Boss which have specific animation sequences and lengths. For instance, Hero would have array members like

//Hero animation arrays
Frame runCycle[4]
Frame jump[1]
Frame shoot[2]

and other classes would be different like this

//FlyingEnemy object animation
Frame swoopAndShoot[3]
Frame shoot[2]
Frame explode[4]

That'll allow me to remove one nested layer of animations and keep track of which animations are in the object. I could simply call hero.runCycle[2] to get the 3rd frame of the run cycle animation. If there were a way to dynamically declare the size, names and numbers of arrays I'll need within these class headers, that'd be great, but I think this'll have to do for now. I'm not about to throw away c++ for one limitation.

Thanks for the IO suggestion though! That'll definitely keep things organized.

Share this post


Link to post
Share on other sites
There are many different ways of doing this kind of thing, but let me give you one possible view of it.

First you have your image container. It stores the image data and has a map from names to images for quickly figuring out if something is in the container.

class ImageContainer
{
getImage ( name )
addImage ( image, name )

vector<Image *> _images
map<string, int> _names
}


Then you have something like your animation. I'm going to compact this to contain more than some people would say it should (I'm breaking srp).

class Animation
{
load ( string ) // from the text file
update ( float deltaTime )
getImage
getTextureCoordinates // the sub-rectangle that contains the current cell
clone

string _name;
Image *_image
float _time;
float _secondsPerFrame;
int _currentCell
int _frames
// ... whatever else you need for calculating your animation
}


Then you have some kind of factory or container for animations.

class AnimationFactory
{
loadAnimations ( filename )
cloneAnimation ( name ) { return _animations[_map[name]]->clone() }

vector<Animation *> _animations;
map<string, int> _names;
}


Finally you have your game object (actor, entity, whatever you like to call it)

class ObjectMegaMan
{
initialize
{
_runningAnimation = animationFactory.cloneAnimation ( "mega_man_runs" );
_jumpingAnimation = animationFactory.cloneAnimation ( "mega_man_jumps" );
_standingAnimation = animationFactory.cloneAnimation ( "mega_man_stands" );
_currentAnimation = _runningAnimation;
_state = running
}
update ( float deltaTime )
{
switch ( _state )
// do some logic, change animations as needed
_currentAnimation->update ( deltaTime );
}
render
{
bindImage ( _currentAnimation->getImage )
setTextureCoordinates ( _currentAnimation->getTextureCoordinates );
// etc.
}

_state
Animation * _currentAnimation
Animation * _runningAnimation
Animation * _jumpingAnimation
Animation * _standingAnimation
}


Something like that anyway.

Share this post


Link to post
Share on other sites
I guess you have sprites, so instead of render you'd have


void update ( float deltaTime )
{
// logic stuff as before
_currentAnimation->update ( deltaTime );
_sprite->setAnimation ( _currentAnimation )
}


Or you could put the update function on the sprite and call set animation when you switch animations (ie, there is no _currentAnimation, only _sprite). Or you could do something like

sprite->setSubRect ( _currentAnimation->getTextureCoordinates )


As with everything, there are many ways of doing things. It just depends.

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