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
\$\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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.