web-dev-qa-db-ja.com

Javaメインゲームループ

私はゲームループを書いています。次の例のコードを見つけました hereこの記事 など、ゲームループを実行する他の方法も検討しました。私はそれらのどれも動作させることができませんでした。だから私は最初のリンクからのものを続けた。

私が知りたいこと:

  • これを行うには、ゲームループの作成方法が適していますか?
    • 助言がありますか?
  • ゲームループでThread.sleep();を使用する必要がありますか?

ここに私の現在のコードがあります:

public void run(){
    long lastLoopTime = System.nanoTime();
    final int TARGET_FPS = 60;
    final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
    long lastFpsTime = 0;
    while(true){
        long now = System.nanoTime();
        long updateLength = now - lastLoopTime;
        lastLoopTime = now;
        double delta = updateLength / ((double)OPTIMAL_TIME);

        lastFpsTime += updateLength;
        if(lastFpsTime >= 1000000000){
            lastFpsTime = 0;
        }

        this.updateGame(delta);

        this.repaint();

        try{
            Room.gameTime = (lastLoopTime - System.nanoTime() + OPTIMAL_TIME) / 1000000;
            System.out.println(Room.gameTime);
            Thread.sleep(Room.gameTime);
        }catch(Exception e){
        }
    }
14
Get Off My Lawn

最終的には [〜#〜] lwjgl [〜#〜] のようなものに移行したいと思うでしょうが、ここで今やっていることを続けてください。それはあなたに基礎を教えます。

あなたのループの良い仕事。よさそうだ、私はいくつかのポインタを提供させてください:

  • 再描画では、画面はすぐにはレンダリングされません。 RepaintManager に準備ができたらレンダリングするように指示します。使用する 無効にする paintImmediately 代わりに。 paintImmediatelyは、コンポーネントが再描画されるまで実行をブロックするため、レンダリング時間を測定できます。

  • Thread.sleep通常、数ミリ秒のドリフトがあります。ループでCPUを使いすぎないようにするために使用する必要がありますが、10ミリ秒スリープするか、5ミリ秒スリープするか、20スリープするかを理解してください。

  • 最後に:

    double delta = updateLength / ((double)OPTIMAL_TIME);
    

    updateLengthがOPTIMAL_TIMEより小さい場合、updateを呼び出さないでください。つまり、デルタが1未満の場合、更新しないでください。 このチュートリアル は、私が今までできなかった理由を説明しています。

14

全体として、それは良いループですが、最高のループであると私が経験で見つけたものにいくつかの欠けている側面があります。

最終的に [〜#〜] lwjgl [〜#〜] または他のJavaゲームAPIに移動しますが、現時点では、基本的な方法を学びます。ゲームループが機能し、ニーズに最適なものが決まります。

  • まず、あなたのポイントの1つに答えて、いいえ。あなたはより良い滞在をするでしょう

    Thread.sleep()

    これは、スリープに設定した実際の時間から逸脱する可能性があります。
    例えば。 10ミリ秒間スリープするように設定すると、プログラムが5〜20ミリ秒間スリープする可能性があります。

  • すぐにわかる2番目の問題は、カスタムのstop()メソッドのゲームループを停止する方法がないことです。試して

    boolean running = true;
    while(running){
    //ここにコード//
    }

  • 第三に、デルタ変数の使用方法の変更を検討する必要がある場合があります。以下のコードの方法は、あなたにとってより良い使用と構築かもしれません。

    これは、プログラムで使用するゲームループの例です。

    @Override
    public void run() {
    
    long initialTime = System.nanoTime();
    final double timeU = 1000000000 / UPS;
    final double timeF = 1000000000 / FPS;
    double deltaU = 0, deltaF = 0;
    int frames = 0, ticks = 0;
    long timer = System.currentTimeMillis();
    
        while (running) {
    
            long currentTime = System.nanoTime();
            deltaU += (currentTime - initialTime) / timeU;
            deltaF += (currentTime - initialTime) / timeF;
            initialTime = currentTime;
    
            if (deltaU >= 1) {
                getInput();
                update();
                ticks++;
                deltaU--;
            }
    
            if (deltaF >= 1) {
                render();
                frames++;
                deltaF--;
            }
    
            if (System.currentTimeMillis() - timer > 1000) {
                if (RENDER_TIME) {
                    System.out.println(String.format("UPS: %s, FPS: %s", ticks, frames));
                }
                frames = 0;
                ticks = 0;
                timer += 1000;
            }
        }
    }
    
4
Robert E Fry