基本的な使い方は例のとこにもあるのですが、
webに上がってる情報だけではいろいろと不足ということで。
index は当てにするべからず
コントローラ1つだけという仕様であれば気にする必要ないですが、
複数のコントローラを扱うときは要注意。
Gamepad.indexは、認識された順に0から付与されていきます。
すなわち
- 実行中にコントローラを追加
- ページをリロード
といった手順でindexの入れ替わり、すなわち操作対象の入れ替わりが発生し得ると。
仕様的にあかんやつですね。
というわけで…
プレイヤー本位の仕様にしよう
大抵のゲームでは、プレイヤーは最大何人で、それぞれのプレイヤーはどんな位置付けか
仕様として明確に決まっています。つまり、Gamepad.indexではなく、この仕様に準じた
プレイヤー番号で配列を扱うべきであり、それぞれのプレイヤーに対応するGamepad.index
のコントローラを参照(または未割り当て)といった構造にすることが最善手となります。
コントローラを合理的に割り当てよう
では、認識順に入ってくるgamepadconnectedイベントでは、
それぞれどのプレイヤーに割り当てるとよいでしょうか。
-
切断前に使っていたコントローラに合わせる
ゲーム中に一旦コントローラを外してまた戻したとき、そのコントローラは
どのプレイヤーに割り当てるべきでしょうか。いうまでもなく、
外す前に使っていたプレイヤーです。
というわけで、gamepaddisconnectedイベントが発生した後でも
使っていたコントローラのGamepad.id値は保持しておきましょう。
再度同じGamepad.idでgamepadconnectedイベントが来たとき、
外したプレイヤーに再優先で割り当てます。 -
ユーザ設定優先
多くのPCゲームでは、何番目のプレイヤーがどのコントローラを扱うかという
ユーザ設定があります。
その設定をプレイヤー順に調べ、Gamepad.idと一致するところを優先します。
ただし、そのプレイヤーが既に別のコントローラを扱うことになっている場合は、
勝手に差し替えるのもよくないのでスルーとします。 -
その他のプレイヤー
特別な措置が必要なくなったところで、他の未設定プレイヤーに割り当てていきます。
さらなる問題点
Gamepad.idって、idを名乗ってるくせに同一製品が複数繋がっていると重複してます。
実際に参照されるのはindexの方なので、共存して使い分けることはできます。
ただ、どのプレイヤーがどちらという観点では、明確に区別する方法が(たぶん)ない。
同一製品2つ外して差し直したら入れ替わる可能性ありますが、諦めましょう。
動作確認はChrome/EdgeとFirefox双方で
Firefoxでは、gamepadconnectedイベントで入ってきたGamepadインスタンスを
保持しておけばそこから操作を読み取ることは可能ですが、この実装では
ChromeやEdgeで反応しなくなります。
公式手順通りnavigator.getGamepads()で取得すればよいのですが、
テストする側としてはChromeやEdgeで行う必要あるところです。
逆に、Firefoxではコントローラの操作が発生するまでgamepadconnectedイベントが
来ない特性があったりして、実装によっては検出漏れもあり得るので、
Firefoxでのテストも必要になってきます。
他のブラウザは…未調査(ぉ
DInputコントローラにも対応しよう
近年ではXbox仕様の13ボタンコントローラが主流となっていますが、
ボタンが13個にデグレで決め打ちされててセガサターン等の6ボタン配列にもなってなくて
ゲームによってはとても不便なので、筆者は16ボタンのDInputコントローラを
主に使ってたりします。
(現行製品がもうサンワサプライぐらいしか残ってないの困ったもんだ)
ボタン数
筆者が確認した限りでは、最大24ボタン
方向キー
XInputでは方向キーも通常のボタン扱いですが、DInputではハットスイッチ扱いに
なっているので、特殊な扱いが必要となります。
筆者が確認した限りでは Gamepad.axis[9] が該当のようですが、全てそこかは不明。
ニュートラルのとき±1から大きく離れた値になっているので、それを検出するのが確実。
方向キーを上方向に入れると-1、そこから時計回りに左上で+1、その間は7等分
…というなんか変な仕様。
これって本物の無段階ハットスイッチが正しく反応しないような。
製品持ってないから確認できないけど。
(20年ぐらい前に店頭で見かけたやつ、確保してなかったのが悔やまれる)
(あとSteamDeckのトラックパッドがハットスイッチらしいのだが確認できず)
アナログスティック
製品により、右スティックの該当箇所が全く違ってたり。
左スティックは Gamepad.axis[0,1] で固定?(信用はしてない)
まぁ、通常ボタンでさえ製品により違うのがDInputなので。
コントローラテスト
とりあえず適当に作ってみた
Unlicenseにしてあるので、ソース持ってって流用してもよいです。
ぼやき
ほんとはSteamDeckでの反応をみたかったのだが、認識されなかった。
OMG.