Time-stepping for Games and Simulations

Previous: A Smarter Game View.

The new TMetronome

Wittner_metronomeA new class TMetronome in System.Metronome allows to obtain fixed time steps from the variable time-steps of the game view repaints (or any other variable time-steps, TMetronome is an independent class).

You just need to create a TMetronome class, initialize it, feed it your variable time steps, and you’ll get fixed-time steps (“ticks”) in it OnProgress event. A typical use case will look like:

procedure TYourApplication.ApplicationStarting;
begin
   ...
   FMetronome := TMetronome.Create;
   FMetronome.TickFrequency := 100;               // run simulation at 100 Hz
   FMetronome.OnProgress := DoSimulationProgress; // fixed time-steps events there
end;

procedure TYourApplication.PaintView(Canvas:TW3Canvas);
begin
   // we come here in variable time-steps
   // we pass the variable time elapsed since the last frame to the metronome
   // which will generate fixed time steps for DoSimulationProgress
   FMetronome.Progress(GameView.LastFrameTime);
   ...
   // paint your view here
end;

Sometimes the hardware may just not be able to keep up (if just temporarily), and you may be faced with having to either stall the simulation, or just skip ahead.

The threshold for that is determined by the MaxTicksPerProgress property, and what to do by the ProgressPolicy, which can be used to determine if you’ll Stall the simulation (Ticks won’t advance by more than MaxTicksPerProgress), or just Skip ahead.

You can have as many metronomes as you want, and then you can let every simulation progress at its own rythm:

FMetronomes : array of TMetronome;
...
for var metronome in FMetronomes do
   metronome.Progress(lastFrameTime);

This will hopefully simplify mix’n’matching different simulations in the same world, and you can easily and independently adjust the frequency at which everything progresses.