C# 通过DirectInput 实现手柄操控
創作背景:近期,一友人希望使用手柄代替鍵盤玩格斗游戲,自行寫了款手柄鍵盤模擬器,結果在游戲時無法正常運行,托在下看看。程序寫得不錯,手柄很準確地在記事本上輸出鍵盤鍵碼。
然而,進入游戲,卻什么反應都沒有。一個念頭閃現出來,游戲的輸入是通過directinput實現的,比WINDOWS API 更接近底層,這樣可以贏取更短的響應時間,程序需向directinput改進,然而這里不得不說下:上網搜索大小網站都是那篇API 實現手柄信息獲取的文章,和友人的代碼90%的相似度,文章寫得很好說真的,但全是這篇就有點過了。國內沒有要找的就找下國外吧,百度的確有些害人,因為太懂中文,國外的directinput一張都沒有,立馬換了搜索頁,2小時就用directinput完成了手柄信息獲取,然而殊不知接下來的震動功能花費了4天時間…
完成后界面:
功能目標: 1、獲取手柄方向、按鍵信息;2、使手柄震動
??????????????? 注意,本程序只是通過DX發送震動信息,并不是什么萬能手柄驅動啊。
?????????????? ?測試手柄震動前,請確認使用的是震動手柄并安裝了手柄驅動。
開發環境:Win7 (DX10傳說中的DX11類庫我沒有找到,結果項目建了.NET 3.5)
???????????????????Microsoft Visual Studio 2010
?????????????????? ? 數據庫無
?????????????????? ?代碼在1920 X 1080 分辨率下無過長換行
?????????????????? ?編寫人數 1人
參考資料:MSDN資料庫
??????? 言歸正傳,在.NET的高封裝的環境下,directinput的使用簡化了許多,不了解COM的朋友,甚至是不知道句柄、指針的新手也可以輕易掌握。
思路與實現:首先,我們要計算機找到我們的搖桿設備
foreach (DeviceInstance info in Manager.GetDevices(DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly)) {Device myJoy = new Device(info.InstanceGuid); }
??????? 然后控制設備,過去用c++的朋友很熟悉了,申請操作級別,這個真的很重要,在最后測試震動報了“沒有獨占打開無法操作”的異常,單步了整整一天,才發現是這里設錯參了。
再設置其他參數
?
myJoy.Properties.AxisModeAbsolute = true; myJoy.Properties.AutoCenter = false; myJoy.Acquire();int[] axis = null; foreach (DeviceObjectInstance doi in myJoy.Objects) {if ((doi.ObjectId & (int)DeviceObjectTypeFlags.Axis) != 0){myJoy.Properties.SetRange(ParameterHow.ById, doi.ObjectId, new InputRange(-128, 128));} }???????好了,目標1完成,很快是不?手柄的狀態已經在myJoy. CurrentJoystickState下了,通過
myJoy. CurrentJoystickState. ToString() 你可以查看到搖桿狀態(微軟大費苦心啊,左搖桿、右搖桿、光槍,壓桿,基本上能想到的有位移的操作桿都有了)
allJoystick.Joysticks[i].CurrentJoystickState.GetButtons()可以得到按下按鈕組合的數組
?
??????? 好,開始進軍震動了。震動不同于按鍵捕捉、不同于模擬鍵盤、鼠標擊鍵,因為這些計算機都是作為信息的接受方,然而這次是手柄作為接受方。也與一些掛起、響應的程序不同,掛起的程序用于監聽端口,當有數據流后運算后反饋硬件。
??????? 例如,我進入一款格斗游戲后不對手柄進行任何輸入,時間到后自動選人開打,在被CPU攻擊時手柄是有震感的。
也就是說震動指令是由計算機發起的,當時還真想用匯編給它來一段,裝了個Bus Hound 5.0 抓包結果Win7藍屏 花了1個多小時恢復。
??????? 扯遠了,手柄的震動是像聲音一樣播放的,看參考資料,資料中例舉了使用SDK下的錄制好的震動文件來驅動,國外一達人說該函數有BUG,剛好我又不想下載幾百兆的SDK。故選擇了最后一種方式,現場定制(錄制)、現場播放。
?
代碼不難,調試卻很羅嗦。
//震動類型 public enum ForceType {VeryBriefJolt,BriefJolt,LowRumble,HardRumble } //錄制函數,照抄參考資料 public static EffectObject InitializeForce(Device Dev, EffectType Type, int[] Axis, int Magnitude, EffectFlags Flags, int Duration){EffectObject eo = null;Effect e;foreach (EffectInformation ei in Dev.GetEffects(EffectType.All)){if (DInputHelper.GetTypeCode(ei.EffectType) == (int)Type){e = new Effect();e.SetDirection(new int[Axis.Length]);e.SetAxes(new int[1]);e.EffectType = Type;e.ConditionStruct = new Condition[Axis.Length];e.Duration = Duration;e.Gain = 10000;e.Constant = new ConstantForce();e.Constant.Magnitude = Magnitude;e.SamplePeriod = 0;e.TriggerButton = (int)Microsoft.DirectX.DirectInput.Button.NoTrigger;e.TriggerRepeatInterval = (int)DI.Infinite;e.Flags = Flags;e.UsesEnvelope = false;eo = new EffectObject(ei.EffectGuid, e, Dev); }}return eo;}//播放 InitializeForce(myJoy, EffectType.ConstantForce, axis, 10000, EffectFlags.ObjectOffsets | EffectFlags.Spherical, 2000000).start(1);
??????? 用震動來按摩還真不錯,附上調試好的源碼,與各位同僚共勉:
源碼下載
總結
以上是生活随笔為你收集整理的C# 通过DirectInput 实现手柄操控的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多媒体SCM格式介绍
- 下一篇: 向量对矩阵列空间的投影_向量(阵列)处理