Proposal: revamp the input system — action maps, rebinding, gamepads, touch, deterministic replay #7
Labels
No labels
area:ci
area:docs
area:input
area:net
area:rendering
area:repo
area:stdlib
area:tooling
area:types
cleanup
dx
priority:high
priority:low
priority:medium
proposal
status:in-progress
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: workshopsoft/ludic#7
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Ludic's input is a single call —
Input.key()returns this frame's key code. That's enough for a demo, not a game. This proposes a full input system, modeled on Godot'sInputMap/Inputand Unity's Input System (action maps, rebinding, multiple devices), plus SDL GameController-style gamepad handling. It supersedes/expands theInput.*additions sketched in #2.Layer 1 — raw devices
Input.key_down(k),Input.key_pressed(k)(edge),Input.key_released(k),Input.any_key(),Input.text()(buffered text for names/chat).Input.mouse_pos() -> vec2,Input.mouse_delta() -> vec2,Input.mouse_down(b),Input.mouse_pressed(b),Input.wheel() -> int.Input.pad_count(),Input.pad_button(pad, b)/pad_pressed,Input.pad_axis(pad, a) -> fixed,Input.pad_stick(pad, side) -> vec2,Input.pad_trigger(pad, side) -> fixed; hotplug eventsPadConnected/PadDisconnected(viaevent/@On). SDL-style standard button/axis names so layouts are portable.Input.touch_count(),Input.touch(i) -> vec2, tap/hold; basic gestures later.Layer 2 — action map (the important idea)
Bind named actions to many physical inputs; gameplay reads actions, not keys — which is what makes rebinding, multiple schemes, and local multiplayer clean (Godot
InputMap, Unity Input System).action_strength/axis/vectorreturnfixed/vec2with deadzones (per-action and global, like Godot's joy-axis deadzone).Input.rebind("jump", event),Input.clear_binding(...),Input.bindings("jump")— for a settings/accessibility menu.Input.assign(player: 1, pad: 0), thenInput.action_pressed("jump", player: 1).Layer 3 — determinism & replay
Input.snapshot() -> InputFramecaptures all action/axis states for the frame.Input.record(on)/Input.replay(stream)— feed recorded snapshots so the sim reproduces exactly. Same read API in live and replay mode. Foundation for netcode rollback and diffable headless tests.Phasing
key_down/pressed/released) + mouse (pos/buttons/wheel).action,action_pressed/down,axis/vector, deadzones.snapshot/record/replay.References
InputandInputMap(actions,action_add_event/action_erase_eventsrebinding,get_vector, joy-axis deadzones).vec2in #1;event/@Onfor device hotplug;Random.stream/determinism ethos in #2.Action-map input with gamepads/touch/rebinding — and per-frame snapshots that turn the deterministic sim into free replays.
Shipped the two ideas this proposal leads with — action maps ("the important idea": gameplay reads actions, not keys) and deterministic record/replay ("a real feature… a standout capability for a deterministic engine") — in
377b6d1.Input.bind(action, key)binds a key to a named action;Input.down(action)/Input.pressed(action)read it (held vs one-shot edge);Input.rebind(action, from, to)remaps it at runtime — the primitive a rebinding menu is built on. Gameplay reads the action, so a rebind changes nothing in the game logic.Input.poll()is the single per-frame input read the actions sit on.Input.record()captures the polled key each frame;Input.replay()feeds the tape back soInput.pollreads the recording instead of the device — a run reproduces exactly. As the issue asks, "read input" and "read a recorded snapshot" are the same call.All integer and deterministic, in
runtime/native/input.ludic, with sevendocs/language/input/pages. Proof:examples/library/input_actions.ludicbinds actions, rebinds one at runtime, records two frames and replays them, asserting1 0 1 1 0 1 0— now in the regression suite (75 passed, self-host fixpoint intact, no golden drift).The raw device layer — simultaneous held keys,
Input.key_down/pressed/released, analogaxis/vectorwith deadzones, mouse, gamepads (SDL-style), and touch — all needs a platform key-state backend (keydown+keyup into a held set) across the Cocoa/headless/wasm targets rather than the current one-key-per-frame poll, so it is a runtime/platform job tracked in #50 (which also covers extending the replay tape to the full multi-key action snapshot). Closing as the action-map + replay core is delivered.