322 7. The Game Loop and Real-Time Simulation
7.5.6. A Simple Clock Class
Some game engines encapsulate their clock variables in a class. An engine
might have a few instances of this class—one to represent real “wall clock”
time, another to represent “game time” (which can be paused, slowed down
or sped up relative to real time), another to track time for full-motion videos,
and so on. A clock class is reasonably straightforward to implement. I’ll pres-
ent a simple implementation below, making note of a few common tips, tricks,
and pitfalls in the process.
A clock class typically contains a variable that tracks the absolute time
that has elapsed since the clock was created. As described above, it’s im-
portant to select a suitable data type and time unit for this variable. In the
following example, we’ll store absolute times in the same way the CPU
does—with a 64-bit unsigned integer, measured in machine cycles. There
are other possible implementations, of course, but this is probably the sim-
plest.
A clock class can support some nift y features, like time-scaling. This can
be implemented by simply multiplying the measured time delta by an arbi-
trary scale factor prior to adding it to the clock’s running total. We can also
pause time by simply skipping its update while the clock is paused. Single-
stepping a clock can be implemented by adding a fi xed time interval to a
paused clock in response to a butt on press on the joypad or keyboard. All of
this is demonstrated by the example Clock class shown below.
class Clock
{
U64 m_timeCycles;
F32 m_timeScale;
bool m_isPaused;
static F32 s_cyclesPerSecond;
static inline U64 secondsToCycles(F32 timeSeconds)
{
return (U64)(timeSeconds * s_cyclesPerSecond);
}
// WARNING: Dangerous -- only use to convert small
// durations into seconds.
static inline F32 cyclesToSeconds(U64 timeCycles)
{
return (F32)timeCycles / s_cyclesPerSecond;
}