消除按键开始时的延迟


11

我正在做一个简单的游戏,遇到的问题之一是连续按下键时令人讨厌的延迟。

因此,基本上,例如,当我按下(很长时间)时Up,我的对象将向上移动1个单位,而不移动(大约1秒钟),然后连续向上移动1个单位(没有任何延迟)。

当前,我使用它来移动对象(SDL2):

while (SDL_PollEvent(&event))
{
    switch (event.type)
    {
    case SDL_KEYDOWN:
        switch (event.key.keysym.sym)
        {
        case SDLK_UP:
            //Move object 1 unit up
            break;
        //Other unrelated things omitted
        }
        break;
    //Omitted other cases
    }
}

我想要的是消除延迟,以便对象可以立即Up快速移动。有什么办法吗?

Answers:


19

通过等待按键事件触发,您很可能会受到操作系统控制的按键事件重复率(以及用户可以自行指定)的摆布。

相反,您可能想SDL_GetKeyboardState在游戏更新循环的顶部(帧发生的更新部分,无论是否发生事件)进行调用,以获取键盘的状态并检查是否向上移动在任何单个帧中,关键帧是否按下。


听窗口消息不是更好吗?使用轮询时,有时会错过很短的按键操作,而当帧频较低时,此问题会变得更加严重。
罗伊(Roy T.)

@RoyT。这实际上取决于您的游戏以及您想通过按键触发的动作类型。如果按键是一次性的事情,例如“操作”键,它会关闭对话框,则消息队列是正确的方法-您想监听原子事件。-另一方面,如果键状态代表“移动”键之类的持续状态,则逻辑通常是while key UP is down move 30 units per second-仅当您在按下和按下之间有可测量的时间(通常超过一帧)时,每秒才有意义。
法尔科

@RoyT。您还可以收听消息(并使用它们来更新自己的键盘状态数组);我选择建议这种方法以简化操作。您当然可以写另一个答案。重要的部分只是避免依赖OS消息来检查密钥是否持续按下,因为这就是将您链接到OS密钥重复率的原因。

按帧表示,您是指游戏滴答声,而不是视频帧,对吗?因为我们并没有在渲染循环中进行游戏逻辑编码。:-)
corsiKa's

@JoshPetrie我完全同意,只是想指出这一小警告,如果您需要检查“单击”而不是“新闻”。:)
Roy T.

10

另一种方法(Josh的方法也很棒!)是在上设置一个布尔值SDL_KEYDOWN,并且还可能忽略所有重复的键事件。您可以通过检查repeat键事件的成员来完成。

然后,您可以实现自己的计时器,而不必花哨任何时间,并实现自己的密钥重复。您可以直接从计时器触发操作,甚至可以生成SDL_KEYDOWN事件,然后统一解决方案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.