1.什么是游戏引擎?
考虑你喜欢的几个不同的游戏,尝试设想一下它们的内部是如何设计的。更重要的是,看一下是否能够找到适用于所有游戏的任何公共设计元素。例如,所有游戏都有背景、片头屏幕、地形图和背景音乐,是不是?如果是,那么它们很可能是围绕游戏引擎的概念设计的。当你计划创建多个游戏,并且不希望每次都做重复的工作时,游戏引擎就特别有用。
游戏引擎对于Windows游戏的另一个重要好处在于,它允许隐藏针对Windows而与游戏无关的繁杂代码。游戏引擎很好地组织了游戏代码,这样常规的应用程序任务就与游戏特有的任务分离开来。它为游戏开发人员带来的好处就是可以向游戏引擎中添加能够在以后的所有游戏中重用的特性。此外,使用游戏引擎还允许简化游戏的代码,将注意力放在最重要的游戏代码上。在习惯了使用游戏引擎之后,你就会想,其他还有什么方法来开发游戏?事实上,大多数商业游戏开发人员都有自己定制的游戏引擎,这是他们多年来在学习大多数游戏所需的公共特性的过程中开发出来的。在设计和开发技术要求更高的游戏时,你自己的游戏引擎可能会在本书的游戏引擎基础之上进行改进和扩充。
2.考虑游戏引擎的作用
游戏引擎负责处理各种琐碎事务:组建游戏、确保它正确运行以及关闭它。虽然这些任务确实是任何程序都需要的,但是初始化、运行以及在游戏结束后进行清理等工作的某些方面确实是游戏所特有的。因此,重要的是,游戏引擎能够满足游戏的独特需求,并帮助使围绕引擎开发游戏的过程尽可能简单和直接。有了一个设计优良的游戏引擎,你就会发现,开发游戏所需要的代码比不使用游戏引擎时少得多。其思想是一次性开发某些核心游戏程序,将其粘贴在游戏引擎中,然后只有在绝对必要时才再次处理它们。例如,在编写加载图像并在屏幕上绘制它得代码之后,就没有什么理由要重新编写这种代码了。加载和绘制图像是所有游戏引擎都需要的一个基本功能。
TIPS:在时间和资源许可时,可以选择优化游戏引擎内部的某些算法,以帮助使其更高效地运行。总地来说,首要目标是实现一个能够正确运行的游戏功能,然后有时间的话再考虑优化它。
2.2.1将游戏分解为事件
每一个Windows程序都可以分解为事件,即在程序运行时发生的事情,例如单击鼠标和更改窗口大小。正如Windows程序包含必须处理的事件一样,游戏也有其在开发过程中必须考虑的一组特有时间。可以将游戏的初始化过程视为一个事件,它负责加载游戏的图形和声音、清空游戏区域、将得分归零等。类似地,游戏中也有用户输入,意味着单击鼠标和按键操作是游戏必须自己处理的时间。此外还要牢记一点,在Windows中,可以最小化游戏或者将其置于后台,意味着可能希望暂停游戏。可以使用两个事件来表示这个激活和停用过程。
TIPS:许多商业Windows游戏都只能以全屏模式运行,这意味着它们不能与其他正在运行的Windows应用程序并列显示在屏幕上。即使如此,在技术上这些游戏仍然是与其他程序同时运行的,因此必须能够在另一个应用程序激活时暂停它们。
许多事件当然都可以包括在游戏引擎之中,但是下面这些事件是适用于任何游戏的部分核心事件:
初始化,
启动,
结束,
激活,
停用,
绘制,
循环。
初始化时间在一开始运行游戏发生,这时游戏将执行重要的初始设置任务,包括创建游戏引擎本身。启动和结束事件对应于游戏的开始和结束,这时很适合执行与特定的游戏会话相关联的初始化和清理任务。在最小化游戏或者将其发送到后台,然后恢复时,就将发生激活和停用事件。当游戏需要绘制本身时,将其发送绘制事件,类似于Windows WM_PAINT消息。最后,循环事件使游戏执行一个单独的游戏周期,它非常重要,随后读者就将了解到这一点。
2.2.2建立游戏的计时机制
如果从来都没有从编程的角度看过游戏,那么你可能会对游戏中实现所有移动和动画的方式感到吃惊。除了及其简单的纸牌游戏之外,几乎每一个游戏都依赖于某种计时机制,使游戏将其执行分解为帧或者周期。游戏的一个周期是一个时间片,通常对应于游戏图形和数据的一个单独的快照。如果将游戏视为在VCR或者DVD播放机上播放的电影,那么按pause键允许查看一个独立的周期。在电影中前进一帧就好像是进入了游戏的下一个周期。在任何给定的周期中,有希望城了更新其图形、执行其他任何与角色和对象如何移动及彼此交互的计算和处理等工作。
理解游戏周期的重要性的一个好方法是举一个实际的游戏作为例子。以space invaders游戏为例,要创建船以及几排外来入侵者。各个对象都有一个初始的位置和速度。如果space invaders没有计时机制或者游戏周期,那么这个游戏将永远停在其初始状态,就好像在游戏开始时按下了一个永久的pause按钮一样。不过,我们知道情况并非如此,因为在游戏开始时,敌人正缓慢地经过屏幕。如果一个周期一个周期地观看space invaders,则会注意到敌人在每一个周期中只是移动一点点。这还少因为在一段给定的时间内会发生许多个周期,产生平滑移动的效果。游戏周期的作用是更新游戏中所有对象的状态,然后再通过更新在屏幕上显示的图形来反映这些变化。从大多数游戏中的事物在视觉上的变化速度来判断,你能猜出发生游戏周期的频率吗?即使对于最慢的游戏,这个频率也不低于12周期每秒,这正好是人眼以为看到的事物在移动而不是看到一系列变化图像的最低频率。作一个比较,电视每秒显示30副不同的图像,而电影每秒是显示24副图像。
TIPS:游戏中一个单独的图形屏幕称为一帧。因为在每一个游戏周期中都要绘制一屏幕新的图形,所以游戏的速度经常是用每秒的帧数来衡量的。因为我们讨论的中心是周期而不是帧,所以我以每秒的周期数来表示游戏速度。不过,每秒的周期数、每秒的帧数以及每秒的图像数实际上都是一个意思。
游戏在指定时间内运行的周期越多,看起来运行得 就越平滑。举一个极端的例子,比较一下演示文稿和电影的平滑度。演示文稿是从一副静止的图像突然转换为另一幅静止的图像,不存在任何过度,也没有平滑移动的感觉:而电影则呈现出流畅的动作,就仿佛在现实中经历一般。类似地,每秒钟只有较少周期的游戏看上去是断断续续的,而每秒钟较多的周期数会使游戏更加平滑。每秒钟较多的周期数还允许灵活地加快或者放慢游戏,从而达到一个理想的速度。
在知道了更多的周期产生更平滑的图形并提供更好的灵活性之后,读者可能会认为能够每秒钟的周期数设置得很高就行。与现实中的大多数情况一样,对于游戏周期和游戏效率来说,也存在一个权衡考虑。问题在于,在游戏的各个中期中发生的处理量经常是相当大的,这意味着要想每秒钟执行多个周期,计算机的处理器和显卡都必须能够跟上这种速度。即使对于目前流行的速度极快的计算机来说,大多数计算机执行游戏处理的速度也是有实际限制的。事实上,大多数游戏设置都在15~20周期每秒的范围内,最快的速度可能达到30周期每秒,比电影的速度还快。除了极少数的一些情况外,应该力求达到的最低速度设置为12周期每秒。
TIPS:商业3D游戏是将当前可用的计算机硬件的性能发挥到极致。现代3D游戏的每秒周期数是用来衡量这个游戏是否过于加重计算机的处理能力负担的最常见标准。在理想情况下,可以将游戏设计为包括非常精致而漂亮的图形,而不用当心游戏是否会使用户系统突然停止运行。在显示情况下,游戏设计者总是很谨慎地使用游戏看上去惊人的效果,同时保持适当的帧频(理想值为30帧/秒或者更大)。
在理解了如何用周期来说明游戏的计时机制之后,读者可能就会明白为什么循环是一种游戏事件。它得工作原理是这样的:一开始运行游戏时,使用游戏速度(每秒的周期数)初始化引擎。加入使用12周期每秒,那么游戏引擎负责设置和管理一个计时器,它每秒出发12个循环事件。游戏代码接收这些循环消息并处理它们---更新游戏中的对象并重新绘制游戏屏幕。可以将一个循环事件视为一个周而复始工作的叫醒入睡者的报警器,只不过在这种情况下是每秒响12次。很显然,游戏不会有太多的睡眠时间!
TIPS:说到睡眠,游戏引擎的另一个作用是每当游戏不再是活动窗口就使其休眠。实际上,使游戏休眠仅仅意味着游戏引擎停止发送循环消息,因为没有发送任何循环性消息,所以游戏实际上就暂停了。