Connect a controller that the browser exposes with the standard mapping, then press a button to wake it. Release the sticks/buttons before playing. The controller guide is under Escape → Make yourself comfortable → Use a controller.
| Control | In the world |
|---|---|
| Left stick | Analog movement |
| Right stick | Look |
| A / Cross | Jump |
| X / Square | Interact |
| Y / Triangle | Satchel |
| LB / L1 | Run |
| D-pad up | Journal |
| Menu | Pause / return |
In menus, the D-pad moves focus; left/right adjust sliders and selects. A / Cross activates the focused control; B / Circle returns to the world. On the welcome screen A / Cross enters when the world is ready. Chat text, passphrases and keyboard rebinding still need a keyboard. Browser sound activation may need a mouse click or keyboard press.
#Ownership and lifecycle
packages/input/gamepad.ts consumes device snapshots without accessing browser globals. Game-authored sticks and button mappings produce semantic values and button edges. The player combines gameplay values with keyboard input through the existing ActionMap source interface; the worker and relay continue to receive the same semantic input frames. The independent test fixture binds a tile-placement game to the same adapter.
The adapter selects one standard-layout controller from the first four browser slots and retains that controller while connected. Nonstandard layouts are ignored. Sticks use a radial 18% deadzone with rescaled analog magnitude and no diagonal acceleration. Invalid/missing axes or buttons produce neutral input. Bindings are copied, counts/indices are bounded, and duplicate action declarations are rejected.
Connection, controller replacement, pause, profile changes, focus loss and recovery reset the adapter. All mapped controls must return to neutral before another press can act. This prevents a held menu-confirm button from becoming a jump and prevents held movement from immediately restarting after a menu. Disconnecting an actively used controller releases its source and pauses the world. Keyboard input remains available; HUD hints follow the last active input device.
Menus use existing DOM controls and handlers, with visible focus and scrolling. Gamepad entry/resume does not request pointer lock, because polling does not carry the browser's transient user activation. Keyboard/mouse entry retains its existing explicit pointer-lock flow.
#Acceptance and limits
Headless tests cover analog magnitude, radial diagonals, fresh button edges, neutral rearming, device selection/replacement/removal, malformed samples, keyboard composition and independent bindings. Browser acceptance injects standard-layout snapshots into navigator.getGamepads and exercises the real player, worker and physics, including interaction, analog movement, looking, jump, satchel, menu focus, focus loss, disconnection and keyboard fallback. Existing keyboard/rebinding/browser-room tests remain regression coverage.
These automated checks do not establish physical controller or Bluetooth compatibility. A physical Xbox-layout and PlayStation-layout controller pass remains required before claiming a supported hardware matrix. Controller rebinding, adjustable deadzone, vibration, nonstandard adapters and touch remain open.