DXライブラリとC言語でゲームプログラミングその8。今回はキーコンフィグの実装。対象はXInputのゲームパッド。
キーコンフィグを実装したい
前々回、前回とゲームパッドの入力を得る実装をしたので今回はその流れのままキーコンフィグの実装に移ろうと思う。ジャンルにもよるがPCゲームの場合まずキーコンフィグ機能は搭載されているはず。
今回キーコンフィグの対象はとりあえずゲームパッドのみ。キーボードの操作もコンフィグできるようにしたいけどまずはゲームパッドから。前回Input.cpp/hに作ったゲーム内の操作をまとめた構造体 config_t の各項目に入っている数字がゲームパッドの各ボタンに対応する番号が入っている。なのでこれを変えれるようにすることでキーコンフィグを実装する。
例のよってXInput対応のゲームパッドで3Dゲームを作る前提です。
実装
キーコンフィグの内容を見れるようにする必要があるのでまずシーン管理作成の際に作ったConfig.cppに以下のコードを追加。
Config.cpp
//以下の変数・関数を追加または変更
const static int KEYCONFIG_X = 64;
const static int KEYCONFIG_Y = 96;
typedef enum {
eConfig_Confirm, //決定ボタン
eConfig_Attack, //攻撃ボタン
eConfig_Jump, //ジャンプ(キャンセル)ボタン
eConfig_Dash, //ダッシュボタン
eConfig_Menu, //メニューボタン
eConfig_Exit,
eConfig_Num, //本項目の数
} eConfig;
static int NowSelect = eConfig_Confirm; //現在の選択状態(初期はメニューの一番上)
//更新
void Config_Update() {
//キーコンフィグ
switch (NowSelect) {
case eConfig_Confirm:
Input_CheckKeyConfig(KEYCONFIG_CONFIRM);
break;
case eConfig_Attack:
Input_CheckKeyConfig(KEYCONFIG_ATTACK);
break;
case eConfig_Jump:
Input_CheckKeyConfig(KEYCONFIG_JUMP);
break;
case eConfig_Dash:
Input_CheckKeyConfig(KEYCONFIG_DASH);
break;
case eConfig_Menu:
Input_CheckKeyConfig(KEYCONFIG_MENU);
break;
default:
break;
}
//中略
if (NowSelect == eConfig_Exit) {
if (Input_GetGamepadDown(config.confirm)) { //キャンセル(ジャンプ)ボタンが押されていたら
NowSelect = eConfig_Confirm;
SceneMgr_ChangeScene(eScene_Menu);//シーンをメニューに変更
}
}
}
//描画
void Config_Draw() {
int y = KEYCONFIG_Y;
DrawString(CONFIG_X, CONFIG_Y, "設定画面です。", GetColor(255, 255, 255));
//キーコンフィグの内容を表示
DrawFormatString(KEYCONFIG_X, KEYCONFIG_Y, GetColor(255, 255, 255), "決定 : %d", config.confirm);
DrawFormatString(KEYCONFIG_X, KEYCONFIG_Y + 20, GetColor(255, 255, 255), "攻撃 : %d", config.attack);
DrawFormatString(KEYCONFIG_X, KEYCONFIG_Y + 40, GetColor(255, 255, 255), "ジャンプ・キャンセル : %d", config.jump);
DrawFormatString(KEYCONFIG_X, KEYCONFIG_Y + 60, GetColor(255, 255, 255), "ダッシュ : %d", config.dash);
DrawFormatString(KEYCONFIG_X, KEYCONFIG_Y + 80, GetColor(255, 255, 255), "メニューを開く : %d", config.menu);
DrawString(KEYCONFIG_X, KEYCONFIG_Y + 120, "キーコンフィグを終了する", GetColor(255, 255, 255));
switch (NowSelect) {
case eConfig_Confirm:
y = KEYCONFIG_Y;
break;
case eConfig_Attack:
y = KEYCONFIG_Y + 20;
break;
case eConfig_Jump:
y = KEYCONFIG_Y + 40;
break;
case eConfig_Dash:
y = KEYCONFIG_Y + 60;
break;
case eConfig_Menu:
y = KEYCONFIG_Y + 80;
break;
case eConfig_Exit:
y = KEYCONFIG_Y + 120;
break;
default:
break;
}
DrawString(KEYCONFIG_X - 30, y, "■", GetColor(255, 255, 255));
}Config_Draw()にキーコンフィグの内容を選択項目として表示させるコードを追加。今回は各項目に入っているゲームパッドボタンの番号を表示させるので DrawString() ではなく DrawFormatString() の方を使用。
本当は番号ごとにAボタン、Bボタンのように表示した方がいいのだがとりあえず数字のままで。
そしてConfig_Updateにキーコンフィグを行う関数を呼ぶ。キーコンフィグを行う関数はInput.cpp/hに記載。
Input.cpp
//以下のコードを追加
//キーコンフィグ本体。他の項目に同じ番号があればそれと交換する
void Input_ChangeKeyConfig(int Number, int ConfigSelect) {
if (ConfigSelect == KEYCONFIG_CONFIRM) {
if (config.attack == Number) {
config.attack = config.confirm;
}
else if (config.jump == Number) {
config.jump = config.confirm;
}
else if (config.dash == Number) {
config.dash = config.confirm;
}
else if (config.menu == Number) {
config.menu = config.confirm;
}
config.confirm = Number;
}
if (ConfigSelect == KEYCONFIG_ATTACK) {
if (config.confirm == Number) {
config.confirm = config.attack;
}
else if (config.jump == Number) {
config.jump = config.attack;
}
else if (config.dash == Number) {
config.dash = config.attack;
}
else if (config.menu == Number) {
config.menu = config.attack;
}
config.attack = Number;
}
if (ConfigSelect == KEYCONFIG_JUMP) {
if (config.confirm == Number) {
config.confirm = config.jump;
}
else if (config.attack == Number) {
config.attack = config.jump;
}
else if (config.dash == Number) {
config.dash = config.jump;
}
else if (config.menu == Number) {
config.menu = config.confirm;
}
config.jump = Number;
}
if (ConfigSelect == KEYCONFIG_DASH) {
if (config.confirm == Number) {
config.confirm = config.dash;
}
else if (config.attack == Number) {
config.attack = config.dash;
}
else if (config.jump == Number) {
config.jump = config.dash;
}
else if (config.menu == Number) {
config.menu = config.dash;
}
config.dash = Number;
}
if (ConfigSelect == KEYCONFIG_MENU) {
if (config.confirm == Number) {
config.confirm = config.menu;
}
else if (config.attack == Number) {
config.attack = config.menu;
}
else if (config.jump == Number) {
config.jump = config.menu;
}
else if (config.dash == Number) {
config.dash = config.menu;
}
config.menu = Number;
}
}
//キーコンフィグをするかの確認。ゲームパッドの入力があれば各項目のキーコンフィグを行う
void Input_CheckKeyConfig(int ConfigCode) {
int i;
//ゲームパッドの入力を確認
//左右スティックは除く(どのゲームも左が移動、右がカメラ操作と固定されているため)
//十字キーも除く(メニュー画面での操作の関係)
for (i = XINPUT_BUTTON_START; i < XINPUT_THUNMBL_UP; i++) {
//入力があればconfigの該当する値を変更
if (Input_Gamepad[i] > 0) {
switch (ConfigCode) {
case KEYCONFIG_CONFIRM:
Input_ChangeKeyConfig(i, KEYCONFIG_CONFIRM);
break;
case KEYCONFIG_ATTACK:
Input_ChangeKeyConfig(i, KEYCONFIG_ATTACK);
break;
case KEYCONFIG_JUMP:
Input_ChangeKeyConfig(i, KEYCONFIG_JUMP);
break;
case KEYCONFIG_DASH:
Input_ChangeKeyConfig(i, KEYCONFIG_DASH);
break;
case KEYCONFIG_MENU:
Input_ChangeKeyConfig(i, KEYCONFIG_MENU);
break;
default:
break;
}
}
}
}Input.h
//以下の変数・関数を追加 const static int KEYCONFIG_UP = 0; const static int KEYCONFIG_DOWN = 1; const static int KEYCONFIG_LEFT = 2; const static int KEYCONFIG_RIGHT = 3; const static int KEYCONFIG_CONFIRM = 4; const static int KEYCONFIG_ATTACK = 5; const static int KEYCONFIG_JUMP = 6; const static int KEYCONFIG_DASH = 7; const static int KEYCONFIG_MENU = 8; void Input_ChangeKeyConfig(int Number, int ConfigSelect); void Input_CheckKeyConfig(int ConfigCode);
Input_CheckKeyConfig() でゲームパッドの入力があるか確認し、入力があればInput_ChangeKeyConfig() を呼んで現在選択中の項目に押されているボタンに対応する番号を格納する。その際他の項目に同じ番号が使われていると困るので被ってないか探し、被っていれば現在選択中の項目に入っている番号と交換する。
補足
今回実装しているキーコンフィグだが、十字キーおよびアナログスティックの入力は拾っていない。アナログスティックについてはどの3Dゲームも左スティックが移動、右スティックがカメラ操作と決まっているので「変える必要はない」ものとして判断。十字キーはメニュー操作ができなくなるので外しているが、もし十字キーもキーコンフィグの対象にしたい場合はコンフィグ画面内ではキーボードかアナログスティックでのみ項目を選択できるようにしておく。
またキーコンフィグをできるようにはしたものの一度終了させるとキーコンフィグ内容が消えてしまうので外部に出力して保存しておく必要がある。セーブデータの作成については後程。

コメント