2009-05-28 48 views
4

我使用Visual C++ 2008 Express和Ogre3D sdk编写游戏。异步屏幕更新为游戏玩法逻辑,C++

我的核心游戏逻辑被设计为以100次/秒的速度运行。为了简单起见,我会说这是一种名为'gamelogic()'的方法。这不是基于时间的,这意味着如果我想将游戏时间提前1秒,我必须将“gamelogic()”调用100次。 'gamelogic()'与游戏的屏幕渲染相比是轻量级的。

Ogre有一个“侦听器”逻辑,告知您的代码何时绘制框架以及何时完成绘制框架。如果我在帧渲染之前调用“gamelogic()”,那么游戏将受到屏幕渲染速度的很大影响,屏幕渲染速度可能从5fps到120fps不等。

想到的最简单的解决方法是:计算自去年渲染的帧中的时间和呼叫“gamelogic()”下一帧之前很多次:100 * timeElapsedInSeconds

不过,我pressume了“正确“的方式是使用多线程;有一个单独的线程运行'gamelogic()'100次/秒。

问题是,我该如何做到这一点?当两个独立的线程发生冲突时,可以做些什么:gamelogic改变屏幕内容(3d对象坐标),同时Ogre同时呈现屏幕。

许多在此先感谢。

回答

6

如果这是您的第一个游戏应用程序,使用多线程来实现您的结果可能比您应该在第一场比赛中真正应对更多的工作。在不同线程中同步游戏循环和渲染循环并不是一个容易解决的问题。

正如您正确指出的那样,渲染时间会极大地影响游戏的“速度”。我建议你不要让你的游戏逻辑依赖于设定的时间片(即1/100秒)。使其依赖于当前的帧时间(好吧,最后一帧时间,因为你不知道你的当前帧需要多长时间来渲染)。

通常我会写类似下面(我写的是大大简化):

float Frametime = 1.0f/30.0f; 
while(1) { 
    game_loop(Frametime);  // maniuplate objects, etc. 
    render_loop();    // render the frame 
    calculate_new_frametime(); 
} 

哪里FRAMETIME是calculcated帧时间,当前帧了。当你处理你的游戏循环时,你正在使用前一帧的帧时间(因此将初始值设置为合理的值,如1/30或1/15秒)。在以前的frametime上运行它足以让您获得所需的结果。使用该时间框架运行你的游戏循环,然后渲染你的东西。您可能必须更改游戏循环中的逻辑,以避免假定固定的时间间隔,但通常这些修复很容易。

异步游戏/渲染循环可能是你最终需要的东西,但这是一个难以解决的问题。它涉及到拍摄对象及其相关数据的快照,将这些快照放入缓冲区,然后将缓冲区传递给渲染引擎。该内存缓冲区必须在关键部分正确分区,以避免在渲染循环正在读取时将游戏循环写入它。在传递到渲染循环之前,您必须小心确保将所有相关数据复制到缓冲区中。此外,您必须编写逻辑来停止游戏或渲染循环,同时等待其中一个或另一个完成。

这种复杂性也是为什么我建议在多个串行的方式先写它(除非你有经验,你可能)。原因在于,首先使用“简单”方法将迫使您了解代码的工作方式,渲染引擎的工作方式,渲染引擎需要的数据类型等。多线程知识在复杂游戏开发中非常明确这些天,但知道如何做得好,需要深入了解游戏系统如何相互作用。

+1

游戏从固定渲染率假设,以追踪框倍切换前一段时间 - 他们习惯了依赖知道处理器在8赫兹运行。当他们推出16Hz的机器时,他们包括一个'turbo按钮'将处理器从16Hz切换到8Hz,这样游戏仍然可以以正确的速度运行。有趣的事实。 – Kieveli 2009-05-28 14:21:46

0

双缓冲的渲染能力的对象是你可以探索的途径。意思是,渲染组件正在使用1个缓冲区,当所有游戏动作已经更新了第二缓冲区中的相关对象时,该缓冲区将被更新。

但我个人不喜欢它,我(和具有的频率)使用马克的做法。

1

这里没有一大堆的好处到你的核心游戏逻辑运行速度比玩家可以做出回应。关于唯一一次真正有用的是物理模拟,在快速,固定的时间步长运行可以使模拟的行为更加一致。

除此之外,只是每帧更新您的游戏循环一次,并通过在可变的时间增量,而不是依赖于固定的。您从多线程中获得的好处与成本相比是微不足道的,特别是如果这是您的第一场比赛。