我正在创建一个简单的Java游戏引擎(只是为了好玩)。这个想法是为开发任何类型的2D游戏创建一个基本的框架,一个抽象的引擎来完成艰苦的工作。你想回顾一下它的核心,并给我一些提示吗?
public class GameTimer {
public static final double ONE_SECOND = java.util.concurrent.TimeUnit.SECONDS.toNanos(1);
private long start;
private long[] ticks = new long[1000];
private int first, last;
private int fps;
public GameTimer(){}
public void start(){
this.start = System.nanoTime();
}
public void tick(){
ticks[last] = System.nanoTime();
while (ticks[last] - ticks[first] > ONE_SECOND){
first = circular(first + 1);
fps--;
}
last = circular(last + 1);
fps++;
}
public long tock(){
return System.nanoTime() - ticks[circular(last-1)];
}
public long getElapsedNanoTime(){
long prev = ticks[circular(last-2)];
return (prev == 0) ? 0 : ticks[circular(last-1)] - prev;
}
public double getElapsedTime(){
return this.getElapsedNanoTime() / ONE_SECOND;
}
public long getNanoTime(){
return System.nanoTime() - this.start;
}
public double getTime(){
return this.getNanoTime() / ONE_SECOND;
}
public int getFPS(){
return this.fps;
}
private int circular(int n){
return Math.floorMod(n, ticks.length);
}
}double desiredFPS = 60d;
long sleep = (long) (GameTimer.ONE_SECOND / desiredFPS);
GameTimer timer = new GameTimer();
timer.start();
try {
while(true){
// tick and print fps
timer.tick();
System.out.println(timer.getFPS());
// input, update and draw (abstract methods of my engine class)
input();
update();
draw();
// sleep
long wake = System.nanoTime() + sleep - timer.tock();
do {Thread.sleep(0);}
while (System.nanoTime() < wake);
}
} catch (InterruptedException e) {
// oh someone paused the game
}备注:
Thread.sleep()方法(它非常不准确)。我的测试表明,发动机可以保持理想的频率相当精确。start变量和GameTimer中相关的get方法--它只是用于游戏逻辑,对于fps计数或滴答操作来说并不重要。发布于 2016-11-24 11:51:21
你的主回路不需要整个滴答机构。
您已经设置了这个精心制作的装置(我花了一段时间才理解),它度量了您最后一次“框架”所用的时间。然后,在决定需要等待多长时间才能到达下一个帧时,检索该时间,并从当前时间减去该时间加上您想要等待的时间。
所有这些都是一个非常复杂的机制:
long sleep = (long) (GameTimer.ONE_SECOND / desiredFPS);
try {
while(true){
// tick and print fps
long lastTick = System.nanoTime();
timer.tick();
System.out.println(timer.getFPS());
// input, update and draw (abstract methods of my engine class)
input();
update();
draw();
// sleep
long wake = lastTick + sleep;
do {Thread.sleep(0);}
while (System.nanoTime() < wake);
}
} catch (InterruptedException e) {
// oh someone paused the game
}这种重写并没有真正的帮助,所以我将解释:
你所做的是跟踪滴答声的东西。那好吧。但是,在计算中使用滴答计时器是没有意义的--你已经有了启动滴答的时间--这是你进入循环的时候!
您的GameTimer对于以图形形式显示调试信息或在滞后点中查找模式等操作非常有用。但是对于这个用法来说,只要一个长就行了。
first和last的命名也是错误的。它不是指向循环缓冲区中的第一个和最后一个项的指针,而是指向过去秒的第一个和最后一个帧的指针。这应该在变量名中进行编码。
https://codereview.stackexchange.com/questions/122611
复制相似问题