Last active
September 9, 2025 23:36
-
-
Save Xorboo/358b1159b51690fb39876d97e8c29442 to your computer and use it in GitHub Desktop.
Joystick reaction checker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Joystick Reaction Test</title> | |
| <style> | |
| html, body { | |
| margin: 0; | |
| padding: 0; | |
| height: 100%; | |
| background-color: red; | |
| color: white; | |
| font-family: sans-serif; | |
| font-size: 3rem; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| user-select: none; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="info">Press joystick button to start</div> | |
| <script> | |
| let state = 'waiting'; // 'waiting', 'ready', 'timing', 'done' | |
| let startTime = 0; | |
| let endTime = 0; | |
| let gamepadIndex = null; | |
| let buttonPressed = false; | |
| const info = document.getElementById('info'); | |
| function waitForGamepad() { | |
| window.addEventListener("gamepadconnected", (e) => { | |
| gamepadIndex = e.gamepad.index; | |
| info.textContent = "Joystick connected. Press button to begin."; | |
| }); | |
| const pads = navigator.getGamepads(); | |
| for (let i = 0; i < pads.length; i++) { | |
| if (pads[i]) { | |
| gamepadIndex = i; | |
| info.textContent = "Joystick connected. Press button to begin."; | |
| break; | |
| } | |
| } | |
| } | |
| function update() { | |
| const gp = navigator.getGamepads()[gamepadIndex]; | |
| if (!gp) { | |
| requestAnimationFrame(update); | |
| return; | |
| } | |
| const pressed = gp.buttons.some(btn => btn.pressed); | |
| if (state === 'waiting') { | |
| if (pressed && !buttonPressed) { | |
| buttonPressed = true; | |
| startReadySequence(); | |
| } | |
| } else if (state === 'ready') { | |
| // Do nothing while waiting to turn green | |
| } else if (state === 'timing') { | |
| if (pressed && !buttonPressed) { | |
| buttonPressed = true; | |
| endTime = performance.now(); | |
| const reaction = Math.round(endTime - startTime); | |
| document.body.style.backgroundColor = 'blue'; | |
| info.textContent = `Reaction: ${reaction} ms (press to retry)`; | |
| state = 'done'; | |
| } | |
| } else if (state === 'done') { | |
| if (pressed && !buttonPressed) { | |
| buttonPressed = true; | |
| document.body.style.backgroundColor = 'red'; | |
| info.textContent = 'Press joystick button to start'; | |
| state = 'waiting'; | |
| startReadySequence(); | |
| } | |
| } | |
| if (!pressed) { | |
| buttonPressed = false; | |
| } | |
| requestAnimationFrame(update); | |
| } | |
| function startReadySequence() { | |
| info.textContent = 'Get ready...'; | |
| state = 'ready'; | |
| const delay = Math.random() * 2000 + 1000; // 1 to 3 sec | |
| setTimeout(() => { | |
| document.body.style.backgroundColor = 'green'; | |
| info.textContent = 'GO!'; | |
| startTime = performance.now(); | |
| state = 'timing'; | |
| }, delay); | |
| } | |
| window.addEventListener('load', () => { | |
| waitForGamepad(); | |
| update(); | |
| }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment