広告あり

【DXライブラリ】ゲームパッドで操作できるようにするその2

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操作でかつ操作数も少ない場合はもちろん統合してもよし。

コメント

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