三自由度的动感座椅可以让玩游戏人员在玩的过程中随座椅一起晃动,通过应用程序对方向盘动作的抓取来实现体感,动作类型主要分为加速(后仰,对应踩油门)、减速(前倾,对应踩刹车 )、左转(向左打方向盘)、右转(向右打方向盘)。座椅通过3个电缸支撑起来,程序初始化之后,会让三个电缸依据自己的行程运动到中间位置,动作类型的角度依据机械结构来进行自定义。以上是针对整体项目的一个简单介绍,接下来想说明一下如何通过代码的方式来实现对游戏方向盘的数据抓取。常规的思路有2种:1种是通过DirectInput技术,一种是通过Win API(Multimedia joystick API),今天这里讲解如何通过前者来实现针对游戏方向盘数据的抓取。
抓取方向盘数据主要通过Joystick类来实现,下面是该类的核心函数runJoystick,代码如下:
INT_PTR Joystick::runJoystick( HWND hDlg) { switch( this->msg ) { case WM_INITDIALOG: InitDirectInput( hDlg ); return TRUE; case WM_TIMER: // Update the input device UpdateInputState( hDlg); return TRUE; case WM_DESTROY: // Cleanup everything FreeDirectInput(); return TRUE; } return FALSE; // Message not handled }
定时器中的UpdateInputState函数在设定的循环周期内将游戏方向盘中的数据抓取出来,代码如下:
HRESULT Joystick::UpdateInputState( HWND hDlg) { HRESULT hr; TCHAR strText[512] = {0}; // Device state text DIJOYSTATE2 js; // DInput Joystick state if( NULL == this->g_pJoystick ) return S_OK; // Poll the device to read the current state hr = this->g_pJoystick->Poll(); if( FAILED( hr ) ) { // DInput is telling us that the input stream has been // interrupted. We aren't tracking any state between polls, so // we don't have any special reset that needs to be done. We // just re-acquire and try again. hr = this->g_pJoystick->Acquire(); if( hr == DIERR_INPUTLOST ) { this->g_pJoystick->Acquire(); return hr; } // hr may be DIERR_OTHERAPPHASPRIO or other errors. This // may occur when the app is minimized or in the process of // switching, so just try again later return S_OK; } // Get the input's device state if( FAILED( hr = this->g_pJoystick->GetDeviceState( sizeof( DIJOYSTATE2 ), &js ) ) ) { this->errorMSG = "Joystick connection lost"; this->msg = WM_DESTROY; //find a new joystick return hr; } //Read values into Joystick object this->setAxis(js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz, js.rglSlider[0], js.rglSlider[1]); this->setPOV(js.rgdwPOV[0], js.rgdwPOV[1], js.rgdwPOV[2], js.rgdwPOV[3]); for( int i = 0; i < 128; i++ ) { if( js.rgbButtons[i] & 0x80 ) this->setButton(i,true); else this->setButton(i,false); } this->errorMSG = "Reading Joystick OK"; return S_OK; }
相关程序的Demo下载地址在这里。