I'm experimenting a little with gamepad api. When a button is pressed, it gets "fired" all the time until the button is released. This is cool for something like running or shooting in a game, but problematic, when I want to navigate inside a menu (e.g. going 16 menu items down instead of one).
On a normal keyboard, I would use onkeyup/onkeydown to see, when a button press has ended. But on gamepad api, I didn't find something like that.
JS:
var gamepadPressCounter = 0;
function update() {
const gamepads = navigator.getGamepads();
if (gamepads[0].buttons[0].pressed === true) {
gamepadPressCounter++;
}
window.requestAnimationFrame(update);
}
So, do you know a way to get the gamepadPressCounter only one up per press and not infinite times?
You have to check it against whether it was pressed
last time you checked. It doesn't fire events, it is stateful. You are directly checking if the button is pressed or not.
Make a variable to store the state of the button last time you checked and compare it to see if it has changed from last time.
const anyButtonPressedChangeListener = {
listeners: [],
addListener(cb) {
this.listeners.push(cb);
},
signal(state) {
for (const cb of this.listeners) {
cb(state);
}
}
}
let buttonstate = false;
const loop = () => {
const gamepads = navigator.getGamepads();
const gamepad = gamepads[0];
if (gamepad) {
const statenow = gamepad.buttons.some(btn => btn.pressed);
if (buttonstate !== statenow) {
buttonstate = statenow;
anyButtonPressedChangeListener.signal(statenow);
}
} else {
console.log("Not connected");
}
setTimeout(loop, 1000);
}
anyButtonPressedChangeListener.addListener((buttonState) => {
console.log(`Any button pressed changed to ${buttonState}`);
});
loop();