Lesson 7 of 22, in world 2: Motion & Math
Handling Input
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:
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
}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.
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
- [object Object]
- [object Object]
- [object Object]