Game Dev 101
Progress
0/22

Lesson 7 of 22, in world 2: Motion & Math

Handling Input

Time
About 15 min
Builds on
The Game LoopVectors

Input is how the player talks to your game. Getting it right is about more than reading keys: games care whether a key is held or was just pressed, they map physical keys to actions, and they quietly forgive slightly-early presses.

Two ways to read input

Events — the browser tells you “Space went down” once, when it happens. Polling — each frame, you ask “is Space down right now?”. Games mostly poll, because the update step wants a snapshot of the current state. A common pattern is to record events into a small state object, then read it during update:

JavaScript
const held = new Set()      // keys down right now
const pressed = new Set()   // keys that went down THIS frame

addEventListener('keydown', e => { if (!held.has(e.code)) pressed.add(e.code); held.add(e.code) })
addEventListener('keyup',   e => held.delete(e.code))

function update(dt) {
  if (held.has('ArrowRight')) player.x += SPEED * dt   // continuous: walking
  if (pressed.has('Space')) player.jump()              // one-shot: jumping, shooting
  pressed.clear()                                      // "just pressed" lasts one frame
}
LiveInput lab: held vs. pressed, actions and buffering
Key bindings

Press keys and watch the keyboard: yellow = held (polling), pink flash = pressed this frame (an event). The character only knows about actions (left/right/jump), so switching the layout needs no gameplay change. Raise the jump buffer and try pressing jump just before landing.

Actions, not keys

Gameplay code should ask “is the player pressing jump?”, not “is Space down?”. A small table maps physical inputs (keyboard, gamepad, touch) to named actions. This makes rebinding, controller support and accessibility options almost free.

JavaScript
const bindings = { jump: ['Space', 'KeyW', 'GamepadA'], left: ['ArrowLeft', 'KeyA'] }
const isAction = name => bindings[name].some(code => held.has(code))

Input buffering: forgiving timing

Players often press jump a few frames before landing. Strictly, they’re still in the air, so the press is ignored and the game feels unresponsive. An input buffer remembers the press for ~0.1–0.15 s and triggers the jump as soon as it becomes possible. You’ll see its sibling, coyote time, in the platformer lesson.

Mouse, touch and gamepads

Mouse and touch give you a position (convert it from page pixels to game coordinates!) and button states. Gamepads give analog sticks (vectors between −1 and 1, with a dead zone to ignore tiny drift) and buttons. With an action layer, all of them can drive the same gameplay code.

Key takeaways

  • Poll a snapshot of input each frame; distinguish held vs just-pressed.
  • Map physical inputs to named actions; gameplay only reads actions.
  • Buffer jump/attack presses briefly so the game feels responsive.

Check yourself

Q1. Shooting should fire ONE bullet per tap. Which check do you use?

Q2. Why map keys to actions?

Q3. A player presses jump 3 frames before landing and nothing happens. The fix is…

Exercises

  1. [object Object]
  2. [object Object]
  3. [object Object]