Concepts

This page explains how play-u1 is structured so the rest of the guides make sense. When you are ready for the full API surface, continue to Input events.

The big picture

  • GamepadManager — one place for connect/disconnect, a single requestAnimationFrame loop over navigator.getGamepads(), and GamepadDevice instances with named inputs via layouts.
  • GamepadDevice — per-controller API: subscribe to presses, holds, sticks, triggers, rumble, and snapshots.

Raw Gamepad objects use opaque button indices and axis numbers. Layouts map them to stable names like A, LS, LT.

Lifecycle: start and stop

  • start() registers gamepadconnected / gamepaddisconnected and runs the rAF polling loop.
  • stop() tears that down: no more frames, no more connection listeners.

The first subscription to onConnect, onDisconnect, onAnyPress, or onAnyInput calls start() if the manager was idle—which is why the quick start can omit start() when you begin with onConnect.

In environments without window (SSR, some tests), start() is a no-op until a browser global exists.

Manager-level listeners

APIWhen it runs
onConnectA new GamepadDevice is tracked for a physical gamepad.
onDisconnectA tracked device goes away.
onAnyPressAny named button goes down on any device — handler receives (event, pad).
onAnyInputAny input change on any device — handler receives the GamepadDevice.

Each on* method returns a disposer. Call it to remove that listener.

Dead zone

Pass deadzone into createGamepadManager (or call setDeadzone later).

  1. A number — radial dead zone: small stick vectors snap to center; the outer range is rescaled so full tilt still reaches magnitude 1 by default.
  2. DeadzoneOptionsradial, optional per-axis axial, and rescale toggles.

Exact math: resolveDeadzone and applyAxisDeadzone in the API reference.

Layouts (names instead of indices)

Each GamepadDevice uses a LayoutProfile: maps raw button and axis indices to names like A, LS, LT.

  • detectLayout(rawGamepad) picks xboxLayout for standard mapping or common Xbox / XInput IDs; otherwise genericLayout (Button0, Axis0, …).
  • createGamepadManager({ layouts: { 'VendorName': myProfile } }) adds profiles. Keys match as case-insensitive substrings of gamepad.id.
  • manager.setLayoutForId('DualSense', playStationLayout) updates patterns at runtime.

Built-in exports: xboxLayout, genericLayout, detectLayout from @interfaces-technology/play-u1.