Sign in to follow this  

[SDL] Sprite Animation Changes

This topic is 3837 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

Stupid question... that's why I'm here. Most of the sprite tutorials out there show you how to animate a sprite with one walking animation or jumping or whatever... But not specifically how to have a unit come up to another unit, hit it, and if the unit has low heath, play a death animation... My real question is this: How would a professional do it? Do they have each unit have a animation queue, and you just add animations to it? I know I could hack something together but I'm looking for an efficient method. Right now I've got it based on states, when an "attack" method is called, an attack boolean is set to true and the attack animation plays, sometimes more than once... which is not what I want. Please give me some ideas, I'm confusing myself here. -mw

Share this post


Link to post
Share on other sites
Personally, I wouldn't combine an animation system with AI states. They're two separate things. I'd write a system that allows you to load sprites and animation data, and then allows you to create visual objects, using a specified sprite. This system should allow you to set the animation of the object you just created - which animation to play, how often it should repeated, etc. It should also allow you to change the position of this object, and probably various other properties as well, depending on your needs.

The unit AI can then control a visual object: it selects an attack animation when it attacks, a death animation when it dies, and so on. The big advantage here is that this animation system can be used by any other unit or game object: it's not tied to your unit logic anymore, so you don't have to copy and modify it each time you want a new unit to play some animations.

I hope that answers some of your questions? :)

Share this post


Link to post
Share on other sites
Thank you for the response Captain P.

So what you're saying is have a separate data structure that loads all the sprites I need and controls how they playback and then have the unit AI access this structure when it wants to do something?

Something like:

void walk_to(int x, int y){
animation.play(WALKING, //Animation identifier
_x, //Sprite X location
_y); //Sprite Y location
}




?

Please help me clarify what you are trying to say, because I definitely see it as the right direction.

Thanks so far!

mw

Share this post


Link to post
Share on other sites
I think you're mixing up two different things: animation and movement. Movement is game logic. It should work regardless of which things you display on the screen.
So when you start walking, you'd call animation.changeTo(WALKING), and when you're done walking, you'd call animation.changeTo(STANDING). The animation object would only be responsible for keeping track of which frame of the walking animation to display at which point in time. Somewhere in your rendering code you'd do something like Image imageToDisplay = animation.nextFrame();.

Something like an animation queue might be useful if you're doing things like in-game cutscenes, though.





Share this post


Link to post
Share on other sites
i haven't actually tried any animation, so my ideas probably aren't very valid. i've been thinking about animation on and off lately(working on other stuff at the moment so i haven't tried anything out). anyway i was thinking about some structs/classes for animation:


struct frame{
SDL_Rect clipArea;
int frameNumber;
};

struct animationSet{
string setName;
vector<frame> frames;
vector<frame>::iterator currentFrame;
int animationType;
};

class animatedSprite{
public:
animatedSprite(const char* fileName); //or string
void update();
bool play();
bool pause();
[other rewind/fast fowared/ESP/skip chapter functions]
bool changeAnimationSet(const char* newSet); //or string

vector<animationSet> types;
animationSet currentType;
private:
bool sliceImg();

SDL_Surface* img;
int frameSizeX , frameSizeY;
int speed; //how many millisecs between frames
};



i literally just wrote that off the top of my head so i'm sure there's tons of problems with that. anyway the idea was to have an animated sprite object with any number set of animations, and each of those animations could have any number of frames. it would load the data for the animated sprite from a file, example:

Quote:
SPRITE IMAGE: aniSprite1.png
SPRITE SPEED: 100
SPRITE FRAME SIZE X: 32
SPRITE FRAME SIZE Y: 64

STANDING
0
1

RUNNING LEFT
2
3
4

RUNNING RIGHT
5
6
7

JUMPING STRAIGHT
8
9

MID JUMP
10

LANDING
11
12
13

etc, etc...


it would load the data from the "header" area of the file then call sliceImg() where it would cut the image into frames, where it keeps the position and size of the frame, and the frame number.

then it starts reading sets out of the file, ex "RUNNING LEFT". when it reads a string like "RUNNING LEFT" it creates a new animationSet, gives the setName string the string it read, then starts reading the numbers. every number it finds it adds that corresponding frame to the frames vector. ex the "RUNNING LEFT" animation is the 2nd, 3rd, and 4th frames out of the image. so it will look through all the frames until it finds a frame with the same frameNumber, then adds it to the vector.

the animationType int in the animationSet struct could be set to different values representing different styles of animation, for example an animation with 3 frames:
animationType = frame flow (order in which frames are displayed)
0 = 1 [display the first frame, no animation]
1 = 1 -> 2 -> 3 -> 1 -> 2 -> 3 .... [circular i guess]
2 = 1 -> 2 -> 3 -> 2 -> 1 -> 2 .... ["bouncing" might be a good description]

now that i think about it maybe the order of each set described in the file should go
[set name]
[animation type]
[frame 1]
[frame 2]
...
[frame n]

so when you declare an animatedSprite class, you pass it the name of the file containing all that data, then it does the rest of the work for you, after that you call the update() function to update the current animation(it will take care of timing, looping, etc).

and if you want to change the current animation it's using, simply call the changeAnimationSet() function, and pass it whatever new animation you want it to use in a string literal. ex: player.changeAnimationSet("RUNNING RIGHT");

it will look through all the animationSet structs it has, and if it finds one with the setName that's the same as the name passed to the function, it changes it to that. after that just continue to call update()

so you could declare and manage an animated sprite like:
animatedSprite player("blue-player.asi");
player.changeAnimationSet("STANDING");

while(gameLoopContinue){
player.update();

if(/*conditions met to change set to running left*/)
player.changeAnimationSet("RUNNING LEFT");
/*any other number of checks and set changes*/
}


...wow this is a really long post... i could probably keep going but i'm sure you get the gist of it. it probably isn't even a very effective way of doing it, i'm actually pretty much posting this to see if this is a good idea or not, i figured "why make a new topic about the exact same thing?"

Share this post


Link to post
Share on other sites
Looks good, econobeing. I'd write some management code around it, to make sure images and animation data doesn't get loaded more than once into memory, but that's more or less the basic approach.

Personally, I'd also write a Renderer class around all this. This class contains all images, animation data sets, sprites, and also visual objects. Other code can then call this Renderer class to create a visual object, with a given sprite, at a given position. Renderer will take care of loading and rendering that object, and it will also update the animations (which can be done within Renderers draw function). The code that requested this object will receive a handle or reference to the object they requested, so they can manipulate it: change it's position, animation and visibility, destroy it, and so on.


Just a note: I wouldn't use enumerations for setting animations, such as SetAnimation(WALKING). This ties the animation system to your game logic, which means that for every other unit with different behaviour, you'll need to modify your animation system. When you add something, it's best that you only have to add code in one place, because it's easy to forget that some code may depend on some other code elsewhere.

Share this post


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