アフィリエイト

DirectInputの機能

 DirectInputはその名のとおり入力系デバイスを管理するものです。デバイス側でDirectInputに対応したドライバさえ提供されていれば、入力の状態をリアルタイムに取得することが出来ます。管理できるデバイスは「マウス」「キーボード」「ジョイスティック」など、とにかく色々なものです。また、入力だけでなく、こちらからメッセージを送りコントローラーを振動させることなんかも出来ます。つまりは、ゲームを作るのにとっても都合のいい機能がそろっているのです。

DirectInputでキーボードの状態を取得する

 今回は数あるDirectInputの機能の中から一番簡単な「キーボードの状態取得」の方法を紹介します。非常に簡単なので、キーボードの状態を調べて結果を返すようなサンプルプログラムを作りながら、DirectInputのプログラムの流れを説明していくことにします。

今回のサンプルプログラム

 今回のサンプルプログラムの機能を紹介します。

DirectInputSampe1

 左が今回作るプログラムの画面です。これだけ見ても全く胸トキメキませんが、キーボードの方向キー「↑」「↓」「→」「←」を押すことで、フォーム上の文字の位置を動かすことが出来ます。非常に単純ですが、ゲームなんてこれを複雑にしただけですね。

 このプログラムに、自動的に動く敵を作って、「Z」キーやらでレーザーを打てるようにして、ヒット判定を作れば、簡単なシューティングゲームが出来そうです。地味に重要な気がしてきませんか。(まぁ、無理やりですが)

 

サンプルのダウンロード(disample1.lzh)

プロジェクトの生成・参照設定・ネームスペースの追加・フォームのデザイン(諸々)

 それでは、さっさと作ってしまいましょう。前回紹介したとおりに通常のWindowsプロジェクトをつくり、参照設定を行ってください。今回はDirectInputを使用するプログラムなので、「Microsoft.DirectX」と「Microsoft.DirectX.DirectInput」を追加してください。

 参照設定が終わったら、プログラムを書く都合上ネームスペースの追加もしておくといいでしょう。Form1のコードの先頭に以下の文を追加して置いてください。

//ネームスペースにDirectInputを追加
using Microsoft.DirectX.DirectInput;
using DirectInput = Microsoft.DirectX.DirectInput;

 これで、コード中でわざわざ「Microsoft.DirectX.DirectInput」と書かなくても良くなります。また、2行目の文は、「DirectInput」と書くと「Microsoft.DirectX.DirectInput」を意味するようになります。これも何かと便利です。

 サンプルではラベルを動かすので、Form1の適当な位置に「Label」を貼り付けてください。名前はデフォルトの「Label1」で結構です。フォームデザインの仕方はこちらに書いてありますので参考にしてください。

Form1にコードを書き込む

 あまりいじると説明がしにくくなってしまいますので、今回はForm1の「static void Main() 」だけに色々とコードを書き込んでいきます。最終的なMainメソッドは以下のようになります。

static void Main() 
{
	Device DInDev; ///DirectInputデバイス
	KeyboardState DKeyState;  ///キーボード状態

	//メインループ
	//講座で紹介したFPS安定タイマーを使用しています。
	Form1 frm = new Form1();
	double nextframe = (double)System.Environment.TickCount;
	float wait = 1000f/60f;

	//DirectInputデバイスの生成
	DInDev = 
	new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
	//入力制御を開始
	DInDev.Acquire();

	frm.Show(); //フォームの表示

	while(frm.Created)
	{
		
		if ((double)System.Environment.TickCount >= nextframe)
		{

			//計算処理

			//キーボードの状態を取得
			DKeyState = DInDev.GetCurrentKeyboardState();

			//キーボードの「←」が押されていればラベルを動かす
			if (DKeyState[DirectInput.Key.Left])
			{
				frm.label1.Left--;
				frm.label1.Text = "Left";
			}
			//キーボードの「→」が押されていればラベルを動かす
			if (DKeyState[DirectInput.Key.Right])
			{
				frm.label1.Left++;
				frm.label1.Text = "Right";
			}
			//キーボードの「↑」が押されていればラベルを動かす
			if (DKeyState[DirectInput.Key.Up])
			{
				frm.label1.Top--;
				frm.label1.Text = "Up";
			}
			//キーボードの「↓」が押されていればラベルを動かす
			if (DKeyState[DirectInput.Key.Down])
			{
				frm.label1.Top++;
				frm.label1.Text = "Down";
			}

			if ((double)System.Environment.TickCount < nextframe + wait)
			{
				//描画処理
			}

			nextframe += wait;
		}

		Application.DoEvents();
	}
}

文のほとんどは、ゲームプログラムテクニックで紹介したゲームループFPSタイマーです。ループ構造や大まかな処理の流れはこの二つを参照してください。

DirectInputに関係しているのは強調された文の部分だけです。しかも、最初の二文は変数を宣言してるだけ。あとの方のif文はキーの判定をしているだけです。実際には四文程度ですね。

DirectInputデバイスの取得

 文書も少ないので、少しだけ細かく説明していきます。まずは、DirectInputデバイスの取得と入力制御の開始です。この動作には以下の二文が対応しています。

Device DInDev = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
DInDev.Acquire();

 変数宣言はバカらしいのくっつけました。DirectInputで入力制御をするには、Microsoft.DirectX.DirectInput.Device型のインスタンスを生成し、主にそれを使って制御していくことになります。この方法はInputに限らずグラフィック系でもサウンド系でも大体同じです。今回取得したいデバイスはキーボードですので、コンストラクタの引数に「SystemGuid.Keyboard」を渡しています。これでデバイスの取得が完了します。

 デバイスが出来たら、入力制御を開始します。これには「Acquire()」メソッドを呼び出します。これで、DirectInputを使ってキーボードの状態を取得する手順が整いました。

キーボード状態の取得

 すでにDirectInputの入力制御は働いているので、あとはキーボードの状態を取得するだけです。キーボードの状態は「Microsoft.DirectX.DirectInput.KeyboardState」型で受け取ります。最新の状態を取得するにはDeviceの「GetCurrentKeyboardState()」を使います。以下がキーボードを状態を取得する文です。

DKeyState = DInDev.GetCurrentKeyboardState();

DKeyStateの中にキーボードの状態が保持されます。

あとは、「DKeyState[Microsoft.DirectX.DirectInput.Key]」とやって、あるキーが押されているか、押されていないかを判断してやればいいのです。押されていれば「true」が返ってきます。Microsoft.DirectX.DirectInput.Key列挙体はキーボード上の様々なキーの列挙体で、これをDKeyStateのインデクサに渡してやればそのキーの状態が取得できます。たとえば、今回のように「←」キーの状態を取得したい場合は「Key.Left」、「A」ならば「Key.A」のように指定してやるだけです。簡単ですね。

まとめ

 以上が、DirectInputを使ってキーボードの状態取得を行う方法です。非常に簡単ですね。

 DirectInputを使った場合、Windowsのようにキーイベントなどが発生しないため、サンプルのようにループ構造の中で最新のキーボードの状態を取得し毎回調べなくてはなりません。ツール系のソフト上では面倒なことでしょうが、もともとループ上で全てを制御するゲームプログラムでは使いやすいものです。(管理者がなれているだけかな)

 ゲームで必要なループ構造と入力の取得はこれでできるようになりました。次回は…描画系。やりたいですね。