为什么在Java中,当我写入控制台时,纳秒到秒的正确转换会发生变化?
我目前正在用java清理我的游戏循环计时,但我在纳秒到秒的转换方面遇到了一个非常奇怪的问题 由于某些原因,当我不向控制台写入时,将纳秒转换为时间增量(以秒为单位)除以100000000可以正常工作。考虑到每秒有100000000纳秒,我立即发现这很奇怪,所以我尝试测量每秒运行的循环数,并在它飞到我需要的FPS以上时将其打印到控制台。出于完全未知的原因,这导致游戏疯狂地减速,需要除以100000000,以使增量达到其适当的值。我完全不明白为什么会这样 下面是当前的循环。注释掉的“问题触发器”行更改了“问题行”的功能,导致需要更改其除以的值,以将其转换为正确的单位为什么在Java中,当我写入控制台时,纳秒到秒的正确转换会发生变化?,java,jframe,jpanel,seconds,datetime-conversion,Java,Jframe,Jpanel,Seconds,Datetime Conversion,我目前正在用java清理我的游戏循环计时,但我在纳秒到秒的转换方面遇到了一个非常奇怪的问题 由于某些原因,当我不向控制台写入时,将纳秒转换为时间增量(以秒为单位)除以100000000可以正常工作。考虑到每秒有100000000纳秒,我立即发现这很奇怪,所以我尝试测量每秒运行的循环数,并在它飞到我需要的FPS以上时将其打印到控制台。出于完全未知的原因,这导致游戏疯狂地减速,需要除以100000000,以使增量达到其适当的值。我完全不明白为什么会这样 下面是当前的循环。注释掉的“问题触发器”行更改
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
的任何帮助,在未经修改的eclipseide中编写和编译,我将非常感谢所有的帮助,这只是一个容易混淆的问题
编辑:好的,在试用了该代码之后(我所做的只是移动一些东西)作为三重检查,我回到了问题发生时的布局
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;
}
}
现在,根据“哇”行是否被注释掉,它们的运行方式有所不同,仍然非常奇怪,但考虑到与我第一次发布的干净版本和我刚刚发布的古怪粗壮版本的差异,希望问题更容易发现。由于我的声誉,我还不能评论,我将把它扔到那里,尝试将1000000000转换为1000000000.0或1000000000L,这样将是一个漫长的过程。可能会被截断为int
还有,你为什么不把这个放到它自己的线程中呢?如果它是在EDT上运行的,这就可以解释为什么你的程序速度会大大降低。你实际上在浪费时间。以下是您的函数的剪贴版本:
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的实时速率
对于一个具体的示例,假设更新方法需要约15微秒,而“渲染”方法需要约10微秒:
在迭代1中,“now”最初设置为某个时间X。“lastUpdateTime”然后设置为X+15000。在迭代2中,“现在”设置为X+25000。因此,您传递的增量是10000,即使两次迭代之间的“现在”变化实际上是25000 在添加/删除打印输出时,您必须更改“问题行”上的除数的原因是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)要保持传入delta的持续总和,那么它将相当精确地与长期运行中所用的挂钟时间相匹配。计时器和计时器的类型是什么?int还是double?显示的代码段没有问题
delta
将准确地保持now
和lastUpdateTime
之间的秒数,表示为double
,因此我又尝试了一次,是的,我发布的代码片段工作正常或没有评论,这很奇怪,因为我在发布之前只更改了几行,不管怎样,我已经用未更改的代码段进行了编辑,它确实产生了问题。为什么1行会影响循环速度,这仍然令人困惑,但是当注释为稳定的3.019E-6时,查看打印的增量,当未注释时,它会从1.449E-5到8.452E-6剧烈闪烁。运行不是一个问题-整数增加到刚刚超过20亿。在Java中,操作数隐式提升为更高的类型。由于OP的分子被显式转换为double,所以除数也被提升为double。