old school programmatical animation

Started by
10 comments, last by bluntman 15 years, 4 months ago
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 :)
Advertisement
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.
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.
Keyframing is not simply "moving an object". It is the mechanism used for most types of animation (e.g. skeletal animation, Flash web animation) and would allow you to do what you say.
http://en.wikipedia.org/wiki/Keyframe#Animation_by_means_of_computer_graphics
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.
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.
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?
Create-ivity - a game development blog Mouseover for more information.
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.
#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 timestruct 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-framesstruct 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 coordinatestruct 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]
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.

This topic is closed to new replies.

Advertisement