DirectXの中の一つ「DirectInput」を使って、キーボードの状態を取得できるプログラムを作っていこう。
キーボードやマウスは1個しか存在しないので、クラスではなくnamespaceを使って処理をまとめる。
Input.hとInput.cppを作成する。
必要な関数は「初期化」「更新」「任意のキーが押されてるかどうか」「解放処理」の4つ。
<Input.h>
#pragma once
#include <dInput.h>
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dInput8.lib")
#define SAFE_RELEASE(p) if(p != nullptr){ p->Release(); p = nullptr;}
namespace Input
{
void Initialize();
void Update();
bool IsKey(int keyCode);
void Release();
};
<Input.cpp>
#include "Input.h"
namespace Input
{
void Initialize()
{
}
void Update()
{
}
bool IsKey(int keyCode)
{
return false;
}
void Release()
{
}
}
DirectInput本体の準備をしていく。
<Input.cpp>
#include "Input.h"
namespace Input
{
LPDIRECTINPUT8 pDInput = nullptr;
void Initialize()
{
DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&pDInput, nullptr);
}
void Update()
{
}
bool IsKey(int keyCode)
{
return false;
}
void Release()
{
SAFE_RELEASE(pDInput);
}
}
これでpDinputにDirectInput本体が入る。
ちなみにこの変数は外部で使うことはないので、ヘッダーで宣言する必要はない。
次にデバイスオブジェクト、つまりキーボードの準備をする。
namespace Input
{
LPDIRECTINPUT8 pDInput = nullptr;
LPDIRECTINPUTDEVICE8 pKeyDevice = nullptr;
void Initialize()
{
DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&pDInput, nullptr);
pDInput->CreateDevice(GUID_SysKeyboard, &pKeyDevice, nullptr);
pKeyDevice->SetDataFormat(&c_dfDIKeyboard);
pKeyDevice->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
}
これで「pKeyDevice」がキーボードを指すことになる。
1行目でデバイスオブジェクトを作成
2行目でデバイスの種類(今回はキーボード)を指定
3行目で強調レベル(他の実行中のアプリに対する優先度)の設定 をしている。
この処理で、ウィンドウハンドルが必要になるので、Initialize関数の引数でウィンドウハンドルを受け取ろう。
あと、Release関数で解放処理も忘れずに。
ついでに言うと「Create」がつく関数を2回使ったので…。
では、キーが押されているかどうかを調べるプログラムを作っていく。
namespace Input
{
LPDIRECTINPUT8 pDInput = nullptr;
LPDIRECTINPUTDEVICE8 pKeyDevice = nullptr;
BYTE keyState[256] = { 0 };
:
:
:
void Update()
{
pKeyDevice->Acquire();
pKeyDevice->GetDeviceState(sizeof(keyState), &keyState);
}
キーは複数あるので、「押されてるかどうか」を入れておく変数を配列で用意する。
普通、キーボーのキーは256も無いが、一応256個分用意しておく。
そしてUpdate関数で「その瞬間の全キーの状態」を配列に入れる。
どのキーの情報が配列の何番に入るかは決まっている。
例えば、「A」のキーの情報は_keyState[30]に入り、「スペースキー」の情報は_keyState[57]に入る。
もちろん、この番号は覚える必要は無い。
「DIK_A」「DIK_SPACE」という名前で定数宣言されている。
IsKey関数で、引数に渡された番号のキーが押されてるか調べる処理を書く。
たとえば、スペースキーが押されていればkeyState[57]の右から8ビット目が1になっている。
その場合はtrueを、そうでなければfalseを返すようにすればいい。
bool IsKey(int keyCode)
{
if (keyState[●●●] ● ●●●)
{
return true;
}
return false;
}
処理が完成したので、それをつかっていこう。
あとは、どこかで「最初にInitialize関数」「毎フレームUpdate関数」「最後にRelease関数」を呼ぶ必要がある。
引数にウィンドハンドルを渡すことも考えると「Main.cpp」がベストだろう。
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
:
:
:
//Direct3Dの初期化(準備)
Direct3D::Initialize(hWnd);
//DirectInputの初期化
●●●●●●●●●●;
:
:
//メッセージループ(何か起きるのを待つ)
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
:
:
:
//メッセージなし
else
{
//ゲームの処理
//入力情報の更新
●●●●●●●●●●;
:
:
:
}
SAFE_DELETE(pFbx);
●●●●●●●●●●;
Direct3D::Release();
return 0;
}
あとは、試しにメッセージループの中に
if (Input::IsKey(DIK_ESCAPE))
{
PostQuitMessage(0);
}
とでも書いてみよう。
ESCキーでプログラムが終了するはず。