关于在任何计算机上以相同速度运行程序的问题

时间:2010-03-03 15:51:16

标签: c++ opengl glut

我制作了一个程序(在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 ();

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

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

编辑:我刚才注意到,在我想的方式中,end-start最终应该是所有绘图完成后和移动更新之前的时间,因为idle()会尽快调用display()结束了,所以在这里没有考虑的唯一时间是计算机完成所有运动的时间吗? (这应该几乎没有?)

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

提前致谢。

7 个答案:

答案 0 :(得分:4)

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

我会设置一个计时器,并将我的所有动作基于明确和特定的定时事件。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

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

在内部,您可能实际上实现了小的固定时间子步骤,因为尝试使所有内容在可变时间步骤上正常工作并不像x + = v * dt那么简单。

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

答案 3 :(得分:1)

有一个perfect article游戏循环可以为您提供所需的所有信息。

答案 4 :(得分: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次。稍微减少将取决于计算机处理delta计算代码所需的时间。如果你保持代码简单,你的动画将在所有系统上运行相同的速度,只要每个系统可以在不到40毫秒的时间内处理显示功能。为了获得更大的灵活性,您可以使用命令行选项或通过向界面添加控件来在运行时调整帧速率。

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

答案 5 :(得分:0)

我是一名游戏程序员并且多次这样做过。

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

答案 6 :(得分:0)

这是一个非常难的问题。

你需要首先想要的是,你真的希望你的应用程序真正以相同的速度运行,或者只是看起来运行速度相同吗? 99%的时间你只希望它看起来运行速度相同。

现在有两个问题:加快​​应用程序速度或减慢速度。

加速你的应用程序非常困难,因为这需要像动态LOD那样调整当前速度。这意味着所有东西都有LOD,而不仅仅是图形。

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

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