2010-02-10 6 views
1

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

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

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

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

Любые идеи, как исправить это? Это очень раздражает.

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

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

ответ

1

Хорошо ... Я «исправил» его.

Поскольку 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, которое обрабатывается в обычном режиме. Теоретически для игрового фрейма должно быть невозможно выполнить «поддельный» ключUp и keyDown.

+0

да, но как вы обнаруживаете настоящий UP в настоящем? .. вам нужен кровавый таймер, чтобы узнать, скоро ли зарегистрируется Down. так чертовски уродливый. Linux разозлил меня. – Mordan

1

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

+0

Изначально у меня было это работает как это. Но тогда мне нужно было проверить, был ли нажат один раз один раз (так что если вы удерживаете его, он будет запускаться только один раз), поэтому я придумал новый код, который обрабатывал это (http://github.com/BonsaiDen/Bonsai- Game-Library/blob/master/src/org/bonsai/dev/GameInput.java), ну, если нет способа избавиться от этого странного поведения GTK, мне придется переписывать всю клавиатуру с нуля. Также есть проблема, что игра может проверяться сразу после одного из этих ненужных событий keyReleased. –

+0

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

0

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

$ xset -r keycode 
+0

Ну, но это не совсем «портативный», я не могу отключить его от Java, поэтому каждый, кто играет в игру и испытывает эти проблемы, должен сам отключить ее. –

+0

Это глупая особенность. Ключевое повторение относится к домену приложений. Os имеет дело с оборудованием. – Mordan