Java keyPress / keyRelease проблема под Linux / X11 - PullRequest
1 голос
/ 10 февраля 2010

Я занимаюсь разработкой небольшого 2D-движка на Java, поиграв с моей демонстрационной игрой на виртуальной виртуальной машине VirtualBox с Ubuntu, я обнаружил странную ошибку, которая иногда заставляла игру игнорировать тот факт, что клавиша нажата. Таким образом, вы бежите налево, пока внезапно не перестанете двигаться.

Теперь под настоящей Ubuntu я нашел причину проблемы. Когда я удерживаю клавишу, события keyPress / keyRelease отправляются постоянно.

Моя система для проверки нажатых клавиш выглядит следующим образом:
- если клавиша нажата, добавьте ее в «downlist»
- если ключ отпущен, добавьте его в список
- на каждом кадре игры удаляйте ключи из списка вверх из списка вниз
- если клавиша все еще находится в списке, она нажата

Теперь, когда вы нажимаете вторую клавишу, иногда keyRelease был последним событием, вызванным другой клавишей, которая все еще удерживается, но не распознается таким образом.

Есть идеи как это исправить? Это действительно раздражает.

EDIT
Для пояснения это результат, который я получаю, когда постоянно удерживаю клавишу:
нажата: 87
выпущено: 87
выпущено: 87
нажата: 87
выпущено: 87
нажата: 87
выпущено: 87
нажата: 87
выпущено: 87
и т.д.

EDIT2
Хорошо, погуглив немного больше, я обнаружил, что это «особенность» сервера X11, но я до сих пор не знаю, как обнаружить «поддельные» события клавиш в java.

Ответы [ 3 ]

1 голос
/ 11 февраля 2010

Хорошо ... Я "исправил" это.

Поскольку X11 продолжает запускать события авто повторения клавиш, нет способа изменить все это таким образом, чтобы эти «поддельные» события игнорировались, вы не можете различить «реальные» и «поддельные» события в Java.

Таким образом, способ исправить это следующим. Поскольку за каждым «поддельным» событием keyUp следует немедленное событие keyDown, вы просто удаляете событие keyUp из keyRemoveList, если получаете событие keyDown, которое выглядит следующим образом:

public final void keyPressed(final KeyEvent e) {
    int key = e.getKeyCode();

    // Fix AutoKeyRepeat under X11
    if (keysRemove.contains(key)) {
        keysRemove.remove(Integer.valueOf(key));
    }

    if (!keysDown.contains(key)) {
        keysDown.add(key);
        keysPressed.add(key);
        lastKeys.add(key);
        if (lastKeys.size() > 16) {
            lastKeys.remove(0);
        }
    }
    e.consume();
}

Поскольку за «настоящим» событием keyUp не следует немедленное событие keyDown, оно обрабатывается обычным образом. Теоретически игровой фрейм должен быть невозможен между «поддельным» keyUp и keyDown.

1 голос
/ 11 февраля 2010

Возможно, возникли некоторые конфликты из-за способа разрешения нажатий клавиш в каждом кадре и переключения между списками. Может быть немного чище иметь логическое значение для каждой из клавиш, которые вы планируете нажать (например, стрелка вправо, стрелка влево и т. Д.). Когда клавиша нажата, установите для соответствующего логического значения значение true, а затем, когда она отпущена, установите значение false. Это довольно распространенный способ управления клавиатурой в видеоиграх

0 голосов
/ 11 февраля 2010

Конечно, автоповтор настраивается в X11. Просто взгляните на xset параметр команды r или -r . Вы можете отключить автоповтор для некоторых кодов клавиш, используя

$ xset -r keycode
...