SDL2 运行得太快 -- 为什么当我只按一个按钮时它会读取多个输入
SDL2 going too fast -- why does it read multiple inputs when I press just one button?
我已经开始编写SDL2程序了。我希望整数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;
}
以下是我启动程序并短暂点击右键时打印的内容示例 - 所有这些都在一两秒钟内完成:
0
0
0
0
0
0
0
0
0
0
0
1
2
3
4
4
4
4
4
当我快速点击右箭头键时,我希望count
只上升一个,但它却从0
上升到4
。
为什么?
如何解决此问题?
您的问题是,您要求 SDL 提供密钥状态数组,这在您的方案中不是最佳方法。那么,在这种情况下,SDL 会怎么做呢?它只是为您提供一个包含信息的数组,无论是否持有当前密钥。你试着尽可能短地按下按钮,但你的循环在时间上真的很快。因此,要解决此问题,您可以使用事件系统的键控功能,当您按下按钮时,该功能会为您提供 true(它的对是键释放事件的SDL_KEYUP
(。
主要区别在于问题:是握住键,还是我只是按下并更改了其状态?
因此,这里有一个例子(在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_
常量都是键码。此外(如果您考虑游戏(,扫描码有利于玩家移动,键控事件适用于 GUI 元素
更多信息参考:https://www.libsdl.org/release/SDL-1.2.15/docs/html/guideinputkeyboard.html
希望你能理解!拉索洛兹
类似于这个问题(它实际上询问鼠标按钮,但键盘也是如此(:
不要使用 keyboardState,请使用 SDL 事件。SDL 每按下一个按钮将只触发一个事件,而快速while
循环可以在单次按键期间触发多次。
该示例远非一个最小,完整的示例并且无法编译,但我想问题可能是由于缺少对SDL_PumpEvents
的调用。
从文档中:
注意:使用 SDL_PumpEvents(( 更新状态数组。
否则,状态数组将不会更新,并显示您正在经历的结果。
注意
也就是说,尝试依赖事件而不是用于表示键盘的内部状态数组。
编辑
更新问题后更新。
您应该将SDL_PollEvent
上的if
替换为while
,如下所示:
while (SDL_PollEvent(&event)) {
// here you have an event, you can use it
}
否则,即使没有事件,它也会跳过if
并遍历其他语句。
这意味着,如果没有事件,键盘的状态在第一次按键后不会更新,但您仍然会迭代它。
有关SDL_PollEvent
工作原理的更多详细信息,请参阅此处。
我将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
- 如何通过按下第三个窗口中的按钮,将QString从一个窗口获取到另一个窗口
- 单击一个按钮后创建一个按钮
- 触发另一个窗口的菜单按钮
- 如何创建一个接口,允许我访问C++中的按钮(和其他ui)函数,该函数是使用python中的MFC实现的
- Qt创建一个左箭头样式的按钮
- 一个按钮有两个或多个快捷方式
- 如何从另一个类按钮更改当前索引
- 我动态添加一个按钮,如何在Qt的另一个空白中使用此按钮
- 禁用QT安装程序框架中的本机下一个按钮
- 嗨,我正在尝试编码一个允许用户在Visual C 中登录的按钮,程序正在运行,但表单对话框未显示
- 当在C#中的WPF应用程序中单击一个按钮时,如何调用C 代码
- 在Qt Gui中,如何使每次点击都随机出现一个按钮
- 用Arduino编程一个简单的按钮LED电路
- 当我在C++/SFML中按下鼠标按钮时,如何画一个球
- MFC-停用除一个按钮外的所有按钮
- 尝试在单击按钮时捕获编辑框中的文本,然后显示到另一个编辑框
- WinAPI 创建窗口 + 子窗口,处理一个按钮按下
- C++/MFC 有没有办法在单击另一个按钮的同时单击另一个按钮
- 单击按钮时显示另一个 UI 文件
- SDL2 运行得太快 -- 为什么当我只按一个按钮时它会读取多个输入