0
\$\begingroup\$

I am making a basic game loop based on this article. This is the nearly final version:

double previous = getCurrentTime();
double lag = 0.0;
while (true)
{
  double current = getCurrentTime();
  double elapsed = current - previous;
  previous = current;
  lag += elapsed;

  processInput();

  while (lag >= MS_PER_UPDATE)
  {
    update();
    lag -= MS_PER_UPDATE;
  }

  render();
}

But I think the update function should have elapsed time passed to it so that the game state is calculate based on that.

So this should be the correct version:

double previous = getCurrentTime();
double lag = 0.0;
while (true)
{
  double current = getCurrentTime();
  double elapsed = current - previous;
  previous = current;
  lag += elapsed;

  processInput();

  while (lag >= MS_PER_UPDATE)
  {
    update(elapsed);   ---------------->>>??
    lag -= MS_PER_UPDATE;
  }

  render();
}

Am I right? Because I think a physics engine should always have a delta time to calculate state changes.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

NO.

You can see the article begins with a variable timestep loop that passes elapsed as a timestep directly, eg.

double lastTime = getCurrentTime();
while (true)
{
  double current = getCurrentTime();
  double elapsed = current - lastTime;
  processInput();
  update(elapsed);
  render();
  lastTime = current;
}

But it immediately notes that this variable timestep comes with risks:

But, alas, there’s a serious problem lurking ahead: we’ve made the game non-deterministic and unstable. ... This instability is bad enough that this example is only here as a cautionary tale and to lead us to something better…

And so the article introduces the fixed timestep as a way to correct for this.

Since the timestep is a fixed constant MS_PER_UPDATE, there's no need to pass it as a dynamic argument to the update method - the update method can just reference that constant.

If you really wanted to pass it as an argument though, you'd do this:

while (lag >= MS_PER_UPDATE)
{
  update(MS_PER_UPDATE);
  lag -= MS_PER_UPDATE;
}

If one passes elapsed as you propose, then we get incorrect behaviour.

Let's say MS_PER_UPDATE = 10 and this frame our elapsed = 32 and we had lag = 9 left-over from last frame, making for a new lag = 41. We want 40 ms worth of updates to happen (4 fixed steps of 10 ms each, which is as much as will fit in our total accumulated lag).

           update(MS_PER_UPDATE)       update(elapsed)
---------------------------------------------------------
First loop     update(10)                update(32)
Second loop    update(10)                update(32)
Third loop     update(10)                update(32)
Fourth loop    update(10)                update(32)
---------------------------------------------------------
Total accounted    40 ms                    128 ms

lag carried to next frame    1 ms

By passing elapsed as our update step, we'd advance the game state 128 ms in a span of only 32 ms this frame, fast-forwarding the game at 4x speed. Obviously not the desired behaviour.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .