c++ - SDL2 运行得太快了——为什么当我只按一个按钮时它会读取多个输入?

标签 c++ sdl sdl-2

我已经开始编写 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 在这种情况下做了什么?它只是为您提供一个包含信息的数组,无论当前 key 是否被持有。您尝试尽可能短地按下按钮,但您的循环真的很快。因此,要解决此问题,您可以使用事件系统的 keydown 功能,当您按下按钮时,它会为您提供 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

希望你明白! 拉索洛兹

关于c++ - SDL2 运行得太快了——为什么当我只按一个按钮时它会读取多个输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35385658/

相关文章:

C++:不能修改全局变量

c++ - 计算范围内可被 K 整除的数字和范围内的数字之和

c++ - 理论上遍历内存地址?

c++ - 如何从 SDL_PixelFormatEnum 或 SDL_Texture 获取 SDL_PixelFormat?

c++ - SDL 2.0 是否内置了帧速率上限?

C++ 不使用 使用

c++ - Linux、C++、第三方库

c++ - SDL2 - 未检测到操纵杆?

c - 为什么我不能调用这个 SDL2_gfxPrimitives 函数?

c++ - SDL2 为假全屏切换 SDL_WINDOW_RESIZABLE 状态