2012-03-16 64 views
2

所以我想使用Windows API(和DirectX9,如果它很重要)製作程序,並試圖使用WM_KEYDOWN和WM_KEYUP從鍵盤獲得輸入。這是我現在的代碼的相關部分。這個想法是,「keyTimes」數組應該存儲一個鍵被按下的幀數。當使用Windows API和WM_KEYDOWN時,鍵輸入滯後C++

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 


    Game* Game::s_instance = NULL; 

    LPDIRECT3D9 d3dObject; 
    LPDIRECT3DDEVICE9 d3dDevice; 

    Game::Game(){ 
     for(int i=0; i<256; i++){ 
      keyTimes[i]=0; 
     } 

    } 

    //.... 

    Game* Game::Instance(){ 
     if(Game::s_instance==NULL){ 
      s_instance = new Game(); 
     } 
     return s_instance; 
    } 

    //Checks to see if key was pressed, and adds to value 
    void Game::keyCheck(int keyNum, bool pressed){ 
     if(pressed){ 
      keyTimes[keyNum]++; 
     } 
     else{ 
      keyTimes[keyNum]=0; 
     } 

    } 

    //Returns time that key has been pressed 
    int Game::keyPressed(int keyNum){ 
      return keyTimes[keyNum]; 
    } 

    //Returns true if key was hit once, and doesn't return true again until the key is let go and hit again. 
    bool Game::keyHit(int keyNum){ 
     return keyTimes[keyNum]==1; 
    } 

    //Returns true only if the key has been held for delay 
    bool Game::keyHeld(int keyNum, int delay){ 
     if(delay==0) 
      delay=1; 

     return keyTimes[keyNum]==delay; 

    } 

    //Returns true everyXFrame frames. 
    bool Game::keyPressedDelay(int keyNum, int everyXFrame){ 
     if(everyXFrame<2){ 
      return false; 
     } 
     return keyTimes[keyNum]%everyXFrame==1; 
    } 


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ 

    switch (message) 
    { 
      case WM_DESTROY: 
       PostQuitMessage(0); 
      break; 
      case WM_KEYDOWN: 
       { 
        Game::Instance()->keyCheck(wParam,true); 

        return 0; 

       } 
      break; 
      case WM_KEYUP: 
       { 

        Game::Instance()->keyCheck(wParam,false); 
        return 0; 
       } 
      break; 
      default: 
       return DefWindowProc(hWnd, message, wParam, lParam); 
    } 

    return 0; 

} 


    //........ 
    //Inside the main function while loop.... 


    if(Game::Instance()->keyHit(VK_LEFT)){ 
     thing->move(-3,0); 
    } 
    if(Game::Instance()->keyHit(VK_RIGHT)){ 
     thing->move(3,0); 
    } 
    if(Game::Instance()->keyHit(VK_UP)){ 
     thing->move(0,-3); 
    } 
    if(Game::Instance()->keyHit(VK_DOWN)){ 
     thing->move(0,3); 
    } 

    //....... 

所以,當我嘗試使用「的keyPressed」功能的布爾移動「事」中的主要功能,它移動三個像素,停止約半秒鐘,然後再次開始轉動。如果我在按住第一個鍵的同時嘗試敲另一個鍵,它也會停止。當我使用「KeyHit」移動它時,它會變成9-12像素,然後停止(而不是僅去3)。

我該如何更改我的代碼,以便功能可以像評論一樣工作,沒有任何延遲?

編輯3/26/12:我已經設法修復代碼。事實證明,問題僅僅是我在我的主循環中使用了GetMessage函數,它在移動之前等待輸入,我應該使用PeekMessage。

+0

也許一個'WM_MOVEUP'(或類似的)消息可以幫助解決問題,如果你在密鑰關閉的時候繼續發送它。對於非系統定義的消息有指定的消息範圍。 – chris 2012-03-16 22:47:00

回答

4

keyHit只適用於第500毫秒,因爲在自動重複踢,並導致命中計數上面去1

添加一些調試跟蹤觀察您收到什麼消息,什麼的keyTimes值是每當你在你的主遊戲循環中檢查它。這可能會發現問題。

+0

我在代碼中移動了一下,我發現當我按下某個鍵時,它實際上凍結了整個程序,而不是停止輸入。也許還有其他的錯誤...... – nwatson 2012-03-21 10:55:20

1

所以當我嘗試使用「KeyPressed」函數作爲布爾值來移動主函數中的「thing」時,它會移動三個像素,停止大約半秒鐘,然後再次開始移動。

這是標準的windows行爲。

例如,如果你去Windows控制面板並在鍵盤屬性設置重複延遲短,你會發現,你的延遲時間正在減少。

+0

不幸的是,它看起來像我正在處理的筆記本電腦不允許這樣的事情。 – nwatson 2012-03-21 11:03:03