- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
为了创建游戏循环,我遵循了 this excellent tutorial .但我认为下一个关于显示 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
中的变量数量一样高fpsStore
.
有人会查看我的 GameLoop
类,特别是底部的 trackFps()
方法吗?我会提供全部。它有很多评论,但内容并不多,你们中的一些人应该非常熟悉。
GameLoop
(底层包含计算FPS的trackFps()
方法):
package biz.hireholly.engine;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import java.util.ArrayList;
/**
* The GameLoop is a thread that will ensure updating and drawing is done at set intervals.
* The thread will sleep when it has updated/rendered quicker than needed to reach the desired fps.
* The loop is designed to skip drawing if the update/draw cycle is taking to long, up to a MAX_FRAME_SKIPS.
* The Canvas object is created and managed to some extent in the game loop,
* this is so that we can prevent multiple objects trying to draw to it simultaneously.
* Note that the gameloop has a reference to the gameview and vice versa.
*/
public class GameLoop extends Thread {
private static final String TAG = GameLoop.class.getSimpleName();
//desired frames per second
private final static int MAX_FPS = 30;
//maximum number of drawn frames to be skipped if drawing took too long last cycle
private final static int MAX_FRAME_SKIPS = 5;
//ideal time taken to update & draw
private final static int CYCLE_PERIOD = 1000 / MAX_FPS;
private SurfaceHolder surfaceHolder;
//the gameview actually handles inputs and draws to the surface
private GameView gameview;
private boolean running;
private long beginTime = 0; // time when cycle began
private long timeDifference = 0; // time it took for the cycle to execute
private int sleepTime = 0; // milliseconds to sleep (<0 if drawing behind schedule)
private int framesSkipped = 0; // number of render frames skipped
private double lastFps = 0; //The last FPS tracked, the number displayed onscreen
private int fpsTrackCount = 1; // number we'll divide the fpsSTore by to get average
private ArrayList<Double> fpsStore = new ArrayList<Double>(); //For the previous fps values
private long lastTimeFpsCalculated = System.currentTimeMillis(); //used in trackFps
public GameLoop(SurfaceHolder holder, GameView gameview) {
super();
this.surfaceHolder = holder;
this.gameview = gameview;
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run(){
Canvas c;
while (running) {
c = null;
//try locking canvas, so only we can edit pixels on surface
try{
c = this.surfaceHolder.lockCanvas();
//sync so nothing else can modify while were using it
synchronized (surfaceHolder){
beginTime = System.currentTimeMillis();
framesSkipped = 0; //reset frame skips
this.gameview.update();
this.gameview.draw(c);
//calculate how long cycle took
timeDifference = System.currentTimeMillis() - beginTime;
//good time to trackFps?
trackFps();
//calculate potential sleep time
sleepTime = (int)(CYCLE_PERIOD - timeDifference);
//sleep for remaining cycle
if (sleepTime >0){
try{
Thread.sleep(sleepTime); //saves battery! :)
} catch (InterruptedException e){}
}
//if sleepTime negative then we're running behind
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS){
//update without rendering to catch up
this.gameview.update();
//skip as many frame renders as needed to get back into
//positive sleepTime and continue as normal
sleepTime += CYCLE_PERIOD;
framesSkipped++;
}
}
} finally{
//finally executes regardless of exception,
//so surface is not left in an inconsistent state
if (c != null){
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
/* Calculates the average fps every second */
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) && (fpsTrackCount > 0 )){
fps += fpsStore.get(fpsTrackCount-1);
fpsTrackCount--;
}
lastFps = fps / toDivideBy;
lastTimeFpsCalculated = System.currentTimeMillis();
fpsTrackCount = 1;
fpsStore.clear();
}
else{
fpsTrackCount++;
}
}
/* So That it can be drawn in the gameview */
public String getFps() {
return String.valueOf(lastFps);
}
}
最佳答案
好的,让我们先来看这个......
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++;
}
试一试。如果它的表现不太好,请尝试取消对同步块(synchronized block)的注释。
至于您的其他问题,关于 TextDrawable,我查看了您的 GameView...
这是我在 SurfaceChanged() 中发现的内容
fps = new TextDrawable();
fps.setText("HELLO");
现在,为什么不将其移至 SurfaceCreated()?也许您收到了很多 surfaceChanged() 回调,但由于没有 Logcat 调用而没有意识到它? :) 这是我所看到的唯一实例化 TextDrawable 的地方。
关于java - 如何在空游戏中计算 FPS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11738701/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!