DirectInput手柄在Windows环境下震动实现
DirectInput手柄Windows環(huán)境下震動實現(xiàn)
- 背景
- 1.direcrInput手柄震動控制
- 1.1運行環(huán)境
- 1.2代碼實現(xiàn)
- 2 模擬XInput設備,通過XInput實現(xiàn)
- 2.1 x360ce設置
- 2.2 XInput 代碼實現(xiàn)
- 2.3 x360ce分析
背景
近期項目里面有個需求,需要在控制終端上安裝搖桿,且需要通過震動反饋設備的某些重要運行狀態(tài)。自以為機智的自己在萬能的某寶買了一個飛行搖桿,帶震動反饋,DInput接口,結果是踩坑的開始。
Windows下手柄分為兩類,XInput和DirectInput,XInput主要是Xbox系列手柄,比較貴,親兒子;市面上大多雜牌的手柄都只支持DirectInput。查閱官方文檔:xinput and directinput 心涼了半截:The vibration effects will not be available,意思就是directinput不再支持手柄震動了。不過directInput有一個directInputEffect,從文檔看是力反饋,論壇說也能拿來做震動,因此先用directInput做一下嘗試。
1.direcrInput手柄震動控制
1.1運行環(huán)境
環(huán)境搭建就不再贅述,主要就是選一個win10的tool kit,已經(jīng)集成了directx。Qt是項目中用于界面搭建的環(huán)境。
(1)windows 10 1903
(2)Qt 5.9
1.2代碼實現(xiàn)
github 上有比較完整的 QGameController,能夠實現(xiàn)手柄的識別、各參數(shù)的讀取,封裝比較完整,但是沒有手柄震動的驅動。本著不重復造輪子的原則,從這個開源項目開始進行代碼實現(xiàn)。
DWORD dwAxisX = DIJOFS_X; //一個震動電機LONG lDirecX = 0;DIPERIODIC diPeriodic; ZeroMemory(&diPeriodic, sizeof(DIPERIODIC));DICONSTANTFORCE diConstantForce;ZeroMemory(&diConstantForce, sizeof(DICONSTANTFORCE));DIEFFECT diEffect; // general parameters// set up the effect structure itselfdiEffect.dwSize = sizeof(DIEFFECT);diEffect.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;diEffect.dwDuration = (DWORD) INFINITE; diEffect.dwStartDelay = 0;// set up details of effectdiEffect.dwSamplePeriod = 0; diEffect.dwGain = lVibraStrength; diEffect.dwTriggerButton = DIEB_NOTRIGGER;// connect effect to trigger buttondiEffect.dwTriggerRepeatInterval = 0;diEffect.cAxes = 1;diEffect.rgdwAxes = &dwAxisX;diEffect.rglDirection = &lDirecX;diEffect.lpEnvelope = 0;diConstantForce.lMagnitude = DI_FFNOMINALMAX;diEffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);diEffect.lpvTypeSpecificParams = &diConstantForce;// create the effect and get the interface to ithr = g_pJoystick->CreateEffect(GUID_ConstantForce, // standard GUID&diEffect, // where the data is&lpdieffect, // where to put interface pointerNULL); // no aggregationif(FAILED(hr)){qDebug()<< "create effect failed";}g_pJoystick->SendForceFeedbackCommand(DISFFC_RESET);//g_pJoystick->SendForceFeedbackCommand(DISFFC_SETACTUATORSON);if( FAILED(g_pJoystick->SendForceFeedbackCommand(DISFFC_SETACTUATORSON)))qDebug() << "start failed";hr = lpdieffect->Download();if(FAILED(hr))qDebug("download failed, the error NO is %X",hr);hr = lpdieffect->Start(INFINITE,DIES_SOLO);if(FAILED(hr))qDebug("start failed, the error NO is %X",hr);代碼有些冗長,參照了策隨心和code從業(yè)員兩位大佬的一些參數(shù)設置,雖然用的語言不一樣,但是道理都是一樣的。
代碼運行并沒有那么順利,手柄在download和start以后,并沒有反應,整個世界都是清凈的。查找錯誤代碼是0x80040205 DIERR_NOTEXCLUSIVEACQUIRED,注釋是:The operation cannot be performed unless the device is acquired in DISCL_EXCLUSIVE mode。意思是這個操作在獨占模式下才可以實現(xiàn)。因此我在create前面加了:
運行,世界還是一片寂靜。這個bug直到現(xiàn)在都沒調好,有大佬知道為啥,請告訴我!
2 模擬XInput設備,通過XInput實現(xiàn)
deadline越來越近,不能在一條路上撞死。逛論壇找大神的時候,發(fā)現(xiàn)DInput的設備可以通過軟件模擬,變成XInput設備。在微軟提供的XInput庫中,有函數(shù)直接可以實現(xiàn)vibration。嘗試了多個軟件以后,找到了開源的x360ce,程序和源代碼都能在官網(wǎng)上找到。
2.1 x360ce設置
在完成相關設置后,可以一鍵autosetting。上面一排標簽可以看到Force Feedback,在這個選項卡中,拖動test的進度條后,手柄震動起來了,第一步完成。
2.2 XInput 代碼實現(xiàn)
在qt中搭一個簡單界面,按鍵做震動開關。把下面的代碼塊放到按鍵的槽函數(shù)中。
XINPUT_VIBRATION vibration;ZeroMemory( &vibration, sizeof(XINPUT_VIBRATION) );vibration.wLeftMotorSpeed = LeftMotorSpeed; vibration.wRightMotorSpeed = RightMotorSpeed; XInputSetState( uID, &vibration );把x360ce中生成的xinput1_3.dll放到程序的運行目錄下面,點擊運行,動了!果然是親兒子,這么小的代碼量就能解決上面一片的所有問題。
2.3 x360ce分析
看了一下開源的代碼,這個軟件主要分為兩大部分,一部分是生成dll文件,C++;一部分是界面,C#。
x360ce_dll工程里,代碼量不大,主要是通過DirectInput控制手柄,再給XInput提供接口。震動的實時是調用XInputSetState,而不是directInputEffect.start,所以沒有出現(xiàn)上面的獨占問題。
總結
以上是生活随笔為你收集整理的DirectInput手柄在Windows环境下震动实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: csdn切换格式markdown
- 下一篇: Linux下使用QQ