ゲームパッドに対応

基本形

まず接続確認

毎フレーム取得

ゲームループ内で

を呼びます。

Xbox配列

ほぼ標準です。

ボタンindex
A0
B1
X2
Y3
LB4
RB5
LT6
RT7
Select8
Start9
左スティック押し込み10
右スティック押し込み11
12
13
14
15

キーボード風に扱う

例えば

updateGamepad() {
const pad = navigator.getGamepads()[0];
if (!pad) return;

this.lFlip.on = pad.buttons[14].pressed;
this.rFlip.on = pad.buttons[15].pressed;
}

すると

  • ←で左フリッパー
  • →で右フリッパー

になります。

押した瞬間だけ検出

問題は

pad.buttons[0].pressed

は押している間ずっとtrueです。

キーボードのkeydown相当を作るには

this.prevButtons = [];

を用意して

こうすると

  • keydown相当
  • keyup相当

が作れます。

例えば

上キー(W)

上キー離す

アナログスティック対応

左スティック

範囲

左     -1.0
中央 0.0
右 1.0

例えば

navigator.getGamepads();

navigator.getGamepads()メソッドの返り値は、端末に接続されているゲームパッドの情報を格納した 配列(Array または GamepadList です。

この配列の各要素には以下のデータが格納されています:

  • 接続されている場合Gamepadオブジェクト
  • 未接続・スロットが空の場合null

💡 重要なポイント

  • ブラウザによる違い: 配列の要素数はブラウザによって仕様が異なります。たとえば、Google Chromeでは常に固定で4つの枠([Gamepad0, Gamepad1, null, null] など)が用意されています。
  • インデックス番号: 配列の index プロパティ(03など)は、物理的なデバイスのポートや接続順に対応しています。
  • ポーリングの必要性: 状態を常に最新に保つには、このメソッドを毎フレーム呼び出す(ポーリングする)必要があります。

e.gamepad.index

const gamepads = navigator.getGamepads();

で得られる配列の添字と一致します。

例えば、

window.addEventListener('gamepadconnected', (e) => {
console.log('index=', e.gamepad.index);
});

index=1

と表示されたなら、

const pad = navigator.getGamepads()[1];

でそのゲームパッドにアクセスできます。

複数接続時

例えば

Xbox Controller → index=0
PS5 Controller → index=1

なら

navigator.getGamepads()

[
Gamepad, // index 0
Gamepad // index 1
]

となります。

切断すると穴が空く

例えば index=0 のパッドを抜くと

[
null,
Gamepad
]

のようになります。

なので、

for (const pad of navigator.getGamepads()) {
if (!pad) continue;

// 処理
}

のように null を飛ばすのが定番です。

接続時に管理する例

ただし、e.gamepad は接続時のスナップショットなので、

実際のボタン状態を読むときは毎フレーム

const pad = navigator.getGamepads()[index];

で取得し直す方が確実です。

つまり、

e.gamepad.index

navigator.getGamepads() の何番目に入っているか」

を表す番号です。

これを使えば、

  • プレイヤー1 → index 0
  • プレイヤー2 → index 1

のような複数人プレイにも対応できます🙋

コメント

タイトルとURLをコピーしました