予告どおり入力の処理です。
入力はDirectInputを使います。なんかクラス見たらDirectX8のまま変わってなかったんで楽勝、と思ったらやっぱり微妙に違う(汗) まぁほぼ手直し無しで済んだけどね。
今回もDirectXに依存する部分をCInputBaseクラス、入力を処理する部分をCInputクラスに分けます。使うデバイスはキーボードとゲームパッドです。使うボタンはキーボードはテンキーと十字キー、あとZとXとCのボタンにします。ゲームパッドの方は十字キーと0と1と2のボタンです。
キーボードは簡単に初期化出来るんだけど、ゲームパッドはモノによってボタンや十字キー(もしくはアナログスティック)の数が違うので、コールバックで再帰的に設定します。まあ定型処理だし、最低限のボタンしか使わないから、関係ないけどね。
今回はCInputBaseだけ組んで、次回CInputで実際に入力キーを取り出します。
//---------------------------------------------------------
// 初期化
BOOL CInputBase::Init(HWND hWnd)
{
HRESULT hr;
// DirectInputオブジェクトを作成する
hr=DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&DInput, NULL);
if FAILED(hr) {
MessageBox(NULL, "DirectInputオブジェクトの生成に失敗しました", "CInputBase::Init", MB_OK);
return E_FAIL;
}
// キーボードの初期化
hr=InitKeyboard(hWnd);
if FAILED(hr) {
return E_FAIL;
}
// ジョイスティックの初期化
hr=InitJoystick(hWnd);
if FAILED(hr) {
return E_FAIL;
}
return S_OK;
}
//---------------------------------------------------------
// キーボードの初期化
BOOL CInputBase::InitKeyboard(HWND hWnd)
{
HRESULT hr;
// キーボードデバイスを取得する
hr=DInput->CreateDevice(GUID_SysKeyboard, &DIKeyboard, NULL);
if FAILED(hr) {
MessageBox(NULL, "DirectInputキーボードデバイスの生成に失敗しました", "CInputBase::InitKeyboard", MB_OK);
TermDInput();
return E_FAIL;
}
// キーボードのデータ形式を設定する
hr=DIKeyboard->SetDataFormat(&c_dfDIKeyboard);
if FAILED(hr) {
MessageBox(NULL, "DirectInputキーボードのデータ形式の取得に失敗しました", "CInputBase::InitKeyboard", MB_OK);
TermDInput();
return E_FAIL;
}
// キーボードの協調レベルを設定する
hr=DIKeyboard->SetCooperativeLevel(hWnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
if FAILED(hr) {
MessageBox(NULL, "DirectInputキーボードの強調レベルの取得に失敗しました", "CInputBase::InitKeyboard", MB_OK);
TermDInput();
return E_FAIL;
}
// キーボードの入力デバイスにアクセスする
hr=DIKeyboard->Acquire();
if FAILED(hr) {
MessageBox(NULL, "DirectInputキーボードへのアクセスに失敗しました", "CInputBase::InitKeyboard", MB_OK);
TermDInput();
return E_FAIL;
}
return S_OK;
}
//---------------------------------------------------------
// ジョイスティックの初期化
BOOL CInputBase::InitJoystick(HWND hWnd)
{
HRESULT hr;
DIDEVCAPS g_DevCaps;
//ジョイスティックのコールバック設定
hr=DInput->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY);
if FAILED(hr) {
MessageBox(NULL, "DirectInputジョイスティックコールバックの生成に失敗しました", "CInputBase::InitJoystick", MB_OK);
TermDInput();
return E_FAIL;
}
// ジョイスティックが存在しているか?
if (DIJoystick==NULL) {
return S_OK;
}
// ジョイスティックのデータ形式を設定する
hr=DIJoystick->SetDataFormat(&c_dfDIJoystick);
if FAILED(hr) {
MessageBox(NULL, "DirectInputジョイスティックのデータ形式の取得に失敗しました", "CInputBase::InitJoystick", MB_OK);
TermDInput();
return E_FAIL;
}
// ジョイスティックの協調レベルを設定する
hr=DIJoystick->SetCooperativeLevel(hWnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE);
if FAILED(hr) {
MessageBox(NULL, "DirectInputジョイスティックの強調レベルの取得に失敗しました", "CInputBase::InitJoystick", MB_OK);
TermDInput();
return E_FAIL;
}
// ジョイスティックの能力を取得する
g_DevCaps.dwSize = sizeof(DIDEVCAPS);
hr=DIJoystick->GetCapabilities(&g_DevCaps);
if FAILED(hr) {
MessageBox(NULL, "DirectInputジョイスティックの能力の取得に失敗しました", "CInputBase::InitJoystick", MB_OK);
TermDInput();
return E_FAIL;
}
// 全ての軸を列挙する
hr=DIJoystick->EnumObjects(EnumAxesCallback, (void*)hWnd, DIDFT_AXIS);
if FAILED(hr) {
MessageBox(NULL, "DirectInputジョイスティックの軸の列挙に失敗しました", "CInputBase::InitJoystick", MB_OK);
TermDInput();
return E_FAIL;
}
// ジョイスティックの入力デバイスにアクセスする
hr=DIJoystick->Acquire();
if FAILED(hr) {
MessageBox(NULL, "DirectInputジョイスティックへのアクセスに失敗しました", "CInputBase::InitJoystick", MB_OK);
TermDInput();
return E_FAIL;
}
return S_OK;
}
//---------------------------------------------------------
// ジョイスティック列挙コールバック
BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext)
{
HRESULT hr;
// ジョイスティックデバイスを取得する
hr=System->Input->DInput->CreateDevice(pdidInstance->guidInstance, &System->Input->DIJoystick, NULL );
if FAILED(hr) {
return DIENUM_CONTINUE;
}
// ジョイスティックが取得できたらこの関数は呼び出されなくなる
return DIENUM_STOP;
}
//---------------------------------------------------------
// ジョイスティック軸列挙コールバック
BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext)
{
HWND hDlg=(HWND)pContext;
DIPROPRANGE diprg;
diprg.diph.dwSize = sizeof(DIPROPRANGE);
diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
diprg.diph.dwHow = DIPH_BYID;
diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis
diprg.lMin = -1000;
diprg.lMax = +1000;
// ジョイスティックデバイスを設定する
if (FAILED(System->Input->DIJoystick->SetProperty(DIPROP_RANGE, &diprg.diph))) {
return DIENUM_STOP;
}
return DIENUM_CONTINUE;
}
//---------------------------------------------------------
// DirectInput解放
void CInputBase::TermDInput()
{
if (DInput) {
if (DIKeyboard) {
// Release()を呼び出す前は常にデバイスを解放する
DIKeyboard->Unacquire();
DIKeyboard->Release();
DIKeyboard=NULL;
}
if (DIJoystick) {
// Release()を呼び出す前は常にデバイスを解放する
DIJoystick->Unacquire();
DIJoystick->Release();
DIJoystick=NULL;
}
DInput->Release();
DInput=NULL;
}
}
//---------------------------------------------------------
// キーボード入力取得
BOOL CInputBase::ProcessKeyboard(char *buffer)
{
HRESULT hr;
if (DIKeyboard==NULL) {
return E_FAIL;
}
// キーボードステータス取得
hr=DIKeyboard->GetDeviceState(256/*sizeof(buffer)*/,(LPVOID)buffer);
if FAILED(hr) {
return E_FAIL;
}
return S_OK;
}
//---------------------------------------------------------
// ジョイスティック入力取得
BOOL CInputBase::ProcessJoystick(DIJOYSTATE *js)
{
HRESULT hr;
if (DIJoystick==NULL) {
return E_FAIL;
}
// ジョイスティックポーリング
hr=DIJoystick->Poll();
if FAILED(hr) {
hr=DIJoystick->Acquire();
while(hr==DIERR_INPUTLOST)
hr=DIJoystick->Acquire();
return E_FAIL;
}
// ジョイスティックステータス取得
hr=DIJoystick->GetDeviceState(sizeof(DIJOYSTATE), js);
if FAILED(hr) {
return E_FAIL;
}
return S_OK;
}