2
\$\begingroup\$

this is what i did

my game loop is run every REFRESH milliseconds

loop = setInterval(tick,REFRESH);

in the loop i calculate how much time is passed since last tick and subdivide that for how much time i expected to be passed

var now = performance.now();
var elapsedTime = now - lastTick;
var delta = time / REFRESH;
lastTick = now;

and every time based action that should happen every tick is "scaled" with the delta factor, for example my movement code

var distance=ball.dest.x-ball.x;
var movement=distance/speed;
ball.x+=movement;

will have movement multiplied with delta

\$\endgroup\$
3
\$\begingroup\$

Your approach is unfortunately not framerate independent. You correctly notice the need to factor in the amount of time passed between each update in your physics calculations. However, you still specify the amount of time passed in units of frames. If your framerate changes, now your speeds have all changed with respect to the passing of real time. What you should do instead is pass the actual time passed between each frame in units of seconds or ms or us or whatever.

In your first example, the change is simply passing elapsedTime rather than delta. In the second half you need to calculate the speeds of items with respect to the passing of real time, like pixels/second or meters/second rather than pixels/frame.

\$\endgroup\$
1
\$\begingroup\$

Don't use setInterval for game loops. Use requestAnimationFrame. See the simple example below.

console.clear();
const INTERVAL = 16; //16 ms animation interval
var frame = {
  start: null,
  delta: null,
  count: 0,
};

run(test);

function run(func) {
  if (!frame.start) frame.start = performance.now();
  frame.delta = performance.now() - frame.start;
  if (frame.delta >= INTERVAL) {
    func.call();
    frame.start = null; //reset
    frame.count++;
  }
  //for this example the loop will be repeated only 100 time
  if (frame.count < 100) requestAnimationFrame(run.bind(null, func));
  //without counting limit
  //requestAnimationFrame(run.bind(null, func));
}

function test() {
  //simple function for demonstration
  // avoid using console in animation loop, except for debugging
  // console operations are very slow
  console.log(`${frame.count}`);
}

\$\endgroup\$
  • 1
    \$\begingroup\$ Quite often games will use a while( remainingDelta > interval) loop rather than a single if, to run a fixed update function at a rate decoupled from the visual update tick — sometimes multiple calls per visual update. For this, it's good not to null-out the start each time, but to keep track of how much "loose change" is leftover after calling the fixed update, so we can carry it forward to the next loop & avoid "lost time" \$\endgroup\$ – DMGregory Mar 22 '19 at 11:58
  • \$\begingroup\$ @DMGregory, thanks. This is something I have yet to learn. \$\endgroup\$ – Orwol Chiles Mar 22 '19 at 12:09

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.