Webに少しでも関連させればどんなことでも自由に発表していい上にオーディエンスがみんな優しい、日本一発表の敷居が低いイベント「俺聞け11」で、ゲームパッドでブラウザゲームを操作できるGamepad APIについて紹介・発表してきました。
Gamepad APIはその名のとおり、JavaScriptでゲームパッドからの入力を受け取ることが出来るAPIです。
Firefox, Chrome, Operaは既に対応済みですし、IEでも次期バージョンでは対応される予定になっています。
Safari…? ちょっと知らない子ですね…。
発表の時に使ったスライドは、TypeScript+Knockout.jsのWebアプリとして作りました。
ゲームパッドで操作できるようにしているので、発表スライドであると同時にデモも兼ねています。
BitBucketに非公開リポジトリを置いて管理してはいるんですが、権利上の問題でお見せすることはできません…。
代わりに、Gamepad APIを使うサンプルコードと、はまりがちな落とし穴をざっくりですが紹介します。
function checkGamepads(){ var gamepadList = navigator.getGamepads(); for(var i=0; i<gamepadList.length; i++){ var gamepad = gamepadList[i]; // ブラウザによっては配列にundefinedが入っている場合がある if(gamepad){ // Gamepad#id string ゲームパッドのデバイス名等 console.log(gamepad.id) // => "Xbox 360 Controller (XInput STANDARD GAMEPAD)" // Gamepad#mapping string キーマップピングが標準かどうか // ("standard"…標準 ""(空文字列)…独自) console.log(gamepad.mapping); // => "standard" // Gamepad#axes double[] 方向キーの入力方向と強さの配列 // (0が真ん中、-1に近づくと上/左方向、1に近づくと下/右方向) // キーに触ってないときもちょうど0になるわけではなく0.03くらいの値になるので注意 console.log(gamepad.axes); // => [ // -0.9935354739878914, // 0.03535467849054890, // -0.5789490786325657, // 0.6474398798231042 // ] // Gamepad#buttons GamepadButton[] -> ボタンオブジェクトの配列 for(var i=0; i<gamepad.buttons.length; i++){ var button = gamepad.buttons[i]; // GamepadButton#pressed bool ボタンが押されているかどうか console.log(button.pressed); // => true; // GamepadButton#value double (アナログ入力の場合)押されている強さ(0~1) // アナログ入力でない場合は0/1のみ console.log(button.value); // => 0.7893214690458746648 } } } window.requestAnimationFrame(checkGamepads); } // ボタンが押されたり、方向キーの入力強さが変わったりしてもイベントは発生しないので、 // requestAnimationFrameを使い、ブラウザの描画更新タイミングごとに値をチェックする window.requestAnimationFrame(checkGamepads);
標準のキーマッピングとは
Xbox360コントローラやPlayStation3のDualShock3で採用されている、ABXY・LR×2・セレクト・スタート・アナログ方向キー×2・上下左右・センターというキーマッピングがGamepad APIにおける「標準」として扱われています。
各ボタンと、Gamepad#Buttons配列におけるインデックスの対応は次のとおりです
インデックス | ボタン | |
---|---|---|
0 | A | (任天堂系のコントローラとはAとB、XとYの位置が逆) |
1 | B | |
2 | X | |
3 | Y | |
4 | LB | PS系・任天堂系だとLR1 |
5 | RB | |
6 | LT | 〃LR2 アナログ入力対応 |
7 | RT | |
8 | セレクト | |
9 | スタート | |
10 | アナログ方向キー(左) | |
11 | アナログ方向キー(右) | |
12 | 十字キー上 | DualShock3だとアナログ入力対応 |
13 | 十字キー下 | |
14 | 十字キー左 | |
15 | 十字キー右 | |
16 | センター | Xbox360コントローラならXboxロゴ、DualShock3ならPSロゴボタン |
また、アナログ方向キーの強さが格納されているaxes配列の対応は次のとおりです
インデックス | キー |
---|---|
0 | 左側キー左右 |
1 | 左側キー上下 |
2 | 右側キー左右 |
3 | 右側キー上下 |
落とし穴たくさん
Windowsだとセンターボタン(Xox360コントローラで言うとXboxロゴのボタン)が反応しない
Windowsだとセンターボタン(Xox360コントローラで言うとXboxロゴのボタン)が反応しない
よくわかりません。Macでは反応しました。
WindowsだとDualShock3が使えない
ドライバが無いからだと思います。なんでMacでは普通に動くんだろう…。
MacのFirefoxだとXbox360コントローラが認識されない
なんか認識されませんでした。Chromeでは認識されたのでドライバのせいではないと思います。Windowsでは大丈夫でした。
MacのFirefoxだとDualShock3が標準キーマッピング扱いにならない
なぜか独自キーマッピングとして扱われてしまいます。
キーマッピングが標準ではない場合、どの数字がどのボタンに対応しているかは製品によってバラバラ
市販のPC用ゲームパッドの中には、往年の人気ゲーム機のコントローラを模したものもあります。
こういうゲームパッドの場合、ボタン数が少ないので標準のキーマッピングに当てはめることができません。
そういう場合はデバイスごとの独自キーマッピングになるのですが、独自キーマッピングの場合、どのインデックスがどのボタンに対応しているかを知ることはできません。
いちいち対応するのも面倒なので、標準ではないキーマッピングのゲームパッドを使っている人にはキーコンフィグを作って自分で設定してもらうようにするか、あるいはばっさり切り捨ててしまうのも手です。
Gamepad#idがOS・ブラウザによってバラバラ
Gamepad#idで取得できる文字列にはベンダIDとプロダクトIDが埋め込まれているので、独自キーマッピングのデバイスでも個別対応しようと思えばできなくもないのですが、その値がOS・ブラウザごとにバラバラなので使い物になりません
OS | ブラウザ | ID |
---|---|---|
Windows | Chrome |
"USB 2A8K GamePad (Vendor: 040b Product: 6530)" |
Firefox |
"040b-6530-USB 2A8K GamePad " |
|
Mac | Chrome |
"USB 2A8K GamePad (Vendor: 040b Product: 6530)" |
Firefox |
"40b-6530-USB 2A8K GamePad" |
どうしてこうなった
余談
プレゼン中に鳴っていた効果音について
プレゼンの文字を1文字ずつ表示するときや、ページ送りをするときに、「プププププププ…」「ピッ」って感じのファミコン風の効果音が流れるようにしていました。
プレゼン中は特に言及しなかったんですが、あの音は、実はブラウザ上でリアルタイムに生成していました。
音声ファイルは一切使用していません。
JavaScriptで任意の音声波形を生成したり、エフェクトをかけたりして音声を再生できる、Web Audio APIというAPIを使っています。
ゲームの効果音として使う場合、音声ファイルを事前に読み込んでおき、適切なタイミングで再生するのが普通だと思うんですが、今回は音声が単純なのでそれっぽい周波数の矩形波をリアルタイムで生成して再生していました。
コナミコマンドについて
プレゼンの終盤に、ゲームパッドでコナミコマンドを入力すると、画面上部に表示されていたスコアがカンストする(9999999点)という小ネタをやりました。
これは、ゲームパッドで入力されたキーの履歴を最新10回分記録しておいて、その履歴がコナミコマンドと一致したら実行、という仕組みで実装しました。
これはそのうちサンプルコードかライブラリか何かを公開するつもりです。
参考資料とか
- W3C Gamepad API仕様書 (2015年2月14日現在Working Draft)
- マイクロソフト有線 ゲーム コントローラーXbox 360 Controller for Windows リキッド ブラック 52A-00006
プレゼンで使ったゲームパッド - PixelMplus
プレゼン画面に使ったレトロゲーム画面風ドットフォント - Gamepad-Sample
Gamepad APIで取得できるゲームパッドの入力値を視覚化する、Microsoft IEチームのサンプルコード - Escape from XP
Microsoftが、WindowsXPの一刻も早い撲滅を願って制作したブラウザゲーム(ゲームパッド操作対応、音量注意!)
[…] ゲームパッドでブラウザゲームを操作できるGamepad APIが楽しい【俺聞け11】 | mzsm.me [ゲームパッド][ブラウザ][Chrome]VR ゲームとかと相性良さそう/Androidで動くといいのにな […]