GameMakerでPad入力を自力で実装する方法
ゲームをSteamに申請するときに各ゲームパッドに対応しているのか聞かれるので、ちゃんと実装したほうがいい。
今回はライブラリを使わずに自力で実装する。
Pad入力で実際に起こった問題
Xboxのパッドは認識するが、PSのパッドは認識しない。
これは私に実際に起こった問題である。
PSのパッドが使えないとなると、購入をためらう人もいるかもしれない。ちゃんとすべてのパッドを認識するようにしたい。
色々調べた結果わかったのは、PC側がパッドをスロット番号で認識しているということ。
スロットは0~20近く(実際にはそれ以上あるかもしれない)ある。
パッドを差し込んだら、これらの番号が勝手に割り当てられる。どの番号かは我々は知る由もない。
つまりスロット番号0のパッドだけに対応したゲームだと、スロット番号4のパッドでは動かせないということになる。
どうすればいいのか?
スロット番号を調べる
簡単に言うと、パッドが差し込まれているか調べる。そしてスロット番号を変数に入れてしまう。
ゲーム中にパッドが抜かれたり、差し込まれたら検出して対応する。
そのためには非同期システムを使う。
ここらへんは私もよくわかっていないが、GameMakerの公式動画で説明している。その通りに書けば大丈夫。
要となるコードがこれ。
var _gamepad = async_load[? "pad_index"];
これでスロット番号を変数にいれることができているらしい。
そしてasync_load[? "event_type"]でパッドの抜き差しを検出できる。
gamepad discoveredならパッドが差し込まれたということ。
gamepad lostならパッドが抜かれたということ。
これらすべてを使ってコードを書くとこうなる。
コード例
gamepads = [];
gamepad_main = undefined;
スクリプトに記述。
gamepadsという配列を作っておく。
gamepad_mainは開始時には空にしておく。
オブジェクトo_inputを作り、非同期システムイベントに記述。
var _gamepad = async_load[? "pad_index"];
switch ( async_load[? "event_type"])
{
case "gamepad discovered":
array_push(global.gamepads, _gamepad);
break;
case "gamepad lost":
var _array_index = array_get_index(global.gamepads, _gamepad);
if (_array_index >= 0)
{
array_delete(global.gamepads, _array_index, 1);
}
break;
}
if array_length(global.gamepads) > 0
{
global.gamepad_main = global.gamepads[0];
}
else
{
global.gamepad_main = undefined;
}
ここでスロット番号を格納し、さらに抜き差しがあった場合も対応する。
当然ながらこのオブジェクトはroom内に配置。
var _gp = global.gamepad_main;
key_up = gamepad_button_check(_gp ,gp_padu);
そしてプレイヤーを動かす関数にスロット番号を使用する。
こういうことらしいです。よくわからない人は公式動画を自動翻訳して何度も見返してください。
公式リファレンスも一応貼っときます。
参考文献
・GameMaker公式動画
・公式リファレンス
Discussion