使用SDL从键盘读取输入的最佳方法是什么?

Leo*_*ele 10 keyboard sdl input

update()每秒运行一次方法来"更新"用户的键盘输入,以便稍后在程序的逻辑部分中读取它.所以我在SDL Docs中找到了两种实现方法,我不确定应该使用哪一种方法.

1; 使用SDL_PollEvent循环搜索关键/关闭事件并将关键状态保存在地图中,以便我可以检查程序逻辑中的每个关键状态.

注意:或者,我也可以使用SDL_PeepEvents而不是SDL_PollEvent来仅采用重要的事件类型; 所以,它不会"抛弃"队列中的事件.

std::map<int, bool> keyboard; // Saves the state(true=pressed; false=released) of each SDL_Key.

void update()
{
    SDL_Event event;
    while( SDL_PollEvent(&event))
    {
        switch(event.type)
        {
        case SDL_KEYDOWN:
            keyboard[event.key.keysym.sym] = false;
            break;
        case SDL_KEYUP:
            keyboard[event.key.keysym.sym] = true;
            break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

2; 每帧从键盘拍摄快照,以便我可以轻松阅读.

Uint8* keyboard;

void update()
{
    SDL_PumpEvents();
    keyboard = SDL_GetKeyState(NULL);
}
Run Code Online (Sandbox Code Playgroud)

通过以上任何实现,我可以keyboard像这样阅读:

if (key_map[SDLK_Return]) printf("Return has been pressed.");
Run Code Online (Sandbox Code Playgroud)

还有,还有另一种方法吗?

小智 9

我更喜欢做1的变化,我填充三个数组,不仅指示当前状态,还指示哪些键刚刚关闭以及哪些键刚刚上升.这允许我在代码中轻松检查这些事件(不与之前的快照比较),但最重要的是,它不会错过持续少于一帧的事件.例如,如果您的游戏由于机器速度较慢而以10 fps运行,则用户可能会在两次更新例程调用之间按下并释放一个重要的键,然后您的系统将永远不会注册它.这非常令人沮丧.

按住键时,SDL也会发送键事件,这样您就可以为每个键启用多个按键事件.我发现这在通过项目列表实现键盘滚动时特别有用,例如键盘控制的菜单.


Mic*_*rny 5

你应该使用解决方案2.

为什么?正如SDL_GetKeyState()文档所指出的那样,在使用它之前,您需要调用SDL_PumpEvents()更新状态数组.

当你打电话时SDL_PollEvent(),它隐含地打电话SDL_PumpEvents().所以,SDL_GetKeyState()无论如何它基本上都会更新数组.通过手动解析这些事件,您只需创建第二个数组(实际上是一个慢得多的地图),其中包含SDL已经为您收集的相同信息.

所以,我敢说第一个解决方案意味着两次做同样的事情.如果您决定支持诸如重复击键(SDL_EnableKeyRepeat())之类的事情,那么您将重新实现SDL的更大部分.