Advertisement

Data Structures for character animation

Started by March 24, 2000 05:12 AM
32 comments, last by Kylotan 24 years, 8 months ago
quote: Original post by Possibility

Oh, if you want to add a whole new unit type, that would be near impossible. Because for me, I give the calvary bonuses and stuff based on what unit type it attacks, and defensive bonuses, charging, order of movement ect.., making a program so general enough to be able to add all that into a text file without need of recompiling would a severe pain in ass and to just to nasty to warrant its use.


I have to disagree with this. I already have half of this working already. It''s mainly a problem where the added complexity of the animation meets the added complexity of the dynamic type-generation, and that complexity squared messes with my brain

quote: I guess you will have to just think of all the types/modifiers/stats you want to be able to include before hand, and then limit the it to just them.


Well, let''s take a Civ clone, or something similar... you will likely have something which is like:

// Stats for a unit, with values duplicated from some hard-coded source
class Unit
{
int attack;
int defence;
};

So, instead of storing these values with each unit, we grab the values from the corresponding unit type. One way would be to set up the correct pointer:

// Stats for all instances of this type
class Unittype
{
String name; // eg. "Pikemen", "Archers"
int attack;
int defence;
};

// Stats for a single instance
class Unit
{
Unittype* my_type;
int GetAttack() { return my_type->attack; }
int GetDefence() { return my_type->defence; }
};

This saves memory too (not storing redundant variables with each instance). All that then has to be written is a Load function that loads in the attack and defence values into the Unittype class. You can extend this to movement rate, ability to fly, ability to cross water, etc etc, providing you know all these variables and flags beforehand, as you said. Regarding giving attack bonuses, instead of looking at the specific case (cavalry get bonuses against a certain type of opponent), you can generalise it. One way, and the way I would do it, would be to add two booleans for each special ability, eg:

bool HasFastAttack;
bool SusceptibleToFastAttack;

So, your combat routine would have a check that goes something like:

if (attacker->HasFastAttack && defender->SusceptibleToFastAttack)
// give attacker a bonus

That way, you can add more units that have fast attacks, and more units that are susceptible to that kind of attack, without ever touching that part of the code again. This much is straightforward. Loading animations in is a little more tricky, as there are unspecified numbers of frames per state, unspecified numbers of states per unittype (in some systems, anyway - a Civ-like game would mainly just have units sat there, I guess), etc etc. And since I am no animation expert I don''t even know what the best way to do conventional animation is, never mind animation generated dynamically from files. *sigh*
Kylotan: The method you''re describing (storing the creatures with pointers to their creature types) follows a pattern known as Type Object, which is a very solid pattern for many situations, including this one IMO. Type Object uses separate objects which describe the type of an object in a manner beyond that of its intrinsic class object (i.e. not just the layout of the class and its methods etc, but actual general type information). It often works quite well, and is usually a decent system when handling game entity logic like this. I''d say stick with it.
Advertisement
quote: Original post by Chris Hargrove

Kylotan: The method you''re describing (storing the creatures with pointers to their creature types) follows a pattern known as Type Object, which is a very solid pattern for many situations, including this one IMO.


Yeah, I''ve come across the ''Type Object'' concept before, but never really tried to implement it properly. It does what I want it to, it just gets a little unwieldy for me However, I will stick with it, so I just have to figure this animation stuff now
Kylotan,
I''ve work on projects which use an animation-frame activated system and the inverse (animation activated on action).
You want to develop a system which will work equally well in both a RTS and turn based system. Unfortunately the two are geared towards different systems.

In a RTS, one usually interupts the current animation when a new action is taken, as feedback generally needs to be immediate. Usually this means that actions have two states, initiated and complete. The action complete does not key until the animation is done, i.e. if you interupt a swordsman half-way through his swing, he will not hit. Or there is an "activate on" frame which calls the complete action routine.

In a turn-based system one does not usually worry about this and takes/resolves input only when current actions are complete. Of course this can be taken as a subset of the RTS model. Simply have a BOOL which stores a "taking input" state, either as a general game-state or on a per-unit bases. This is always or almost always on in a RTS, but can selectively be disabled for the turn-based system.

How to handle variable frame rates?

My background is actually film animation, so I think in terms of 24 frames per second. I usually extend this to 32 cycles per second when working on games. (television of course animates at 30fps)

So my main game loop attempts to call 32 updates a second.
You can limit animation to an even divisor of this (2,4,8,16,32) fps rather easily. Or get the closest approximation the selectively add cycles to a given frame. If an update takes longer than a 1/32 of a second I skip frames.

example: if an animation has 8 frames/sec, each frame has lasts four cycles before advancing.

if a frame has 7 frames/sec, each frame lasts a base 4 cycles per sec. there are 4 "leftover" frames in this case.
So frame 1 takes 5, frame 3 takes 5, frame 5 takes 5, and frame 7 takes five cycles. How you calculate which frames to add cycles to varies, but try to keep them non-consectutive. This is very similar to how film (24 fps) is mapped onto tv (30 fps). I find it works well for me.

This assumes that for whatever reason you want to sync animations on a per second basis. This may not be the case. If not then simply store a cycles/frame number. I find thinking in frames or cycles to be more useful than thinking in terms of milliseconds.

Incidently the only games which I''ve seen and tested which frame rates over 32 fps make an actual visual and gameplay difference are _very_ fast paced shooters. Most film and television animated leave pictures up for two frames so runs at 12 or 15 fps respectively.

hope this helps.
regards,
thathmew



mat williamsLead Programmer, DesignerZero Sum Softwarewww.zero-sum.com
quote: Original post by Thathmew

Kylotan,
I''ve work on projects which use an animation-frame activated system and the inverse (animation activated on action).
You want to develop a system which will work equally well in both a RTS and turn based system. Unfortunately the two are geared towards different systems.


Well, I can live with that, providing I can separate the common parts from the different parts so I am only reimplementing half of it.

quote: In a RTS, one usually interupts the current animation when a new action is taken, as feedback generally needs to be immediate. Usually this means that actions have two states, initiated and complete. The action complete does not key until the animation is done, i.e. if you interupt a swordsman half-way through his swing, he will not hit. Or there is an "activate on" frame which calls the complete action routine.


So, the way it works, is that the input event is received, which sets the character''s state... animations are done based on that state, and the animation is checked to see if it is the ''activate on'' frame, upon which the action associated with that state will trigger? If so, that makes sense, and was how I thought it would be done, except I had envisaged the possibility of embedding actions with each frame in case they were needed.

quote: In a turn-based system one does not usually worry about this and takes/resolves input only when current actions are complete.


Right now, I am edging around this issue by having things happen instantaneously (ie. when you hit the ''up'' key, the character moves 1 tile north, no animation, no smooth sliding from one place to another). Otherwise I will have to be able to do things such as disabling the input, set the game state so that it knows it is meant to be moving a single character, etc, right?

quote: Of course this can be taken as a subset of the RTS model. Simply have a BOOL which stores a "taking input" state, either as a general game-state or on a per-unit bases. This is always or almost always on in a RTS, but can selectively be disabled for the turn-based system.


Yeah, I see that, but I wonder how to handle that transitionary phase (example: in Civilisation when your unit is moving from one square to another, or when it is in combat). Right now, my system handles all logic in that frame - doing something like you describe will require some way of running these things asynchronously, no?

quote: So my main game loop attempts to call 32 updates a second.


My general frame rates for my tilebased game are in the 40 area. (Which is pretty bad, I figure, but there you go.) So I suppose I could slow it down further without too much trouble - after all, it is generally a still image and only FPSs really need faster frame rates.

quote: You can limit animation to an even divisor of this (2,4,8,16,32) fps rather easily.


Which is the lowest number of frames per second, in your experience, that gives acceptably smooth animation for a game? Having a fixed duration per frame could simplify my code a little (and also the tool I will have to make) but I don''t want it to have such slow resolution that it can''t look vaguely realistic.

quote: This assumes that for whatever reason you want to sync animations on a per second basis. This may not be the case. If not then simply store a cycles/frame number. I find thinking in frames or cycles to be more useful than thinking in terms of milliseconds.


Well, I was trying to get it so that the animation was framerate independent. Maybe for a 2D top-down game it''s not worth the bother. But what if there is a machine that runs too slowly to keep up? I''m still gonna have to keep an accurate timer and pass it to the animation so that it knows whether we took too long, right? And skip frames (while taking care not to skip the associated state-changes) based on that, too.

One thing that interests me is how people synchronise movement to animation. In the Kawick book, he mentioned associating a movement vector with each frame of animation, I think. Obviously this would look the most realistic, but it would certainly require either a fixed frame rate to work well, I''d have thought.

Anyway, thanks for your input, much appreciated.
Kylotan, what you said about the bool HasFastAttack and bool SusceptibleToFastAttack is your unit and unit_type classes is EXACTLY what i described.

How, I called my HasFastAttack as Cavalry, and called the SusceptibleToFastAttack as Infantry. They are the exact same thing, but just different names.

I also dont think using pointers to point to a value in the unit_type isnt such a good idea. Although not storing the actual attack or defense value in the unit class for each unit will save memory, it doesnt allow for customization of the particular unit. For example, you may have certain modifiers acting on that unit that will alter its attack or defense values from the norm. If you store the attack value with each unit, then you only have to calculate once the effect the modifier will have on the attack value, and then store the new attack value. However, if you dont do that, then you will have to calculate the new attack value each and every time you need to use the attack value for that unit.

Granted, storing it with the unit class uses up alot more memory, but it has a great reduction on the processor requirements, and that is often more important then memory, considering most computers today have 64+ megs of ram. And when you get into 128 megs ram, then it becomes insignificant, leaving more processor space open which will allow for more animations and special effects ect... to be shown on the screen.

Also, if you want to include an Edit with your program, and the ability to create ''special'' units, like a normal swordsman that is like a local hero, and has slightly boosted stats. It will be alot easier to edit the stats of specific units if they are stored with the unit class.

Possibility
Advertisement
quote: Original post by Possibility

Kylotan, what you said about the bool HasFastAttack and bool SusceptibleToFastAttack is your unit and unit_type classes is EXACTLY what i described.

How, I called my HasFastAttack as Cavalry, and called the SusceptibleToFastAttack as Infantry. They are the exact same thing, but just different names.


Sorry, I thought you had one boolean value per unit type, and so therefore you wouldn''t have a unit where Cavalry and Infantry could both be true, for example.

quote: I also dont think using pointers to point to a value in the unit_type isnt such a good idea. Although not storing the actual attack or defense value in the unit class for each unit will save memory, it doesnt allow for customization of the particular unit.


You could store attack_bonus and defence_bonus in the individual unit. That way, you obviously lose the memory savings, but can give bonuses out as much as you like. Or do it the way Alpha Centauri does, which is just have a morale stat, which is a multiplier for the base stats - no ''bonus'' stats needed.

quote:
Granted, storing it with the unit class uses up alot more memory, but it has a great reduction on the processor requirements, and that is often more important then memory, considering most computers today have 64+ megs of ram. And when you get into 128 megs ram, then it becomes insignificant, leaving more processor space open which will allow for more animations and special effects ect... to be shown on the screen.


How often do you need to find out a unit''s combat stats? Let''s look at a Civ-like game... maybe once per 5 seconds. (Well, twice, since 2 units will be involved.) In an RTS, it might be as much as 30 or 40 times a second... still, you would usuall draw the graphics more often than that, which would be far more processor intensive. So the CPU hit is minimal. However, memory limitations you always have to keep in mind. Remember that making your structures too large means they won''t fit in the cache (or fewer of them will), so you may lose mroe processing time there than you would by calculating the attack values each time you need them.

quote:
Also, if you want to include an Edit with your program, and the ability to create ''special'' units, like a normal swordsman that is like a local hero, and has slightly boosted stats. It will be alot easier to edit the stats of specific units if they are stored with the unit class.


Two ways I could get around this:
1) I am storing the CreatureTypes, UnitTypes, whatever you want to call them, in a file to be loaded in at runtime. This file would be available to the editor - you could then easily duplicate a type, modify it, and save it out as a another type.
2) If you just want to represent ''heros'' or the like, you could choose to create a unit with a higher morale than usual. Or set a ''hero'' flag which anyone can have, like Civ has a veteran flag.

Thanks for the comments
Well, you can do it anyway you want, I will choose the simplest programming way, and I know my engine runs really fast right now, so I dont care to much if I use up loads of memory, hehe, but it seems we are basically making the same thing, and we should compare our code again soon.

I am also really interested in the initial question about the animations. If you figure out a way to do, drop me an email please.

Possibility
Um, instead of having multiple inheritance etc, just do the following:

typedef struct
{

BITMAPINFO picture;

} anim;

struct character_typ
{

// Whatever else you need

anim *next;

} character;

Well, thats the code in C, but you get the idea. Then just fiddle around with linked list functions and it will allow numerous pictures loaded and no set limit.

quote: Original post by Anonymous Poster

Um, instead of having multiple inheritance etc, just do the following:



Well, I wasn''t using multiple inheritance for the animations. Just composition, if you want to use OO terminology. My CreatureType class contains the animations for all instances of that Creature, who get to those animations through their pointer to the CreatureType.

The set limit is not the problem I have. It''s how to use the variable sized lists effectively that is the issue.

A simple linked list of images for a character''s animation is too simple for my needs. I want to know the animation runs at about the same speed on all computers. I want a different animation for each action for each direction of travel for each type of character or object in the game. I want to be either able to synchronise an action to the animation or the animation to the action (detailed above). I can see ways of doing all these things, but they seem to involve inelegant hacks and therefore I am intrigued as to whether anyone had some ''good'' answers. (Judging by the animation code in Mickey Kawick''s book, if that is ''professional'' quality, then I''m guessing no, animation is one big hack )

This topic is closed to new replies.

Advertisement