我目前正在使用java清理我的游戏循环计时,但是我遇到了一个非常奇怪的问题,即纳秒到秒的转换。
出于某种原因,当我不写入控制台时,将纳秒传递到时间增量(以秒为单位)可以正常工作,除以100,000,000。我立即发现奇怪,因为一秒钟内有1000,000,000纳秒,所以我尝试测量每秒运行多少个循环,当它超过我需要的FPS时将其打印到控制台。由于一个完全未知的原因导致游戏疯狂减速,需要除以1000,000,000以使三角洲达到其正确值。我完全不知道为什么会这样。
以下是目前的循环。注释掉时“问题触发”行会更改“问题行”功能,导致需要更改其除以的值以将其转换为正确的单位
while (isRunning)
{
now = System.nanoTime();
delta = (double)(now - lastUpdateTime) / 1000000000; //problem line
timer += delta;
timerplus += delta;
ticks++;
gamePanel.Update(delta);
lastUpdateTime = System.nanoTime();
if (ticks / timerplus > 60)
{
System.out.println("fast"); //problem trigger?
}
gamePanel.Render(delta);
timer = 0;
}
非常感谢任何和所有帮助,如果信息是我使用JPanel
和JFrame
的任何帮助,在未经修改的Eclipse IDE中编写和编译,这只是一个简单的混乱问题
编辑:好的,所以在尝试了它可行的代码之后(我所做的就是移动一些东西)作为三重检查我回到问题发生时如何布局
while (isRunning)
{
now = System.nanoTime();
delta = (double)(now - lastUpdateTime) / 1000000000;
timer += delta;
timerplus += delta;
ticks++;
gamePanel.Update(delta);
lastUpdateTime = System.nanoTime();
if (ticks / timerplus > 120)
{
//System.out.println("wow");
}
if (timer >= (double)1 / TICKS_PER_SECOND)
{
gamePanel.Render(delta);
timer = 0;
}
if (timerplus >= 1)
{
System.out.println("FPS: " + ticks);
ticks = 0;
timerplus = 0;
}
}
现在他们的运行方式有所不同,取决于“哇”线是否被注释掉,仍然绝对奇怪,但鉴于与我首次发布的清洁版本的差异以及我刚刚发布的奇怪强壮的版本,希望问题更容易被发现
答案 0 :(得分:0)
由于我的声誉,我不能发表评论,我将把它扔出去,尝试将1000000000变成1000000000.0或1000000000L,这样它就会很长。也许它会被截断为int。
另外,为什么不把它扔进自己的线程?如果它在EDT上运行,这可以解释为什么你的程序会大大减慢。
答案 1 :(得分:0)
你基本上是在浪费时间。这是你的功能的剪辑版本:
while (isRunning)
{
now = System.nanoTime();
delta = (double)(now - lastUpdateTime) / 1000000000; //problem line
//snip 1
lastUpdateTime = System.nanoTime();
//snip 2
}
随着时间的推移,如果你总结所有的增量,你将以略低于实时的速度增长。以下多少取决于设置“now”和“lastUpdateTime”之间的操作需要多长时间。例如,如果“snip1”和“snip2”中的操作花费的时间大致相同,那么您将看到~1 / 2实时的速率。
对于一个具体的例子,假设你的update方法需要大约15微秒而你的“render”方法需要大约10:
在迭代1中,“now”最初设置为某个时间X.“lastUpdateTime”然后设置为X + 15000。
在迭代2中,“now”设置为X + 25000.因此,即使两次迭代之间“now”的变化实际为25000,您传入的delta也是10000.
当您添加/删除该打印输出时,您必须在“问题行”上更改除数的原因是I / O 慢,因此它会改变在snip1和snip2相当戏剧性。
你可能真正想做的是:
while (isRunning)
{
now = System.nanoTime();
delta = (double)(now - lastUpdateTime) / 1000000000; //problem line
//snip 1
lastUpdateTime = now;
//snip 2
}
这将保证如果gamePanel.update(delta)保持传入的增量的持续总和,它将与长期运行的挂钟时间相当精确地匹配。