Home | Lesson | Game | Tool | Link

B09.キーの複数入力

様々なゲームでキーの複数入力が必要となるため、
簡易的ではありますが、複数キーの操作方法を紹介します。
一部処理できないキーがあったり、同時押しをしているのに
処理されない場合もありますが、大体の操作は大丈夫なようです。
※画面で背景が黒くなっているキーは処理できません。
また、この方法でも最大8個程度の同時押ししかできないようです。
F10も処理できないようです。OSによってはF12もだめなようです。


構造体と配列の用意
画面にキーの状態を表示する際に使用するデータを準備しておきます。
ゲームで使用する場合は、準備する必要はありません。
構造体には、表示する位置と大きさ、文字を用意しておきます。
EKEY_CODEに対応した配列を用意しておいた方がよいでしょう。
typedef struct
{
	s32 x,y;
	s32 w,h;
	char str[8];
}KEY_ARRAY;

//キーボード描画用配列
KEY_ARRAY KEY[256] =
{
	{0,0,0,0,""},//0x00:
	{0,0,0,0,""},//0x01:KEY_LBUTTON
	{0,0,0,0,""},//0x02:KEY_RBUTTON
	{0,0,0,0,""},//0x03:KEY_CANCEL
	{0,0,0,0,""},//0x04:KEY_MBUTTON
	{0,0,0,0,""},//0x05:KEY_XBUTTON1
	{0,0,0,0,""},//0x06:KEY_XBUTTON2
	{0,0,0,0,""},//0x07:
	:
	:
};

レシーバーの用意
キー操作を受け付けるレシーバーを用意します。
今までは、この中でキーの処理を行っていましたが、今回はキーの状態を取得するだけにしてあります。
キーの状態を保存する配列を用意して、初期化しておきます。
OnEventでは、キーが押されたら、または離されたらキーの状態を変更します。
特定のキーが押されているかどうかを調べるには、isKeyPressedで調べます。
※複数キーを押しても、1個ずつしか処理されないのが問題かもしれません。
最初から配列で処理するように設計されていれば、簡単だったかもしれません。

class MyEventReceiver : public IEventReceiver
{
public:
	//配列の初期化
	MyEventReceiver()
	{
		u32 i;
		for(i=0;i<KEY_KEY_CODES_COUNT;i++)
			Keys[i] = false;
	}

	virtual bool OnEvent(const SEvent& event)
	{
		//キー操作の場合
		if(event.EventType == EET_KEY_INPUT_EVENT)
		{
			//キーの状態を保存
			Keys[event.KeyInput.Key] = event.KeyInput.PressedDown;
			return true;
		}
		return false;
	}

	//キーが押されているかどうか
	bool isKeyPressed(EKEY_CODE key) const
	{
		return Keys[key];
	}

private:
	bool Keys[KEY_KEY_CODES_COUNT];
};
MyEventReceiver Receiver;


キーボードの描画
キーの状態をキーボードにして画面に表示します。
押されているキーが明るく表示されます。
最初に作成したキーの配列にそってキーを描画していきます。
nullBoxでは、処理できないキーを描画しています。
subKeyでは、Shift/Ctrlなど左右にそれぞれついているキーを描画しています。
//キーボードの描画
void makeScene(IVideoDriver *driver)
{
	s32 i;

	FillRect(driver,5,5,310,125,0xFF666666);

	nullBox();

	for (i=0x0;i<KEY_KEY_CODES_COUNT;i++)
	{
		if (KEY[i].x > 0 && KEY[i].w > 0)
		{
			subKey((EKEY_CODE)i);

			FillRect(driver,KEY[i].x,KEY[i].y,KEY[i].w,KEY[i].h,
				0xFF999999,PS_SOLID);
			if (Receiver.isKeyPressed((EKEY_CODE)i))
				FillRect(driver,KEY[i].x,KEY[i].y,KEY[i].w,KEY[i].h,
					0xFFCCCCCC,PS_SOLID);
			Printf(driver,KEY[i].x,KEY[i].y,0xFF000000, "%s" ,KEY[i].str);
		}

		if (Receiver.isKeyPressed((EKEY_CODE)i))
			Printf(driver,100,160,0xFF000000, "0x%02X" ,i);
	}
}


メモ
なぜ全てのキーを取得できないのか?
これは、使用しているドライバに影響を受けているためです。
DirectXであれば、全てのキーを取得可能でしょう。
ただし、MacやLinuxではDirectXは使用できません。
そのため、DirectXを基本としてキー情報を取得することができません。
OpenGLであれば、Windows/Mac/Linuxで動作するため可能なように見えますが、
3Dの描画を主として作成されているため、キー操作には本腰が入っていません。
そのため、ある程度のキーしか取得できません。

ダウンロード
今回作成したファイル一式です。

宿題
1.カーソルキーやテンキーの部分も作成してみましょう。