Games are packed with movement. Characters running here, bullets flying
there−basically there's a slew of objects moving about your game world. The
smooth motion of these objects is a very important aspect that can't be
overlooked. Have you ever thought about the use of movement and animation based
on time? Using time−based motion is hot, and to keep up with the rest of the
world you must fully understand how it can help your game project. In fact, you
need to understand not only using time−based motion, but also motion in general.
Do you think only characters move about in your game? Nope, your in−game
cinematic cameras need your guidance as well.
Using Time−Based Motion
Although it might not seem important at first, timing plays a crucial role in
your game projects. I'm not talking about the time of day; rather, I'm referring
to down−to−the−millisecond timing of animation. This sort of precise timing is
required for smooth animation and movement of objects in your project. Although
it is a basic topic, it is one that all game programmers should understand quite
well.
When it comes to moving your meshes, time−based motion is the best of the
bunch.
The whole basis of using time−based motion is simple−movement and animation
always take the same amount of time to perform on any system, regardless of the
computer's actual speed. For example, a 2−GHz system processing a 20−second
animation will undoubtedly do so quickly and produce a very smooth motion,
whereas the same animation running on a 500−MHz system will be choppy but will
still maintain the 20−second animation length.
More than likely, the slower computer will drop specific frames of the
animation to keep up with the speed of the faster computer. Therein lies the
secret−slower computers can drop more frames and still maintain a somewhat
reasonable representation of the actual motion.
Okay, I think you're starting to get the idea. As simple as the techniques
sound, time−based animation and movement remain a slight mystery to fledgling
game programmers. For that reason, I want to introduce (or re−introduce) you to
the world of time−based motion. I'll start with a brief look at reading time in
Windows.
Reading Time in Windows
The easiest method of reading time in Windows is by using the timeGetTime
function. This function does not take any parameters. As the following code
demonstrates, timeGetTime only returns the number of milliseconds that have
passed since Windows was started.
DWORD TimeSinceStarted = timeGetTime();
What good does this do you? Typically, you call the timeGetTime function once
per frame that your game processes. For each frame, you then subtract the time
from the last frame processed to obtain the number of milliseconds that have
elapsed since your last frame. You can use this elapsed time to compute your
time−based motion.
Storing the time of the last frame update is as easy as using a static
variable. At the beginning of your frame's update function, insert a static variable that stores the current time.
void FrameUpdate()
{
static DWORD LastTime = timeGetTime();
At the end of the FrameUpdate function, you can then store the current time
in LastTime.
LastTime = timeGetTime();
In this manner (storing the current time at the end of your frame's update
function), you have managed to store the time at which the frame update ended.
During the next call to FrameUpdate, the LastTime variable will still contain
the time at which the last frame update ended. Using this time value, you can
calculate the amount of time that has elapsed since you last called FrameUpdate
by subtracting LastTime from the current time.
DWORD ElapsedTime = timeGetTime() − LastTime;
Now what about those instances when you want to calculate the number of
elapsed milliseconds based on a specific time, such as when an animation starts,
instead of counting the elapsed time or when the FrameUpdate function was first
called?
Just as you used a static variable to store the last frame's update time, you
can store the time at which the function was first called. Using that static
variable, you can determine how many milliseconds have passed since the function
was first called.
void FrameUpdate()
{
static DWORD StartTime = timeGetTime();
DWORD ElapsedTime = timeGetTime() − StartTime;
// ElapsedTime is the number of milliseconds
that has passed since you first called FrameUpdate.
}
In the same way the previous bit of code tracked the total amount of time
that has passed since the first call to the FrameUpdate function, you can embed
the starting time of an animation inside your data structures.
Combined with key frames, time−based animation is a perfect solution for
creating smooth animation. Read on to take a closer look at using time−based
animation.