【问题标题】:SDL 2.0 Key repeat and delaySDL 2.0 按键重复和延迟
【发布时间】:2015-03-31 16:04:40
【问题描述】:

我在类似乒乓球的游戏中遇到 SDL 2.0 键盘输入问题。当我通过按左箭头命令向左移动时,它由 SDL_PollEvents() 处理,如果按下一次键,它就会正确响应。但是,如果我一直按住该键,我会在持续移动之前获得短暂的延迟(只要 Windows 键重复延迟)。

这里是函数处理事件:

void Event::PlayerEvent (Player &player)
{
    while (SDL_PollEvent (&mainEvent))
    {
        switch (mainEvent.type)
        {
            case SDL_KEYDOWN :
                switch (mainEvent.key.keysym.sym)
                {
                    case SDLK_ESCAPE :
                        gameRunning = false;
                        break;
                    case SDLK_LEFT :
                        player.moving = player.left;
                        break;
                    case SDLK_RIGHT :
                        player.moving = player.right;
                }
                break;
            case SDL_QUIT :
                gameRunning = false;
        }
    }
}

编辑:毕竟,我设法通过调用解决了这个问题 SystemParametersInfo (SPI_SETKEYBOARDDELAY, 0, 0, 0) 在程序开始时和 SystemParametersInfo (SPI_SETKEYBOARDDELAY, 1, 0, 0) 在程序结束时返回标准键重复延迟。

【问题讨论】:

  • 看看this教程。作者使用了2个技巧:(1)按键影响物体速度而不是位置; (2) 检测按键向下和向上以及过滤的重复。因此,当按键按下时,速度会增加。一旦增加,继续按下不会改变它,所以对象继续移动。当键向上时,速度降低,物体停止移动。这可能有助于解决您的延迟问题。
  • 它减少了一点延迟,但仍然不是我想要的。
  • 在对代码进行了一些调整之后,我必须说本教程是解决我的问题的正确方法。我摆脱了延迟。非常感谢。

标签: c++ keyboard-events sdl-2


【解决方案1】:

对于游戏移动,您通常不会使用事件,而是使用状态。

尝试在事件循环之外使用 SDL_GetKeyboardState():

const Uint8* keystates = SDL_GetKeyboardState(NULL);

...

if(keystates[SDL_SCANCODE_LEFT])
    player.moving = player.left;
else if(keystates[SDL_SCANCODE_RIGHT])
    player.moving = player.right;

【讨论】:

  • 感谢提示,我以后肯定会使用keystates,但是它并没有解决key delay的问题。
  • 即使使用 SPI_SETKEYBOARDDELAY(当然不是跨平台的),也只能保证延迟到 250 毫秒。使用关键状态时不会有延迟。如果您想立即使用关键事件,则需要以不同的方式响应它们。在 keydown 上,设置移动。在 keyup 上,停止移动。另请注意,您可以通过检查 event.key.repeat 来忽略重复的按键操作。
  • 延迟是因为系统键盘驱动程序...您必须将键盘延迟与游戏机制分开...向上键意味着例如向上方向设置为true,而它也就是说,你可以在每一帧更新你的玩家位置
  • 当你想移动时,我不建议在那种情况下使用 else ifs。特别是在游戏开发中。例如,您将无法结合 W+A 自动向左移动。这意味着您必须像else if(W_pressed && A_pressed) move.up_left; 一样自己实现它们。我只是建议只使用 ifs,一切都会自然而然。
【解决方案2】:

使用SPI_SETKEYBOARDDELAY 不是一个好方法。这样,您的游戏将不再可移植,因为它仅在 Windows 上可用。

相反,您应该在 SDL_GetKeyboardState 之前的答案中使用 like menthind。

但是请注意,您仍然需要收集SDL_PollEvent。否则SDL_GetKeyboardState 将始终为空。

所以应该是这样的:

//...
SDL_Event sdlEvent;
while (SDL_PollEvent(&sdlEvent)) {
    if (sdlEvent.type == SDL_QUIT) {
        //..
    }
}

const Uint8* keystates = SDL_GetKeyboardState(NULL);

if(keystates[SDL_SCANCODE_LEFT]) {
    //...
}
if(keystates[SDL_SCANCODE_RIGHT]) {
    /...
}
//...

【讨论】:

    【解决方案3】:

    就这么简单

    int vertical = 0;
    int horizontal = 0;
    
    float x = 500;
    float y = 500;
    
    float speed = 5.0;
    

    在您的 sdl 循环中:

        if (SDL_PollEvent(&event))
        {
            switch (event.type)
            {
                case SDL_KEYDOWN:
                {
                    switch (event.key.keysym.sym)
                    {
                        case SDLK_LEFT:  horizontal=-1; break;
                        case SDLK_RIGHT: horizontal = 1; break;
                        case SDLK_UP:    vertical=-1; break;
                        case SDLK_DOWN:  vertical=+1; break;
                    }
                    break;
                }
                case SDL_KEYUP:
                {
                    switch (event.key.keysym.sym)
                    {
                    case SDLK_LEFT:  horizontal = 0; break;
                    case SDLK_RIGHT: horizontal = 0; break;
                    case SDLK_UP:    vertical = 0; break;
                    case SDLK_DOWN:  vertical = 0; break;
                    }
                    break;
                }
            }
        }
        x += horizontal * speed;
        y += vertical * speed;
    

    【讨论】:

      【解决方案4】:

      在 - while (SDL_PollEvent (&mainEvent)) 之外使用 SDL_GetKeyboardState 捕获,效果很好。

      【讨论】:

      • Jonny D 的回答已经提出了这种方法,所以我认为这个回答没有增加任何新的东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-14
      • 2012-07-18
      • 2020-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多