①環境構築

最初から躓いたところは環境構築である,昨年度の先輩方もジョイパッドを使ってビークルを操作していたのだが,詳しい資料がない.

C++.netでジョイパッドのイベントを検出する際にDirectXSDKを使うのだが,先輩方はDirectX9.0SDKとしか書いていなかった.

Microsoft DirectX 9.0 SDK Update (August 2005)を最初インストールしたのだが,使うか分からないがlibとincludeファイルの数が少なかったので.Microsoft DirectX 9.0 SDK Update (Summer 2003)をインストールした.

SDKの他にDirectX9.0本体も入れた(ゲームから入手)

プログラミング環境はMicrosoft Visual Studio .NET 200 C++ MFCを使ってコーディングをした.
ケルトンはまだ使わずコーディングしている.(スケルトンを使うとコードが勝手に書かれてよく分からない)

  • 新しいプロジェクト→visual C++→win32プロジェクト→アプリケーションの設定で空のオブジェクトにチェックを入れる
  • メニューバーのプロジェクトのプロバティ→構成のプロバティで以下の3つの設定を行う
  • 全般→MFCの使用→共有 DLL で MFC を使用する
  • C++→全般→追加のインクルードディレクトリ→先ほどインストールしたDirectxSDKのフォルダの中のincludeフォルダを選ぶ
  • リンカ→全般→追加のライブラリデイレクトリ→先ほどインストールしたDirectxSDKのフォルダの中のlibフォルダを選ぶ


以上を行えばプログラムを打つ環境ができるはず,
後,普通はC\DX90SDKにDirectXSDKがインストールされているはず.

②プログラムについて

DirectInputでJOYPADの情報は手にいれることができるらしい.
サンプルコードやサンプルプログラムも沢山ネットに公開されているのだが,難しい.(ゲームを作ろうと思った人でJYOPADを動かそうっておもって挫折した人も多そう)

以下の三つのファイルをコピーしてプロジェクトに追加すれば動くはず.
コードは長いけど.txtでUPしてないのは来年の後輩のため.

実際にこのプログラムを実行すると,ジョイパッドのボタン1を押すとメッセージが表示される.
さらに右クリックをウィンドウ内でするとメッセージが表示される.

③サンプルプログラム(main.cpp)

#include
#include
#include

#include "BlueInput.h"


//追加
#include
#include
#include
#include // MFC のソケット拡張機能

#include // 数学関数用ヘッダファイル
#include // DirectShow用ヘッダファイル
#include // DirectSound用ヘッダファイル

class CMyWindow : public CFrameWnd
{

private:
CBlInput m_blInput;
public:

void OnPaint();
CMyWindow();
DECLARE_MESSAGE_MAP()
CString m_message;
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

};
BEGIN_MESSAGE_MAP(CMyWindow,CFrameWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_TIMER()
ON_WM_CREATE()
END_MESSAGE_MAP()


CMyWindow::CMyWindow()
{
Create(NULL,"猫でもわかるMFC");
m_message = "";
}
void CMyWindow::OnPaint()
{

CPaintDC dc(this);
dc.TextOut(20, 20, m_message);


}

class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};

BOOL CMyApp::InitInstance()
{
// TODO : ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。
m_pMainWnd=new CMyWindow();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();


return CWinApp::InitInstance();
}
CMyApp MyApp;



void CMyWindow::OnLButtonDown(UINT nFlags, CPoint point)
{
m_message = "猫でも分かるプログラミング";
InvalidateRect(NULL);
CFrameWnd::OnLButtonDown(nFlags, point);
}

void CMyWindow::OnTimer(UINT nIDEvent)
{
// TODO : ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。
//m_blInput.RefreshJoystickData();
//MessageBox("test");
if( m_blInput.RefreshJoystickData() ){
if( m_blInput.GetJoystickButton( BLINP_1BUTTON, 0 ) == FALSE ){
InvalidateRect(NULL);
//MessageBox("test");
}
else{
m_message = "バカ・・・";
InvalidateRect(NULL);
//MessageBox("test");

}
}

CFrameWnd::OnTimer(nIDEvent);
}

int CMyWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
SetTimer( 100, 17, NULL );
int nNum;
if( m_blInput.InitJoystick( ::AfxGetInstanceHandle(), GetSafeHwnd(), 1, &nNum ) != 0 ){
PostMessage( WM_DESTROY );
}
// TODO : ここに特定な作成コードを追加してください。

return 0;
}

④サンプルプログラム(BlueInput.cpp)

#include "StdAfx.h"
#include "BlueInput.h"
#include
#include

#pragma comment ( lib, "dinput8.lib" )
#pragma comment ( lib, "dxguid.lib" )

// 実験用
LPDIRECTINPUTEFFECT g_pDIEffect[MAX_JOYSTICK];

CBlInput::CBlInput( void )
{
m_pDInput = NULL;
m_pDInputDevMouse = NULL;
m_pDInputDevKeyboard = NULL;
for( int i = 0; i < MAX_JOYSTICK; ++i ){
m_pDInputDevJoystick[i] = NULL;
}

m_nJoystickCount = 0;

ZeroMemory( m_lMouseAxis, sizeof(m_lMouseAxis) );
ZeroMemory( m_btMouseButton, sizeof(m_btMouseButton) );
ZeroMemory( m_btKeyData, sizeof(m_btKeyData) );
ZeroMemory( m_dwJoystickButton, sizeof(m_dwJoystickButton) );
ZeroMemory( m_lJoystickAxis, sizeof(m_lJoystickAxis) );
ZeroMemory( m_dwJoystickPOV, sizeof(m_dwJoystickPOV) );

m_dwPolling = 0;

// 実験用
ZeroMemory( g_pDIEffect, sizeof( g_pDIEffect ) );
}

/****************************************************************
引数: hInst アプリのインスタンスハンドル
戻り値: 成功 TRUE
失敗 オブジェクトが既に作成されている FALSE
説明: DirectInput初期化

***************************************************************/

BOOL CBlInput::InitDxInput( const HINSTANCE &hInst )
{
BOOL bRet = TRUE;

try{
if( m_pDInput != NULL ){
throw FALSE;
}
HRESULT hr = 0;
// DirectInputオブジェクト作成
hr = DirectInput8Create(
hInst,
DIRECTINPUT_VERSION,
IID_IDirectInput8,
(LPVOID*)&m_pDInput,
NULL);

if FAILED( hr ){
throw FALSE;
}
}
catch( BOOL bFlag ){
bRet = bFlag;
}

return bRet;
}

/****************************************************************
引数: なし
戻り値: なし
説明: DirectInput解放

***************************************************************/

void CBlInput::Release( void )
{
// マウスデバイス解放
ReleaseMouse();

// キーボードデバイス解放
ReleaseKeyboard();

// ジョイスティックデバイス解放
ReleaseJoystick();

// 実験用
for( int i = 0; i < MAX_JOYSTICK; ++i ){
if( g_pDIEffect[i] != NULL ){
g_pDIEffect[i]->Unload();
}
}

// DirectInput8オブジェクト解放
if( m_pDInput != NULL ){
m_pDInput->Release();
}
}

/****************************************************************
引数: hInst アプリのインスタンスハンドル
hWnd アプリのウィンドウハンドル
戻り値: 成功 0
DxInputオブジェクト作成失敗 DLINP_ERROR_CREATE
マウスデバイス作成失敗 MOUSE_ERROR_CREATE
データフォーマット設定失敗 MOUSE_ERROR_DATAFORMAT
協調モードの設定 MOUSE_ERROR_MODE
軸モード設定 MOUSE_ERROR_AXIS
説明: マウスモード初期化

***************************************************************/

DWORD CBlInput::InitMouse( const HINSTANCE &hInst, const HWND &hWnd )
{

DWORD dwRet = 0;

try{
if( m_pDInput == NULL ){
if( InitDxInput( hInst ) == FALSE ){
throw BLINP_ERROR_CREATE;
}
}
HRESULT hr = 0;

ReleaseMouse();

// マウス用のデバイス作成
hr = m_pDInput->CreateDevice(
GUID_SysMouse,
&m_pDInputDevMouse,
NULL);
if FAILED( hr ){
throw MOUSE_ERROR_CREATE;
}

// データフォーマットの設定
hr = m_pDInputDevMouse->SetDataFormat( &c_dfDIMouse2 ); // xyz(ホイール)軸と8つのボタン
if FAILED( hr ){
throw MOUSE_ERROR_DATAFORMAT;
}

// 協調モードの設定
hr = m_pDInputDevMouse->SetCooperativeLevel( hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE ); // フォアグラウンド、非排他モード
if FAILED( hr ){
throw MOUSE_ERROR_MODE;
}

// 軸モードの設定
DIPROPDWORD diprop;
diprop.diph.dwSize = sizeof( diprop );
diprop.diph.dwHeaderSize = sizeof( diprop.diph );
diprop.diph.dwObj = 0;
diprop.diph.dwHow = DIPH_DEVICE;
diprop.dwData = DIPROPAXISMODE_REL; // 相対モード
hr = m_pDInputDevMouse->SetProperty( DIPROP_AXISMODE, &diprop.diph );
if FAILED( hr ){
throw MOUSE_ERROR_AXIS;
}

// デバイス入力制御開始
m_pDInputDevMouse->Acquire(); // フォアグラウンドモードの為、フォーカスを失うと制御が止まるので注意
}
catch( DWORD dwError ){
dwRet = dwError;
ReleaseMouse();
}

return dwRet;
}

/****************************************************************
引数: hInst アプリのインスタンスハンドル
hWnd アプリのウィンドウハンドル
戻り値: 成功 0
DxInputオブジェクト作成失敗 DLINP_ERROR_CREATE
キーボードデバイス作成失敗 KEYBOARD_ERROR_CREATE
データフォーマット設定失敗 KEYBOARD_ERROR_DATAFORMAT
協調モードの設定 KEYBOARD_ERROR_MODE
説明: キーボードモード初期化

***************************************************************/

DWORD CBlInput::InitKeyboard( const HINSTANCE &hInst, const HWND &hWnd )
{
DWORD dwRet = 0;

try{
if( m_pDInput == NULL ){
if( InitDxInput( hInst ) == FALSE ){
throw BLINP_ERROR_CREATE;
}
}
HRESULT hr = 0;

ReleaseKeyboard();

// キーボード用のデバイス作成
hr = m_pDInput->CreateDevice(
GUID_SysKeyboard,
&m_pDInputDevKeyboard,
NULL);
if FAILED( hr ){
throw KEYBOARD_ERROR_CREATE;
}

// データフォーマットの設定
hr = m_pDInputDevKeyboard->SetDataFormat( &c_dfDIKeyboard ); // キーボード用のフォーマット 256バイトの配列
if FAILED( hr ){
throw KEYBOARD_ERROR_DATAFORMAT;
}

// 協調モードの設定
hr = m_pDInputDevKeyboard->SetCooperativeLevel( hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE ); // フォアグラウンド、非排他モード
if FAILED( hr ){
throw KEYBOARD_ERROR_DATAFORMAT;
}

// デバイス入力制御開始
m_pDInputDevKeyboard->Acquire(); // フォアグラウンドモードの為、フォーカスを失うと制御が止まるので注意
}
catch( DWORD dwError ){
dwRet = dwError;
ReleaseKeyboard();
}

return dwRet;
}

/****************************************************************
引数: hInst アプリのインスタンスハンドル
hWnd アプリのウィンドウハンドル
nNum 使用できるジョイスティックの最大数
pnSetNum 実際に確保できたジョイスティックの数(接続数ではない) NULL可
戻り値: 成功 0
DxInputオブジェクト作成失敗 DLINP_ERROR_CREATE
ジョイスティック列挙失敗 JOYSTICK_ERROR_ENUM
説明: ジョイスティック初期化

***************************************************************/

DWORD CBlInput::InitJoystick( const HINSTANCE &hInst, const HWND &hWnd, const int nNum, int *pnSetNum )
{
DWORD dwRet = 0;
HRESULT hr = 0;
if( pnSetNum != NULL ){
*pnSetNum = 0;
}

try{
if( m_pDInput == NULL ){
if( InitDxInput( hInst ) == FALSE ){
throw BLINP_ERROR_CREATE;
}
}

ReleaseJoystick();

// ジョイスティックの列挙
hr = m_pDInput->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, (void*)this, DIEDFL_ATTACHEDONLY );
if FAILED(hr){
throw JOYSTICK_ERROR_ENUM;
}

// ジョイスティックの初期化
for( int i = 0; i < m_nJoystickCount; ++i ){
// データフォーマットの設定
hr = m_pDInputDevJoystick[i]->SetDataFormat( &c_dfDIJoystick2 ); // フォースフィードバックにも対応
if FAILED(hr){
m_pDInputDevJoystick[i]->Release();
m_pDInputDevJoystick[i] = NULL;

continue;
}

// 協調モードの設定
hr = m_pDInputDevJoystick[i]->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND ); // フォアグラウンド、排他モード
if FAILED(hr){
m_pDInputDevJoystick[i]->Release();
m_pDInputDevJoystick[i] = NULL;

continue;
}

// オートセンター設定
DIPROPDWORD dipdw;
ZeroMemory( &dipdw, sizeof( dipdw ) );
dipdw.diph.dwSize = sizeof( dipdw );
dipdw.diph.dwHeaderSize = sizeof( dipdw.diph );
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = DIPROPAUTOCENTER_OFF;

hr = m_pDInputDevJoystick[i]->SetProperty( DIPROP_AUTOCENTER, &dipdw.diph );

// 軸モードの設定
hr = m_pDInputDevJoystick[i]->EnumObjects( EnumAxesCallback, (void*)m_pDInputDevJoystick[i], DIDFT_AXIS );
if FAILED(hr){
m_pDInputDevJoystick[i]->Release();
m_pDInputDevJoystick[i] = NULL;

continue;
}

// デバイス情報取得
DIDEVCAPS caps;
ZeroMemory( &caps, sizeof( caps ) );
caps.dwSize = sizeof( DIDEVCAPS );
m_pDInputDevJoystick[i]->GetCapabilities( &caps );

// ポーリングが必要かを調べる
if( caps.dwFlags & (DIDC_POLLEDDATAFORMAT & DIDC_POLLEDDEVICE) ){
m_dwPolling |= (0x00000001UL << i);
}

// デバイス入力制御開始
m_pDInputDevJoystick[i]->Acquire(); // フォアグラウンドモードの為、フォーカスを失うと制御が止まるので注意

// 実験
DICONSTANTFORCE diCForce;
diCForce.lMagnitude = DI_FFNOMINALMAX;

DIENVELOPE diEnvelope;
diEnvelope.dwSize = sizeof( DIENVELOPE );
diEnvelope.dwAttackLevel = 0;
diEnvelope.dwAttackTime = (DWORD)(0.5 * DI_SECONDS );
diEnvelope.dwFadeLevel = 0;
diEnvelope.dwFadeTime = (DWORD)(1.0 * DI_SECONDS );

DIEFFECT diEffect;
diEffect.dwSize = sizeof( DIEFFECT );
diEffect.dwFlags = DIEFF_POLAR | DIEFF_OBJECTOFFSETS;
diEffect.dwDuration = INFINITE;
diEffect.dwSamplePeriod = 0;
diEffect.dwGain = DI_FFNOMINALMAX;
diEffect.dwTriggerButton = DIEB_NOTRIGGER;
diEffect.dwTriggerRepeatInterval = 0;
diEffect.cAxes = 2;
DWORD dwAxes[2] = { DIJOFS_X, DIJOFS_Y };
diEffect.rgdwAxes = dwAxes;
long lDirection[2] = { 5, 5 };
diEffect.rglDirection = lDirection;
diEffect.lpEnvelope = 0;
diEffect.cbTypeSpecificParams = sizeof(diCForce);
diEffect.lpvTypeSpecificParams = &diCForce;
diEffect.dwStartDelay = 0;
hr = m_pDInputDevJoystick[i]->CreateEffect( GUID_ConstantForce,
&diEffect,
&g_pDIEffect[i],
NULL );

if SUCCEEDED( hr ){
hr = DIERR_NOTEXCLUSIVEACQUIRED;
hr = g_pDIEffect[i]->Start( 1, 0 );
hr = hr;
}
}
}
catch( DWORD dwError ){
dwRet = dwError;
ReleaseJoystick();
}

return dwRet;
}

/****************************************************************
引数: pDidInstance デバイスについての情報
pContext CBlInputのインスタンスへのポインタを渡してください
戻り値: DIENUM_CONTINUE 列挙続行
DIENUM_STOP 列挙終了
説明: ジョイスティックの列挙のためのコールバック関数

***************************************************************/

BOOL CBlInput::EnumJoysticksCallback( const DIDEVICEINSTANCE* pDidInstance, void* pContext )
{
BOOL bRet = DIENUM_STOP;
CBlInput *pBlInput = (CBlInput*)pContext;

assert(pBlInput);

HRESULT hr = pBlInput->m_pDInput->CreateDevice( pDidInstance->guidInstance, &(pBlInput->m_pDInputDevJoystick[pBlInput->m_nJoystickCount]), NULL );

if SUCCEEDED(hr){
++pBlInput->m_nJoystickCount;
bRet = (pBlInput->m_nJoystickCount == MAX_JOYSTICK) ? (DIENUM_STOP):(DIENUM_CONTINUE);
}

return bRet;
}

/****************************************************************
引数: DidOI デバイスのインスタンスについての情報
pContext CBlInputのインスタンスへのポインタを渡してください
戻り値: DIENUM_CONTINUE 設定続行
DIENUM_STOP 設定終了
説明: ジョイスティックの軸設定とオートセンター設定のためのコールバック関数

***************************************************************/

BOOL CBlInput::EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pDidOI, void *pContext )
{
BOOL bRet = DIENUM_STOP;

// 軸の範囲設定
DIPROPRANGE diprg;
ZeroMemory( &diprg, sizeof( diprg ) );
diprg.diph.dwSize = sizeof( diprg );
diprg.diph.dwHeaderSize = sizeof( diprg.diph );
diprg.diph.dwObj = pDidOI->dwType;
diprg.diph.dwHow = DIPH_BYID;
diprg.lMin = LOWER_JOYSTICK_AXIS;
diprg.lMax = UPEER_JOYSTICK_AXIS;

LPDIRECTINPUTDEVICE8 pDevJoystick = (LPDIRECTINPUTDEVICE8)pContext;

if SUCCEEDED( pDevJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ){
bRet = DIENUM_CONTINUE;
}
return bRet;
}
/****************************************************************
引数: なし
戻り値: なし
説明: マウスデバイスを解放する

***************************************************************/

void CBlInput::ReleaseMouse( void )
{
// マウスデバイス解放
if( m_pDInputDevMouse != NULL ){
m_pDInputDevMouse->Unacquire(); // 入力制御停止
m_pDInputDevMouse->Release();
m_pDInputDevMouse = NULL;
}

ZeroMemory( m_lMouseAxis, sizeof(m_lMouseAxis) );
ZeroMemory( m_btMouseButton, sizeof(m_btMouseButton) );
}

/****************************************************************
引数: なし
戻り値: なし
説明: キーボードデバイスを解放する

***************************************************************/

void CBlInput::ReleaseKeyboard( void )
{
// キーボードデバイス解放
if( m_pDInputDevKeyboard != NULL ){
m_pDInputDevKeyboard->Unacquire(); // 入力制御停止
m_pDInputDevKeyboard->Release();
m_pDInputDevKeyboard = NULL;
}

ZeroMemory( m_btKeyData, sizeof(m_btKeyData) );
}

/****************************************************************
引数: なし
戻り値: なし
説明: ジョイスティックデバイスを解放する

***************************************************************/

void CBlInput::ReleaseJoystick( void )
{
// ジョイスティックデバイス解放
for( int i = 0; i < MAX_JOYSTICK; ++i ){
if( m_pDInputDevJoystick[i] != NULL ){
m_pDInputDevJoystick[i]->Release();
m_pDInputDevJoystick[i] = NULL;
}
}

m_dwPolling = 0;

ZeroMemory( m_dwJoystickButton, sizeof(m_dwJoystickButton) );
ZeroMemory( m_lJoystickAxis, sizeof(m_lJoystickAxis) );
ZeroMemory( m_dwJoystickPOV, sizeof(m_dwJoystickPOV) );

m_nJoystickCount = 0;
}

/****************************************************************
引数: なし
戻り値: マウスデータ更新成功 TRUE
マウスデバイスが作成されていない FALSE
説明: マウスデータを更新する

***************************************************************/

BOOL CBlInput::RefreshMouseData( void )
{
BOOL bRet = FALSE;

if( m_pDInputDevMouse != NULL ){
// マウスデータの履歴を一つ後ろにずらす
m_btMouseButton[1] = m_btMouseButton[0];
for( int i = 0; i < MAX_MOUSE_AXIS; ++i ){
m_lMouseAxis[1][i] = m_lMouseAxis[0][i];
}

// 履歴の一番新しい所をクリア
ZeroMemory( &m_btMouseButton[0], sizeof(BYTE) );
ZeroMemory( m_lMouseAxis[0], sizeof(long)*MAX_MOUSE_AXIS );

// マウスデータ取得
DIMOUSESTATE2 mouse;
HRESULT hr = m_pDInputDevMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &mouse );
if SUCCEEDED( hr ){
m_lMouseAxis[0][BLINP_X] = mouse.lX;
m_lMouseAxis[0][BLINP_Y] = mouse.lY;
m_lMouseAxis[0][BLINP_Z] = mouse.lZ;

for( int j = 0; j < MAX_MOUSE_BUTTON; ++j ){
m_btMouseButton[0] += ((mouse.rgbButtons[j] & 0x80) == 0x80) ? ( 0x01 << j) : 0;
}
}
else{
m_pDInputDevMouse->Acquire(); //入力制御が停止しているので動かす
}

bRet = TRUE;
}

return bRet;
}

/****************************************************************
引数: なし
戻り値: キーボードデータ更新成功 TRUE
キーボードデバイスが作成されていない FALSE
説明: マウスデータを更新する

***************************************************************/

BOOL CBlInput::RefreshKeyboardData( void )
{
BOOL bRet = FALSE;

if( m_pDInputDevKeyboard != NULL ){
// キーボードデータの履歴を一つ後ろにずらす
for( int i = 0; i < MAX_KEY; ++i ){
m_btKeyData[1][i] = m_btKeyData[0][i];
}

// 履歴の一番新しい所をクリア
ZeroMemory( m_btKeyData[0] ,sizeof(BYTE)*MAX_KEY );

// キーボードデータ取得
BYTE btKeyData[MAX_KEY];
HRESULT hr = m_pDInputDevKeyboard->GetDeviceState( MAX_KEY, btKeyData );
if SUCCEEDED( hr ){
memcpy( m_btKeyData, btKeyData, 256 );
}
else{
m_pDInputDevKeyboard->Acquire(); //入力制御が停止しているかもしれないので動かす
}

bRet = TRUE;
}

return bRet;
}

/****************************************************************
引数: なし
戻り値: ジョイスティックデータ更新成功 TRUE
ジョイスティックデバイスが作成されていない FALSE
説明: ジョイスティックデータを更新する

***************************************************************/

BOOL CBlInput::RefreshJoystickData( void )
{
BOOL bRet = FALSE;

// ジョイスティックの履歴を一つ後ろにずらす
for( int i = 0; i < m_nJoystickCount; ++i ){
if( m_pDInputDevJoystick[i] != NULL ){
if( m_dwPolling & (0x00000001UL << 1) != 0 ){
m_pDInputDevJoystick[i]->Poll();
}
// ボタン
m_dwJoystickButton[1][i] = m_dwJoystickButton[0][i];
// 軸
for( int j = 0; j < MAX_JOYSTICK_AXIS; ++j ){
m_lJoystickAxis[1][j][i] = m_lJoystickAxis[0][j][i];
}
// POV
for( j = 0; j < MAX_POV; ++j ){
m_dwJoystickPOV[1][j][i] = m_dwJoystickPOV[0][j][i];
}
// 履歴の一番新しい所をクリア
ZeroMemory( &m_dwJoystickButton[0][i], sizeof(DWORD) );
ZeroMemory( m_lJoystickAxis[0][i], sizeof(long)*MAX_JOYSTICK_AXIS );
ZeroMemory( m_dwJoystickPOV[0][i], sizeof(DWORD)*MAX_POV );

// ジョイスティックデータ取得
DIJOYSTATE2 joystick;
HRESULT a = DIERR_INPUTLOST;
a = DIERR_INVALIDPARAM;
a = DIERR_NOTACQUIRED;
a = DIERR_NOTINITIALIZED;
a = E_PENDING;
HRESULT hr = m_pDInputDevJoystick[i]->GetDeviceState( sizeof(DIJOYSTATE2), &joystick );
if SUCCEEDED( hr ){
for( int k = 0; k < MAX_JOYSTICK_BUTTON; ++k ){
m_dwJoystickButton[0][i] += ((joystick.rgbButtons[k] & 0x80) == 0x80) ? (0x00000001 << k) : 0;
}
m_lJoystickAxis[0][BLINP_X_ABS][i] = joystick.lX;
m_lJoystickAxis[0][BLINP_Y_ABS][i] = joystick.lY;
m_lJoystickAxis[0][BLINP_Z_ABS][i] = joystick.lZ;
m_lJoystickAxis[0][BLINP_X_ROTATE][i] = joystick.lRx;
m_lJoystickAxis[0][BLINP_Y_ROTATE][i] = joystick.lRy;
m_lJoystickAxis[0][BLINP_Z_ROTATE][i] = joystick.lRz;
m_lJoystickAxis[0][BLINP_U][i] = joystick.rglSlider[0];
m_lJoystickAxis[0][BLINP_V][i] = joystick.rglSlider[1];
m_lJoystickAxis[0][BLINP_X_VELOCITY][i] = joystick.lVX;
m_lJoystickAxis[0][BLINP_Y_VELOCITY][i] = joystick.lVY;
m_lJoystickAxis[0][BLINP_Z_VELOCITY][i] = joystick.lVZ;
m_lJoystickAxis[0][BLINP_U_VELOCITY][i] = joystick.rglVSlider[0];
m_lJoystickAxis[0][BLINP_V_VELOCITY][i] = joystick.rglVSlider[1];
m_lJoystickAxis[0][BLINP_X_ACCELERATION][i] = joystick.lAX;
m_lJoystickAxis[0][BLINP_Y_ACCELERATION][i] = joystick.lAY;
m_lJoystickAxis[0][BLINP_Z_ACCELERATION][i] = joystick.lAZ;
m_lJoystickAxis[0][BLINP_U_ACCELERATION][i] = joystick.rglASlider[0];
m_lJoystickAxis[0][BLINP_V_ACCELERATION][i] = joystick.rglASlider[1];
m_lJoystickAxis[0][BLINP_X_VELOCITY_RAD][i] = joystick.lARx;
m_lJoystickAxis[0][BLINP_Y_VELOCITY_RAD][i] = joystick.lARy;
m_lJoystickAxis[0][BLINP_Z_VELOCITY_RAD][i] = joystick.lARz;
m_lJoystickAxis[0][BLINP_X_FORCE][i] = joystick.lFX;
m_lJoystickAxis[0][BLINP_Y_FORCE][i] = joystick.lFY;
m_lJoystickAxis[0][BLINP_Z_FORCE][i] = joystick.lFZ;
m_lJoystickAxis[0][BLINP_U_FORCE][i] = joystick.rglFSlider[0];
m_lJoystickAxis[0][BLINP_V_FORCE][i] = joystick.rglFSlider[1];
m_lJoystickAxis[0][BLINP_X_TORQUE][i] = joystick.lFRx;
m_lJoystickAxis[0][BLINP_Y_TORQUE][i] = joystick.lFRy;
m_lJoystickAxis[0][BLINP_Z_TORQUE][i] = joystick.lFRz;

for( k = 0; k < MAX_POV; ++k ){
m_dwJoystickPOV[0][k][i] = joystick.rgdwPOV[k];
}
}
else{
m_pDInputDevJoystick[i]->Acquire();
}
bRet = TRUE;
}
}

return bRet;
}

/****************************************************************
引数: nButtonID データを取得したいボタンの定数
BLINP_LBUTTON 左ボタン
BLINP_RBUTTON 右ボタン
BLINP_MBUTTON 中ボタン
戻り値: TRUE 押されていた
FALSE 押されていなかった nButtonIDが不正
説明: マウスボタンの押下状態を提供する

***************************************************************/

BOOL CBlInput::GetMouseButton( const int nButtonID )
{
BOOL bRet = FALSE;
if( (nButtonID >= 0) && (nButtonID < MAX_MOUSE_BUTTON) ){
if( (m_btMouseButton[0] & nButtonID) != 0 ){
bRet = TRUE;
}
}

return bRet;
}

/****************************************************************
引数: nButtonID データを取得したいボタンの定数
BLINP_LBUTTON 左ボタン
BLINP_RBUTTON 右ボタン
BLINP_MBUTTON 中ボタン
戻り値: BLINP_TRIGGER_DOWN DOWNトリガー(OFF→ON)
BLINP_TRIGGER_UP UPトリガー(ON→OFF)
0 トリガー検出なし nButtonIDが不正
説明: マウスボタンのトリガーを提供する

***************************************************************/

int CBlInput::GetMouseButtonTrigger( const int nButtonID )
{
int nRet = 0;

if( (nButtonID >= 0) && (nButtonID < MAX_MOUSE_BUTTON) ){
if( (m_btMouseButton[0] & nButtonID) == 0 ){
if( (m_btMouseButton[1] & nButtonID) != 0 ){
nRet = BLINP_TRIGGER_DOWN;
}
}
else{
if( (m_btMouseButton[1] & nButtonID) == 0 ){
nRet = BLINP_TRIGGER_UP;
}
}
}

return nRet;
}

/****************************************************************
引数: nDataID データを取得したい軸の定数
BLINP_X X軸
BLINP_Y Y軸
BLINP_Z Z軸
戻り値: 軸の動いた量
説明: マウスの軸データを提供する
注意: 引数のnAxisIDが存在しない場合、戻り値は0を返す

***************************************************************/

int CBlInput::GetMouseAxisData( const int nAxisID )
{
int nAxisLevel = 0;

if( (nAxisID >= 0) && (nAxisID < MAX_MOUSE_AXIS) ){
nAxisLevel = m_lMouseAxis[0][nAxisID];
}

return nAxisLevel;
}

/****************************************************************
引数: nKeyID データを取得したいキーの定数(DIK_〜)
戻り値: TRUE 押されていた
FALSE 押されていなかった
説明: キーボードのキーの押下状態を提供する

***************************************************************/

BOOL CBlInput::GetKey( const int nKeyID )
{
BOOL bRet = FALSE;

if( (nKeyID >= 0) && (nKeyID < MAX_KEY) ){
if( (m_btKeyData[0][nKeyID]&0x80) != 0 ){
bRet = TRUE;
}
}

return bRet;
}

/****************************************************************
引数: nKeyID データを取得したいキーの定数(DIK_〜)
戻り値: BLINP_TRIGGER_DOWN DOWNトリガー(OFF→ON)
BLINP_TRIGGER_UP UPトリガー(ON→OFF)
0 トリガー検出なし nKeyIDが不正
説明: キーボードのキーのトリガーを提供する

***************************************************************/

int CBlInput::GetKeyTrigger( const int nKeyID )
{
int nRet = 0;

if( (nKeyID >= 0) && (nKeyID < MAX_KEY ) ){
if( (m_btKeyData[0][nKeyID]&0x80) == 0 ){
if( (m_btKeyData[1][nKeyID]&0x80) != 0 ){
nRet = BLINP_TRIGGER_DOWN;
}
}
else{
if( (m_btKeyData[1][nKeyID]&0x80) == 0 ){
nRet = BLINP_TRIGGER_UP;
}
}
}

return nRet;
}

/****************************************************************
引数: dwButtonID データを取得したいボタンの定数
nPlayer プレイヤー
戻り値: TRUE 押されていた
FALSE 押されていなかった
説明: キーボードのキーのトリガーを提供する

***************************************************************/

BOOL CBlInput::GetJoystickButton( const DWORD dwButtonID, const int nPlayer )
{
BOOL bRet = FALSE;

if( (nPlayer >= 0) && (nPlayer < MAX_JOYSTICK) ){
if( (m_dwJoystickButton[0][nPlayer]&dwButtonID) != 0 ){
bRet = TRUE;
}
}

return bRet;
}

/****************************************************************
引数: dwButtonID データを取得したいボタンの定数
戻り値: BLINP_TRIGGER_DOWN DOWNトリガー(OFF→ON)
BLINP_TRIGGER_UP UPトリガー(ON→OFF)
0 トリガー検出なし nPlayerが不正
説明: ジョイスティックのボタンのトリガーを提供する

***************************************************************/

int CBlInput::GetJoystickButtonTrigger( const DWORD dwButtonID, const int nPlayer )
{
int nRet = 0;

if( (nPlayer >= 0) && (nPlayer < MAX_JOYSTICK) ){
if( (m_dwJoystickButton[0][nPlayer]&dwButtonID) == 0 ){
if( (m_dwJoystickButton[1][nPlayer]&dwButtonID) != 0 ){
nRet = BLINP_TRIGGER_DOWN;
}
}
else{
if( (m_dwJoystickButton[1][nPlayer]&dwButtonID) == 0 ){
nRet = BLINP_TRIGGER_UP;
}
}
}

return nRet;
}


/****************************************************************
引数: nAxisID データを取得したい軸の定数
nPlayer プレイヤー
戻り値: 軸の動いた量
説明: ジョイスティックの軸データを提供する
注意: 引数のnAxisIDが存在しない場合、戻り値は0を返す

***************************************************************/

int CBlInput::GetJoystickAxisData( const int nAxisID, const int nPlayer )
{
int nRet = 0;

if( (nAxisID >= 0) && (nAxisID < MAX_JOYSTICK_AXIS) &&
(nPlayer >= 0) && (nPlayer < MAX_JOYSTICK) ){
nRet = m_lJoystickAxis[0][nAxisID][nPlayer];
}

return nRet;
}

/****************************************************************
引数: nPOVID データを取得したいPOVの定数
nPlayer プレイヤー
戻り値: POV軸の動いた量
説明: ジョイスティックのPOV軸データを提供する
注意: 引数のnPOVIDが存在しない場合、戻り値は0を返す

***************************************************************/

int CBlInput::GetJoystickPOVData( const int nPOVID, const int nPlayer )
{
DWORD dwRet = 0;

if( (nPOVID >= 0) && (nPOVID < MAX_POV) &&
(nPlayer >= 0) && (nPlayer < MAX_JOYSTICK) ){
dwRet = m_dwJoystickPOV[0][nPOVID][nPlayer];
}

return dwRet;
}

⑤サンプルプログラム(BlueInput.h)

#pragma once

#include

// マウスの左ボタン定数
const int BLINP_LBUTTON = 0x01;
// マウスの右ボタン定数
const int BLINP_RBUTTON = 0x02;
// マウスの中ボタン定数
const int BLINP_MBUTTON = 0x04;
// マウスのX軸定数
const int BLINP_X = 0;
// マウスのY軸定数
const int BLINP_Y = 1;
// マウスのZ軸定数
const int BLINP_Z = 2;

// ジョイスティックの1ボタン定数
const int BLINP_1BUTTON = 0x00000001;
// ジョイスティックの2ボタン定数
const int BLINP_2BUTTON = 0x00000002;
// ジョイスティックの3ボタン定数
const int BLINP_3BUTTON = 0x00000004;
// ジョイスティックの4ボタン定数
const int BLINP_4BUTTON = 0x00000008;
// ジョイスティックの5ボタン定数
const int BLINP_5BUTTON = 0x00000010;
// ジョイスティックの6ボタン定数
const int BLINP_6BUTTON = 0x00000020;
// ジョイスティックの7ボタン定数
const int BLINP_7BUTTON = 0x00000040;
// ジョイスティックの8ボタン定数
const int BLINP_8BUTTON = 0x00000080;
// ジョイスティックの9ボタン定数
const int BLINP_9BUTTON = 0x00000100;
// ジョイスティックの10ボタン定数
const int BLINP_10BUTTON = 0x00000200;
// ジョイスティックの11ボタン定数
const int BLINP_11BUTTON = 0x00000400;
// ジョイスティックの12ボタン定数
const int BLINP_12BUTTON = 0x00000800;
// ジョイスティックの13ボタン定数
const int BLINP_13BUTTON = 0x00001000;
// ジョイスティックの14ボタン定数
const int BLINP_14BUTTON = 0x00002000;
// ジョイスティックの15ボタン定数
const int BLINP_15BUTTON = 0x00004000;
// ジョイスティックの16ボタン定数
const int BLINP_16BUTTON = 0x00008000;
// ジョイスティックの17ボタン定数
const int BLINP_17BUTTON = 0x00010000;
// ジョイスティックの18ボタン定数
const int BLINP_18BUTTON = 0x00020000;
// ジョイスティックの19ボタン定数
const int BLINP_19BUTTON = 0x00040000;
// ジョイスティックの20ボタン定数
const int BLINP_20BUTTON = 0x00080000;
// ジョイスティックの21ボタン定数
const int BLINP_21BUTTON = 0x00100000;
// ジョイスティックの22ボタン定数
const int BLINP_22BUTTON = 0x00200000;
// ジョイスティックの23ボタン定数
const int BLINP_23BUTTON = 0x00400000;
// ジョイスティックの24ボタン定数
const int BLINP_24BUTTON = 0x00800000;
// ジョイスティックの25ボタン定数
const int BLINP_25BUTTON = 0x01000000;
// ジョイスティックの26ボタン定数
const int BLINP_26BUTTON = 0x02000000;
// ジョイスティックの27ボタン定数
const int BLINP_27BUTTON = 0x04000000;
// ジョイスティックの28ボタン定数
const int BLINP_28BUTTON = 0x08000000;
// ジョイスティックの29ボタン定数
const int BLINP_29BUTTON = 0x10000000;
// ジョイスティックの30ボタン定数
const int BLINP_30BUTTON = 0x20000000;
// ジョイスティックの31ボタン定数
const int BLINP_31BUTTON = 0x40000000;
// ジョイスティックの32ボタン定数
const int BLINP_32BUTTON = 0x80000000;

// ジョイスティックのX軸絶対座標定数
const int BLINP_X_ABS = 0;
// ジョイスティックのY軸絶対座標定数
const int BLINP_Y_ABS = 1;
// ジョイスティックのZ軸絶対座標定数
const int BLINP_Z_ABS = 2;
// ジョイスティックのX軸回転量定数
const int BLINP_X_ROTATE = 3;
// ジョイスティックのY軸回転量定数
const int BLINP_Y_ROTATE = 4;
// ジョイスティックのZ軸回転量定数
const int BLINP_Z_ROTATE = 5;
// ジョイスティックの追加軸Uの座標定数
const int BLINP_U = 6;
// ジョイスティックの追加軸Vの座標定数
const int BLINP_V = 7;
// ジョイスティックのX軸速度定数
const int BLINP_X_VELOCITY = 8;
// ジョイスティックのY軸速度定数
const int BLINP_Y_VELOCITY = 9;
// ジョイスティックのZ軸速度定数
const int BLINP_Z_VELOCITY = 10;
// ジョイスティックの追加軸Uの速度定数
const int BLINP_U_VELOCITY = 11;
// ジョイスティックの追加軸Vの速度定数
const int BLINP_V_VELOCITY = 12;
// ジョイスティックのX軸加速度定数
const int BLINP_X_ACCELERATION = 13;
// ジョイスティックのY軸加速度定数
const int BLINP_Y_ACCELERATION = 14;
// ジョイスティックのZ軸加速度定数
const int BLINP_Z_ACCELERATION = 15;
// ジョイスティックの追加軸Uの加速度定数
const int BLINP_U_ACCELERATION = 16;
// ジョイスティックの追加軸Vの加速度定数
const int BLINP_V_ACCELERATION = 17;
// ジョイスティックのX軸角速度定数
const int BLINP_X_VELOCITY_RAD = 18;
// ジョイスティックのY軸角速度定数
const int BLINP_Y_VELOCITY_RAD = 19;
// ジョイスティックのZ軸角速度定数
const int BLINP_Z_VELOCITY_RAD = 20;
// ジョイスティックのX軸角加速度定数
const int BLINP_X_ACCELERATION_RAD = 21;
// ジョイスティックのY軸角加速度定数
const int BLINP_Y_ACCELERATION_RAD = 22;
// ジョイスティックのZ軸角加速度定数
const int BLINP_Z_ACCELERATION_RAD = 23;
// ジョイスティックのX軸フォース定数
const int BLINP_X_FORCE = 24;
// ジョイスティックのY軸フォース定数
const int BLINP_Y_FORCE = 25;
// ジョイスティックのZ軸フォース定数
const int BLINP_Z_FORCE = 26;
// ジョイスティックの追加軸Uのフォース定数
const int BLINP_U_FORCE = 27;
// ジョイスティックの追加軸Vのフォース定数
const int BLINP_V_FORCE = 28;
// ジョイスティックのX軸フォース定数
const int BLINP_X_TORQUE = 29;
// ジョイスティックのY軸フォース定数
const int BLINP_Y_TORQUE = 30;
// ジョイスティックのZ軸フォース定数
const int BLINP_Z_TORQUE = 31;

// ジョイスティックのPOV1定数
const int BLINP_1POV = 0;
// ジョイスティックのPOV1定数
const int BLINP_2POV = 1;
// ジョイスティックのPOV1定数
const int BLINP_3POV = 2;
// ジョイスティックのPOV1定数
const int BLINP_4POV = 3;

// ボタンのトリガー定数
const int BLINP_TRIGGER_DOWN = 1; // DOWNトリガー
const int BLINP_TRIGGER_UP = -1; // UPトリガー

// DirectInputオブジェクト作成失敗
const DWORD BLINP_ERROR_CREATE = 0x0600;
// マウスデバイス作成エラー
const DWORD MOUSE_ERROR_CREATE = 0x0700;
// マウスデバイスのデータフォーマット設定エラー
const DWORD MOUSE_ERROR_DATAFORMAT = 0x0701;
// マウスデバイスのモード設定エラー
const DWORD MOUSE_ERROR_MODE = 0x0703;
// 軸モードの設定エラー
const DWORD MOUSE_ERROR_AXIS = 0x0704;
// キーボードデバイス作成エラー
const DWORD KEYBOARD_ERROR_CREATE = 0x0800;
// キーボードデバイスのデータフォーマット設定エラー
const DWORD KEYBOARD_ERROR_DATAFORMAT = 0x0801;
// キーボードデバイスのモード設定エラー
const DWORD KEYBOARD_ERROR_MODE = 0x0803;
// ジョイスティック列挙エラー
const DWORD JOYSTICK_ERROR_ENUM = 0x0900;

// マウスの軸数
#define MAX_MOUSE_AXIS (3)
// マウスのボタン数
#define MAX_MOUSE_BUTTON (8)
// キーボードのキー数
#define MAX_KEY (256)
// ジョイスティックの接続可能最大数
#define MAX_JOYSTICK (16)
// ジョイスティックの軸の上限
#define UPEER_JOYSTICK_AXIS (32767)
// ジョイスティックの軸の下限
#define LOWER_JOYSTICK_AXIS (-32768)
// ジョイスティックのボタンデータの数
#define MAX_JOYSTICK_BUTTON (32)
// ジョイスティックの軸データの数
#define MAX_JOYSTICK_AXIS (32)
// 視点ハット等コントローラの数
#define MAX_POV (4)
// 履歴の数
#define MAX_HISTORY (2)

/*************************************
クラス名: CBlInput
説明: DirectInput8を使うクラス

************************************/

class CBlInput
{
private:
LPDIRECTINPUT8 m_pDInput; // DirectInput8インターフェイス
LPDIRECTINPUTDEVICE8 m_pDInputDevMouse; // DirectInput8デバイス:マウス用
LPDIRECTINPUTDEVICE8 m_pDInputDevKeyboard; // DirectInput8デバイス:キーボード用
LPDIRECTINPUTDEVICE8 m_pDInputDevJoystick[MAX_JOYSTICK]; // DirectInput8デバイス:ジョイスティック用
long m_lMouseAxis[MAX_HISTORY][MAX_MOUSE_AXIS]; // マウスの軸データ
BYTE m_btMouseButton[MAX_HISTORY]; // マウスのボタンデータ
BYTE m_btKeyData[MAX_HISTORY][MAX_KEY]; // キーボードデータ格納
DWORD m_dwJoystickButton[MAX_HISTORY][MAX_JOYSTICK]; // ジョイスティックのボタンデータ
long m_lJoystickAxis[MAX_HISTORY][MAX_JOYSTICK_AXIS][MAX_JOYSTICK]; // ジョイスティックの軸データ
DWORD m_dwJoystickPOV[MAX_HISTORY][MAX_POV][MAX_JOYSTICK]; // ジョイスティックの視点ハット等コントローラデータ
int m_nJoystickCount; // 接続中のジョイスティック数
DWORD m_dwPolling; // ポーリングのフラグ

BOOL InitDxInput( const HINSTANCE &hInst ); // DirectInput初期化

void ReleaseMouse( void ); // マウスデバイス解放
void ReleaseKeyboard( void ); // キーボードデバイス解放
void ReleaseJoystick( void ); // ジョイスティックデバイス解放

//コールバック関数
static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pDidInstance, void* pContext ); // ジョイスティック列挙
static BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pDidOI, void *pContext ); // 軸設定

public:
CBlInput( void );
DWORD InitMouse( const HINSTANCE &hInst, const HWND &hWnd ); // マウスモード初期化
DWORD InitKeyboard( const HINSTANCE &hInst, const HWND &hWnd ); // キーボードモード初期化
DWORD InitJoystick( const HINSTANCE &hInst, const HWND &hWnd, const int nNum, int *pnSetNum ); // ジョイスティックモード初期化
void Release( void ); // DirectInput解放
BOOL RefreshMouseData( void ); // マウスデータを更新する
BOOL RefreshKeyboardData( void ); // キーボードデータを更新する
BOOL RefreshJoystickData( void ); // ジョイスティックデータを更新する
BOOL GetMouseButton( const int nButtonID ); // マウスのボタンの押下状態を提供する
int GetMouseButtonTrigger( const int nButtonID ); // マウスのボタンのトリガーを提供する
int GetMouseAxisData( const int nAxisID ); // マウスの軸のデータを提供する
BOOL GetKey( const int nKeyID ); // キーボードのキーの押下状態を提供する
int GetKeyTrigger( const int nKeyID ); // キーボードのキーのトリガーを提供する
BOOL GetJoystickButton( const DWORD dwButtonID, const int nPlayer ); // ジョイスティックのボタンの押下状態を提供する
int GetJoystickButtonTrigger( const DWORD dwButtonID, const int nPlayer ); // ジョイスティックのボタンのトリガーを提供する
int GetJoystickAxisData( const int nAxisID, const int nPlayer ); // ジョイスティックの軸データを提供する
int GetJoystickPOVData( const int nPOVID, const int nPlayer ); // ジョイスティックのPOVデータを提供する
};