我每秒运行一次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;
}
}
}
2;每帧从键盘拍摄快照,以便我可以轻松阅读。
Uint8* keyboard;
void update()
{
SDL_PumpEvents();
keyboard = SDL_GetKeyState(NULL);
}
通过上述任何实现,我可以像这样阅读keyboard
:
if (key_map[SDLK_Return]) printf("Return has been pressed.");
另外,还有另一种方法吗?
答案 0 :(得分:9)
我更喜欢做1的变体,其中我填充三个数组,不仅指示当前状态,还指示哪些键刚刚关闭以及哪些键刚刚上升。这允许我在代码中轻松检查这些事件(不与之前的快照比较),但最重要的是,它不会错过持续少于一帧的事件。例如,如果您的游戏由于机器速度较慢而以10 fps运行,则用户可能会在两次更新例程调用之间按下并释放一个重要的键,然后您的系统将永远不会注册它。这非常令人沮丧。
SDL还会在按住按键时发送按键事件,这样您就可以为每个按键启用多个按键事件。我发现这在实现键盘滚动项目列表时特别有用,例如:键盘控制的菜单。
答案 1 :(得分:5)
您应该使用解决方案2.
为什么呢?正如SDL_GetKeyState()
文档指出的那样,在使用它之前,您需要调用SDL_PumpEvents()
来更新状态数组。
当您致电SDL_PollEvent()
时,它会隐式调用SDL_PumpEvents()
。所以,它基本上更新了SDL_GetKeyState()
的数组。通过手动解析这些事件,您只需创建第二个数组(实际上是一个慢得多的映射),其中包含SDL已经为您收集的相同信息。
所以,我敢说第一个解决方案意味着两次做同样的事情。如果您决定支持诸如重复击键(SDL_EnableKeyRepeat())之类的事情,那么您将重新实现SDL的更大部分。
答案 2 :(得分:1)
我意识到这个问题已经很老了,但我的回答可能会使某些人受益。就个人而言,我使用两个SDL_GetKeyState
数组。我存储一个保持当前帧键盘状态的数组,以及一个保存最后一帧键盘状态的数组。 (使用一些memcpy
命令,它们很容易更新它们。)除了这两个数组,我还有一个转换字符串的地图,如&#34; A&#34;到SDL扫描码值,但这是可选的。
然后,当您需要检查某些内容是否被释放或按下时,您可以组合这两个数组进行检查。 (我把它变成了一个函数。)例如,如果你知道按键被按下了这一帧,但是最后一帧没有被按下,那么显然只是按下了这一帧。 if (currentFrame["A"] == true && lastFrame["A"] == false) {/*just pressed*/}
然后你会对发布的事情做相反的事情。我发现这种方法非常容易实现和使用。