我正在建立一个非常注重物理学的游戏。因此我需要游戏以非常特定的间隔运行。目前的代码:
public double period = .02; //this is the run interval in seconds
//main gameLoop
public void gameLoop(){
long startTime;
long sleep;
while(running){
startTime = System.nanoTime();
Graphics2D g = s.getGraphics();
operateEntities(g);
g.dispose();
s.update();
//figure out how long it must sleep to take .02s altogether
sleep = ((int)(period*1000) - (System.nanoTime() - startTime)*100000);
try{
if(sleep > 0){
Thread.sleep(sleep);
}else{
System.err.println("Warning: program runtime exceeded period");
}
}catch(Exception ex){}
gameTime += period;
}
}
这不按预期工作。目前主线程正在执行而根本没有休眠,并且“警告:程序运行时超出期限”警告正在触发。
以前我使用的是System.currentTimeMillis(),但是对于我的目的来说它不够准确,所以我切换到了System.nanoTime()
增加周期实际上可以加速程序,同时减少它会减慢它。
有一个简单的逻辑faw?是我对System.nanoTime()的理解了吗?或者是否有更好的方法来运行特定时间间隔的操作实体,处理和更新?
编辑:为了记录,该程序完成的时间不会超过.02秒。它已经过测试
答案 0 :(得分:8)
纳秒小于毫秒,因此,转换纳米 - > millis,你必须除以100000,而不是多余的;
//figure out how long it must sleep to take .02s altogether
sleep = ((int)(period*1000) - (System.nanoTime() - startTime)*100000);
应改为
//figure out how long it must sleep to take .02s altogether
sleep = ((int)(period*1000) - (System.nanoTime() - startTime)/100000);
你当前的代码试图睡眠200ms减去一个大数字,使睡眠变为负数,并给你“警告:程序运行时间超过期限”输出
答案 1 :(得分:2)
分解你的代码有很多问题:
//Multiplies by 100,000 rather than divides.
sleep = ((int)(period*1000) - (System.nanoTime() - startTime)*100000);
//Note that sleep here is a very small number minus a very large number: probably negative.
try{
if(sleep > 0){//If positive, sleep
Thread.sleep(sleep);
} else{//throws an error in all other cases.
System.err.println("Warning: program runtime exceeded period");
}
}catch(Exception ex){}//Empty exception handling poorly handles the thread.sleep() Exception requirement.
除非您使period
值更大,否则此代码将始终出错。然而,即使超出此范围,您的方法也不可能产生您想要的结果:准确的计时。你的核心循环是什么:
如果时间片足够小,这将是准确的。但是,线程不能像那样工作。你无法保证线程什么时候醒来。它可能永远不会。可能会在三秒钟内完成。它可能是即时的。无论你的时间段是什么,你都有可能超越你,你将永远不会辜负它。
您需要在实际经过的时间段内扩展所有物理,而不是依赖于每次都经过的特定时间段,而不是依赖于特定的增量周期。
您仍然需要一个小的时间片来休眠,但这样就可以消除线程调度程序引入的错误。