2016-02-13 19 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

相关问题