How do you keep pixel-art sprites crisp while moving smoothly on a 120hz display?

Hey folks, I’m working on a little canvas pixel-art game and I’m trying to make camera + sprite motion feel smooth without the art turning into blurry mush on high refresh monitors, and the tradeoff is jittery snapping vs smeary filtering.

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.imageSmoothingEnabled = false;

let camX = 0;
let last = performance.now();

function frame(t) {
  const dt = (t - last) / 1000;
  last = t;

  camX += 60 * dt; // pixels per second

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

  // draw at subpixel camera positions
  ctx.setTransform(1, 0, 0, 1, -camX, 0);
  ctx.drawImage(spriteSheet, 32, 0, 16, 16, 100, 50, 16, 16);

  requestAnimationFrame(frame);
}
requestAnimationFrame(frame);

Should I be rounding the camera/sprite positions to integers every frame (accepting tiny stutter), or is there a better pattern like rendering to an integer-scaled offscreen buffer and compositing, so motion stays smooth but pixels stay crisp?

Quelly

@Quelly, Keep your camera in floats for smooth motion, but snap only at the final draw by rounding the translation (or baking it into the draw positions) so every sprite lands on whole pixels. Canvas will still “blend” when the destination x/y is fractional even with imageSmoothingEnabled = false, because it’s sampling between device pixels; integer-aligning the transform avoids that. One gotcha: if you’re scaling the canvas (CSS size ≠ width/height, or DPR handling), you need to snap in backbuffer pixels (after multiplying by devicePixelRatio), otherwise you’ll still get shimmer.

const dx = Math.round(camX);
ctx.setTransform(1, 0, 0, 1, -dx, 0);

BobaMilk

@BobaMilk, snap the final transform in backbuffer pixels by rounding camX * devicePixelRatio, not camX, or 120hz will still shimmer.

Non-integer zoom (like 1.25x) will also force sampling blur even with imageSmoothingEnabled off.

Ellen