# Keyboard input without stuck keys
URL: https://wwadd.dev/moves/game-dev/keyboard-input-state

Track which keys are held in a Set and read it during update, instead of moving things inside event handlers. Use `e.code` (physical key) so WASD works on any keyboard layout. Clear the set on blur: if the player alt-tabs while holding a key, keyup never fires and the character walks forever.


```ts
const held = new Set<string>();
const GAME_KEYS = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Space"];

addEventListener("keydown", (e) => {
  if (GAME_KEYS.includes(e.code)) e.preventDefault(); // stop page scrolling
  held.add(e.code);
});
addEventListener("keyup", (e) => held.delete(e.code));
addEventListener("blur", () => held.clear()); // alt-tab never sends keyup

// In update():
const right = held.has("ArrowRight") || held.has("KeyD");
const left = held.has("ArrowLeft") || held.has("KeyA");
player.dirX = Number(right) - Number(left); // -1, 0, or 1
```

## Related Moves
- [Fixed-timestep game loop](https://wwadd.dev/moves/game-dev/fixed-timestep-loop)
- [Frame-rate independent movement](https://wwadd.dev/moves/game-dev/delta-time-movement)

