Sign in to follow this  

old school programmatical animation

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

In learning to program games, iv come to find animation being much more simple to make interesting when using a scripting language. As these usually make us of some kind of multithreading/VM it makes animation timing more easily achieved by running a script in the background to control the entity. But iv working to write a small game that seems too small to really add a scripting language to. My question is, whats the best way to be able to move objects around? To simply move a block of a text object onto screen and wait a few seconds before moving off seems difficult to achieve without freezing execution of the game to only that animation. It would seem that i would almost have to make a new class for every kind of animation i would want to achieve, in order to write a separate update routine. This may well be the case and if so i feel sorry for programmers who had to do it like this, and i will graciously take the time to add in a simple scrip language into all future game projects :) This might be a ridiculous question to ask, perhaps im totally missing something that makes this very simple, i claim ignorance if that's the case :)

Share this post


Link to post
Share on other sites
If I understand correctly, you are probably looking for keyframe animation.
Basically every value you want to be animatable has keyframes associated with it where a keyframe consists of a time T and a value V, indicating that at time T the value is V. You then use interpolation to calculate the value between adjacent keyframes.

Share this post


Link to post
Share on other sites
I understand the idea behind simply moving an object. but what about moving it it two directions, like it moves into the center from the top, waits there for a few seconds, and then moves back out.

Share this post


Link to post
Share on other sites
hmmm so, basically, unless i add in scripts which control my objects in a threaded type of way(literally moving my objects around), i would be forced to create complete frame by frame animations to do something such as having "YOU WIN!", float in the center and then fade away after a second. From looking around some more and after what you said im beginning to think its actually much easier to simply add scripting functionality if i plan to move things such as particle effects around.

Share this post


Link to post
Share on other sites
NO! Keyframe is NOT frame by frame. You would only need to add 4 key frames to do the animation you describe. Much easier than scripting it in my opinion.
Try using some animation packages (2D or 3D) and you will understand what I mean.
/edit
Particle effects are generally not done using keyframing, but are animated using a single algorithm (or set of algorithms) with a set of parameters (e.g. wind direction, gravity, fade speed, etc). These could be scripted, but that is probably overkill.

Share this post


Link to post
Share on other sites
Quote:
Original post by schragnasher
My question is, whats the best way to be able to move objects around? To simply move a block of a text object onto screen and wait a few seconds before moving off seems difficult to achieve without freezing execution of the game to only that animation.

I think you're missing something here. You don't need threading for animations. You don't need to freeze an application to wait for something. Why do you think so?

Quote:
It would seem that i would almost have to make a new class for every kind of animation i would want to achieve, in order to write a separate update routine. This may well be the case and if so i feel sorry for programmers who had to do it like this, and i will graciously take the time to add in a simple scrip language into all future game projects :)

What's the problem with that? Writing such classes would perhaps take a few hours, that's all. After that, you can easily reuse them. Of course, you want those animations to be data-driven, but when you take care of that, I really don't think there will be so many different kinds of animations.

But, you seem to think it's unwieldy, so you're probably doing something inefficient here and there. Perhaps you can show us some code or explain your ideas in more detail so we can give you some more specific tips?

Share this post


Link to post
Share on other sites
I definitely wouldn't put it past me to be missing the bus here lol so ill try to explain myself better. And i appreciate the help.

I have a generic text object. It's basically just a text box that...displays text. I have a number of different texts that i will create. Each one will have a separate movement animation it needs to follow.

move to x,y
pause
move to x,y

Obviously i cant just make a function that completes this animation in full, so i need it to complete in increments as my game loops. Using a form of scripting/threading i could create this as a script fairly easily.
Without scripting i would seem to need to make a new type of text object simply for creating this movement. Am i being too generic with my objects? What if i need a new one that has three targets? Do i need to create another class that can move three times? Alot of 2d animation tutorials iv looked at seem to only cover using multiframe animation strips to change sprite textures to create movement. But i want to move my actual objects.

Do i make a new class, called animation? So i create a gameobject that takes another gameobject pointer and a movement target? Perhaps even a pause before movement starts. This is added to my object list and updated each frame, it then is what actually moves my objects. I could have a move animation, and a fade animation even using them at the same time. lol sorry for the brain dump, just thinking out loud.

Share this post


Link to post
Share on other sites

#include <vector>
#include <string>
#include <iostream>
#include <time.h>

// sorry had to include this to get easy access to the Sleep method, but one could easily be made
#include <windows.h>

// class representing a value at a moment in time
struct KeyFrame
{
float t;
float val;

KeyFrame(float t_, float val_) : t(t_), val(val_) {}
};

// class containing an animated value represented as a set of key-frames
struct Animation
{
std::vector<KeyFrame> keys;

void add_key(const KeyFrame& key)
{
keys.push_back(key);
}

// return a value for time t, interpolating between keys
float get_val(float t) const
{
// if there are no keys return default value
if(keys.size() == 0)
return 0.0f;

// if there is only one key then this is the value
if(keys.size() == 1)
return keys[0].val;

// if time is before time of first key then return first key's value
if(t <= keys[0].t)
return keys[0].val;

// if time is after time of last key then return last key's value
if(t >= keys[keys.size()-1].t)
return keys[keys.size()-1].val;

// otherwise find the keys before and after the time, and interpolate between their values
unsigned int prevKey = 0;
for(; prevKey < keys.size() && keys[prevKey].t < t; ++prevKey) {}

// calculate the fraction between the keys
float tFrac = (t - keys[prevKey-1].t) / ( keys[prevKey].t - keys[prevKey-1].t);
// use the fraction to calculate the value we should return
return keys[prevKey-1].val + tFrac * (keys[prevKey].val - keys[prevKey-1].val);
}
};

// a simple demonstration class with an animatable x and y coordinate
struct AnimatedTextBox
{
private:
Animation xAnim, yAnim;
std::string text;
float time_offs;
public:
AnimatedTextBox(const std::string& text_) : text(text_), time_offs(0.0f) {}

void add_key(float t, float x, float y)
{
xAnim.add_key(KeyFrame(t, x));
yAnim.add_key(KeyFrame(t, y));
}

void start_anim(float t)
{
time_offs = t;
}

void draw(float t)
{
float x = xAnim.get_val(t - time_offs);
float y = yAnim.get_val(t - time_offs);

//drawImpl(x, y, text.c_str());
std::cout << "<" << x << "," << y << "> " << text << std::endl;
}
};

int _tmain(int argc, _TCHAR* argv[])
{
AnimatedTextBox tbox("Its game over man, GAME OVER!!!");

// add keys at 0s, 5s, 10s and 15s
// starts at the top of the screen
tbox.add_key(0.0f, 0.0f, 0.0f);
// moves to the 'middle' over 5 seconds
tbox.add_key(5.0f, 0.0f, 10.0f);
// stays in the 'middle' for 5 seconds
tbox.add_key(10.0f, 0.0f, 10.0f);
// moves back to the top for 5 seconds
tbox.add_key(15.0f, 0.0f, 0.0f);

bool playing_game = true;

// your timing function should be used here, 1 sec accuracy is not enough for animation!!
time_t start_t = time(NULL);

// set the start time for the animation
tbox.start_anim(5.0f);

// this is your main game loop, standard update and draw loop
while(playing_game)
{
// your timing function should be used here, 1 sec accuracy is not enough for animation!!
float curr_t = static_cast<float>(time(NULL) - start_t);

// update and draw are rolled up into one function here, but could easily be seperate
tbox.draw(curr_t);

if(curr_t > 20.0f)
playing_game = false;

// a delay to stop undue screen scrolling!!
Sleep(500);
}

return 0;
}



I'm in work so its no master piece, but it took all of 15 minutes. You can animate any value using this method.

/edit
A couple of things to bear in mind:
The interpolation above is linear, you can get nicer results using other types of interpolation, and you are best off abstracting the interpolation method so you can easily change it, even between keys. Some other types of interpolation: Tension Continuity Bias: a very powerful interpolation method, used in 3DS MAX and most other animation programs.
Stepped: simply use the value from the previous key, good if the object should only appear in discreet positions.
Hermite: interpolation based on the Hermite spline.

Also you should not (generally speaking) use float as a representation of time (I was too lazy to typedef the time in above), as it is inherently inaccurate. Better off using 64bit ints.

If you want to keep animation code and your 'objects' (e.g. text box) seperate, you would need to write code to stitch them together:

struct TextBox
{
float x_, y_;
std::string text_;
// methods
void set_pos(float x_, float y_)
};

struct AnimPosition2D
{
Animation x_, y_;

void add_key(...) {...}

float get_x(time_type t) const { return x_.get_val(t); }
float get_y(time_type t) const { return y_.get_val(t); }
};

void update_textbox(TextBox& textbox, const AnimPosition2D& anim, time_type t)
{
textbox.set_pos(anim.get_x(t), anim.get_y(t));
}





[Edited by - bluntman on December 8, 2008 9:36:26 AM]

Share this post


Link to post
Share on other sites
Ok great thanks bluntman, that helps me understand the relationship between the object and the animation alot better. So i could use the animation class to animate any value i setup inside my base object class. giving all my derived objects the ability to animate those values.

Thats exactly what i was searching to find. Especially the ideas behind multiple keyframes. thanks.

Share this post


Link to post
Share on other sites
@bluntman: while the idea behind your code is useful, I don't think inheriting from Animation is the best approach here. After all, a textbox is not an animation, it can be animated.


My suggestion would be to let textboxes and other visual objects inherit from an abstract base class that provides an interface to set positions and perhaps also rotation, scaling, or whatever makes sense for this game. Animation objects then store a pointer to such an animateable object. This enables you to use the same animation code for multiple types of objects, and also to build different animations, derived from a base Animation class, that perform different kinds of animations on their target objects. Two hierarchies that play nice together.

With a scene-node approach for the visual objects, it's also possible to animate groups of objects by animating the parent node (an alternative would be to give Animation objects a list of targets, rather than a single target). And with a bit of work, you could also write a stackeable animation system (multiple animations that operate on top of each other). Of course, only put in effort in these things if it's actually needed. :)

Share this post


Link to post
Share on other sites
I didn't inherit from Animation, I used composition, which for a simple example makes sense. I didn't want to clutter code meant to demonstrate how Keyframe animation works with other design details. I wouldn't expect this to be copy and pasted!

Share this post


Link to post
Share on other sites

This topic is 3294 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.

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