Gamepad
Gamepad input handler supporting up to 4 controllers. Tracks button state, analog stick axes with dead zone, and axis auto-repeat for menu navigation.
Automatically connected and polled by Input, but can also be used standalone.
ts
import { Gamepad, GamepadButton, GamepadAxis } from "@jolly-pixel/engine";
const gamepad = new Gamepad();
gamepad.connect();
gamepad.on("connect", (pad) => console.log("connected", pad.id));
function gameLoop() {
gamepad.update();
if (gamepad.buttons[0][GamepadButton.A].wasJustPressed) {
console.log("Player 1 pressed A!");
}
const stickX = gamepad.axes[0][GamepadAxis.LeftStickX].value;
if (stickX !== 0) {
console.log("Left stick X:", stickX);
}
requestAnimationFrame(gameLoop);
}
gameLoop();Constructor
new Gamepad(options?)
ts
interface GamepadOptions {
navigatorAdapter?: NavigatorAdapter;
windowAdapter?: WindowAdapter;
}
new Gamepad(options?: GamepadOptions);Types
ts
type GamepadIndex = 0 | 1 | 2 | 3;
// W3C Standard Gamepad button mapping
// @see https://w3c.github.io/gamepad/#remapping
const GamepadButton = {
// Face buttons
A: 0, // Xbox: A, PlayStation: Cross
B: 1, // Xbox: B, PlayStation: Circle
X: 2, // Xbox: X, PlayStation: Square
Y: 3, // Xbox: Y, PlayStation: Triangle
// Shoulder buttons
LeftBumper: 4, // L1
RightBumper: 5, // R1
LeftTrigger: 6, // L2
RightTrigger: 7, // R2
// Center buttons
Select: 8, // Back/Share
Start: 9, // Start/Options
// Stick buttons
LeftStick: 10, // L3
RightStick: 11, // R3
// D-Pad
DPadUp: 12,
DPadDown: 13,
DPadLeft: 14,
DPadRight: 15,
// Special
Home: 16
} as const;
// Axis values range from -1.0 (left/up) to 1.0 (right/down)
const GamepadAxis = {
LeftStickX: 0,
LeftStickY: 1,
RightStickX: 2,
RightStickY: 3
} as const;
interface GamepadButtonState {
isDown: boolean;
wasJustPressed: boolean;
wasJustReleased: boolean;
value: number;
}
interface GamepadAxisState {
wasPositiveJustPressed: boolean;
wasPositiveJustAutoRepeated: boolean;
wasPositiveJustReleased: boolean;
wasNegativeJustPressed: boolean;
wasNegativeJustAutoRepeated: boolean;
wasNegativeJustReleased: boolean;
value: number;
}
interface GamepadAutoRepeat {
axis: number;
positive: boolean;
time: number;
}Events
ts
type GamepadEvents = {
connect: [gamepad: globalThis.Gamepad];
disconnect: [gamepad: globalThis.Gamepad];
};Properties
ts
interface Gamepad {
static readonly MaxGamepads: 4;
static readonly MaxButtons: 16;
static readonly MaxAxes: 4;
// Per-gamepad, per-button state
buttons: GamepadButtonState[][];
// Per-gamepad, per-axis state
axes: GamepadAxisState[][];
// Per-gamepad auto-repeat tracking (for held axes)
autoRepeats: (GamepadAutoRepeat | null)[];
// Number of currently connected controllers
connectedGamepads: number;
// Dead zone threshold for analog sticks (default 0.25)
axisDeadZone: number;
// Delay before first auto-repeat in ms (default 500)
axisAutoRepeatDelayMs: number;
// Interval between auto-repeats in ms (default 33)
axisAutoRepeatRateMs: number;
readonly wasActive: boolean;
}API
ts
interface Gamepad {
// Lifecycle
connect(): void;
disconnect(): void;
reset(): void;
update(): void;
}