Повторение блокировки ключевых событий - PullRequest
2 голосов
/ 07 марта 2011

Я написал простую программу с SFML и OpenGL , которая рисует вращающийся квадрат, который можно перемещать по экрану с помощью клавиш со стрелками.

Он отлично работает на всех компьютерах 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
}

Есть какие-нибудь идеи относительно точной проблемы и как я могу ее исправить?

1 Ответ

3 голосов
/ 04 сентября 2011

Я знаю, что это старый вопрос, но я хотел бы ответить на него, чтобы помочь другим, кто может оказаться здесь, испытывающим подобные проблемы.

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 несколько раз, пока нажата клавиша.

Попробуйте использовать метод на основе запросов вне основного цикла событий и посмотрите, подходит ли он вам.

...