3

我制作了一个程序(在 C++ 中,使用 gl/glut)用于学习目的,您基本上可以在屏幕上运行(第一人称),并且它在场景周围有几个实体。我试图在另一台计算机上运行它并且速度完全不同,所以我搜索了这个主题,我目前正在做这样的事情:

空闲功能:

    start = glutGet (GLUT_ELAPSED_TIME);
    double dt = (start-end)*30/1000;

    <all the movement*dt>

    glutPostRedisplay ();

    end = glutGet (GLUT_ELAPSED_TIME);

显示功能:

    <rendering for all objects>

    glutSwapBuffers ();

我的问题是:这是正确的方法吗?空闲功能后显示的场景对吗?

我尝试将 end = glutGet (GLUT_ELAPSED_TIME) 放在 glutSwapBuffers () 之前并没有注意到任何变化,但是当我将它放在 glutSwapBuffers () 之后时,它会减慢很多甚至有时会停止。

编辑:我只是注意到,以我的想法,结束开始应该是从所有绘图完成到移动更新之前经过的时间,因为空闲()将在显示()后立即被调用结束了,那么这里唯一没有考虑的时间是计算机完成所有运动所花费的时间,这是真的吗?(这应该不算什么?)

对不起,如果这太混乱了..

提前致谢。

4

7 回答 7

4

我不知道“Glut”是什么,但作为游戏开发的一般规则,我绝不会根据计算机处理指令的速度来确定移动速度。这就是他们在 80 年代后期所做的,这就是为什么当您玩旧游戏时,事情会以光速发展。

我会设置一个计时器,并将我的所有动作都建立在明确而具体的定时事件之上。

于 2010-03-03T15:56:33.913 回答
1

我不会使用计时器。如果 PC 太慢或太忙而无法以所需的速率运行,事情可能会出错,并且事件可能会堆积起来。我会让循环尽可能快地运行,并且每次计算已经过去了多少时间并将其放入您的运动/逻辑计算中。

在内部,您实际上可能会实现小的固定时间子步骤,因为试图使一切在可变时间步骤上正常工作并不像 x+=v*dt 那样简单。

试试 gamedev.net 这样的东西。很多文章和繁忙的论坛。

于 2010-03-03T16:59:28.663 回答
1

有一篇关于游戏循环的完美文章应该为您提供所需的所有信息。

于 2010-03-04T13:21:50.787 回答
1

设置一个高分辨率计时器(例如 Windows 上的 QueryPerformanceCounter)并测量每一帧之间的时间。这个时间,称为增量时间 (dt),应该用于所有运动计算,例如。每一帧,将对象的位置设置为:

obj.x += 100.0f * dt; // to move 100 units every second

由于 dt 的总和在 1 秒内应始终为 1,因此无论帧速率如何,上述代码每秒都会将 x 递增 100。您应该对所有随时间变化的值执行此操作。这样,您的游戏在所有机器上以相同的速率进行(与帧速率无关),而不是取决于计算机处理逻辑的速率(取决于帧速率)。如果帧速率开始下降,这也很有用 - 游戏不会突然开始以慢动作运行,它会保持相同的速度,只是渲染频率降低。

于 2010-03-03T16:46:59.367 回答
1

关于如何以“正确”的方式进行操作,您有很多答案,但是您正在使用 GLUT,并且 GLUT 有时会为了简单性和保持平台独立性而牺牲“正确”的方式。GLUT方式是用glutTimerFunc()注册一个定时器回调函数。

static void timerCallback (int value)
{
    // Calculate the deltas

    glutPostRedisplay(); // Have GLUT call your display function
    glutTimerFunc(elapsedMilliseconds, timerCallback, value);
}

如果将 elapsedMilliseconds 设置为 40,则每秒调用此函数的次数略少于 25 次。稍微少一点将取决于计算机处理您的增量计算代码需要多长时间。如果您保持该代码简单,那么您的动画将在所有系统上以相同的速度运行,只要每个系统可以在不到 40 毫秒的时间内处理显示功能。为了获得更大的灵活性,您可以在运行时使用命令行选项或通过向界面添加控件来调整帧速率。

glutTimerFunc(elapsedMilliseconds, timerCallback, value);您可以通过调用初始化过程来启动计时器循环。

于 2010-03-04T14:23:58.733 回答
0

这是一个非常难的问题。

您需要自己做的第一件事是,您真的希望您的应用程序真正以相同的速度运行还是只是看起来以相同的速度运行?99% 的时间你只希望它看起来以相同的速度运行。

现在有两个问题:加速你的应用程序或减慢它。

加速你的应用程序真的很难,因为这需要动态 LOD 之类的东西来调整到当前速度。这意味着所有事物的细节层次,而不仅仅是图形。

减慢你的应用程序是相当容易的。你有两个选择睡觉或“忙着等待”。它基本上取决于您的模拟目标帧速率。如果您的模拟时间超过 50 毫秒,您可以睡觉。问题是,在睡眠时,您依赖于进程调度程序,它在平均系统上以 10 毫秒的粒度工作。

在游戏中忙着等待并不是一个坏主意。您所做的是更新您的模拟并渲染您的帧,然后为下一帧使用时间累加器。在没有模拟的情况下渲染帧时,您可以插入状态以获得平滑的动画。可以在http://gafferongames.com/game-physics/fix-your-timestep/找到一篇关于该主题的非常棒的文章。

于 2010-03-04T13:16:30.363 回答
0

我是一名游戏程序员,已经做过很多次了。

大多数游戏以固定的时间增量运行 AI,例如 60hz。此外,大多数都同步到显示器刷新以避免屏幕撕裂,因此即使机器非常快并且可以达到 1000 fps,最大速率也将是 60。因此,如果机器速度很慢并且以 20 fps 的速度运行,那么它会在每次渲染时调用 update ai 函数 3 次。这样做可以解决小值的舍入误差问题,并且由于 AI 更新率与机器速度分离(在线多人游戏所必需),因此还使 AI 在多台机器上具有确定性。

于 2010-03-03T18:20:44.837 回答