-1

我目前正在用java清理我的游戏循环计时,但是我在纳秒到秒的转换方面遇到了一个非常奇怪的问题。

出于某种原因,当我不写入控制台时,将纳秒传递到时间增量(以秒为单位)除以 100,000,000 即可正常工作。鉴于每秒有 1000,000,000 纳秒,我立即发现这很奇怪,所以我尝试测量每秒运行了多少循环,并在它飞到我需要的 FPS 之上时将其打印到控制台。由于一个完全未知的原因,这导致游戏异常减速,需要除以 1000,000,000 才能使 delta 达到其正确值。我完全不知道为什么会这样。

下面是当前的循环。注释掉的“问题触发器”行会改变“问题行”的功能,导致需要更改其除以的值以将其转换为正确的单位

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;
        }
    }

现在它们的运行方式不同,具体取决于“哇”行是否被注释掉,仍然非常奇怪,但考虑到我第一次发布的清理版本和我刚刚发布的奇怪的粗壮版本的差异,希望问题更容易发现。

4

2 回答 2

0

由于我的声誉,我还不能发表评论,我会把它扔在那里,试着把 1000000000 变成 1000000000.0 或 1000000000L,这样它会很长。也许它被截断为int。

另外,你为什么不把它扔到它自己的线程中呢?如果它在 EDT 上运行,这可以解释为什么您的程序会显着变慢。

于 2014-02-17T21:58:03.290 回答
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 的实时速率。

举一个具体的例子,假设你的更新方法需要大约 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) 要保持传入的增量的持续总和,从长远来看,它将与经过的挂钟时间相当精确地匹配。

于 2014-02-17T22:22:51.840 回答