//// // Support for gamepads. // Maps incoming gamepad button presses to keyboard buttons. // const BUTTONS = [ "A", "B", "X", "Y", "LB", "RB", "LT", "RT", "Select", "Start", "LStick", "RStick", "DPad Up", "DPad Down", "DPad Left", "DPad Right" ] const BUTTONS_TO_KEYS: Record = { 0: "z", // A → Z 1: "x", // B → X 2: "c", // X → C 3: "v", // Y → V 12: "ArrowUp", 13: "ArrowDown", 14: "ArrowLeft", 15: "ArrowRight", 9: "Enter", // Start 8: "Escape" // Select } const activePads = new Set() const prevState: Record = {} export function initGamepad() { window.addEventListener("gamepadconnected", e => { console.log("Gamepad connected:", e.gamepad) activePads.add(e.gamepad.index) requestAnimationFrame(handleGamepad) }) window.addEventListener("gamepaddisconnected", e => { console.log("Gamepad disconnected:", e.gamepad) activePads.delete(e.gamepad.index) }) } function handleGamepad() { const pads = navigator.getGamepads() for (const gp of pads) { if (!gp) continue if (!prevState[gp.index]) prevState[gp.index] = gp.buttons.map(() => false) gp.buttons.forEach((btn, i) => { const was = prevState[gp.index]![i] const is = btn.pressed if (was !== is) { const key = BUTTONS_TO_KEYS[i] if (key) { const type = is ? "keydown" : "keyup" window.dispatchEvent(new KeyboardEvent(type, { code: key, key })) } prevState[gp.index]![i] = is } }) } requestAnimationFrame(handleGamepad) }