首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 遊戲手柄程式開發 - API 篇 (2):主動/被動模式與按鍵去抖動

     編輯:關於C#

C# 遊戲手柄開發系列 (2):主動輪詢模式、按鍵狀態去重與組合鍵完美解法

上篇介紹「被動模式」(系統定時推送訊息),本篇深入「主動模式」(程式主動輪詢)並解決按鍵重複觸發與組合鍵並發的核心難題。

一、回顧:被動模式痛點

系統以 uPeriod 間隔推送狀態,人類按下→釋放極短時間內可能收到 N 次「按下」訊息,若直接處理會導致遊戲角色連續移動多步(單次點擊卻觸發多次)。

二、主動模式:joyGetPosEx API

[DllImport("winmm.dll")]
public static extern int joyGetPos(int uJoyID, ref JOYINFO pji);

[DllImport("winmm.dll")]
public static extern int joyGetPosEx(int uJoyID, ref JOYINFOEX pji);

joyGetPos 僅支援 4 個按鈕,實務建議使用 joyGetPosEx。

三、JOYINFOEX 結構體定義

[StructLayout(LayoutKind.Sequential)]
public struct JOYINFOEX
{
    public int dwSize;        // 結構大小,必須初始化
    public int dwFlags;       // 指定欲取得資料項
    public int dwXpos;        // X 座標
    public int dwYpos;        // Y 座標
    public int dwZpos;        // Z 座標
    public int dwRpos;        // 第四軸
    public int dwUpos;        // 第五軸
    public int dwVpos;        // 第六軸
    public int dwButtons;     // 32 個按鈕狀態位元組合
    public int dwButtonNumber;// 當前按下按鈕編號
    public int dwPOV;         // 視角控制器角度 (0-35900)
    public int dwReserved1;
    public int dwReserved2;
}

四、主動輪詢實作步驟

JOYINFOEX infoEx = new JOYINFOEX();
infoEx.dwSize = Marshal.SizeOf(typeof(JOYINFOEX));
infoEx.dwFlags = (int)JOY_RETURNBUTTONS; // 需取得按鈕狀態

int result = joyGetPosEx(this.Id, ref infoEx);
if (result == JOYERR_NOERROR) // 0 代表成功
{
    // 解析 infoEx.dwXpos, dwYpos, dwButtons...
}

五、輪詢實現方式

  • 獨立執行緒 + 迴圈 + Thread.Sleep(uPeriod)
  • System.Windows.Forms.Timer 定時觸發
本質上系統被動模式也是內部輪詢,主動模式將控制權交還開發者。

六、解決按鍵重複觸發:狀態比對法

記錄上一輪按下的按鈕集合,本輪僅通知「新增」的按鍵。

previousButtons = 無;
// 死循環輪詢
while (true) {
    if (joyGetPosEx(手柄ID, ref joyInfo) == 成功) {
        JoyButtons buttons = 取得當前按下按鈕(joyInfo);
        if (buttons != 無) {
            if (buttons != previousButtons) {
                // 本輪按鍵組合與上輪不同 -> 通知
                OnClick(buttons);
                previousButtons = buttons; // 記錄本輪
            }
        }
    }
    Thread.Sleep(uPeriod);
}

七、組合鍵並發問題與完美解法

場景:長按「右鍵」移動,同時連打「A」、「B」攻擊。

原始狀態序列:

右鍵(1) → 右鍵(2) → 右鍵+A(3) → 右鍵(4) → 右鍵+B(5) → 右鍵(6)...

簡單比對法會誤判右鍵觸發 5 次。正確解法:僅通知「差集」按鍵。

  • (1) 首次右鍵 → 通知「右鍵」
  • (2) 仍為右鍵 → 無新增 → 不通知
  • (3) 右鍵+A → 新增 A → 通知「A」
  • (4) 僅右鍵 → A 釋放非新增 → 不通知
  • (5) 右鍵+B → 新增 B → 通知「B」

結果:右鍵僅通知 1 次,A、B 各通知 1 次,完美符合人類操作語意。

八、下一步預告

下一篇將整合鍵盤模擬 API,完成「手柄 → 鍵盤/滑鼠」外掛軟體。請支持回覆!

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved