0

私は単純なゲームエンジンに取り組んできました。順調に進み、基礎が完成しました。つまり、ゲームはユーザー定義の表示設定でセットアップし、初期化して、ゲーム ループを開始します。ウィンドウモードとフルスクリーンの両方で問題があることを除いて、すべてがうまく機能します。

ウィンドウ モードでは、ウィンドウのサイズを変更するか最小化するまで、画面が空白になることがあります。

全画面表示では、デフォルトのディスプレイ解像度を使用すると、空白の画面しか表示されません。他の解像度のほとんどは問題なく表示されます。

画面の表示に関連するコードを次に示します。

これは、ユーザーが表示設定ダイアログの再生ボタンを押したときに実行されます

public void actionPerformed(ActionEvent e) {
            DisplayMode dm = modes[resolutionBox.getSelectedIndex()];
            boolean fs = fullscreenBox.getSelectedItem().equals ("Fullscreen");
            boolean vs = vSyncCheckBox.isSelected();

            game.initScreen (dm, fs, vs);
            runGame (game);

            f.dispose();
        }
    });

private final void runGame(EGame g)
{
    Thread t = new Thread (g);
    t.start();
}

EGame クラスの run メソッドです。

public final void run() {
    start();
    isRunning = true;
    gameLoop();
    endGame();
}

エンジンのユーザーは、start() メソッドでメソッド setGameCanvas() を呼び出します。他のものは start() メソッドに入れることができますが、私のテストゲームでは、そのメソッドだけです:

protected final void setGameCanvas(EGameCanvas c)
{
    screen.remove (canvas);
    canvas = c;
    canvas.addKeyListener (keyboard);
    screen.add (canvas);
}

最後に、gameLoop を次に示します。

private final void gameLoop()
{
    // Final setup before starting game
    canvas.setBuffer (2);
    screen.addKeyListener (keyboard);
    canvas.addKeyListener (keyboard);

    int TARGET_FPS = screen.getTargetFps();
    final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;

    long lastLoopTime = System.nanoTime();

    long now = 0;
    long lastFpsTime = 0;
    long updateLength = 0;
    double delta = 0;

    int fps = 0;

    while (isRunning)
    {
        now = System.nanoTime();
        updateLength = now - lastLoopTime;
        lastLoopTime = now;
        delta = updateLength / ((double) OPTIMAL_TIME);

        lastFpsTime += updateLength;
        fps++;

        if (lastFpsTime >= 1000000000)
        {
            screen.setFps (fps);
            lastFpsTime = 0;
            fps = 0;
        }

        keyboard.poll();
        keyboardEvents();

        update (delta);

        render();

        try {
            Thread.sleep( (lastLoopTime-System.nanoTime() + OPTIMAL_TIME)/1000000 );
        }
        catch (Exception ex) {}
    }
}

ここで、run メソッドを追加して別のスレッドで実行するまで、どちらの問題も存在しなかったことに注意してください。スレッドの問題であることはほぼ保証できます。

でも、私は専門家ではないので、アドバイスをいただければ幸いです。

4

1 に答える 1

0

問題は、イベント ディスパッチ スレッドの外部で GUI 関連のコンポーネントを変更しようとしていることにあると思います。これは、グラフィカル インターフェイスを変更できる唯一のスレッドです。そうしないと、このような問題が発生する可能性があります。

これを確認するには、次の方法で問題が解決するかどうかを試してください。

try {
    if (!SwingUtilities.isEventDispatchThread()) {
        SwingUtilities.invokeAndWait( new Runnable() {
            @Override
            public void run() {
                // Do rendering and other stuff here...
            }
        });
    }
} catch (InterruptedException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}

それが役立つ場合は、Concurrency in Swing チュートリアルを参照することをお勧めします。

于 2012-11-21T08:26:38.070 に答える