- 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/
我有一个计数器可以计算每一帧。我想做的是将其除以时间以确定我的程序的 FPS。但是我不确定如何在 python 中对计时函数执行操作。 我试过将时间初始化为 fps_time = time.time
我发布了我的 original question here .试过suggested solution .但这并不能解决我的问题。 这就是我所做的。下载 this video来自 Youtube 作为
JavaFX UI 线程上限为每秒 60 次更新(1、2)似乎是一种共识。据我了解,更新意味着 pulse。 A pulse is an event that indicates to the Jav
在处理来自相机的帧时,我正在尝试测量每秒帧数。计算没什么特别的,可以在这个问题中找到:How to write function with parameter which type is deduce
我在 Xcode 6.1.1 中使用 OpenGL ES 3.0 开发了一款针对 iPad Air 的游戏。当我捕获 OpenGL ES 帧时,FPS 数字和着色器程序时间始终显示为 0。 我在项目方
我正在尝试通过 ffmpeg 对视频进行编码在 Linux 系统中。原始视频有 60 FPS,我需要将其更改为 25,但是当我这样做时,视频比原始视频慢。 当我将其更改为 30 时,一切都很好(我想编
我正在尝试将视频从 25 fps 加速到 60 fps。我想要完全相同的帧数,只是更快地呈现给我,并且每秒可以让我获得 60 帧。 ffmpeg -i Spider.mov -r 62500/1000
我们如何才能以更高的帧速率(例如 500 - 800 FPS)运行 OpenGL 应用程序(例如游戏)? 例如,AOE 2 的运行速度超过 700 FPS(我知道它与 DirectX 有关)。尽管我只
为了高性能的科学目的,我们需要渲染视频并在设备上以 60fps 的速度播放。我假设 H.264 视频的通常帧率低于该值。 这是可能的,还是帧率是固定的?如果是这样,在设备上全屏播放 H.264 视频时
拥有 50 fps 的 5 秒视频 想要在 10 秒内将其转换为 25 fps 的视频,而且一切都变慢了,即使是音频 是否可以使用 ffmpeg 最佳答案 利用 ffmpeg -i input.mp4
我有下面的代码(移植到 JOGL 2.0 的 Nehe 教程 1 的基本版本)请求一个以 30 FPS 为动画的 FPSAnimator。当我运行代码时,它会打印 21.321962 或 21.413
我在下面有一些非常简单的性能测试代码,用于在 2011 年末的 Macbook Pro 上使用 OpenCV 3.1 + Python3 测量我的网络摄像头的 FPS: cap = cv2.Video
我正在开发 ARKit 应用以及 Vision/AVKit 框架。我正在使用 MLModel 对我的手势进行分类。我的应用程序可以识别Victory、Okey 和¡No pasarán! 手势来控制视
我从其他 SO 问题中使用了这个命令: $ ffmpeg -i obraz%04d.png -framerate 1 -c:v libx265 output.mkv 我告诉它最多 1 FPS,但日志和
我错误地在 iPhone SE (2) 上录制了慢动作视频,而不是延时摄影。 我知道这里有很多关于这个问题的答案,但我一次又一次地尝试并且总是出现问题(比如一个视频的总帧数正确,但持续了 3 个小时并
任何人都可以帮助我默认情况下以 240 fps 或 120 fps 录制视频,使用 AVCapture session 录制 session 需要 30 fps。 用这个库录制视频 https://g
我目前正在用 Java 制作 3D 游戏。我的问题是当我通过 Eclipse 运行它时,我得到了大约 40 fps,这很好。虽然当我在导出的 jar 文件中运行它时,我得到了 18 fps? 我不太确
自从我在 C++ 项目中从 OpenCV 3.x 更改为 4.x(从源代码编译)以来,我遇到了一些麻烦。我在一个小例子中复制了这个行为,这个例子只打开了一个网络摄像头并记录了 5 秒钟。 使用 3.x
我通过 VLC 录制了一个 RTSP 流(4K)大约一个小时,发生了一些奇怪的事情。 文件大小为 6.6 GB,但视频长度只有 12 分钟。 当我在 VLC 上播放时,进度条到达末尾,但视频仍在连续播
我正在尝试运行此命令。 ffmpeg -i out_frames/frame%08d.jpg -i input.mp4 -map 0:v:0 -map 1:a:0 -c:a copy -c:v lib
我是一名优秀的程序员,十分优秀!