1

私は一般的な 2D タイル スタイルのゲームに取り組んできました。現在、私のメインスレッドには、可能な限り速く進み、ゲームのものを処理する別のクラスにある JPanel の repaint メソッドを呼び出すループがあります。次のようになります。

public class Main {
    public static void main(String[] args) {
        Island test = new Island();
        while(true) {
            test.getCanvas().requestFocus();
            test.getCanvas().repaint();
        }
    }
}

getCanvas() は JPanel を返すだけです。

現在、これは私が望んでいたことを行いました。プレーヤーに動きを追加し始めたので、明らかに、できるだけ速く画面上でプレーヤーを動かしたくありません。そのため、Island クラスに入力マップとアクション マップがあり、キーのプレスとリリースを検出して、保持されているキーをプレーヤー クラスに通知します。次に、10 ミリ秒ごとに呼び出されるスイング タイマーを使用して、プレーヤー クラス内でプレーヤーを動かします。これは私のゲーム ティックのようなものだと思います。私のゲームは可能な限り高速にフレームを作成し、ゲームはすべてのロジックを 1 秒間に 100 回実行します。もちろん、動きだけでなく、ゲームロジックにもさらに追加します。

いくつかの調査を行った後、スイングタイマーは小さなタスクとスイングタスクを実行するように設計されているため、これを行うための最良の方法ではないようです. だから私の質問は、私のフレームを私のメインメソッドのようにするのは賢明ですか、そして私のゲームを10ミリ秒ごとに確実に刻む良い方法は何でしょうか? ゲームロジックを処理する新しいスレッドを作成し、 System.getnanotime またはそれが呼び出されたものを使用して、ティックを実行するのにかかる時間を測定してから、わずかな thread.sleep を実行する必要があるなど、いくつかのアイデアがありました。 10 ミリ秒に達するまで長く、それから繰り返します。

必要に応じて、より多くのコードを投稿させていただきます:)、事前に感謝します。

4

2 に答える 2

3

これを行う標準的な方法は、スレッド内にあります。これは、標準的なゲームのベアボーン ゲーム スレッドです。

public class GameThread implements Runnable {
    private Thread runThread;
    private boolean running = false;
    private boolean paused = false;
    public GameThread() {
    }

    public void start() {
        running = true;
        paused = false;
        if(runThread == null || !runThread.isAlive())
            runThread = new Thread(this);
        else if(runThread.isAlive())
            throw new IllegalStateException("Thread already started.");
        runThread.start();
    }

    public void stop() {
        if(runThread == null)
            throw new IllegalStateException("Thread not started.");
        synchronized (runThread) {
            try {
                running = false;
                runThread.notify();
                runThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void pause() {
        if(runThread == null)
            throw new IllegalStateException("Thread not started.");
        synchronized (runThread) {
            paused = true;
        }
    }

    public void resume() {
        if(runThread == null)
            throw new IllegalStateException("Thread not started.");
        synchronized (runThread) {
            paused = false;
            runThread.notify();
        }
    }

    public void run() {
        long sleep = 0, before;
        while(running) {
            // get the time before we do our game logic
            before = System.currentTimeMillis();
            // move player and do all game logic
            try {
                // sleep for 100 - how long it took us to do our game logic
                sleep = 100-(System.currentTimeMillis()-before);
                Thread.sleep(sleep > 0 ? sleep : 0);
            } catch (InterruptedException ex) {
            }
            synchronized (runThread) {
                if(paused) {
                    try {
                        runThread.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        paused = false;
    }
}

ゲームを開始するには、gameThead.start() を呼び出す必要があることに注意してください。

于 2013-05-03T17:35:06.417 に答える