2010-01-29 46 views
13

我正在研究C++ DirectX 2D遊戲,我需要鍵盤和鼠標輸入。
維基說:我應該使用DirectInput還是Windows消息循環?

Microsoft建議新的應用程序使用Windows的消息循環的鍵盤和鼠標輸入的DirectInput

代替

所以,我應該如何使用它呢?
我有一個GameScreen類來照顧繪圖和更新(遊戲邏輯),我在Windows消息循環中調用Draw和Update方法。

感謝

回答

14

由於您幾乎必須運行消息泵才能擁有一個窗口,因此您還可以使用該泵來處理鍵盤和鼠標輸入。無論您是否將鍵盤事件發送到子窗口,完全取決於您的泵,如果您願意,可以在泵中處理它們。

你典型的消息泵看起來是這樣的:

while (GetMessage(&msg, NULL, 0, 0)) 
{ 
    if (WM_QUIT == msg.message) 
     break; 
    TranslateMessage(&msg); // post a WM_CHAR message if this is a WM_KEYDOWN 
    DispatchMessage(&msg); // this sends messages to the msg.hwnd 
} 

對於一個遊戲,你的泵可能看起來更像是這個

while (true) 
{ 
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD)) 
    { 
     bool fHandled = false; 
     if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) 
     fHandled = MyHandleMouseEvent(&msg); 
     else if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) 
     fHandled = MyHandleKeyEvent(&msg); 
     else if (WM_QUIT == msg.message) 
     break; 

     if (! fHandled) 
     { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
     } 
    } 
    else 
    { 
     // if there are no more messages to handle right now, do some 
     // game slice processing. 
     // 
    } 
} 

當然,你的實際的泵將有可能比數量更爲複雜即可能有MsgWaitForMultipleObjects,這樣即使沒有要處理的消息,也可以定期喚醒,但在有消息時立即進行喚醒。

+4

我想知道爲什麼我不應該使用DirectInput。 謝謝 – Adir 2010-01-30 10:32:17

+1

通過回答亞歷克斯在http://stackoverflow.com/questions/2165230/should-i-use-directinput-or-windows-message-loop/2168067#2168067 – bobobobo 2010-02-10 04:22:08

1

如果遊戲中有一個窗口,比據我可以告訴區分純粹是口味的問題。但是,如果你有(或正計劃擁有或不能肯定排除未來有多個窗口),那麼Windows消息傳遞可能會讓人厭煩。

問題在於,默認情況下,鍵盤/鼠標消息僅路由到當前焦點窗口,並且通常在希望能夠切換焦點的遊戲中(到高分視圖,雷達視圖上的敵人或任何其他)仍然保持交互性。簡單的解決方案是每個需要鍵盤/鼠標輸入的模塊直接查詢它,而不依賴於消息轉發 - 因此,DirectInput。

我不能說你的具體情況,當然 - 只是我的2C。

+1

鍵盤和鼠標事件不是真的進入焦點窗口。鍵盤事件通過您的消息泵_發送到焦點窗口_(這是DispatchMessage的功能)。鼠標事件進入光標下的窗口。 – 2010-01-30 00:32:27

+0

對。謝謝!我原本只使用鍵盤評論,然後纔將其「固定」到鍵盤/鼠標上。 – 2010-01-30 22:00:40

-1

XInput絕對是最佳選擇。低延遲輸入對遊戲至關重要,XInput(在新的DirectXSDK中替換DirectInput)專爲這些用例設計。

此外,您還支持遊戲控制器,遊戲杆等開箱即用。

+1

DirectInput對於鍵盤和鼠標事件的延遲並不低。但是,如果您稍後想要支持遊戲杆等,它確實會爲您提供更一致的輸入模型。 – 2010-01-30 00:28:53

+0

您是絕對正確的,但我的意思是DirectInput(和XInput是DInputs後繼程序)的延遲低於Windows消息。 – DarthCoder 2010-01-30 01:22:37

+1

但不適用於鍵盤和鼠標輸入。DirectInput只是用於鍵盤和鼠標的Win32 API的一個包裝。 – 2010-01-30 03:10:40

1

是的,MSDN的帖子是正確的。使用Windows消息,您可以使用多語言支持(對於用戶可能使用的任何類型的鍵盤)/用戶的個人設置(鼠標右鍵而不是左鍵)等。您必須放棄使用DirectInput/XInput 。 僅將這2個用於遊戲手柄/遊戲杆支持。其餘的只是使用Windows消息。

詳情請參閱John Knoeller的答案。

4

DirectInput已被棄用,原因很多。正如我所知,它創建了一個額外的線程,只是查詢Windows的'Raw Input接口。爲了獲得最佳性能,我會直接使用原始輸入。

如果性能對您來說不是問題(我猜這就是當前硬件上2D遊戲的情況),請按照John Knoeller所述的Microsoft建議和使用窗口消息。

+0

你能證實「只是查詢Windows'原始輸入接口「進一步(也許是一個參考)? – bobobobo 2010-02-10 05:43:52

3

FYI:重新約翰Knoeller的答案......一個簡單的消息泵看起來是這樣的:

while (GetMessage(&msg, NULL, 0, 0)) 
{ 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
} 

的WM_QUIT測試,他包括在內,因爲GetMessage函數返回收到WM_QUIT時零永遠是真實的。但是,在PeekMessage循環中測試WM_QUIT的值是,因爲無論是否返回消息,PeekMessage都會返回true/false。由於GetMessage阻塞直到返回一條消息,所以它可以有不同的返回值。

0

使用,只能使用DirectInput的特殊情況下

約與使用的GetMessage在Windows消息循環的好處是,它使用0%的CPU使用率。如果您正在做非處理器密集型的事情,比如等待用戶的密鑰,從用戶收集數據(例如數據庫或稅務程序,甚至是文字處理器),則只需使用帶有getmessage的Windows消息即可。我所有的上述程序日期是當用戶按下一個鍵時的過程。

Windows消息循環需要處理密鑰的所有內容都是要切換到的程序。鼠標甚至不需要在窗口中。

特殊情況下使用的DirectInput

如果您需要: 1)當一個鍵被按下並釋放認識。您也可能不希望重複檢測爲按鍵。
2)另一個程序切換到後臺處理鍵。

如果以上任一情況屬實,請使用directinput。

如果您只是從用戶收集數據,那麼您將需要使用sleep命令暫停程序的執行。如果程序只是坐在那裏等待用戶的密鑰,您希望程序在任務管理器中的CPU使用率爲0%。

使用休眠功能使程序進入休眠狀態,直到您想輪詢鍵的直接輸入爲止。

因此,如果您正在從用戶那裏收集密鑰的簡單普通任務,那麼直接輸入只會浪費編程時間,正如您所看到的。

相關問題