Игра OpenGL / Gtkmm - перемещение клавиатуры - PullRequest
3 голосов
/ 10 февраля 2010

Я программирую игру в "OpenGL" и использую "Gtkmm" в качестве оконного менеджера. Я хочу использовать клавиатуру для перемещения камеры (таким образом, «кнопка ВВЕРХ» для перемещения вперед, «кнопка ВНИЗ» для перемещения назад и т. Д.)

Некоторое время назад, когда я программировал на Java, я использовал эту технику для «перемещения»:
Когда приложение получило, например, сигнал «UP-key- press », оно впоследствии установило для флага «shouldMoveForward» значение «true», а затем оно получило «UP-key- release"сигнал, он установил флаг обратно на" ложь ".
И «игровая петля» постоянно проверяется на наличие этого флага, и если это правда, она перемещает камеру вперед, в противном случае она ничего не делает.

Так что я бы хотел использовать ту же технику в "Gtkmm". Поэтому я просто переопределил эти функции моего "Gtk :: DrawingArea" :

bool Gtk::Widget::on_key_press_event(GdkEventKey* event)
bool Gtk::Widget::on_key_release_event(GdkEventKey* event)

Но проблема заключается в следующем: когда я, например, нажимаю клавишу «ВВЕРХ» и удерживаю ее в течение 5 секунд, генерируется следующая последовательность сигналов:

press  ...<little time waiting>...  release  press  release  press  release  press  release   ..........   press  release  press  release

Предыдущая ситуация возникает, когда я запускаю свою игру "в Linux" .

Когда я "на Windows" , это так, как я хочу, поэтому:

press  ...<little time waiting>...  press  press  press  press  press  ..........  press  press  release

Похоже, это "непереносимое" решение для камеры, движущейся в Гткмм.

Так есть ли другое ( "ПОРТАТИВНОЕ" ) решение для перемещения камеры с использованием Gtkmm в качестве оконного менеджера?

Ответы [ 2 ]

2 голосов
/ 10 февраля 2010

В этой теме описывается проблема (которой нет в самой GTK +) и некоторые обходные пути.

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

Я только что столкнулся с функцией «автоповтор» в моей Java-игре, и я исправил ее.

Поскольку вы знаете Java, у вас не должно возникнуть проблем при переносе следующего кода:

// Keyboard
private final List<Integer> keysPressed = new LinkedList<Integer>();
private final List<Integer> keysDown = new LinkedList<Integer>();
private final List<Integer> keysRemove = new LinkedList<Integer>();

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);
    }
    e.consume();
}

public final void keyReleased(final KeyEvent e) {
    int key = e.getKeyCode();
    keysRemove.add(key);
    e.consume();
}

public final void clearKeys() {
    for (Integer key : keysRemove) {
        keysDown.remove(Integer.valueOf(key));
        if (keysPressed.contains(key)) {
            keysPressed.remove(Integer.valueOf(key));
        }
    }
    keysRemove.clear();
    keysPressed.clear();
}

Метод clearKeys вызывается в основном цикле сразу после того, как состояние игры было обновлено (проверено на ввод с клавиатуры / перемещенные объекты), трюк здесь первый, если в keyPressed Автоматически сгенерированные события клавиш происходят в одно и то же время, поэтому почти невозможно, чтобы что-то произошло между поддельными событиями keyReleased и keyPressed. Единственный способ, которым ключ может быть в списке keyRemove, когда происходит событие keyPressed, - это поддельное событие, поэтому в этом случае мы просто удаляем ключ из списка keyRemove.

При обычном отпускании ключа за ним не следует немедленное событие keyPressed, поэтому оно не удаляется из списка и не обрабатывается clearKeys.

Для остальной части кода (например, проверка, нажата ли клавиша или была нажата), проверьте источник: http://github.com/BonsaiDen/Bonsai-Game-Library/blob/master/src/org/bonsai/dev/GameInput.java

...