Java 如何在我的空游戏中计算FPS?

Java 如何在我的空游戏中计算FPS?,java,android,game-engine,frame-rate,game-loop,Java,Android,Game Engine,Frame Rate,Game Loop,创建我遵循的游戏循环。但是我认为下一个关于显示FPS的教程有点不确定,所以我试着单飞。我对自己制定的trackFps()方法相当有信心;它在计算帧之间的时间差后调用,每次运行时测量预测的FPS,将这些预测的FPS值存储在ArrayList中,然后在经过一秒钟后,将这些预测的FPS相加并除以添加的值的数量,得到平均FPS 当我使用调试器运行它时,它可以正常工作,但当我正常运行它时,会出现以下异常: FATAL EXCEPTION: Thread-11 java.lang.IndexOutOfBou

创建我遵循的游戏循环。但是我认为下一个关于显示FPS的教程有点不确定,所以我试着单飞。我对自己制定的
trackFps()
方法相当有信心;它在计算帧之间的时间差后调用,每次运行时测量预测的FPS,将这些预测的FPS值存储在
ArrayList
中,然后在经过一秒钟后,将这些预测的FPS相加并除以添加的值的数量,得到平均FPS

当我使用调试器运行它时,它可以正常工作,但当我正常运行它时,会出现以下异常:

FATAL EXCEPTION: Thread-11
java.lang.IndexOutOfBoundsException: Invalid index 26, size is 6
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257)
at java.util.ArrayList.get(ArrayList.java:311)
at biz.hireholly.engine.GameLoop.trackFps(GameLoop.java:120)
at biz.hireholly.engine.GameLoop.run(GameLoop.java:73)
这是非常解释性的,出现在这一行
fps+=fpsStore.get(fpsTrackCount-1)。但是我看不出
fpsTrackCount
变量怎么会高达26个,它应该只高达
ArrayList
fpstore
中存储的变量数

有人会浏览我的
GameLoop
类,特别是底部的
trackFps()
方法吗?我会提供一切的。评论很多,但没有太多,你们中的一些人应该非常熟悉

GameLoop
(包含底部计算FPS的
trackFps()
方法):

package biz.hireholly.engine;
导入android.graphics.Canvas;
导入android.view.SurfaceHolder;
导入java.util.ArrayList;
/**
*GameLoop是一个线程,它将确保以设定的间隔完成更新和绘图。
*当线程更新/渲染速度快于达到所需fps时,线程将休眠。
*如果更新/绘制周期过长,循环设计为跳过绘制,直至跳过最大帧。
*画布对象在一定程度上是在游戏循环中创建和管理的,
*这是为了防止多个对象试图同时绘制到它。
*请注意,gameloop引用了gameview,反之亦然。
*/
公共类GameLoop扩展线程{
私有静态最终字符串标记=GameLoop.class.getSimpleName();
//每秒所需帧数
专用最终静态int MAX_FPS=30;
//如果上一个周期的绘制时间过长,则要跳过的最大绘制帧数
私有最终静态int MAX_FRAME_SKIPS=5;
//更新和绘制所需的理想时间
私人最终静态整数周期=1000/最大FPS;
私人地勤人员地勤人员;
//gameview实际上处理输入并绘制到曲面
私人游戏视图游戏视图;
私有布尔运行;
private long beginTime=0;//循环开始的时间
private long-timeDifference=0;//循环执行所用的时间

private int sleepTime=0;//睡眠毫秒(我认为这段代码应该适合您

cputhrottle=(int) System.currentTimeMillis();
cputhrottle = (int)System.currentTimeMillis() - cputhrottle;cputhrottle=33-cputhrottle;

它每秒30帧,对您很有用

我认为这段代码应该适合您

cputhrottle=(int) System.currentTimeMillis();
cputhrottle = (int)System.currentTimeMillis() - cputhrottle;cputhrottle=33-cputhrottle;

它每秒30帧,这对你很有用

好的,让我们先看一下

java.lang.IndexOutOfBoundsException: Invalid index 26, size is 6
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257)
at java.util.ArrayList.get(ArrayList.java:311)
at biz.hireholly.engine.GameLoop.trackFps(GameLoop.java:120)
所以在trackFPS中的某个地方,get()是出人意料的

private void trackFps()
{
    long currentTime = System.currentTimeMillis();

    if(timeDifference != 0)
    {
        fpsStore.add((double)(1000 / timeDifference));
    }
    //If a second has past since last time average was calculated,
    // it's time to calculate a new average fps to display
    if ((currentTime - 1000) > lastTimeFpsCalculated)
    {
        int fps = 0;
        int toDivideBy = fpsTrackCount;
        while ((fpsStore !=  null || !fpsStore.isEmpty()) && (fpsTrackCount > 0 ) && (fpsTrackCount < fpsStore.getCount()))
        {
            //synchronized(this) {
            fps += fpsStore.get(fpsTrackCount-1);
            fpsStore.remove(fpsTrackCount-1);  //otherwise we'll get stuck because of getCount condition
            fpsTrackCount--;
            //}
        }
        lastFps = fps / toDivideBy;
        lastTimeFpsCalculated = System.currentTimeMillis();
        //fpsTrackCount = 1;
        //fpsStore.clear();
        Log.d("trackFPS()", "fpsTrackCount = "+fpsTrackCount+"\tfpsStore.size() = "+fpsStore.size()+"\t"+fpsStore.toString());
    }
    else   
        fpsTrackCount++;
}

现在,为什么不把它移到SurfaceCreated()?也许你得到了很多surfaceChanged()回调,但你没有意识到,因为你没有Logcat调用:)这是我能看到的唯一一个TextDrawable被实例化的地方。

好的,让我们先来看一下

java.lang.IndexOutOfBoundsException: Invalid index 26, size is 6
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257)
at java.util.ArrayList.get(ArrayList.java:311)
at biz.hireholly.engine.GameLoop.trackFps(GameLoop.java:120)
所以在trackFPS中的某个地方,get()是出人意料的

private void trackFps()
{
    long currentTime = System.currentTimeMillis();

    if(timeDifference != 0)
    {
        fpsStore.add((double)(1000 / timeDifference));
    }
    //If a second has past since last time average was calculated,
    // it's time to calculate a new average fps to display
    if ((currentTime - 1000) > lastTimeFpsCalculated)
    {
        int fps = 0;
        int toDivideBy = fpsTrackCount;
        while ((fpsStore !=  null || !fpsStore.isEmpty()) && (fpsTrackCount > 0 ) && (fpsTrackCount < fpsStore.getCount()))
        {
            //synchronized(this) {
            fps += fpsStore.get(fpsTrackCount-1);
            fpsStore.remove(fpsTrackCount-1);  //otherwise we'll get stuck because of getCount condition
            fpsTrackCount--;
            //}
        }
        lastFps = fps / toDivideBy;
        lastTimeFpsCalculated = System.currentTimeMillis();
        //fpsTrackCount = 1;
        //fpsStore.clear();
        Log.d("trackFPS()", "fpsTrackCount = "+fpsTrackCount+"\tfpsStore.size() = "+fpsStore.size()+"\t"+fpsStore.toString());
    }
    else   
        fpsTrackCount++;
}

现在,为什么不把它移到SurfaceCreated()?也许你有很多surfaceChanged()回调,但由于您没有Logcat调用,所以没有意识到它?:)这是唯一一个从我看到的TextDrawable被实例化的地方。

您也可以使用android play store中的应用来测量FPS。最近发布的一个非常好的应用是GameBench。它不仅可以捕获FPS,还可以捕获屏幕截图,这样您就可以了解FPS下降时发生的情况。它还提供CPU使用情况以及某些设备的GPU使用情况。我相信你会发现它很有用


链接是

您也可以使用android play store中的应用程序来测量FPS。最近发布的一个非常好的应用程序是GameBench。它不仅捕获FPS,而且还提供屏幕截图,以便您了解FPS下降时的情况。它还提供CPU使用情况以及某些设备的GPU使用情况。我相信您会发现它很有用


链接是

对不起,但这个答案需要更多的解释,虽然它是相关的,但我不确定它是否真的能回答我的问题。对不起,这个答案需要更多的解释,虽然它是相关的,但我不确定它是否真的能回答我的问题。我看不到有人打电话到你的可写文本,你能发布吗你用它来绘制FPS值的代码?啊,找到了。对不起,是的,那是我在Pastebin上上传的GameView中的,因为我不想让我的问题变得混乱。我没有看到对你的TextDrawable的调用,你能把你用它来绘制FPS值的代码发布到哪里吗?啊,找到了。对不起,是的,那是我在Pasteb上上传的GameView中的因为我不想让我的问题变得杂乱无章。非常感谢你花时间!首先,这是日志的结果,不是我想要的结果。我认为行
fpsTrackCount=1
可能仍然应该保留。当我取消注释时,尽管日志输出没有太好,但它只显示了一个fpsTrackCount为1,fpsStore中的数字仍然为500和1000,如上图所示。将初始化位移动到SurfaceCreated的好处很好,但我恐怕在屏幕上仍然看到模糊的重叠数字,因此我不确定这是什么原因。感谢您的帮助!另外,未识别.getCount(),我认为应该是.size()是:)size()…至于TextDrawable,可能是这样的…canvas.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR);我稍微编辑了一下