2016-02-13 58 views
0

我已經開始編寫SDL2程序。我希望整數count上升一個,當用戶按下右箭頭鍵,當用戶按下左鍵向下。SDL2速度太快 - 當我按下一個按鈕時,爲什麼它會讀取多個輸入?

#include <iostream> 
#include <SDL2/SDL.h> 

int main(){ 
    SDL_Window *window= SDL_CreateWindow("test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN); 
    int count=  0; 
    bool isRunning= true; 
    SDL_Event ev; 
    while(isRunning){ 
     if(SDL_PollEvent(&ev)){ 
      if(ev.type == SDL_QUIT || ev.key.keysym.scancode == SDL_SCANCODE_ESCAPE) 
       return 0; 
     } 

     const Uint8 *keystate= SDL_GetKeyboardState(NULL); 

     if(keystate[SDL_SCANCODE_LEFT]) 
      --count; 
     else if(keystate[SDL_SCANCODE_RIGHT]) 
      ++count; 

     std::cout << count << std::endl; 
    } 

    SDL_DestroyWindow(window); 
    SDL_Quit(); 

    return 0; 
} 

這裏,當我啓動程序和簡要自來水權氏印刷什麼樣 - 都在一兩秒鐘:

0 
0 
0 
0 
0 
0 
0 
0 
0 
0 
0 
1 
2 
3 
4 
4 
4 
4 
4 

當我做一個快速點擊右側的箭頭鍵,我想要count上升一個,但它從04

爲什麼?

我該如何解決這個問題?

回答

0

我改變了while循環,以這樣的:

while(isRunning){ 
    while(SDL_PollEvent(&ev)){ 
     if(ev.type == SDL_QUIT || ev.key.keysym.scancode == SDL_SCANCODE_ESCAPE) 
      return 0; 
     else if(ev.type == SDL_KEYDOWN){ 
      if(ev.key.keysym.scancode == SDL_SCANCODE_LEFT){ 
       --count; 
       std::cout << count << std::endl; 
      } 
      else if(ev.key.keysym.scancode == SDL_SCANCODE_RIGHT){ 
       ++count; 
       std::cout << count << std::endl; 
      } 
     } 
    } 
} 

如果我的理解對不對,SDL_PollEvent火災僅在對象ev的地址是真實的。如果用戶按下某個鍵,它將繼續。如果該鍵是左箭頭,則count下降一個。如果鍵是右箭頭,count增加一個。

現在cout打印我希望它的方式。

輸出後,我按正確的幾次:

0 
1 
2 
3 
4 

然後離開:

4 
3 
2 
1 
0 
+0

如果您有其他問題,請創建一個新問題。如果這是*謝謝*答案,請接受其中一個答案(正確答案)並刪除那個答案。謝謝。 – skypjack

1

this Question類似(它實際上詢問鼠標按鍵,但其同樣爲鍵盤):

而不是使用keyboardState使用SDL事件。每按下一次按鍵,SDL就會觸發一個事件,而在單次按鍵期間,快速觸發多次。

1

即使這個例子遠非最小的,完整的也不能編譯,我猜這個問題可能是由於缺少對SDL_PumpEvents的調用。

如從documentation

注意:使用SDL_PumpEvents()來更新狀態陣列。

否則,狀態數組將不會被更新,而您正在遇到的結果。

這就是說,儘量依靠事件,而不是用來代表鍵盤的內部狀態陣列。

編輯

問題已被更新後更新。

你應該用while更換SDL_PollEventif,像下面的一個:

while (SDL_PollEvent(&event)) { 
    // here you have an event, you can use it 
} 

否則,即使沒有活動,它跳過if並通過其他語句去。
這意味着如果沒有事件,鍵盤的狀態在第一次按鍵後將不會更新,但是您仍在迭代它。

有關SDL_PollEvent如何工作的詳細信息,請參閱here

1

您的問題是你問SDL的keystate陣列,這在您的方案,是不是最好的方法。那麼,SDL在這種情況下做了什麼?它只是給你一個包含信息的數組,當前鍵是否被保留。你儘量按下按鈕儘可能短,但你的循環時間確實很快。所以,爲了解決這個問題,當你按下一個按鈕時(它的對是關鍵發佈事件的SDL_KEYUP),你可以使用事件系統的keydown功能,它可以讓你真實。

主要區別在於問題:是關鍵,還是我剛剛按下並改變了狀態?

所以,這裏是一個例子(SDL_PumpEvent或SDL_PollEvent內使用):

//... 
if (event.type == SDL_KEYDOWN) 
{ 
    if (event.key.keysym.sym == SDLK_LEFT) 
    //do left key things...; 
    else if (event.key.keysym.sym == SDLK_RIGHT) 
    //do right key stuff...; 
} 
//... 

注意,此方法不使用掃描碼,但鍵碼。 (由於鍵盤類型不同,它們可能會產生與掃描碼不同的結果)。 SDLK_常量都是鍵碼。而且(如果你想遊戲),掃描碼是良好的玩家運動,KEYDOWN事件是良好的GUI元素

參考的詳細資料:https://www.libsdl.org/release/SDL-1.2.15/docs/html/guideinputkeyboard.html

我希望你能理解! Lasoloz

相關問題