C++ SDL2运行得太快了——为什么我只按一个按钮,它就会读取多个输入?
我已经开始编写SDL2程序。我希望integerC++ SDL2运行得太快了——为什么我只按一个按钮,它就会读取多个输入?,c++,sdl,sdl-2,C++,Sdl,Sdl 2,我已经开始编写SDL2程序。我希望integercount在用户按向右箭头键时上升一个,在用户按向左键时下降一个 #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);
count
在用户按向右箭头键时上升一个,在用户按向左键时下降一个
#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;
}
当我快速点击右箭头键时,我希望count
只增加一个,但它却从0
增加到4
为什么?
如何解决此问题?类似于(它实际上询问鼠标按钮,但键盘也是如此):
不要使用键盘状态,而是使用SDL事件。SDL每按下一个按钮将触发一个事件,而快速while
-循环可以在一次按键过程中触发多次。类似于(它实际上询问鼠标按钮,但键盘也是如此):
不要使用键盘状态,而是使用SDL事件。SDL每按下一个按钮将触发一个事件,而快速
while
-循环可以在一次按键过程中触发多次。即使该示例远不是一个最小的、完整的示例,并且它无法编译,我想问题可能是由于缺少对SDL\u PumpEvents
的调用
自以下日期起:
注意:使用SDL_PumpEvents()更新状态数组
否则,状态数组将不会被更新,并且不会产生您正在经历的结果
注意
也就是说,尝试依赖事件,而不是用来表示键盘的内部状态数组
编辑
问题更新后更新
您应该将SDL\u polleevent
上的if
替换为while
,如下所示:
while (SDL_PollEvent(&event)) {
// here you have an event, you can use it
}
否则,即使没有事件,它也会跳过if
并遍历其他语句。这意味着,如果没有任何事件,键盘的状态在第一次按键后不会被更新,但您仍然会对其进行迭代
有关
SDL_polleevent
如何工作的更多详细信息,请参阅。尽管示例远不是一个最小的、完整的示例,而且它无法编译,但我想问题可能是由于缺少对SDL_PumpEvents
的调用
自以下日期起:
注意:使用SDL_PumpEvents()更新状态数组
否则,状态数组将不会被更新,并且不会产生您正在经历的结果
注意
也就是说,尝试依赖事件,而不是用来表示键盘的内部状态数组
编辑
问题更新后更新
您应该将SDL\u polleevent
上的if
替换为while
,如下所示:
while (SDL_PollEvent(&event)) {
// here you have an event, you can use it
}
否则,即使没有事件,它也会跳过if
并遍历其他语句。这意味着,如果没有任何事件,键盘的状态在第一次按键后不会被更新,但您仍然会对其进行迭代
有关
SDL\u polleevent
工作原理的更多详细信息,请参阅。我在循环时更改了:
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;
}
}
}
}
然后离开:
4
3
2
1
0
我将循环更改为以下内容:
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;
}
}
}
}
然后离开:
4
3
2
1
0
您的问题是向SDL请求一个keystate数组,在您的场景中,这不是最好的方法。那么,SDL在这种情况下做什么?它只提供一个包含信息的数组,不管当前密钥是否被持有。你试着尽可能短地按下按钮,但是你的循环时间真的很快。因此,要解决这个问题,您可以使用事件系统的按键功能,当您按下一个按钮时,该功能会为您提供true(按键释放事件的配对是SDL\u KEYUP
)
主要的区别在于:是按键被按住了,还是我只是按下并改变了它的状态
下面是一个示例(在SDL_PumpEvent或SDL_PollEvent中使用):
请注意,此方法不使用扫描代码,而是使用键代码。(由于键盘类型不同,它们可能产生与扫描码不同的结果)<代码>SDLK
常量都是键代码。此外(如果你想玩游戏的话),扫描代码有利于玩家移动,按键事件有利于GUI元素
有关更多信息,请参阅:
我希望你能理解!
Lasoloz您的问题是向SDL请求一个keystate数组,在您的场景中,这不是最好的方法。那么,SDL在这种情况下做什么?它只提供一个包含信息的数组,不管当前密钥是否被持有。你试着尽可能短地按下按钮,但是你的循环时间真的很快。因此,要解决这个问题,您可以使用事件系统的按键功能,当您按下一个按钮时,该功能会为您提供true(按键释放事件的配对是SDL\u KEYUP
)
主要的区别在于:是按键被按住了,还是我只是按下并改变了它的状态
下面是一个示例(在SDL_PumpEvent或SDL_PollEvent中使用):
请注意,此方法不使用扫描代码,而是使用键代码。(由于键盘类型不同,它们可能产生与扫描码不同的结果)<代码>SDLK
常量都是键代码。此外(如果你想玩游戏的话),扫描代码有利于玩家移动,按键事件有利于GUI元素
有关更多信息,请参阅:
我希望你能理解!
Lasoloz如果您还有其他问题,请创建一个新问题。如果这是一个谢谢你的答案,请接受其中一个答案(正确的一个)并删除该答案。谢谢。如果您还有其他问题,请创建一个新问题。如果这是一个谢谢你的答案,请接受其中一个答案(正确的一个)并删除该答案。非常感谢。