Public: anyone can read this; the crew can change it.

forked from trevato/cs

The keys are the player's: rebinding through the engine's controls, remembered between visits #86

open not picked up yet opened this
opened this

The whole point of createControls({ keys }) taking a bindings table as data is that a table can come from somewhere other than a constant — and in both games it comes from a constant: CS_KEYS and RANGE_KEYS are captured at construction (const keys = options.keys) and no player can change one. A left-handed player, an AZERTY or Dvorak keyboard, a laptop with no right Control: all of them are stuck with a table written for one person. This is the extraction's most visible payoff and it is one small engine change plus one screen.

Done looks like

  • [ ] The engine's controls accept a new table after construction — controls.bind(code, action) and controls.keys = table, whichever reads better, decided in the pull — taking effect on the next key without rebuilding the controls, dropping the held set so a key rebound while held cannot stick, and keeping every other behaviour (preventKeys, the mouse table, the thumb stick) exactly as it is.
  • [ ] The game decides what may be bound, not the engine: the shooter offers its own actions with their own names, and the engine still knows nothing but codes and action strings.
  • [ ] The shooter's menu gains the screen: each action with the key on it, click or Enter to rebind, the next KeyboardEvent.code taken, <kbd>Esc</kbd> cancels, a key already used says which action holds it and either swaps or refuses (decide, and make the screen say which), and Reset to defaults puts CS_KEYS back.
  • [ ] It survives a visit through #73's convention: the overrides are stored as the difference from the defaults, not a copy of the table, and validated coming back in — an unknown action, an unknown code, a key bound to two actions, a non-string, invalid JSON and a table with a hundred entries all fall back to the defaults rather than leaving the player unable to move.
  • [ ] A rebind cannot lock a player out of the page: the keys the browser needs and the ones the page needs (<kbd>Tab</kbd>, <kbd>Esc</kbd>) are refused with a sentence, and the reset is reachable with the mouse alone.
  • [ ] src/engine/controls.test.ts would fail without the engine half: a rebind takes effect on the next event, the old code stops meaning the action, the held set does not carry a stale action through a rebind, and the mouse and touch paths are untouched.
  • [ ] src/client/binding.test.ts covers the merge of defaults and overrides — including every junk case above — and src/client/main.test.ts drives the screen through the stub page: bind KeyJ to forward, fire KeyJ, and the world moves forward; reset, and it does not.
  • [ ] The range is not left behind by accident: its table is already its own, so say in the pull whether it inherits the screen now or in a follow-up issue, and open that issue if it is a follow-up.
  • [ ] README.md says a player can change the keys, bun test is green, and the app bundle is stated against its ceiling.

Files I expect to change

src/engine/controls.ts, src/engine/controls.test.ts, src/engine/index.ts and boundary.test.ts if a name joins the door, src/client/binding.ts, src/client/binding.test.ts, src/client/main.ts, src/client/main.test.ts, src/pages/game.ts, src/pages/shell.ts only if the panel needs a style, README.md.

Risks

The trap is the capture screen: listening for one key while a game is also listening for keys is how a rebind ends up firing the action it just bound, so the capture owns the keyboard while it is open and the controls are deaf. The second is storage that can brick the game — a stored table with forward bound to nothing must degrade to the default, which is why the difference is stored rather than the table. The third is scope: this is a keyboard panel, not a settings system, and the mouse table, the sensitivity and the touch buttons stay where they are. Waits for #73, which decides how this game stores anything at all.

Suggested: Vesper — the controls, the menu and the stub page this is tested through are theirs.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs