2

我用SFMLOpenGL编写了一个简单的程序,它绘制了一个可以用箭头键在屏幕上移动的旋转正方形。

它在我测试过的所有 Linux 和 Mac 计算机上都可以正常工作,但是当我尝试在 Windows 上移动方块时(通过按住箭头键)它会移动一小段距离,然后停止移动和旋转。我很确定程序卡在GetEvent方法中 - 我的猜测是,当我按住键足够长的时间让它开始重复时,事件堆栈会不断添加新事件,然后我才能弹出所有内容它(如果我将 Windows 上的键重复率调到最低,那么问题就会消失 - 虽然我并不喜欢这种解决方案)。

我发现按住 Alt、Ctrl、Delete、Page up、Page down、Home、End 等也会导致这种行为(即使我没有在程序中专门检测到这些键中的任何一个),但是所有字母键,以及空格、回车、退格和键盘箭头键都可以正常工作(即,如果我按住它们太久,它们不会导致程序暂停)。

我没有确切的代码(我刚刚关闭了我的笔记本电脑),但它看起来像:

while(running) {
    while(app.GetEvent(event))
        if(event.Type==sf::Event::Closed) running=false;
    if(input.IsKeyDown(sf::Key::Right)); // move right
    // etc etc
    // update rotation
    // draw everything
}

关于确切的问题可能是什么以及如何解决它的任何想法?

4

1 回答 1

3

我知道这是一个老问题,但我想回答这个问题是为了帮助可能在这里遇到类似问题的其他人。

SFML 1.6 有两种获取用户输入的方式。一种是基于事件的,您可以在其中处理通过 发送给您的每个事件sf::Window::GetEvent()。另一种是基于查询的,您可以sf::Input直接检查窗口的类。

您在此处使用了基于查询的方法,但将其置于事件循环中,这并不是它的预期使用方式。它本来是这样使用的。这是一个很好的功能,因为 SFML 本质上会自动为您保留一个布尔值的键表,因此您不需要自己管理键状态。恕我直言,使用重复输入更优雅,因为您不会向事件队列发送垃圾邮件,只需检查布尔值。

while(app.GetEvent(event))
    if(event.Type == sf::Event::Closed) running=false;
    if(event.Type == sf::Event::KeyPressed && event.Key.Code == sf::Key::Right)
    {
      // move right
    }
}

如果您只想直接查询 sf::Input ,则使用与上面相同的代码,但将其放在事件循环之外。

while(app.GetEvent(event)
{
}

if (myWindow.GetInput().IsKeyDown(sf::Key::Right))
{
}

默认情况下,应该为 sf::Windows 启用自动键重复,但您可以确保使用sf::Window::EnableKeyRepeat(true). KeyPressed这意味着它会在按住一个键时重复发送一个事件。

尝试在主事件循环之外使用基于查询的方法,看看是否适合您。

于 2011-09-04T08:17:40.887 回答