Archived

This topic is now archived and is closed to further replies.

ZadrraS

[SDL] Sprite animation. How?

Recommended Posts

How do i do sprite animation. Cone3D, tutorials, are harder as they could be. All i need to know is how do i play some kind of action, if i have, for example, 4 sprites of running character.

Share this post


Link to post
Share on other sites
Cone3d'' sprite tutorial is horrible I feel, the way that I wrote my SDL animated sprite class was to store each frame of the animation in individual files - its perfectly possible to store all frames in a single file but it was simpler to use separate files to get started.

If you do go for the separate file approach then I would recommend using a different folder for the different sprites.

The way that the animation was achieved was through using a vector of SDL_Surfaces - one entry for each frame. When you load in the sprite all you need to do is loop through the number of frames and store the sprite frame image in the vector.

Now if you keep an internal frame counter to keep track of what frame the sprite is currently on you can increment this counter each time you draw the sprite, then when the counter is greater than the number of frames you reset it back to 1.

Share this post


Link to post
Share on other sites
More surfaces.... My Ping-pong had 8 surfaces, is it normal to have LOTS of surfaces ? If a game is a more advanced 2D game it should have LOTS of surface if done that way you described...

Share this post


Link to post
Share on other sites
And another Q so i wouldn''t have to make another thread. How do i make that if player presses left, the cube would go left 40pixels but if the player holds left it would only go 40 pixels left and wouldn''t move until you press the key again.

Share this post


Link to post
Share on other sites
I am not sure if it is covered in the book, but there is a free copy of ''Programming Linux Games'' which uses SDL.

Yes, you probably don''t use linux BUT, SDL is cross-platform, so you should run into little trouble...

Programming Linux Games


------------------------------------------------------------
// TODO: Insert clever comment here.

Share this post


Link to post
Share on other sites
I need an array structure thingie, but it doesn''t work..:

struct Tiles {
int x;
int y;
};

then:

int num;
Tiles tiles[num];

But it doesn''t work, i get these errors:

error C2057: expected constant expression
error C2466: cannot allocate an array of constant size 0
error C2133: ''tile'' : unknown size

if i change "int num" to "const int num" it works but i get an error:

error C2105: ''++'' needs l-value

when i do:

num++;

What to do?

Share this post


Link to post
Share on other sites
1. Statically declared arrays (such as that one there) in C++ must have a constant size. That is, the exact size of the array must be known before you compile the code.

The problem when you used const int was that a const int, is... well... constant. It can''t be changed using conventional (ie: normal) ways. So ++ is out.

To do what you want, you''re looking for this:
int num;
Tiles *tiles = new Tiles [num];

And when you are done with tiles, you have to do this:
delete tiles;

2. Get a book on C++. This problem is elementary enough to be attracting flames around here. Dynamic memory allocation is usually covered very early on in C++ books.

-Auron

Share this post


Link to post
Share on other sites
Oh, and if you're using C and not C++, change the line:
Tiles *tiles = new Tiles [num];

to:
Tiles *tiles = (Tiles *)malloc (sizeof (Tiles) * num);

Change:
delete tiles;

To:
free (tiles);

And change all references to C++ to C.

-Auron

[edited by - Auron on March 21, 2004 12:20:59 PM]

Share this post


Link to post
Share on other sites
There is a problem about c++ books here where i live.. theres only few of them and theyre extremely hard to find, so, the only way to learn is through the internet...

Share this post


Link to post
Share on other sites
quote:
Original post by ZadrraS
And another Q so i wouldn''t have to make another thread. How do i make that if player presses left, the cube would go left 40pixels but if the player holds left it would only go 40 pixels left and wouldn''t move until you press the key again.


At the end of the frame, use a static or global variable to record whether the button is down. Then, in the next frame, check if the button is down and that it wasn''t down last frame. Then and only then do you move the cube. Rinse and repeat.

Pseudo-code:

void frame () {
static bool leftHeld = false;
if (keyDown[LEFT] && !leftHeld) MoveCube();
leftHeld = keyDown[LEFT];
}


You get the idea...

______________________________________________________________
The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ
MySite
______________________________________________________________

Share this post


Link to post
Share on other sites
quote:
Original post by ZadrraS
More surfaces.... My Ping-pong had 8 surfaces, is it normal to have LOTS of surfaces ? If a game is a more advanced 2D game it should have LOTS of surface if done that way you described...

A question I, too, would very much like to see answered: Allocating potentially very large numbers of surfaces (whether one deals with, say, SDL or DirectDraw) would certainly be much easier; should one go with this approach or be worried about overhead?

Share this post


Link to post
Share on other sites
quote:
Original post by Auron
Oh, and if you''re using C and not C++, change the line:
Tiles *tiles = new Tiles [num];

to:
Tiles *tiles = (Tiles *)malloc (sizeof (Tiles) * num);

Change:
delete tiles;

To:
free (tiles);

And change all references to C++ to C.

-Auron

[edited by - Auron on March 21, 2004 12:20:59 PM]



Thats a memory leak, you need to use delete [] tiles.

Share this post


Link to post
Share on other sites
you dont need to use vectors to make animations. in fact, i dont see a direct reason too, but i could be wrong, i never worked with vectors yet but i understand the concept. its just a STL lib which calls new and delete for you so you can have expandable/shrinking arrays, without the hassle, correct?

anyway, i have a system similar to cone3d''s. there system seems very clever, instead of having ALL of the frames inside your main class, you make a class called SpriteBase which holds all the frames for you. then you make a pointer to this spritebase and load it into the appropriate sprite. i actually liked cone3d system a lot, it gives you full control over everything, down to how many milliseconds you want to pause for even a specific frame. its also very OOP oriented, as in, you have "sprites", which have bases. i dunno, i can just visualize that system all in my head, like you have "sprites" which have sets of frames, i thought it was a good system.

im not using it, though. well, i did something similar. i have a Base class for all of my Entities, this base loads in all the frames for a specific entity. i only hard-coded the loading of the frames into SpriteBase, instead of reading in a file. the file reading system is much more easier to work with/ less sloppy, but i havent quite grasped how to read/write to files, and i dont like to copy and paste things from tutorials. you dont learn anything that way. so i hard-coded that part.

whoa, i just sort of rambled for awhile, anyway, back to helping you:

dont bother with a vector (unless you like using them, in which case this will work with either one). if you have 4 images, each a frame of a person walking, then make an array of SDL *Surface person[4]. now load in each image to each element of the array. NOW, start out by making something called int frame_count. now use SDL_GetTicks() and get the current time. after a certain number of milliseconds pass (however fast you want the person to walk) you increment frame_count. then you draw by doing

Draw(person[frame_count])

now, after x amount of milliseconds passed, the next image will be drawn. then the next, etc etc. be sure to have something like

if(frame_count > 4)
frame_count = 0;

if i didnt explain this clear enough, let me know

Share this post


Link to post
Share on other sites
Here is my system:

I have a Base Class called Animation which handles all the common taks such as loading frames from files and organizing them all in order.

Each animation in the game that i have is derived from Animation class. For each animation i have, there are X number of associated image files (1 per frame), and a very simple config file that lists, in order, each image filename and the duration of play for each frame. The animation class parses the config file and loads all images as seperate SDL surfaces. Each frame is now stored in an ordered vector. There is a seperate but syncronized vector that also lists the play time for that frame. you might refer to them as:

frames[x] --> an SDL_Surface* frame of animation
times[x] --> The length of time that frame plays (integer).

Each animation class has a function called Poll(int time). If the object is polled with the time, it blits the *appropriate* image for that chunk of time.

That's pretty much it. I'll leave the internals for you to figure out.

[edited by - leiavoia on March 21, 2004 5:12:05 PM]

Share this post


Link to post
Share on other sites
The way i have done it is create one image file which holds all relevant info. For example, a trees.bmp would hold all of the trees, and characters.bmp would hold all of the character images. Each "line" or "row" of the bmp which holds a certain object holds the animation frame, and each frame is a standard size, maybe around 16x16 or 32x32 or something, and a standard number of frames, say around 4.
so, if "[x]" is an animation frame, the image file might look like this:
[1][2][3][4][5] //default sequence
[1][2][3][4][5] //object two
[1][2][3][4][5] //object three

Then to set up the objects in the game, you create a base class which holds an array of SDL_Rect''s which represent the current animation frame, and a function called Animate() which increments the animation based on the time. In the constructor you initialise the animation array to the first row, which is some default animation sequence. But this class does not know about any images. it just knows that there are 5 frames of animation, each of which are nXn size, and at a cetain y value, and that after n time it should increment the frame.

After all that is done, you can derive from the base class and all of your animating objects you create will have these methods and members, so all you need to do is call Animate() and it takes care of everything else. All you would need to do in the derived class is Change the poition the Animation start point (or the "y" value) and it does the rest. (Remember what animation is: changeing images based on time. so all you need to do is move through a series of images when a certain amount of time has past. The base class already does this for you though. That is why we created it.)

Since the object class doesn''t care about loading objects, it shouldn''t care about destroying them either. That functionality rests with the main application. The main app loads the image files, and tells the objects in the game where they should be looking (ie pointers)to get their render images from. Then at the end, the main app closes after destroying everything, nobody tries to access a null pointer, and everybody is happy.

What makes this system good is that it allows you to make anything in the game animate. all you would need to do is inherit from the base class and call animate from the inheriting class. Lets say for example that all of your "people" in the game animated and looked cool. But their is a problem. The water flows, the "animals" move, but the trees stand rigidly still. No movement in the leaves from wind or something. SO you inherit the base tree class from the AnimationBase, create and set the animation textures, and you are good to go. Now the trees animate.

this is kinda long. i can post some code if you like though...

Share this post


Link to post
Share on other sites