From c29a9a4a2b7eed1df8286b49317791479e639734 Mon Sep 17 00:00:00 2001 From: Corwin Date: Wed, 10 Apr 2024 18:30:12 +0100 Subject: [PATCH] add controller support --- website/agb/src/app/mgba/mgba.tsx | 2 + .../agb/src/app/mgba/useController.hook.ts | 98 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 website/agb/src/app/mgba/useController.hook.ts diff --git a/website/agb/src/app/mgba/mgba.tsx b/website/agb/src/app/mgba/mgba.tsx index 0c16bdf2..974f5668 100644 --- a/website/agb/src/app/mgba/mgba.tsx +++ b/website/agb/src/app/mgba/mgba.tsx @@ -9,6 +9,7 @@ import mGBA, { mGBAEmulator } from "./vendor/mgba"; import { GbaKey, KeyBindings } from "./bindings"; import { styled } from "styled-components"; import { useFrameSkip } from "./useFrameSkip.hook"; +import { useController } from "./useController.hook"; type Module = any; @@ -105,6 +106,7 @@ export const Mgba = forwardRef( }, [state]); useFrameSkip(mgbaModule); + useController(mgbaModule); useEffect(() => { if (!gameLoaded) return; diff --git a/website/agb/src/app/mgba/useController.hook.ts b/website/agb/src/app/mgba/useController.hook.ts new file mode 100644 index 00000000..ff874e7c --- /dev/null +++ b/website/agb/src/app/mgba/useController.hook.ts @@ -0,0 +1,98 @@ +import { MutableRefObject, useEffect } from "react"; +import { mGBAEmulator } from "./vendor/mgba"; +import { GbaKey } from "./bindings"; + +export function useController(mgbaModule: MutableRefObject) { + useEffect(() => { + let stopped = false; + + + let previouslyPressedButtons = new Set(); + + function raf(time: DOMHighResTimeStamp) { + + const controllers = navigator.getGamepads(); + const currentlyPressed = new Set(); + for (let controller of controllers) { + if (!controller) continue; + + + if (controller.buttons[1].pressed) { + currentlyPressed.add(GbaKey.A); + } + if (controller.buttons[0].pressed) { + currentlyPressed.add(GbaKey.B); + } + if (controller.buttons[5].pressed) { + currentlyPressed.add(GbaKey.R); + } + if (controller.buttons[4].pressed) { + currentlyPressed.add(GbaKey.L); + } + + if (controller.buttons[8].pressed) { + currentlyPressed.add(GbaKey.Select); + } + + if (controller.buttons[9].pressed) { + currentlyPressed.add(GbaKey.Start); + } + + if (controller.buttons[12].pressed) { + currentlyPressed.add(GbaKey.Up); + } + if (controller.buttons[13].pressed) { + currentlyPressed.add(GbaKey.Down); + } + if (controller.buttons[14].pressed) { + currentlyPressed.add(GbaKey.Left); + } + if (controller.buttons[15].pressed) { + currentlyPressed.add(GbaKey.Right); + } + + if (controller.axes[0] < -.5) { + currentlyPressed.add(GbaKey.Left); + } + if (controller.axes[0] > .5) { + currentlyPressed.add(GbaKey.Right); + } + if (controller.axes[1] < -.5) { + currentlyPressed.add(GbaKey.Up); + } + if (controller.axes[1] > .5) { + currentlyPressed.add(GbaKey.Down); + } + + + } + + for (let oldButton of previouslyPressedButtons) { + if (!currentlyPressed.has(oldButton)) { + mgbaModule.current.buttonUnpress(oldButton); + } + } + + for (let newButton of currentlyPressed) { + if (!previouslyPressedButtons.has(newButton)) { + mgbaModule.current.buttonPress(newButton); + } + } + + previouslyPressedButtons = currentlyPressed; + + if (!stopped) { + window.requestAnimationFrame(raf); + } + } + + function gamepadConnectedEvent() { + + } + + window.addEventListener("gamepadconnected", gamepadConnectedEvent); + + window.requestAnimationFrame(raf); + return () => { stopped = true; window.removeEventListener("gamepadconnected", gamepadConnectedEvent); }; + }, [mgbaModule]); +} \ No newline at end of file