Skip to content

Instantly share code, notes, and snippets.

@Kos
Last active December 13, 2020 20:37
Show Gist options
  • Save Kos/531a5646333bf5eac2eb3db051df35a6 to your computer and use it in GitHub Desktop.
Save Kos/531a5646333bf5eac2eb3db051df35a6 to your computer and use it in GitHub Desktop.
// https://w3c.github.io/gamepad/#dfn-standard-gamepad-layout
const Dpad = {
UP: 12,
LEFT: 14,
RIGHT: 15,
DOWN: 13,
};
const Buttons = {
A: 0,
B: 1,
X: 2,
Y: 3,
R1: 5,
R2: 7,
L1: 6,
L2: 8,
};
const gamepad = {
isUp: function () {
return buttonPressed(Dpad.UP) || axisIs("up");
},
isLeft: function () {
return buttonPressed(Dpad.LEFT) || axisIs("left");
},
isRight: function () {
return buttonPressed(Dpad.RIGHT) || axisIs("right");
},
isDown: function () {
return buttonPressed(Dpad.DOWN) || axisIs("down");
},
isSpace: function () {
// A or right shoulder or right trigger
return (
buttonPressed(Buttons.A) ||
buttonPressed(Buttons.R1) ||
buttonPressed(Buttons.R2)
);
},
};
function buttonPressed(index) {
if (typeof navigator.getGamepads !== 'function') {
return false;
}
return [...navigator.getGamepads()]
.filter(
(gamepad) =>
gamepad && gamepad.buttons[index] && gamepad.buttons[index].pressed
)
.length > 0;
}
function axisIs(direction) {
if (typeof navigator.getGamepads !== 'function') {
return false;
}
return [...navigator.getGamepads()]
.filter(
(gamepad) =>
gamepad &&
gamepad.axes.length >= 2 &&
checkAxis(direction, gamepad.axes[0], gamepad.axes[1])
)
.length > 0;
}
function checkAxis(direction, bx, by) {
// Given expected direction (as string) and a vector, return true if cardinal direction matches the vector.
const DEADZONE = 0.8;
const DEADZONE_SQUARED = DEADZONE * DEADZONE;
if (bx * bx + by * by < DEADZONE_SQUARED) {
return false;
}
const v = Math.atan2(bx, by);
if (direction == "down") {
return v > -Math.PI / 4 && v < Math.PI / 4;
} else if (direction == "left") {
return v > (-3 * Math.PI) / 4 && v < -Math.PI / 4;
} else if (direction == "right") {
return v > Math.PI / 4 && v < (3 * Math.PI) / 4;
} else if (direction == "up") {
return v > (3 * Math.PI) / 4 || v < (-3 * Math.PI) / 4;
}
}
// Demo
function display() {
requestAnimationFrame(display);
gamepad.isUp();
document.body.innerText = [
"Status:",
gamepad.isSpace() ? "SPACE" : "",
gamepad.isUp() ? "Up" : "",
gamepad.isDown() ? "Down" : "",
gamepad.isLeft() ? "Left" : "",
gamepad.isRight() ? "Right" : "",
].join(" ");
}
requestAnimationFrame(display);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment