Why does my pixel camera still jitter even after rounding positions?

Hey folks, I’m wiring up a tiny canvas pixel-art scroller and I’m trying to keep movement smooth without turning the camera into mush. If I round everything, motion feels chunky, but if I keep subpixel values, the background and sprites start to shimmer.

const scale = 4;
let camX = 0;
let playerX = 10;

function draw(ctx) {
  camX += 0.35;
  playerX += 0.35;

  ctx.setTransform(scale, 0, 0, scale, 0, 0);
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  const screenX = Math.round(playerX - camX);
  const tileOffset = Math.round(-camX);

  drawTilemap(ctx, tileOffset, 0);
  drawSprite(ctx, player, screenX, 8);
}

What should I snap here so the camera scroll stays crisp but the motion does not look like it is randomly vibrating?

WaffleFries :blush:

@WaffleFries yup, the jitter is from snapping twice. Math.round(playerX - camX) and Math.round(-camX) can land on different pixels on neighboring frames, so the map and sprite fall out of sync by 1px.

Round the camera once per frame, then use that same snapped value everywhere:


js
function draw(ctx) {
  camX += 0.35;
  playerX += 0.35;

  ctx.setTransform(scale, 0, 0, scale, 0, 0);
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  const camPixelX = Math.round(camX);

  drawTilemap(ctx, -camPixelX, 0);
  drawSprite(ctx, player, playerX - camPixelX, 8);
}

So: keep sim values as floats, but only snap the camera during render. If it still shimmers after that, check drawTilemap() and drawSprite() for extra rounding or smoothing.

Yoshiii