GameLoop fps控制器

时间:2015-04-08 19:32:28

标签: java game-engine

我一直关注如何使用java创建一个2D游戏的youtube系列,我似乎无法解决这段代码是如何工作的,如果有人能详细说明这段代码是如何工作的那样非常感激。

public void run() {
    long lastTime = System.nanoTime();
    final double clock = 1000000000.0 / 60.0;
    double delta = 0;

    while (running) {
        long now = System.nanoTime();
        delta +=(now - lastTime) / clock;
        System.out.println(now-lastTime);
        lastTime = now;

        while (delta >= 1){
            update();
            delta--;
        }
        render();
    }
}

我从这段代码中理解的是,如果我们的游戏每秒运行60帧,时钟变量包含一帧应该花多少时间,但我似乎无法绕过now-lastTime变量因为它们似乎一直在变化,但是我们在循环的每次执行中获得相同的时间,因此获得60 fps。 我理解循环的目的,我实际上不理解的是它在数学上是如何一起降低的,因此delta> = 1每秒发生60次。

3 个答案:

答案 0 :(得分:0)

编辑。 基本上,代码首先计算每1/60秒的纳秒数,然后使用它将delta转换为标准化值。尽管如此,这是一种令人困惑的方式。

这可能更容易思考:

double nano = 1000000000.0;
double updateIntervalInSec =  1 / 60.0;
double delta = 0;

delta += (now-lastTime) / nano;//convert nano to seconds here

while(delta >= updateIntervalInSec)
{
  delta -= updateIntervalInSec;
}

早些时候回答;可能对某人有用。

这种类型的游戏循环旨在解决一些问题。

  1. 使更新率与渲染率无关
  2. 使每次更新的时间增量保持不变。
  3. 首先要考虑的是慢速或潜在的慢速计算机;即使你不能足够快地显示更新,游戏也应该(通常)仍然以正常速度更新。

    第二个考虑对于物理游戏很重要;用可变的时间间隔/增量更新物理系统会使物理不快。

    现在进行实施。

    //run this loop as fast as possible
    while (running) { 
        long now = System.nanoTime();
    
        //delta is to collect up the amount of time since the last loop and put it
        //into our bucket of time
        delta +=(now - lastTime) / clock;
    
    
        System.out.println(now-lastTime);
        lastTime = now;
    
        //if we have accumulated enough time to meet the minimum requirements for an update, then run one update, and remove one increment of time from our bucket of available time.
        //but what if we have more time left in the delta bucket?   We need to keep doing updates until we've used up all the available time.
        while (delta >= 1){
        //update requires 1 time
            update();
            delta--;
        }
        //now that we've made sure all the updates are up to date, we can render
        //note that render happens no matter if 10 updates, or 0 updates were just run
        render();
    }
    

答案 1 :(得分:0)

这被视为Delta Timing;它消除了在快速和慢速计算机上观察应用程序时可能出现的视觉速度差异。


逻辑是这样的:

我们指定每帧应该有多少纳秒秒。这是1000000000/60:1b是纳秒,60是多少帧(你可能知道)。

以下是打印now-last时计算机的一些结果,即每帧之间经过的纳秒数:

7270.0
2566.0
4704.0
4276.0

想法是添加所有结果,直到达到16m~nano秒。一旦达到16米,就需要更新了。你实际上可以这样做:

double timePerFrame = 1000000000/60; //16m
long last = System.nanoTime();
while(true) {
    long now = System.nanoTime();
    double elapsedTime = now - last;

    delta += elapsedTime;
    last = now;

    if(delta >= timePerFrame) {
        update();
        delta = 0;
    }
}

相反,条件为delta >= 1,其中1代表“一帧”。将经过的时间除以更新前应经过的时间,可以得出当前帧的进度百分比。而不是每个循环都是一个帧,每次都会传递一个帧delta >= 1delta代表该框架的当前进展。

答案 2 :(得分:0)

时钟速度基本上只是每秒可以发生的纳秒数。 final double clock = 1000000000.0 / 60.0;只是在一秒内返回纳秒的1/60。

下一个有趣的部分是计算delta变量(当它大于或等于1时,我们需要再次绘制,因为至少已经过了1/60秒。)

他们执行now - lastTime以获得从现在到最后一次循环运行之间的纳秒差异。然后我们将这个数字除以时钟速度(1/60秒)。

现在delta只显示自上次循环执行以来已经过了1/60秒。

然后我们检查是否已经过了1/60秒,如果有,那么我们更新游戏并减少delta(因为我们做了一帧/我们做了1/60秒)。

循环继续更新,因此它为每1/60秒抽取一次,基本上强制游戏以60fps运行(技术上但实际上这可能不是真的)。​​

希望这有点道理。我不太善于解释事情。

修改

这里只是澄清一下。 Delta只是过去1/60秒的数字。所以delta可能是60(意味着1秒已经过去或360意味着6秒已经过去或其他一些数字)。 while(delta >= 1)将一直运行,直到delta回到0.如果delta足够大,那么更新可以连续运行300次。

如果update()以某种方式阻塞,则delta可能大于1(这意味着update()执行的时间超过1/60秒)。