Skip to content

Instantly share code, notes, and snippets.

@Xorboo
Last active September 9, 2025 23:36
Show Gist options
  • Select an option

  • Save Xorboo/358b1159b51690fb39876d97e8c29442 to your computer and use it in GitHub Desktop.

Select an option

Save Xorboo/358b1159b51690fb39876d97e8c29442 to your computer and use it in GitHub Desktop.
Joystick reaction checker
<!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