入力の基本
■概要
入力処理はゲームで必ず用意する必要がある処理の1つです。 入力は入力デバイスが「押された」「押されてない」の判断をします。
サンプル
サンプルはここからダウンロードでき、環境については以下の内容となっています。
VSのバージョン | DirectXのバージョン |
---|---|
VisualStudio 2017 | DirectX9(June 2010) |
入力デバイス
入力は外部の入力デバイスの情報を取得します。 対象となるデバイスでよく使用するのは「ゲームパッド」「キーボード」 「マウス」「液晶(スマホ)」などです。 これらのデバイスから入力された、されていないという情報を取得します。
必須処理
入力処理の中でも最低限ライブラリ(ゲームエンジン)に必要な処理として 次の3つの処理があげられます。 「キーを押した瞬間の判定」 「キーを押しているか否かの判定」 「キーを離した瞬間の判定」 その他にゲームパッドでアナログスティックを使用する場合は スティックを倒した角度を取得する必要があったりと、 各デバイスによって取得処理が増えることがあります。 ※今回の説明やサンプルはキーボードの入力取得で行っています。
入力情報取得方法
ゲームを作成する場合に入力デバイスから入力されたかどうかを取得する方法は DirectInputやXInputなどのゲームライブラリが提供してくれている機能を使って行います。 しかし、ライブラリのサポートでは「どのキー(ボタン)が押されたか否か」しか 判断してくれないことが多いです。 なので、「キーを押しているか否かの判定」という処理は簡単にできますが、 その他の「キーを押した瞬間の判定」や「キーを離した瞬間の判定」は自分で実装します。
準備
今回のサンプルを含めた入力の説明は最も簡単とされている方法で実装します。 それは各キーの状態を保存しておくという方法です。 状態は「押されていない」「押された瞬間」「押されてる」 「離された瞬間」の4種類を用意します。
状態定義
状態の定数はdefineやconstではなく、enumで定義されてることが多いです。
enum INPUT_STATE
{
NOT_PUSH, // 押されてない
PUSH_ENTER, // 押された瞬間
PUSH, // 押されてる
PUSH_EXIT, // 離された瞬間
};
キーの割り当て
各ライブラリではキーボードの各キーの情報は定数で用意されていますが ゲームではそのキー情報の定数をそのまま使うのではなく、 まずはゲームで使用するキーの種類のenumを用意します。// ゲームで使うキー情報 enum KEY_INFO { UP_KEY, DOWN_KEY, LEFT_KEY, RIHGT_KEY, MAX_KEY_INFO, };
そして、このenumの順番とリンクした、ライブラリ側のキーの定数の配列を用意します。// ライブラリ側キー情報配列 // 定数はDirectInputで用意されているDIK_~を使用する int g_KeyInfo[] = { DIK_UP, DIK_DOWN, DIK_LEFT, DIK_RIGHT, };
ゲーム中では、KEY_INFOを使用してキーの情報を取得します。 こうすることで、割り当てているキーを変更したとしても キーを取得している部分のコードの変更する必要がなくなります。
キー状態を保存する変数の配列を用意
キー状態の宣言とキーの割り当てが終わったら、この二つの情報を使用して、
キー状態変数の配列を用意します。
この配列内の各状態を毎フレーム変更することでキーの状態を確認できるようにします。
// キー状態定数とキー情報の宣言は終わっているとする
// キーの入力状態を保存する配列
INPUT_STATE g_InputState[KEY_INFO::MAX_KEY_INFO];
状態の更新
DirectInputなどのライブラリでは入力情報の更新関数が用意されているので、 必ず毎フレーム実行して、最新の入力情報を取得します。 そして、この取得した情報を現在の入力状態と照らし合わせて状態を更新します。
キーを押した瞬間状態
「キーを押した瞬間」状態に設定する条件は以下の通りです。
該当するキーの状態が「押されていない」で 「そのフレームにキーが押された」 |
該当するキーの状態が「離された瞬間」で 「そのフレームにキーが押された」 |
キーを押している状態
「キーを押している」状態に設定する条件は以下の通りです。
該当するキーの状態が「キーを押している」で 「そのフレームでもキーが押されている」 |
該当するキーの状態が「キーを押した瞬間」で 「そのフレームでもキーが押されている」 |
キーを離した瞬間状態
「キーを離した瞬間」状態に設定する条件は以下の通りです。
該当するキーの状態が「キーを押している」で 「そのフレームでキーが押されていない」 |
該当するキーの状態が「キーを押した瞬間」状態で 「そのフレームでもキーが押されていない」 |
押していない状態
押していない状態にする条件は、今まで上で書いていた条件に当てはまらない 「全て」となるので条件分岐で「else」を用意し、状態を「押されていない」に 変更すれば、押してない状態の対応は終了です。 一応変更の条件を書いておくと以下の通りです。
該当するキーが「離された瞬間状態」で 「そのフレームでもキーが押されていない」 |
該当するキーが「押してない状態」で 「そのフレームでもキーが押されていない」 |
判定処理
各状態の判定処理は簡単で、各状態を判定する関数を用意します。 この関数の引数に判定したいキーを指定し、関数内で状態の値をチェックして 判定したい状態(押された瞬間、押されている等)だったらtrue、 そうではなかったらfalseを返します。
例
// 押した瞬間かどうかの判定関数
bool GetKeyEnter(KEY_INFO key_info)
{
// 指定されたキーの状態が押された瞬間ならtrue
return (g_InputState[key_info] == INPUT_STATE::PUSH_ENTER);
}
// 押されてるかどうかの判定関数
bool GetKey(KEY_INFO key_info)
{
// 指定されたキーの状態が押されてるならtrue
return (g_InputState[key_info] == INPUT_STATE::PUSH);
}
// 話した瞬間かどうかの判定関数
bool GetKeyExit(KEY_INFO key_info)
{
// 指定されたキーの状態が離した瞬間ならtrue
return (g_InputState[key_info] == INPUT_STATE::PUSH_EXIT);
}