Basic

Input that does not repeat or drop

Holding a key produces many events, and a jump that fires on every one is a hover. The fix is to separate the press from the hold: press is a one-time event, hold is a state read each frame.

What you will see

The rules see the press. Clearing before the rules read it drops the input entirely.

About 1 min of reading

Quick check

Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.

Try It

Separate press from hold

1

Record both flags

printf 'const keys = {}; function down(k) { keys[k] = { held: true, pressed: true }; } function up(k) { keys[k] = { held: false, pressed: false }; } ' | tee game/input.js

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Two flags per key. The pressed flag is the one-time event.
2

Read press once

printf 'function pressed(k) { const v = keys[k] && keys[k].pressed; if (v) keys[k].pressed = false; return !!v; } ' | tee -a game/input.js

Before you run it, say out loud what it will print. Then open the answer.

What it prints
True on the first read after the event, false on every later read.
3

Prove no hover

node -e 'const m=require("./game/input.js"); m.down("j"); console.log(m.pressed("j"), m.pressed("j"), m.pressed("j"))' 2>/dev/null || echo 'must print true false false'

Before you run it, say out loud what it will print. Then open the answer.

What it prints
true false false. Three trues means the jump fires every frame and the player hovers.
4

Clear at the right time

call the clear at the end of the frame, after the rules have read pressed

Before you run it, say out loud what it will print. Then open the answer.

What it prints
The rules see the press. Clearing before the rules read it drops the input entirely.
Do not read the raw key state in the draw step. The draw must be a function of state only, or the paint changes with timing.

Put it in order

Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.

Data Flow

Key event to a one-time press
1 Key event sets held true and pressed true
↓
2 Rules read pressed once
↓
3 Rules read held every frame
↓
4 End of frame clears pressed
Why this works
The two reads

A boolean for held and a one-frame flag for pressed. Naming them differently is what keeps the two uses apart.

Where input is lost

A press that arrives between frames has to be buffered. Clearing the buffer before the rules read it drops the input.

Examples

Press once, hold always

A jump belongs to press. A run belongs to hold. Two different reads of the same key, and the game needs both.

Clear the press each frame

The press flag is set on the event and cleared at the end of the frame. If it is never cleared, the press repeats forever.

Never read the key in the draw

Input is read once per frame into the state. A draw that reads a key makes the paint depend on timing.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← The game loop and time that is not frames
Previous Lesson
The game loop and time that is not frames
Next Lesson
Movement, gravity, and collision that does not tunnel
Movement, gravity, and collision that does not tunnel →