Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何将游戏逻辑与显示分开?_Algorithm - Fatal编程技术网

Algorithm 如何将游戏逻辑与显示分开?

Algorithm 如何将游戏逻辑与显示分开?,algorithm,Algorithm,如何使每秒的显示帧独立于游戏逻辑?因此,无论视频卡渲染速度有多快,游戏逻辑都以相同的速度运行 您可以使游戏循环看起来像: int lastTime = GetCurrentTime(); while(1) { // how long is it since we last updated? int currentTime = GetCurrentTime(); int dt = currentTime - lastTime; lastTime = currentT

如何使每秒的显示帧独立于游戏逻辑?因此,无论视频卡渲染速度有多快,游戏逻辑都以相同的速度运行

您可以使游戏循环看起来像:

int lastTime = GetCurrentTime();
while(1) {
    // how long is it since we last updated?
    int currentTime = GetCurrentTime();
    int dt = currentTime - lastTime;
    lastTime = currentTime;

    // now do the game logic
    Update(dt);

    // and you can render
    Draw();
}

然后您只需编写
Update()
函数来考虑时间差;e、 例如,如果你让一个物体以某种速度移动,那么每一帧更新它的位置。

我认为这个问题揭示了对游戏引擎应该如何设计的一点误解。这完全没关系,因为它们非常复杂,很难正确处理;)

您有一个正确的印象,即您需要所谓的帧速率独立性。但这不仅仅指渲染帧

单线程游戏引擎中的框架通常称为勾号。处理输入、处理游戏逻辑和基于处理结果渲染帧的每个勾号

您想要做的是能够以任何FPS(每秒帧数)处理游戏逻辑,并获得确定的结果

在以下情况下,这将成为一个问题:

检查输入: -输入是键:“W”,这意味着我们将玩家角色向前移动10个单位:

播放位置+=10

现在,因为你每帧都要这样做,如果你以每秒30帧的速度运行,你将每秒移动300个单位

但是如果你以每秒10帧的速度运行,你每秒只能移动100个单位。因此,您的游戏逻辑与帧速率无关

幸运的是,要解决这个问题并使您的游戏逻辑与帧速率无关是一项相当简单的任务

首先,您需要一个计时器,它将计算每个帧渲染所需的时间。这个以秒为单位的数字(因此0.001秒完成一个勾号)然后乘以您希望与帧速率无关的值。因此,在这种情况下:

拿着“W”的时候

playerPosition+=10*frameTimeDelta

(Delta是“某物的变化”的一个奇特的词)

因此,你的玩家将在一个滴答声中移动10的一小部分,在滴答声一整秒钟后,你将移动全部10个单位

然而,当涉及到变化率也随时间变化的特性时,这将下降,例如加速车辆。这可以通过使用更高级的积分器来解决,例如“Verlet”

多线程方法 如果您仍然对您的问题的答案感兴趣(因为我没有回答,但提出了一个替代方案),请看这里。将游戏逻辑和渲染分离为不同的线程。但它有它的后退。足够让绝大多数游戏引擎保持单线程

这并不是说在所谓的单线程引擎中只有一个线程在运行。但所有重要任务通常都集中在一个中心线程中。一些事情,比如冲突检测,可能是多线程的,但通常情况下,勾号的冲突阶段会阻塞,直到所有线程都返回,引擎返回到单个线程执行

多线程处理带来了一大类问题,甚至是一些性能问题,因为所有东西,甚至容器,都必须是线程安全的。而且游戏引擎一开始是非常复杂的程序,因此很少值得多线程处理它们所增加的复杂性

固定时间步长方法 最后,正如另一位评论者所指出的,拥有一个固定大小的时间步长,并控制你“步进”游戏逻辑的频率,也是一种非常有效的处理方法,有很多好处

为完整起见,此处链接,但其他评论员也链接到:

根据我的经验(不多),杰西和亚当的回答应该会让你走上正轨

如果您想了解更多信息并深入了解其工作原理,我发现的示例应用程序非常有用。

Koen Witters对不同的游戏循环设置有自己的见解

他包括:

  • FPS依赖于恒定的游戏速度
  • 游戏速度取决于可变FPS
  • 游戏速度恒定,FPS最大
  • 与可变FPS无关的恒定游戏速度

(这些标题是根据可取性从文章中提取出来的。)

那天flipcode上有一篇关于这方面的优秀文章。我想把它挖出来送给你

这是一个经过深思熟虑的运行游戏的循环:

  • 单螺纹
  • 在一个固定的游戏时钟
  • 使用插值时钟尽可能快地使用图形
  • 嗯,至少我是这么想的。:-)可惜的是,这篇帖子之后的讨论很难找到。也许回程机器能帮上忙

    time0 = getTickCount();
    do
    {
      time1 = getTickCount();
      frameTime = 0;
      int numLoops = 0;
    
      while ((time1 - time0)  TICK_TIME && numLoops < MAX_LOOPS)
      {
        GameTickRun();
        time0 += TICK_TIME;
        frameTime += TICK_TIME;
        numLoops++;
    // Could this be a good idea? We're not doing it, anyway.
    //    time1 = getTickCount();
      }
      IndependentTickRun(frameTime);
    
      // If playing solo and game logic takes way too long, discard pending
    time.
      if (!bNetworkGame && (time1 - time0)  TICK_TIME)
        time0 = time1 - TICK_TIME;
    
      if (canRender)
      {
        // Account for numLoops overflow causing percent  1.
        float percentWithinTick = Min(1.f, float(time1 - time0)/TICK_TIME);
        GameDrawWithInterpolation(percentWithinTick);
      }
    }
    while (!bGameDone);
    
    time0=getTickCount();
    做
    {
    time1=getTickCount();
    帧时间=0;
    int numLoops=0;
    while((time1-time0)勾选\u TIME&&numLoops
    有一个稍微不同但有趣的方法:任务池。

    在显示图形之前具有时间延迟的单线程解决方案很好,但我认为渐进的方法是在一个线程中运行游戏逻辑,在另一个线程中显示

    但您应该以正确的方式同步线程;)这要花很长时间才能实现