OpenGL / Gtkmm游戏 - 键盘移动

时间:2010-02-10 17:36:51

标签: opengl keypress gtkmm keyrelease

我在“OpenGL”中编写游戏并使用“Gtkmm”作为窗口管理器。我想用键盘移动相机(因此,“向上键”向前移动,“向下键”向后移动等等)

前段时间,当我用Java编程时,我用这种技术“移动”:
当应用程序收到例如“UP-key- ”信号时,它随后将标志“shouldMoveForward”设置为“true”,并在之后收到“UP-key- 发布时“信号,它将标志设置回”假“ 并且“游戏循环”不断检查该标志,如果是真的,它会向前移动摄像机,否则它什么也没做。

所以我想在“Gtkmm”中使用相同的技术。所以我刚刚覆盖了我的“Gtk :: DrawingArea”的这些功能:

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

但问题在于:例如,当我按下“UP”键并按住它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相机移动的“非便携式”解决方案。

还有其他(“PORTABLE”)解决方案,使用Gtkmm作为窗口管理器来实现相机移动吗?

2 个答案:

答案 0 :(得分:2)

This thread描述了问题(GTK +本身没有),以及一些解决方法。

答案 1 :(得分:0)

我刚刚在我的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事件之间几乎不可能发生某些事情。当keyPressed事件发生时,密钥可以在keyRemove列表中的唯一方法是它是一个假事件,所以在这种情况下我们只是从keyRemove列表中删除密钥。

当您正常释放密钥时,它不会立即跟随keyPressed事件,因此它不会从列表中删除并由clearKeys处理。

对于其余代码(例如检查键是否已按下或已被按下),请查看源代码: http://github.com/BonsaiDen/Bonsai-Game-Library/blob/master/src/org/bonsai/dev/GameInput.java