Game development

Track held keys separately from key events

A key-down event records that a key became pressed. Continuous movement should read a set of held keys during each simulation update, rather than relying on the operating system’s repeated key events.

Clear the set when the window loses focus so a released key cannot leave the player moving indefinitely. Suppress browser scrolling only for controls the active game actually uses, and preserve a clear way to leave the playfield.

Map keyboard and on-screen buttons into the same action state. The movement rule should read left, right or jump actions instead of knowing which physical key or touch target produced them.

Try the idea

const held = new Set();
addEventListener("keydown", e => held.add(e.code));
addEventListener("keyup", e => held.delete(e.code));
addEventListener("blur", () => held.clear());
function update(dt) {
  const axis = Number(held.has("ArrowRight")) - Number(held.has("ArrowLeft"));
  player.x += axis * player.speed * dt;
}