GamepadAPIを利用することで、ブラウザ上からゲームパッドにアクセスできるようになります。GamepadAPIはChrome、Firefox、Edgeが対応しています。
ゲームパッドAPIの利用方法
接続・切断を検出する
入力を検知するには、まずゲームパッドの接続を検出する必要があります。ゲームパッドの接続はgamepadconnectedイベント、切断はgamepaddisconnectedイベントで検出することができます。
ブラウザによっては、ゲームパッドを接続してページを開いただけではgamepadconnectedイベントが発火されないことがあります。これはセキュリティのためです。その場合は何かしらのボタンをおすことでgamepadconnectedイベントが発火されます。
addEventListener("gamepadconnected", (e) => {
let gamepad = e.gamepad;
console.log("ゲームパッドが接続されました。");
console.log("Index: %d, ID: %s, Type: %s",
gamepad.index, gamepad.id, gamepad.mapping);
});
addEventListener("gamepaddisconnected", (e) => {
let gamepad = e.gamepad;
console.log("ゲームパッドが切断されました。");
console.log("Index: %d, ID: %s, Type: %s",
gamepad.index, gamepad.id, gamepad.mapping);
});
現時点でのゲームパッドの入力情報を取得する
navigator.getGamepadsメソッドを使用することで、現時点で接続されている全てのゲームパッドの情報を取得することができます。navigator.getGamepadsメソッドはGamepadオブジェクトの配列を返すので、index値を利用して任意のゲームパッドの情報を取り出します。
addEventListener("gamepadconnected", (e) => {
let connectedGamepadIndex = e.gamepad.index;
let gamepads = navigator.getGamepads();
let gp = gamepads[connectedGamepadIndex];
});
ボタンが押されているかどうかを確認する
Gamepadオブジェクトはbuttons配列を持ちます。buttons配列にはGamepadButtonオブジェクトが格納されています。GamepadButtonオブジェクトは押下されているかどうかを表すpressedと、押されている強さを表すvalueプロパティを持ちます。通常、valueプロパティは0.0か1.0の値しか取りませんが、感圧式ボタンやLRトリガーなどの場合は0.0〜1.0の間の値を取ります。
let connectedGamepadIndex;
let loopID;
addEventListener("gamepadconnected", (e) => {
connectedGamepadIndex = e.gamepad.index;
loopID = requestAnimationFrame(loop);
});
addEventListener("gamepaddisconnected", (e) => {
connectedGamepadIndex = null;
cancelAnimationFrame(loopID);
});
// standardタイプのコントローラのマッピングです。
const BUTTON_A_INDEX = 0;
const BUTTON_B_INDEX = 1;
const BUTTON_X_INDEX = 2;
const BUTTON_Y_INDEX = 3;
const BUTTON_LB_INDEX = 4;
const BUTTON_RB_INDEX = 5;
const BUTTON_LT_INDEX = 6;
const BUTTON_RT_INDEX = 7;
const BUTTON_BACK_INDEX = 8;
const BUTTON_START_INDEX = 9;
const BUTTON_L3_INDEX = 10;
const BUTTON_R3_INDEX = 11;
const BUTTON_UP_INDEX = 12;
const BUTTON_DOWN_INDEX = 13;
const BUTTON_LEFT_INDEX = 14;
const BUTTON_RIGHT_INDEX = 15;
const BUTTON_HOME_INDEX = 16;
function loop(timestamp) {
// ゲームパッドの入力情報を毎フレーム取得します。
let gamepads = navigator.getGamepads();
let gp = gamepads[connectedGamepadIndex];
// ボタンが押されているかどうかを取得します。
let aButton = gp.buttons[BUTTON_A_INDEX];
if(aButton.pressed) {
console.log(`Aボタンが押されました。value:${aButton.value}`);
}
requestAnimationFrame(loop);
}
スティックが倒されているかどうかを確認する
スティックについても同様です。Gamepadオブジェクトはaxesプロパティを持ちます。axesプロパティは配列で、0.0から1.0のdouble値が入っています。
let connectedGamepadIndex;
let loopID;
addEventListener("gamepadconnected", (e) => {
connectedGamepadIndex = e.gamepad.index;
loopID = requestAnimationFrame(loop);
});
addEventListener("gamepaddisconnected", (e) => {
connectedGamepadIndex = null;
cancelAnimationFrame(loopID);
});
// standardタイプのコントローラのマッピングです。
const AXIS_L_HORIZONTAL_INDEX = 0;
const AXIS_L_VERTICAL_INDEX = 1;
const AXIS_R_HORIZONTAL_INDEX = 2;
const AXIS_R_VERTICAL_INDEX = 3;
function loop(timestamp) {
// ゲームパッドの入力情報を毎フレーム取得します。
let gamepads = navigator.getGamepads();
let gp = gamepads[connectedGamepadIndex];
// スティックが倒されているかどうかを取得します。
let leftAxisHorizontal = gp.axes[AXIS_L_HORIZONTAL_INDEX];
let leftAxisVertical = gp.axes[AXIS_L_HORIZONTAL_INDEX];
if(leftAxisHorizontal > 0 || leftAxisVertical > 0) {
console.log(`Lスティックが倒されました。Hor:${leftAxisHorizontal}, Ver:${leftAxisVertical}`);
}
requestAnimationFrame(loop);
}