0

ゲームを60fpsに維持しようとしていますが、コードから「2-8000 fps」のような奇妙な結果が得られます。なぜこれが60にとどまらないのですか?

public static void main(String[] args) {

        joglplat m = new joglplat();
        while(true){
            long startTime = System.nanoTime() / 1000000;
                try
            {
                //                 123456: 6 zeros => 16ms
                long nsToSleep = 16000000 - (System.nanoTime() - lastFrame);
                System.out.println("ns: " + nsToSleep);
                lastFrame = System.nanoTime();

                if(nsToSleep > 0)
                {
                   System.out.println("ns2: " + (nsToSleep/1000));
                   System.out.println("ns3: " + (nsToSleep%1000));
                   Thread.sleep(nsToSleep/16000000, (int)(nsToSleep % 1000));
                }
                else
                {
                   Thread.yield();  // Only necessary if you want to guarantee that
                                    // the thread yields the CPU between every frame
                }

            }

            catch(Exception e){
                e.printStackTrace();
            }

            m.controls();
            m.update();
            m.repaint();
            System.out.println("framerate: " + (System.nanoTime() / 1000000  - startTime));
        }
    }
4

2 に答える 2

1

私の疑いは、これはThread.sleep()の不正確さが原因であるということです。

システムタイマーとスケジューラの精度と精度に応じて、現在実行中のスレッドを指定されたミリ秒数と指定されたナノ秒数の間スリープ(実行を停止)させます。スレッドはモニターの所有権を失うことはありません。

このようにフレームレートを抑えなければならない理由はありますか?おそらく、あなたはあなたが達成しようとしていることをより完全に説明することができますか?

于 2009-04-20T15:55:55.863 に答える
1

出力は、フレームレートではなく、プログラムが実行された秒数です。フレーム数(収集していない)を実行時間の合計で割る必要があります。

フレーム数を取得するには、ゲームループの外に新しい変数を追加し、毎回インクリメントします...

public static void main(String[] args) {
    long frames = 0;
    joglplat m = new joglplat();
    while(true){
        frames++;
        // other code here
        System.out.println("framerate: " + ((System.nanoTime() / 1000000  - startTime) / frames ) );
    }
}

ただし、これにより、プログラムの実行全体の平均フレームレートが得られることに注意してください。他に2つのオプションは、瞬間フレームレートと、過去Nフレームの平均フレームレートを取得することです。

すべてのスタイルを1つにまとめたもの(テストされていない/コンパイルされていないため、エラーが発生する可能性がありますが、正しい方向から始める必要があります):

public static void main(String[] args) {
    long startTime = System.nanoTime();
    long lastFrameTime = startTime;
    long frames = 0;
    int framesToAverage = 10;
    long[] frameTimes = new long[framesToAverage];
    joglplat m = new joglplat();
    while(true){
        // logic here
        long currentFrameDuration = System.nanoTime() - lastFrame;
        lastFrameTime = System.nanoTime();
        long instantFramerate = currentFrameDuration / 1000000;
        int currentFrameIndex = frames % frameTimes.length;
        frameTimes[currentFrameIndex] = currentFrameDuration;
        frames++;
        long averageFramerate = ( ( lastFrameTime - startTime) / frames ) / 1000000;
        long instantFramerate = currentFrameDuration / 1000000;
        if( frames > frameTimes.length ) { // if it isn't, we don't have enough data yet
            int firstFrameIndex = currentFrameIndex + 1;
            if( firstFrameIndex > frameTimes.length ) {
                firstFrameIndex = 0;
            }
            long averageFrameratePerN = ( ( frameTimes[currentFrameIndex] - frameTimes[firstFrameindex] ) / frameTimes.length ) / 1000000;
        }

        // yield/sleep here
    }
}
于 2009-04-20T16:01:54.210 に答える