为OpenGL(ES)创建一个稳定的(帧率稳定的)游戏引擎

时间:2009-03-13 00:59:59

标签: opengl-es

我在为OpenGL应用程序创建可靠的游戏引擎时遇到了麻烦。这是一个由几个精灵组成的游戏。

我创建的对象基本上都是我的所有精灵。另一个名为“gameEngine”的对象每隔一秒钟(一个计时器)循环一组计算,从而产生新的游戏变量。之后,精灵对象现在知道他们的绘图数据。

问题是,在收集完所有绘图数据后,绘图应该恰好在恰当的时刻进行,从而产生稳定的动画。根据当前场景的复杂程度,游戏计算需要不确定的时间。因此,实际绘图发生在不同的时刻。我该如何防止这种情况发生?

为了澄清,我的方法类似于:

// Every something of a second I call tick
-(void)tick
{
  drawingData = gameEngine();
  draw(drawingData); 
}

必须有一个最好的做法来构建我不知道的游戏引擎吗?

4 个答案:

答案 0 :(得分:6)

游戏循环有很多种,但更好的游戏循环将动画与绘图或更经典的术语模型和视图分开。基本上你想构建一个游戏模型,你可以建立时间的流逝并更新模型(物理帧速率),然后在连续的时刻独立渲染模型的快照(渲染帧速率)。

以下是一些文章,详细解释了游戏循环的一些变化及其优缺点。还有源代码。我希望它有所帮助。

Fix Your Timestep!deWiTTERS Game Loop Article

答案 1 :(得分:1)

这真的不是关于OpenGL;它更多地与您正在使用的操作系统或系统API(即Carbon / Cocoa / Win32)有关。但真正非常简单的情况就是这个(伪代码):

checkTime = currentTime
while not exitCondition
    if currentTime - checkTime >= 50 milliseconds
        checkTime = checkTime + 50 milliseconds
        updateScene
    else drawScene

您正在尽可能多地绘图,但仅每50毫秒(即每秒20次)进行更新。显然有很多很多的其他事情需要考虑,尤其是当你落后时你所做的事情(跳帧)。

进入OpenGL的最佳位置是Nehe的课程:

http://nehe.gamedev.net/lesson.asp?index=01

他们有点过时了,但是每节课底部的示例代码是一个很好的起点,它可以用多种语言和许多操作系统提供。

答案 2 :(得分:0)

它在某种程度上依赖于平台,但通常可以使用的一种基本方法是在渲染循环中使用高性能计时器,并使用它来帮助您在帧之间休眠以获得稳定,稳定的帧速率。

您可以为帧的渲染计时,然后按照数量进行睡眠以保持稳定的帧速率。

但是,如果您的平台无法跟上您想要达到的帧率,您需要开始寻找优化游戏引擎的方法。这只会减慢速度,使它们保持一致和平滑 - 而不是加快速度。

---澄清----

-(void)tick
{
    time = now() // from high perf. timer
    drawingData = gameEngine();

newTime = now()
// pause for the time required to make the framerate consistent
Sleep(totalTimeForTickToBeStable - newTime + time)
draw(drawingData); 

}

答案 3 :(得分:0)

最好的解决方案是多线程应用程序 - 一个线程将绘图数据计算到缓冲区中,一个线程渲染数据。

如果您正在寻找一个真正简单的解决方案,只需颠倒计算和渲染的顺序。

void Initialize()
{    
   DrawingData = GameEngine();
}

void Tick()
{
   Draw(DrawingData);
   DrawingData = GameEngine();
}

您计算应用程序启动时的第一个绘图数据,当计时器触发时,您只需绘制它。之后,您将一直有时间到下一个计时器事件,再次计算绘图数据。

但总的来说,以可变帧速率渲染可能是一个更好的解决方案 - 如果机器要降低所需的帧速率并且在快速机器上提供高帧率,则可以避免出现问题。

void Main()
{
   StartTime = Now();

   while (!ExitRequested)
   {     
      DrawingData = GameEngine(Now() - StartTime);
      Draw(DrawingData);
   }
}

尽可能快地渲染帧 - 不是每帧之间有固定的间隔,而是应用程序运行的实时。这意味着每帧不要超过20毫秒,只需将它们移动到当前运行时间所在的位置。