An efficient discrete step timing loop.

I’m going to try to explain a timing loop I’ve used in pretty much all my recent games.
It lets you have discrete time steps for game logics, and still works with high FPS.

There are two kinds of “ticks”, or pulses that are sent through the system: gameticks and clientticks.
Gameticks are sent at a regular interval, and clientticks are sent as often as possible.

First we define how often we want the gameticks, and a very useful derived value

private static final int GAMETICKS_PER_SECOND = 25;
private static final int MILLISECONDS_PER_GAMETICK = 1000 / GAMETICKS_PER_SECOND;

(This can also be done in the constructor if you dislike hardcoded stuff)

Then we build the run method that calls gameTick() and clientTick()

long previousTime = timer.getTimeInMillis();
long passedTime = 0;
while (keepGoing)
{
  clientTick();

  long time = timer.getTimeInMillis;
  passedTime += (time-previousTime);
  previousTime = time;
   
  while (passedTime>MILLISECONDS_PER_GAMETICK)
  {
    gameTick();
    passedTime-=MILLISECONDS_PER_GAMETICK;
  }
}

The basic idea is to call clientTick() while there is less “unprocessed time” in passedTime than MILLISECONDS_PER_GAMETICK, then call gameTick() until passedTime is lower than MILLISECONDS_PER_GAMETICK again.

This ensures that gameTick() will be called exactly GAMETICKS_PER_SECOND times per seconds on average, and that clientTick() will be called as often as possible.

(more to come)

gameTick() should manage all physics and other things that should happen at a fixed speed.
clientTick() should handle all the other things that should happen as often as possible, like rendering and sound updating.
I tend to put all networking in gameTick() as well.

If we just let the system be as it is now, we’d get lots of fps, but the camera position would only update 25 times per second, so it wouldn’t really work.
To fix this, we interpolate the values in clientTick().
That means that clientTick() will need to know how far along the we are between two gameTicks(), and all previous values for the values that should be interpolated.

To interpolate values, I use a small class called IFloat:

public class IFloat
{
      private float last;
      private float value;
      
      public IFloat()
      {
            this(0);
      }
      
      public IFloat(float newValue)
      {
            last = newValue;
            value = newValue;
      }
      
      public void setValue(float newValue)
      {
            last = value;
            value = newValue;
      }
      
      public float getValue(float interpolation)
      {
            return (value-last)*interpolation+last;
      }
}

We also need to change the definition of clientTick() to clientTick(float interpolation).
To calculate the interpolation in the main loop, we just have to divide the “unprocessed time” by MILLISECONDS_PER_GAMETICK.

So the new main loop looks like this:

long previousTime = timer.getTimeInMillis(); 
long passedTime = 0; 
while (keepGoing) 
{ 
  float interpolation = passedTime/(float)MILLISECONDS_PER_GAMETICK;
  clientTick(interpolation); 
 
  long time = timer.getTimeInMillis; 
  passedTime += (time-previousTime); 
  previousTime = time; 
    
  while (passedTime>MILLISECONDS_PER_GAMETICK) 
  { 
    gameTick(); 
    passedTime-=MILLISECONDS_PER_GAMETICK; 
  } 
} 

J3d and LWJGL comes with good timers, but for other things you’re going to have find a third party timer if you want it to work on Windows.

I like AdvancedTimer from GAGE.

Advantages:
Very solid code. The game will behave exactly the same regardless of what FPS you’re getting.

Disadvantages:
Because of the interpolation, you’ll always have a “latency” of at least MILLISECONDS_PER_GAMETICK ms, plus whatever mouse/network/videocard latency you have.

my question is when is IFloat used.

Another question is why gameTick (happens every so many milliseconds) is called in an inner while loop, and clientTick(interpolation) is called on the outside. And what is the interpolation used for in clientTick?

Thanks.

-Nick

Edit: I think I may understand it. It only goes into the nested while if so many milliseconds has passed, right? And if this is correct, couldn’t it be replaced by an if statement?

It has to be a while loop in case clientTick() ever takes longer than MILLISECONDS_PER_GAMETICK.
Like if your game suddenly pauses for 10 seconds, and you’ve got 10 ticks per second… The while loop would “catch up” by running the gamelogic tick 100 times, but the if statement would lag behind for a long time.

IFloat is a class that interpolates between two floats.
Most of the time, clientTick() will get called far more often than gameTick() gets called, so we have to interpolate between the values the last call to gameTick() produced, and the ones before that.

An example:


IFloat xPlayerPos = new IFloat(0);

public void clientTick(float interpolation)
{
  renderPlayerAt(xPlayerPos.getValue(interpolation));
}

public void gameTick()
{
  float xPos = xPlayerPos.getValue(1);
  xPos+=1;
  xPlayerPos.setValue(xPos);
}

Now if gameTick() gets called once every second, the player would move exactly one “unit” per second, but clientTick() would still make the motion smooth.

I’ve been testing it out, and it works beautifully in my experiments.

An interesting thought I had, to see if I understand this correctly:

Am I right in saying that you are doing all of this in one thread? That is to say, there is a clock running in its own thread (GAGE?) and giving you ticks, and you’re just reacting at the appropriate times to do rendering and ALSO to do your game management?

What happens on the lower end if your painting is taking too long and not leaving enough time for your management tasks (gameTick() if I’m not mistaken is where you have all that code)?

Yes, it’s all in one thread. if clientTick() (the rendering method) takes too long, gameTick() would execute several times in a row to catch up.

I really don’t believe in multithreading applications that don’t use a lot of blocking methods, as you just end up with a bunch of synchronisation and duplication of data, with no performance gain whatsoever.

[quote]I really don’t believe in multithreading applications that don’t use a lot of blocking methods, as you just end up with a bunch of synchronisation and duplication of data, with no performance gain whatsoever.
[/quote]
Unless you are running on a multi-processor system, in which case that’s exactly when you want to have multiple threads, since it implies that each thread has useful work to do.

Not the norm for games, but I thought I would point it out.

You still have to synchronize and duplicate all data. You can’t have an item move in the middle of the rendering loop. I don’t think the gain in cpu power will outweigh the messier code.

Stuff like AI and IO could probably be split off into separate threads with very good results on multiprocessor systems, however.

Yes, AI is something I think can benefit from multi-threading and multiple processors. Chess being one example, but taken further it might become practical at some point to train a neural net with a background thread so your game AI adapts to the users playing style. I don’t think we are at that point yet though.

Hmm. Outside of the fact that I called it “animate” and “render” this looks a whoe lot like my loop for Scroller :slight_smile:

or am I missing something?

I wouldn’t know, I haven’t looked at your Scroller.

And the main point isn’t that it uses two methods… It’s how the data produced from the math method is used in the render method (that generally gets called a lot more often).

Markus I have tried your loop and it works well but I do get image stutter every now and then. Anyway to fine tune it? I am guessing that I ma drawing a lot of frams but most of them go to the garbage bin. Is there a way to limit the fps in your loop?

[bogus answer, new one coming below]

You can limit the framerate by just adding a Thread.sleep() in the main loop, or if you want to be more scientific you can time the clientTick() call and sleep n-t milliseconds, where t is 1000/, and n is the number of milliseconds the clientTick() call took.

You might want to use your timer’s sleep methods if it has one instead of the Thread sleep method, though.

Do you yourself find this necessary to do in order to prevent image stutter?

Simply interpolating floats will NOT work correctly for Matrices and most 3D rotation representations. If it did, animation systems would be a WHOLE lot easy and cheaper to implement

Which also means it won’t work for physics that use those rotation representations. :frowning:

This technique can still be applied to those systems, but the interpolation must be computed on a type by type basis, it can’t be done generally.

What would be a better technique for a game loop then? I understand that the best method is probably using real time.

I think the gameTick pattern is fine and good.
I was just pointing out that the 'tween code will need a higher order of “awareness” of the data it needs to interpolate, so as to use the correct process.
Or from another point of view, each data class can implement the 'tween functionality and main loop and game control can simple call interp on everything.

However, in both cases, I think allot of context specific optimizations will be ugly/difficult. For example, in character animation, the animation data is compressed and decompressed on the fly. The decompression code typically will accept a time value in an animation as the target for a matrix generate. Just like other types of media compression, this may be a directional decompress, i.e only forward, and may take as addition feed, previous generate d values.

Anyway the point is, global, timeless (ticked) based control is bound to have it’s pro and cons just as the all-on-one syncronized update does. Perhaps your particular app would be the deciding factor.