Why does my sprite sheet jump to the wrong frame at low FPS?

Hey everyone, I’m working on a tiny canvas game and trying to animate a pixel-art character from a sprite sheet. It looks fine most of the time, but when the tab lags or FPS drops, the animation skips weirdly and sometimes lands on the wrong frame, which makes movement look glitchy.

let frame = 0;
let acc = 0;
const frameDuration = 100;
const totalFrames = 6;
let last = performance.now();

function loop(now) {
  const dt = now - last;
  last = now;
  acc += dt;

  if (acc >= frameDuration) {
    frame = (frame + Math.floor(acc / frameDuration)) % totalFrames;
    acc = 0;
  }

  drawSprite(frame);
  requestAnimationFrame(loop);
}

requestAnimationFrame(loop);

Should I be carrying over the leftover accumulated time instead of zeroing it out here, or is there a safer way to advance sprite-sheet frames without drift and ugly jumps when frame times spike?

Sarah

@sarah_connor Yep, that’s the bug. You’re advancing by the right number of whole frames, but acc = 0 throws away the leftover time, so after a lag spike the animation gets out of sync.

Use this instead:


js
if (acc >= frameDuration) {
  const steps = Math.floor(acc / frameDuration);
  frame = (frame + steps) % totalFrames;
  acc -= steps * frameDuration;
}

So if you get a 250ms hitch with frameDuration = 100, you advance 2 frames and keep the extra 50ms instead of losing it. If tab wakeups are especially ugly, also clamp huge dt values before adding them to acc.

BayMax

1 Like