DXライブラリとC言語でゲームプログラミングその7。前回作ったゲームパッドで操作する機能の改善。XInputで3Dゲームを作る前提です。
前回はこちら↓
キーボードとゲームパッドの入力の統合
前回ゲームパッドで操作できるようにしたがキーボードとは独立してでの判定。このままでも操作することはできるが、先人の実装コードを見るとキーボードとゲームパッドの入力を統合するのが普通。キーコンフィグを実装するなら特に。
実装するにあたりまずはゲーム内での操作(左右上下に移動、ジャンプ、攻撃、ダッシュetc)をまとめた構造体を定義し、各操作ごとに番号を振っていく。そしてその番号を使ってキーボードとゲームパッドの入力を統合していく。
実装
さっそくコードをペタリ。
Input.h
//Input.hに以下の変数・関数を追加 //ゲームの操作をまとめた構造体(中身は一例) typedef struct { int up; int down; int left; int right; int confirm; //決定ボタン int attack; int jump; //今回はキャンセルボタンも兼ねる int dash; int menu; }config_t; extern config_t config; void Input_Initialize(); void Input_Merge(int* p, int k);
まず Input.h にゲーム内の操作一覧をまとめた構造体 config_t を記載して extern config_t configを宣言。externをつけないと多重定義エラーが出るので注意。
Input.cpp
//以下の変数・関数を追加 config_t config; //入力関連の初期化 void Input_Initialize() { config.up = 0; config.down = 1; config.left = 2; config.right = 3; config.confirm = 13; config.attack = 14; config.jump = 12; config.dash = 9; config.menu = 4; } //2つの引数の比較。大きい方を1つ目の引数に代入 void Input_Merge(int *p, int k) { //片方が離された瞬間(-1)でもう片方が入力なし(0)の場合 if (*p == -1 && k == 0) { return; } else if (*p == 0 && k == -1) { *p = k; return; } //それ以外 *p = *p > k ? *p : k; } //ゲームパッドの入力状態を更新する void Input_UpdateGanepad() { //中略 //以下を追加 //キーボードとゲームパッドの入力を統合 Input_Merge(&Input_Gamepad[config.up], Input_Keyboard[KEY_INPUT_UP]); Input_Merge(&Input_Gamepad[config.down], Input_Keyboard[KEY_INPUT_DOWN]); Input_Merge(&Input_Gamepad[config.left], Input_Keyboard[KEY_INPUT_LEFT]); Input_Merge(&Input_Gamepad[config.right], Input_Keyboard[KEY_INPUT_RIGHT]); Input_Merge(&Input_Gamepad[config.confirm], Input_Keyboard[KEY_INPUT_RETURN]); Input_Merge(&Input_Gamepad[config.attack], Input_Keyboard[KEY_INPUT_A]); Input_Merge(&Input_Gamepad[config.jump], Input_Keyboard[KEY_INPUT_S]); Input_Merge(&Input_Gamepad[config.dash], Input_Keyboard[KEY_INPUT_LSHIFT]); Input_Merge(&Input_Gamepad[config.menu], Input_Keyboard[KEY_INPUT_SPACE]); }
Input.cpp には先ほどのconfig_t configを再度宣言し、初期化する関数を追加。次にキーボードとゲームパッドの入力内容を比較する関数を用意。ゲームパッドの入力を得る関数の最後に入力を統合する関数を追加。結果はゲームパッドの入力を格納する方の配列に入れる。
あとはMenu.cppなどのキー入力確認の部分を以下のように変更する。
Menu.cpp
//更新 void Menu_Update() { if (Input_GetGamepadDown(config.down) || Input_GetGamepadDown(XINPUT_THUNMBL_DOWN)) { //下が押されていたら NowSelect = (NowSelect + 1) % eMenu_Num;//選択状態を一つ下げる } if (Input_GetGamepadDown(config.up) || Input_GetGamepadDown(XINPUT_THUNMBL_UP)) { //上が押されていたら NowSelect = (NowSelect + (eMenu_Num - 1)) % eMenu_Num;//選択状態を一つ上げる } if (Input_GetGamepadDown(config.confirm)) { //攻撃(決定)ボタンが押されたら switch (NowSelect) {//現在選択中の状態によって処理を分岐 case eMenu_Game://ゲーム選択中なら SceneMgr_ChangeScene(eScene_Game);//シーンをゲーム画面に変更 break; case eMenu_Config://設定選択中なら SceneMgr_ChangeScene(eScene_Config);//シーンを設定画面に変更 break; default: break; } } }
Config.cppおよびGame.cppの方も同様にキー入力確認の部分を書き変えていく。
補足
今回でキーボードとゲームパッドの入力を統合したわけだが、上の実装例を見て「ゲームパッドの十字キーと左スティックの入力も1つにまとめないのか」と思った人がいると思う。
これは実際の3Dゲーム上で操作する場合、十字キーと左スティックには違う操作を割り当てる必要がある(例:十字キーはホットキー移動・切り替え、左スティックはプレイヤーの移動)ことがあるので今回は統一していない。
弾幕STGゲームなど2D操作でかつ操作数も少ない場合はもちろん統合してもよし。
コメント