Skip to main content
GameDev.net gamedev.net
🔒 Locked

What's the best way to store sprite animations?

Started by The Forgotten Mindset Apr 27, 2005 at 12:41 PM 25 replies 9k views
Original Post
The Forgotten Mindset
The Forgotten Mindset
Alright guys, I am making a 2d tile-based game using SDL for my C++ programming class, and I am currently designing the CSprite base class. So what is the best way to store animations for a sprite? I was thinking of storing it as text file:
WalkNorth:
	(0,0)(0,1)(0,2)(0,3)(0,4)(0,5)
WalkSouth:
	(1,0)(1,1)(1,2)(1,3)(1,4)(1,5)
WalkEast:
	(2,0)(2,1)(2,2)(2,3)(2,4)(2,5)
StandLeft:
	(2,0)(2,1)(2,2)(2,3)(2,4)(2,5)
Each coordinate pair represents a tile in the tileset where 0,0 is the first tile. What do you think? I've got till May 17 to get the game done, so the quickest method would be good to know.
The G'Bro GameDev Society! -The Southeastern US GameDev Gathering Group
peter_b
peter_b
A better way is to store the tiles number instead of its (x,y) coordinate in the tileset.
For instance, what if you wish to change tileset, but use the same animation? All creatures may have "walk", but they use diffrent art.

This would not work with your approach if the tilesets dont look exactly the same. For instance, the tileset for "squirrle" is only 32x32 big per tile and all tiles fit on one single row in the image. While the "knight" tile is 256x256, and the tileset image has 4 rows and 3 columns or something.

Instead just save the tiles number, and calculate the position with:
x = (int)(number / num_rows_of_this_tileset);
y = number % num_rows_of_this_tileset;
(atleast i think it was like this)

And your animations look like this:
walk = 0,1,2,3,2,0,1;
Then it can be used with any tileset.


Another thing may be to save the number of millisecs that each frame should be visible. For instance if you have some spell casting animation where the character holds his arms up, you may want to display that frame for a longer period of time than the rest of the frames.


Hope this was of any help.

Shields up! Rrrrred alert!
The Forgotten Mindset
The Forgotten Mindset
Thanks peter_b, but I think I wasn't clear enough.

I don't have to calculate any coordinates, my CTileSet class does that already.
int x = 45;int y = 100;int tsRow = 0;int tsCol = 0;CTileSet tileset("graphics\tileset1.bmp");tileset.BlitTile(tsCol, tsRow, x, y);


That blits the the tile in the first row and first column in the tileset onto the screen at 45 and 100.

But I was considering what you said about having a specified time period for each frame, the other option would to type the same frame multiple times (kinda ugly though).

Example with miliseconds per frame:
WalkNorth:         (0,0)15,         (0,1)2,         (0,2)4,         (0,3)9,         (0,4)5,         (0,5)5,


(number next to coord pair is the miliseconds per frame)

How 'bout that?
The G'Bro GameDev Society! -The Southeastern US GameDev Gathering Group
H_o_p_s
H_o_p_s
I have mine like this:
//THIS IS JAVAclass animationData {   int dmx; //CHANGE IN MAP POSITION AFTER ANIMATION IS DONE   int dmy;   int[] x,y,t,s; //Map_x, Map_y, Pixel_x, Pixel_y, Time in ms, Sprite cache key}
For Example:

dmx = 0;
dmy = -1;
x = {0,2,4,6,8,10,12,14,16,18};
y = {0,1,2,3,4,5,6,7,8,9};
t = {10,10,10,10,10,10,10,10,10};
s = {1,2,3,4,5,4,3,2,1};

Makes the animation go 'south' with 9 frames of animation, and then moves the character y-1 after the animation is done...

Your needs are probably different though...
BRING BACK THE BLACK (or at least something darker)
The Forgotten Mindset
The Forgotten Mindset
Ooh, I like your approach h_o_p_s. ([lol] -inside joke)

But I don't wan't to hardcode the animations, nor use a binary format, I want as much flexibility as possible.

How's this for a text file:

// Guy.txtWalkSouth {	dmx =  0;	dmy =  1; 	// tile coordinates (not cartesian)	x   = {0,1,2};	y   = {0,0,0};	t   = {5,5,5};}StandSouth {	dmx =  0;	dmy =  0;	x   = {3,4};	y   = {0,0};	t   = {7,8};}


Not much different from the source I know, but it looks cool!

One question though, how will this individual frame timing system affect non-fixed game loop frame timing?

oh, h_o_p_s, it looks like you put 1 too many numbers (10 as opposed to 9) in your x and y array, or was this intentional?
The G'Bro GameDev Society! -The Southeastern US GameDev Gathering Group
H_o_p_s
H_o_p_s
It is intentional. The first in the xy is the position when the Animation is not animated. This way I can define an animation and turn it on and off and still have control over the graphics.
BRING BACK THE BLACK (or at least something darker)
barakus
barakus
Why not have rectangles representing the dimensions and position of the frame?
With a rectangular array the size of the animation, you can quite easily store the information needed for animation. Say something like this:
RECT* frames = new RECT[numberOfFrames];if(nextFrameHorizontal){  for(int i = 0; i < numberOfFrames;i++)  {    frames.top = topOfFrameY    frames.left = topOfFrameX *i;    frames.right = frames.left + frameWidth;    frames.bottom = frames.top + frameHeight;  }}else if(nextFrameVertical){  for(int i = 0; i < numberOfFrames;i++)  {    frames.top = topOfFrameY*i;    frames.left = topOfFrameX ;    frames.right = frames.left + frameWidth;    frames.bottom = frames.top + frameHeight;  }}


There are a few potential problems you may have with this approach, mainly that the frames need to be next to each other either vertically or horizontaly for this to work.The size of each frame must also be the same.
The Forgotten Mindset
The Forgotten Mindset
Thanks barakus, but that kind of limits flexibility.

I want to be able to splice lots of different frames together to make new and crazy animations (like in Chrono Trigger, when you dance).

Also keep in mind that I am simply asking for a method of which to store animation data, not tile coordinates data or blitting, I've already got that down with my tileset class.

I'm also doing pixel by pixel movement and collision, so I'll replace the 'change in map position' variables with 'change in pixels' variables.

// Guy.txtWalkSouth {	dpx =  0;	dpy =  15; 	// pixel coordinates (not cartesian)	r   = {0,1,2};  // tileset row	c   = {0,0,0};  // tileset column	t   = {5,5,5};}StandSouth {	dpx =  0;	dpy =  0;	r   = {3,4}; // has an idle, subtle breathing, frame	c   = {0,0};	t   = {7,8};}


Oh, and I understand that the milliseconds per frame system would not complicate my non-fixed game loop speed. (milliseconds is constant, fps isn't, duh)

I'm pretty pleased with this approach, but I'd still like to hear some other ideas before I get too far in my code. [grin]

EDIT: Changed x and y in the text file to r and c. It just makes more sense for my use.

[Edited by - The Forgotten Mindset on April 28, 2005 12:01:05 PM]
The G'Bro GameDev Society! -The Southeastern US GameDev Gathering Group
Tarviathun
Tarviathun
My suggestion, if you're just wondering about storing data, would be to use a simple XML format and TinyXML(link: http://www.grinninglizard.com/tinyxml/) to input it. XML is easy to read, TinyXML is really easy to use. It took me about 20 minutes to get it up and running with a basic format(for storing my characters). that would be my suggestion. If you don't want to take the time, what you have seems to be fine in my opinion.

NOTE: I'm not the best at this. As of yet, I haven't completed a full and working 2D tile engine(*tear*) I've tried like hell, though. I keep on getting too bogged down with small features that I really shouldn't be thinking about. So yeah, I'm not the best reference for this, but there's my 2 odd yen.
EDI
EDI
I concur, we use XML for storing most of our data, and it makes for a very uniform and extensable data structure, which provides hierarcial relation data as well as Tag->Parameters type data.

H_o_p_s
H_o_p_s
JUST SAY NO TO XML. Not that it isn't great in some cases, BUT I think that you should not have it in a human readable format at all. Create a small application that makes your serialized animation files. This way you can have little archives of a whole bunch of animations. You could even include the graphics in the archive also. By including the graphics in the archives you also make it so if other people create resources, there aren't any problems that arrise with missing graphics etc... You could also include default stats...

PC001.fma      //Forgotten Mindset's Animation File -WALK_NORTH      //Individual animations for the character  -WN001.png         //Graphics needed for the animation  -WN002.png  -WN003.png -WALK_EAST -WALK_SOUTH -WALK_WEST -STAND_NORTH -STAND_EAST -STAND_SOUTH -STAND_WEST[optional] -EQUIPMENT_DEFAULT //The Default equipment list  -Sword+9999          //Individual items  -Potion+9999 -STATS_DEFAULT     //The Default stats of the Character  -NAME: H_o_p_s  -HP: 9999  -MP: 9999  -STR: 9999  -INT: 9999
The small Animation resource file would essentially make all human readable, and make it so there would not be any incorrect animation files... But if you want it able to be read by humans in a text editor... well, to each their own [smile]
BRING BACK THE BLACK (or at least something darker)
The Forgotten Mindset
The Forgotten Mindset
Well that's a good idea h_o_p_s, but I don't want to take the time to make a tool, instead I want my artist (or story guy) to define animations and stuff, therefore human-readable is the way to go.

I don't like the look of xml any more than you do, but I've got time constraints, so the easiest/fastest method is what I should use (beware of the feature creep)

I was torn between xml or my own text format, but then I realized that I could store everything about a character in an xml file, not just animations. That would take care of other problems too:
<Character name="Guy">	<Stats>		<hp>50</hp>		<mp>50</mp>		<maxhp>55</maxhp>		<maxmp>55</maxmp>		<strength>50</strength>	</Stats>	<Inventory>		<Weaponds>			<Sword equip="true">Broad Sword</Sword>			<Bow equip="false">Long Bow</Bow>		</Weaponds>		<Armor>			<armor equip="true">Leather Armor</armor>			<armor equip="false">Chain Mail</armor>		</Armor>		<Potions>			<Cheeseburger count="3"/>		</Potions>		<Items>			<key lockId="26">Secret Key</key>		</Items>	</Inventory>	<Animations>		<WalkNorth>			<dx>0</dx>			<dy>-15</dy>						<r>0</r>			<r>0</r>			<r>0</r>			<c>0</c>			<c>0</c>			<c>0</c>			<t>30</t>			<t>30</t>			<t>30</t>		</WalkNorth>	</Animations></Character>


My organization probably sucks, so for you xml guys, let me know if there are some tips you'd like to give.
The G'Bro GameDev Society! -The Southeastern US GameDev Gathering Group
EDI
EDI
Quote:
Original post by H_o_p_s
JUST SAY NO TO XML. Not that it isn't great in some cases, BUT I think that you should not have it in a human readable format at all.


I would have expected better from you =/

It is common when developing somthing, to change the data format, and in the case of using binary files you are looking for trouble.

example1: I need to add a field to my animation file

XML: simply add the field and query for it in the loader

Binary: modify the loader, and create a compatibility loader to convert all files that use the old format

IMHO, the 'smartest' way to develop things, is to use a textual type file (xml for instance) for most files (except thing that are very very huge to implement in XML, like, maps.) and then use some type of packed-archiver, to put all of the files into a single binary (and perhaps zip them), this makes development easy, and makes this non-human readable.
benishor
benishor
I have a few classes dealing with sprites : Rect, Texture, ImageObject, SpriteFrame, SpriteData and eventually the Sprite class.

- a Rect simply defines a rect in a 2D space ( texture space )
- a Texture loads a texture and provides informations about the size of the texture, etc.
- an ImageObject has a definition file that links certain Rects to a texture ( these actually define the drawable part of the sprites within a texture )
- a SpriteFrame defines ( as the name implies ) a sprite frame. It has assigned an ImageObject and a rect index so that it will know what source rect of what texture to draw
- a SpriteData has a collection of SpriteFrames ( for animated sprites ). Its definition file ( text based ) tells it what frames is the animation consisted of, what the delay between the frames is and what kind of animation does the sprite data have.
- a Sprite has a reference to a SpriteData object ( served by the asset manager so it can be cached ) and it has its own attributes, such as : current frame index, elapsed time, etc ..

as for the actual storage I am using plain text files that are easy to modify and that allow me to test whatever I have in mind without having to recompile everything.

If you really want to use binary data in order to store your sprites and stuff, make sure you only use it when your game is not subject to change anymore.
---novocaine thru yer veinz
The Forgotten Mindset
The Forgotten Mindset
Yeah, benishor, I realized that I need a Rect object for each sprite in order to perform collision detection.

Even though I am using pixel perfect collision, I still need a rect because some of the sprite is supposed to be overlapped by other sprites (feet, for instance).

But this will be easy to add on thanks to TinyXML! :)

Thanks again guys [smile]
benishor
benishor
what method are you using for doing pixel perfect collision ? sprite masks related, obviously.

of course, a bbox check would greatly increase collision test speed before testing for pixels. in my project I'm thinking of using a poly based collision hull, tho.
---novocaine thru yer veinz
The Forgotten Mindset
The Forgotten Mindset
Hmm, actually, I think I should have said pixel perfect movement. I'm going to use tile-based collision for the most part (sprites, walls, ect).

And forget what I said in that last post, I've already got rectangle data in my tilesets. [lol]
But I realize that I won't need them for that purpose anyways.

Ultimately, I want my game to play like Chrono Trigger and Secret of Mana as far as character control is concerned. And I belive that those games do collision of the characters at their feet's rect, and the rest of the body just overlaps over what's behind them, so that's what I'll do.

But I still want to use pixel perfect collision for some environments like shorelines and cliffs (anywhere with rough boundries) though, but haven't decided on a method at this point. ;)
The G'Bro GameDev Society! -The Southeastern US GameDev Gathering Group
Tom
Tom
I'd recommend going the extra mile and building a WYSIWYG editor that doesn't require *any* typing (except perhaps to name files before saving them). As for your storage format, you should stick with something readable during development. Prior to publication, you can swap your file loader out for a binary version and batch-convert all your data files. (I don't really see the point. The life cycle of a game is directly related to how modable it is, and if someone wants to edit your data, they'll make a tool to do it.)
GDNet+. It's only $5 a month. You know you want it.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.