ゲーム開発8:入力処理1

予告どおり入力の処理です。

入力は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;
}

コメントを残す

メールアドレスが公開されることはありません。