Creating a Game Timer

Started by
7 comments, last by matthughson 18 years, 11 months ago
Hey All, Just working on a new little engine, and I'm about to start making the timer classes. Traditionally what I have done is create a singleton that basically wraps the QueryPerformance functions. With that class, I do stuff like keep track of how much time passes between frames, and base movement/calculations/etc on that time. I also create a stopwatch class which has similar functionality, but works on an induvidual basis. For example, it would be used if a particle system needed to emmit for X number of seconds. The problem comes in stuff like pausing the game. With this setup I simply stop updating the main singleton timer, which in turn pauses all the stupwatch objects, who rely on the timer class for updates on the passage of time. I discovered though that this can cause problems, since when I pause, I really don't want everything to pause, as the pause menu and stuff like that still needs to be updated based on time. I got around this by adding a flag to my base class that basically said whether or not to stop updating when the timer stops. It was a pretty crude, and last minute fix, so I'm not very happy with the solution. So basically, I'm just curious as to how other people have handled timer classes in their own code. Matt Hughson
__________________________________[ Website ] [ Résumé ] [ [email=contact[at]matthughson[dot]com]Contact[/email] ][ Have I been Helpful? Hook me up! ]
Advertisement
Mine works much like yours. Except I get the timer values using the winmm.lib with timeBeginPeriod / timeSetEvent, etc.

I basically have two timers. The one that's updated all the time (unless the app tabs out), and one that game objects and physics use, which is converted to a float for math purposes. The float is the only one that becomes paused when menues pop up or other such in-game features. I also speed time up and slow it down with it. The integer version just keeps on going, though. All menu effects and non-worldly objects use the integer.

One thing I have learned while playing with timers is that it's always better to track the amount of time that is left rather than the amount that has passed. So if a stop watch records the time it started and keeps track of it's running time until it reaches it's limit, a better solution would be to set it to it's limit and count down to zero.

It helps with things such as the timer rolling over (rare) and saving to disk (not rare at all). It's also much cleaner to update.

edit: Actually, if your game is a long RPG, and you save your game world time to disk, the timer rolling over is not as rare.
Still looking for suggestions.

Matt Hughson
__________________________________[ Website ] [ Résumé ] [ [email=contact[at]matthughson[dot]com]Contact[/email] ][ Have I been Helpful? Hook me up! ]
In the past, I've used only the sort of thing you describe as a stopwatch class. [also counting down as Jiia suggests] Every frame, the project would check the time, and update the stopwatches. During the actual rendering/processing process, the objects that own the stopwatches would check [and perhaps re-set] them.

In the past, I've never had a pause implimentation because the game was turned based [and because ui objects don't need paused]. If I did, I would simply add a global and a check in the various stopwatch checks, or perhaps add a toggle to the stopwatch class.

In the future, I will likely move more towards a single timer setup.
I've don't think it's a good idea to stop the main game timer itself using a pause flag. I see it as the responsibility of the game using the timer to implement pausing, because, as you say, time stops for some components when a game is paused, and continues for others. Putting pause functionality in the main timer is just too general.

The only choice you really have in this situation is to use variables to dictate what should be updated with time when the game is paused, and what shouldn't...
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
I ran into the same problem some time ago and came ut with this simple but pretty handy solution.

I defined different parts of the program to be in different time spaces; different parts that were to percieve and be affected by the system time differently and independently from each other.

For example the interface was in one time space while the gameflow was in another.

Each of these time spaces had a float value associated to it which was called time scale. This value defined to what magnitude the parts in the time space would be affected by the flow of the system time.

For example the interface had a time scale of 1.0f and so had the gameflow initially. Then when I pressed the pause button all that happened was that the gameflow time scale was set to 0.0f instead, which effectively paused the gameflow without affecting the interface.

The code for this couldn't be simpler. Basically all you do is efery time you update something using the time difference between frames you also multiply that difference with the respective time scale value. Simple as that.

The real neatness with this is that you can use other time scale values than 0.0f and 1.0f for adjusting the game speed. You can create slow motion effects or, if you animate the time scale from 0.0f to 1.0f over a set time when you unpause you would get a "warm-up" effect that gradually speeds the game up to normal speed.

My guess is that similar approaches are used in many commercial games.

Regards.
Hack my projects! Oh Yeah! Use an SVN client to check them out.BlockStacker
I recommend using a hierarchy of timers.

struct I_Clock {  virtual Time time() = 0;};class PhysicalClock : public I_Clock {  virtual Time time() {    QueryPerformanceCounter( &ctr );    return TicksToTime( ctr );  }};class OffsetClock : public I_Clock {  virtual Time time() {    return offset_ + clock_->time();  }  void setOffset( Time offset ) {    offset_ = offset;  }  OffsetClock( I_Clock * clock ) {    clock_ = clock;  }};class PausableClock : public OffsetClock {  virtual Time time() {    if( paused_ ) {      return pauseTime_;    }    return OffsetClock::time();  }  void pause() {    pauseTime_ = time();    paused_ = true;  }  void unpause() {    assert( paused_ );    offset_ = pauseTime_ - clock_->time();    paused_ = false;  }};


You can also build clocks that affect time by making it pass slower/faster, if you want to be fancy. Build a hierarchy of clocks, something like:

Physical -> Offsettable -> Pausable

The GUI would use the Offsettable clock for its needs; the game play would use the Pausable clock for its simulation. The reason to use an Offsettable clock for GUI is so that each game can start at time 0 (or time 100, or whatever), no matter how long the computer's been up.

You can also build animation time bases as clocks, by defining time() functions that modulo the incoming time by some animation loop time, etc. Using a single interface for all time-getting functionality is really quite powerful.
enum Bool { True, False, FileNotFound };
I am not sure if this will help you but the way I used to do it was my base class for object all contained an tick() or update() method, as well as the managers for my base classes. The game engine would create a game timer and use a finite state machine to determine which managers needed to have tick() or update() called based on the game state.

This way you could just pause the game by setting the gameState == paused or something like that. It will also help in determining other other program flow between states.

I hope that helps.
Awesome. Some really great ideas in there guys. Should help alot!

Matt Hughson
__________________________________[ Website ] [ Résumé ] [ [email=contact[at]matthughson[dot]com]Contact[/email] ][ Have I been Helpful? Hook me up! ]

This topic is closed to new replies.

Advertisement