DirectInputでのジョイスティックの入力取得について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
atori
記事: 43
登録日時: 13年前

DirectInputでのジョイスティックの入力取得について

#1

投稿記事 by atori » 12年前

最近DirectXを始めました。
Visual Studio2008を使っています。

ネットで調べたりして見様見真似でジョイスティックの入力取得をしようとしたんですが、うまくいきません。
ジョイスティックを接続していない状態でデバッグするとデータ形式の設定の所でランタイムエラーを吐いてしまいます。

存在しないジョイスティックの設定をしているのだから当然だとは思うのですが・・・このエラーを回避するにはどうしたらいいのでしょうか?

コード:

//=============================================================================
// ジョイスティックの初期化(さっぱりわからんでぇ)
//=============================================================================
HRESULT InitJoystick(HINSTANCE hInst, HWND hWnd)
{
	HRESULT hr;

	hr = g_pDInput->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY);
	
	// デバイスの作成
	if(FAILED(hr))
	{
		MessageBox( hWnd, "デバイス作成失敗", "エラー", MB_OK);
		return hr;
	}

	// データフォーマットの設定
	hr = g_pDIDevJoystick->SetDataFormat(&c_dfDIJoystick2);
	if(FAILED(hr))
	{
		MessageBox(hWnd, "ジョイスティックのデータ形式を設定できませんでした。", "エラー", MB_OK);
		return hr;
	}

	hr = g_pDIDevJoystick->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
	if(FAILED(hr))
	{
		MessageBox(hWnd, "ジョイスティックの協調モードを設定できませんでした。", "エラー", MB_OK);
	}

	g_diDevCaps.dwSize = sizeof(DIDEVCAPS);
	hr = g_pDIDevJoystick->GetCapabilities(&g_diDevCaps);
	if(FAILED(hr))
	{
		MessageBox(hWnd, "ジョイスティックの能力を取得できませんでした。", "エラー", MB_OK);
		return hr;
	}

	hr = g_pDIDevJoystick->EnumObjects(EnumAxesCallback, (VOID*)hWnd, DIDFT_AXIS);
	if(FAILED(hr))
	{
		MessageBox(hWnd, "ジョイスティックの範囲を指定できませんでした。", "エラー", MB_OK);
		return hr;
	}

	hr = g_pDIDevJoystick->Poll();
	if(FAILED(hr))
	{
		hr = g_pDIDevJoystick->Acquire();
		while(hr == DIERR_INPUTLOST){
			hr = g_pDIDevJoystick->Acquire();
		}
	}

	return S_OK;
}

//=============================================================================
// ジョイスティックの終了処理
//=============================================================================
void UninitJoystick(void){

	if(g_pDIDevJoystick)
	{
		g_pDIDevJoystick->Unacquire();

		g_pDIDevJoystick->Release();
		g_pDIDevJoystick = NULL;
	}

}
//=============================================================================
// ジョイスティックのコールバック関数
//=============================================================================
BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE *pdidInstance , VOID *pContext )
{
	HRESULT hr;
	
	hr = g_pDInput->CreateDevice( pdidInstance->guidInstance , &g_pDIDevJoystick , NULL );
	
	if ( FAILED( hr ) ) return DIENUM_CONTINUE;
	
	return DIENUM_STOP;
}

//=============================================================================
// のコールバック関数
//=============================================================================
BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE *pdidoi , VOID *pContext )
{
	HRESULT     hr;
	DIPROPRANGE diprg;
	
	diprg.diph.dwSize       = sizeof( DIPROPRANGE );
	diprg.diph.dwHeaderSize = sizeof( DIPROPHEADER );
	diprg.diph.dwHow        = DIPH_BYID;
	diprg.diph.dwObj        = pdidoi->dwType;
	diprg.lMin              = 0 - 1000;
	diprg.lMax              = 0 + 1000;
	hr = g_pDIDevJoystick->SetProperty( DIPROP_RANGE , &diprg.diph );
	
	if ( FAILED( hr ) ) return DIENUM_STOP;
	
	return DIENUM_CONTINUE;
}

HRESULT UpdateJoystick(){
	DIJOYSTATE	joystick;
	HRESULT		hr;
	char		keyStateOld[36];


	if(NULL == g_pDIDevJoystick) return FALSE;

	hr = g_pDIDevJoystick->Poll();
	if(FAILED(hr))	return E_FAIL;

	// 押されたボタンの取得
	hr = g_pDIDevJoystick->GetDeviceState(sizeof(DIJOYSTATE), &joystick);
	if(FAILED(hr))	return E_FAIL;

	memcpy(&g_jsKeyState[0], &joystick.rgbButtons[0], JS_KEY_MAX);

	if(joystick.lY == -1000)	g_jsKeyState[32] = true;	// 十字キー上
	else						g_jsKeyState[32] = false;
	if(joystick.lY ==  1000)	g_jsKeyState[33] = true;	// 十字キー下
	else						g_jsKeyState[33] = false;
	if(joystick.lX == -1000)	g_jsKeyState[34] = true;	// 十字キー左
	else						g_jsKeyState[34] = false;
	if(joystick.lX ==  1000)	g_jsKeyState[35] = true;	// 十字キー右
	else						g_jsKeyState[35] = false;

	memcpy(&keyStateOld[0], &g_jsKeyState[0], JS_ALL_KEY_MAX);

	for(int cnt=0; cnt<JS_ALL_KEY_MAX; ++cnt){
		// トリガーとリリースの取得
		g_jsKeyStateTrigger[cnt] = g_jsKeyState[cnt] & (g_keyState[cnt] ^ keyStateOld[cnt]);
		g_jsKeyStateRelease[cnt] = keyStateOld[cnt] & (g_keyState[cnt] ^ keyStateOld[cnt]);
	}
	if(GetJoystickPress(DIJOFS_BUTTON1)){
		return S_OK;
	}

	return S_OK;
}
Done is better than perfect.(Mark Elliot Zuckerberg)

atori
記事: 43
登録日時: 13年前

Re: DirectInputでのジョイスティックの入力取得について

#2

投稿記事 by atori » 12年前

いい忘れていた事があるので補足します。
このプログラムで実際にランタイムエラーになるのは18行目です。
Done is better than perfect.(Mark Elliot Zuckerberg)

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: DirectInputでのジョイスティックの入力取得について

#3

投稿記事 by ISLe » 12年前

18行目の直前に、g_pDIDevJoystickがNULLだったらジョイスティックが存在しなかった(列挙されなかった)ということで、InitJoystick関数を抜ける処理を加えたら良いと思います。
g_pDIDevJoystickに何も入ってないのに使うのでランタイムエラーになります。

他の部分はg_pDIDevJoystickがNULLである場合を想定して書かれているので、その場合のInitJoystick関数の戻り値はS_FAILですかね。

atori
記事: 43
登録日時: 13年前

Re: DirectInputでのジョイスティックの入力取得について

#4

投稿記事 by atori » 12年前

無事にランタイムエラーを回避できました。
S_OKの反対の意味はS_FAILではなくS_FALSEでした。

ありがとうございました。
Done is better than perfect.(Mark Elliot Zuckerberg)

閉鎖

“C言語何でも質問掲示板” へ戻る