3

「OpenGL」でゲームをプログラミングし、「Gtkmm」をウィンドウマネージャーとして使用しています。カメラの移動にキーボードを使用したい(つまり、「UPキー」で前進、「DOWNキー」で後退など...)

しばらく前に、Java でプログラミングしたとき、この手法を使用して「移動」
しました。たとえば、アプリケーションが「UPキーを押して」信号を受信すると、その後、フラグ「shouldMoveForward」を「true」に設定し、後で「UP-key- release」信号を受信すると、フラグを「false」に戻します。
そして、「ゲームループ」はそのフラグを継続的にチェックし、それが真であればカメラを前方に動かし、そうでなければ何もしませんでした。

「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 でカメラを移動するための「移植性のない」ソリューションのようです。

Gtkmm をウィンドウ マネージャーとして使用してカメラの移動を実現する他の ( 「PORTABLE」 ) ソリューションはありますか?

4

2 に答える 2

2

このスレッドでは、問題 (GTK+ 自体にはありません) といくつかの回避策について説明しています。

于 2010-02-10T17:44:19.503 に答える
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

于 2010-02-11T04:12:47.950 に答える