我每秒运行n次update()方法来“更新”用户的键盘输入,以便稍后在程序的逻辑部分读取它。因此,我在SDL文档中找到了两种实现此功能的方法,但我不确定应该使用哪一种。
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.");另外,有没有其他的方法呢?
发布于 2012-07-29 03:39:10
我更喜欢做1的变化,我填充三个数组,不仅指示当前状态,而且还指示哪些键刚刚向下,哪些键刚刚向上。这使我可以在代码中轻松地检查这些事件(不需要与之前的快照进行比较),但最重要的是,它不会遗漏持续时间少于一帧的事件。例如,如果您的游戏由于机器速度较慢而以10 fps的速度运行,则用户可能会在两次调用更新例程之间按下并释放一个重要的键,然后您的系统将永远不会注册它。这是非常令人沮丧的。
SDL还会在按住按键时发送按键事件,这允许您为每个按键打开多个按键按下事件。我发现这在实现项目列表中的键盘滚动时特别有用,例如键盘控制的菜单。
发布于 2012-07-28 16:24:05
您应该使用解决方案2。
为什么?正如SDL_GetKeyState()文档指出的那样,在使用它之前,您需要调用SDL_PumpEvents()来更新状态数组。
当您调用SDL_PollEvent()时,它会隐式调用SDL_PumpEvents()。因此,它基本上更新了SDL_GetKeyState()的数组。通过手动解析这些事件,您只需创建第二个数组(实际上是一个慢得多的映射),其中包含SDL已经为您收集的相同信息。
所以,我敢说第一个解决方案意味着做同样的事情两次。如果您曾经决定支持诸如重复击键(SDL_EnableKeyRepeat())之类的东西,那么您将重新实现更大一部分的SDL。
发布于 2016-02-27 09:48:50
我知道这个问题已经很老了,但我的答案可能会让某些人受益。就我个人而言,我在SDL_GetKeyState中使用两个数组。我存储了一个保存当前帧的键盘状态的数组和一个保存最后一帧的键盘状态的数组。(使用一些memcpy命令,更新它们非常容易。)除了这两个数组,我还有一个将"A“之类的字符串转换为SDL scancode值的映射,但这是可选的。
然后,当您需要检查某些内容是否被释放或按下时,您可以组合两个数组进行检查。(我将其作为一个函数。)例如,如果您知道关键点在这一帧被按下,但在上一帧没有被按下,那么它显然就是在这一帧上按下的。if (currentFrame["A"] == true && lastFrame["A"] == false) {/*just pressed*/}
然后,您将对已发布的对象执行相反的操作。我发现这个方法非常容易实现和使用。
https://stackoverflow.com/questions/11699183
复制相似问题