我正在开发一个基础游戏。大多数时候游戏都尊重" 60fps的上限,但是当我故意将fps设置为10fps 5秒(通过调试)来测试游戏渲染和游戏逻辑工作分离时,会发生的事情是在我将游戏fps设置为60fps之后,对于一些几秒钟游戏忽略了" cap"并以10000fps的速度运行,然后再回到上限。所有这一切的原因在于,我希望我的游戏以可变的fps运行,但在所有机器上都保持不变的逻辑速度,但是我不明白为什么我的游戏大部分时间都尊重上限而且从不高于60fps但是当发生减速或滞后尖峰,游戏以超快的速度运行1-2秒,然后恢复正常。无论用户是否运行坏电脑并且游戏以5fps运行,我想要的是确保游戏永远不会超过我的硬帽。
我是否需要实现"跳过的帧"系统什么的? 仅供参考,我的游戏逻辑很轻,但渲染非常重。
new Thread(){
public void run(){
long hintPoint = System.currentTimeMillis();
long nexttickG = System.currentTimeMillis();
long nexttickL = System.currentTimeMillis();
long nexttickV = System.currentTimeMillis();
long ticktimeV = 1000;
long LogicCap = 60;
long ticktimeL = 1000/LogicCap;
short frames = 60;
while(isRunning){
if(Main.servbot){
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
GLOBAL_FPS_CAP=(short)Utils.Clamp(GLOBAL_FPS_CAP,1, 333);
short FramesCap = GLOBAL_FPS_CAP;
long ticktimeG = 1000/FramesCap;
if (System.currentTimeMillis()>nexttickG){
Render();
long elapsed = System.currentTimeMillis() - hintPoint;
frames=(short)((long)1000/(Math.max(elapsed,1)));
hintPoint = System.currentTimeMillis();
nexttickG+=ticktimeG;
}
if (System.currentTimeMillis()>nexttickL){
GameLoop();
nexttickL+=ticktimeL;
}
if (System.currentTimeMillis()>nexttickV){
GLOBAL_FPS_HINT = frames;
nexttickV+=ticktimeV;
}
Thread.yield();
}
}
}.start();
}
答案 0 :(得分:2)
首先,如果可能,请使用.currentTimeMillis()
而不是FPS
,因为第二个更容易出错。
其次,考虑实施"ad-hoc dictionary"系统,其中Game-World Time
和game-world
独立于其他。
Delta-Time是动画和游戏 之类的正确循环模式(基本上是程序化的,系统化的,有时候是 > time-drift bugs
数据的混乱动画 ,因为它是最简单的模式,避免了大多数幼稚/简单化的 animation-loop
{ {1}}或game-loop
实施。
有关天真循环实现问题的完整解释,以及Delta-Time
如何解决时间漂移问题 (因此,使用它的原因) ,看看Here's an example of how to implement a Delta-Time
game-loop in Java.和this article,它们详细解释了游戏循环中的差异。
答案 1 :(得分:1)
这些变化有帮助吗? (见下面的代码,查找/ * new * /)。
推理:您是否在run()方法中设置了断点? 你修改了哪些var
在修改var以更改帧速率时,System.currentTimeMillis()中有多少毫秒的时间?好像如果需要3或4(可能是12)秒来进行更改并恢复执行,你的nextTickL和nextTickG值将远远落后于System.currentTimeMillis()并且可能需要大量的+ = ticktimeG来追赶到系统时钟。
new Thread(){
public void run(){
long hintPoint = System.currentTimeMillis();
long nexttickG = System.currentTimeMillis();
long nexttickL = System.currentTimeMillis();
long nexttickV = System.currentTimeMillis();
long ticktimeV = 1000;
long LogicCap = 60;
long ticktimeL = 1000/LogicCap;
short frames = 60;
while(isRunning){
if(Main.servbot){
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
GLOBAL_FPS_CAP=(short)Utils.Clamp(GLOBAL_FPS_CAP,1, 333);
short FramesCap = GLOBAL_FPS_CAP;
long ticktimeG = 1000/FramesCap;
if (System.currentTimeMillis()>nexttickG){
Render();
long elapsed = System.currentTimeMillis() - hintPoint;
frames=(short)((long)1000/(Math.max(elapsed,1)));
hintPoint = System.currentTimeMillis();
nexttickG+=ticktimeG;
/*new*/ if( nexttickG < System.currentTimeMillis() ) {
/*new*/ // major clock skew somehow, reset.
/*new*/ nexttickG = System.currentTimeMillis() + ticktimeG;
/*new*/ }
}
if (System.currentTimeMillis()>nexttickL){
GameLoop();
nexttickL+=ticktimeL;
/*new*/ if( nexttickL < System.currentTimeMillis() ) {
/*new*/ // major clock skew somehow, reset.
/*new*/ nexttickL = System.currentTimeMillis() + ticktimeL;
/*new*/ }
}
if (System.currentTimeMillis()>nexttickV){
GLOBAL_FPS_HINT = frames;
nexttickV+=ticktimeV;
}
Thread.yield();
}
}
}.start();