✚ Game development

Handling input in games: keyboard, gamepad and abstract actions

How to design input handling in a video game: events and polling, abstract actions, gamepads and dead zones, key remapping and accessibility options.

Players perceive a game through the screen, but they control it through input. A delay of a few frames, a button that sometimes fails to respond or an analogue stick that makes the character drift on its own is enough to ruin the experience. Good input handling rests on a simple idea: separate what the player presses from what they want to do.

Events and polling

There are two ways to read input:

  • events: the operating system reports «key pressed» or «key released» when it happens. Useful for one-off actions and for typing text.
  • polling: every frame you query the current state, «is the key down?». Useful for continuous actions such as movement.

The most robust solution combines them: you collect the frame's events and keep a state table for each key, from which three distinct pieces of information are derived.

Information Meaning Typical use
Just pressed Down this frame, up in the previous one Jumping, firing a shot
Held Down this frame Walking, charging an attack
Just released Up this frame, down in the previous one Cutting a jump short, throwing

Confusing «just pressed» with «held» is one of the most common mistakes: the character jumps repeatedly as long as the button stays down.

Abstract actions

Game code should never ask «is the space bar pressed?», but «has the jump action been triggered?». You define a map between actions and physical inputs:

actions = {
  "jump":  [Key.SPACE, Pad.A],
  "fire":  [Key.J, Mouse.LEFT, Pad.X],
  "left":  [Key.A, Key.LEFT_ARROW, Pad.LEFT_STICK_LEFT],
  "pause": [Key.ESC, Pad.START],
}

The advantages are considerable:

  • several devices can trigger the same action without duplicating code;
  • remapping becomes simple: you change the table, not the code;
  • menus and gameplay can use different maps, enabling one or the other depending on context.

Most modern engines offer an action system of this kind, and it is always preferable to reading keys directly.

Axes and analogue input

Gamepad sticks and triggers return continuous values, typically from −1 to 1 for sticks and from 0 to 1 for triggers. To unify keyboard and gamepad, it is worth defining abstract axes as well: the «horizontal» axis is −1 if left is pressed, 1 if right is pressed, or the stick's value.

The dead zone

No stick returns exactly to the centre: at rest it reports small values such as 0.03 or −0.05. Without correction, the character slowly drifts by itself. The dead zone ignores values below a threshold:

length = sqrt(x*x + y*y)
if length < dead_zone:
    x, y = 0, 0
else:
    scale = (length - dead_zone) / (1 - dead_zone) / length
    x, y = x * scale, y * scale

This is a radial dead zone, applied to the whole vector. Applying it separately to the two axes creates a cross-shaped zone that makes gentle diagonals difficult. The rescaling means that just outside the zone the value starts again from zero instead of jumping to the threshold.

Diagonal movement on the keyboard

With four keys, pressing right and up together produces the vector (1, 1), roughly 1.41 long. The character moves faster diagonally. Simply normalise the vector when its length exceeds 1.

Latency

Perceived latency depends on many factors: input polling rate, number of frames queued for rendering, vertical sync, the display. Some practical rules:

  • read input as late as possible before the update, not at the start of a long loop;
  • give immediate visual feedback, even just an animation that starts in the same frame;
  • avoid deep render queues when the game demands quick reflexes.

Multiple players and devices

In local multiplayer games each device must be assigned to a player. The classic method is a join screen where each person presses a button on their own controller to «join». Disconnection must be handled too: if a gamepad disconnects mid-match, the game should pause and wait, rather than leave a character standing still.

Accessibility

Good input handling makes the game accessible to more people with little effort:

  • full remapping of every action, menus included;
  • a choice between hold and toggle for actions such as running or aiming;
  • adjustable sensitivity and axis inversion;
  • the option to play with one hand or a single device;
  • button icons updated automatically according to the device in use.

In short

  • Separating physical inputs from game actions simplifies code and remapping.
  • Distinguishing just pressed, held and just released avoids unwanted behaviour.
  • Sticks need a radial dead zone with rescaling.
  • Diagonal keyboard movement must be normalised.
  • Low latency, device management and accessibility options complete a good input system.
MM
Marco Marzaduri

Marco Marzaduri works in cybersecurity, digital forensics and web development. A computer science graduate, he combines rigorous technical analysis with attention to the people who use technology.

Read also