从帧速率代码获得奇怪的结果

时间:2009-04-20 15:46:22

标签: java counter frame-rate

我正试图让我的游戏保持在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));
        }
    }

2 个答案:

答案 0 :(得分:1)

我怀疑这是由Thread.sleep()的不准确引起的:

  

导致当前正在执行的线程   为了睡觉(停止执行)   指定的毫秒数加上   指定的纳秒数,   受精确和准确的影响   系统计时器和调度程序。该   线程不会失去任何所有权   显示器

你有必要像这样保持帧率吗?也许你可以更全面地解释你想要完成的事情?

答案 1 :(得分: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 ) );
    }
}

但请注意,这将为您提供整个程序执行期间的平均帧速率。另外两个选项是获得瞬时帧率,以及过去N帧的平均帧率。

所有样式合二为一(未经测试/未经编译,因此可能会出现一些错误,但应该让您从正确的方向开始):

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
    }
}