在五年级的时候,我和我的小伙伴们被获准使用一个容放着一些非常破旧的 TRS-80s (译者注:见维基百科TRS-80s) 的废弃教室。为了激励我们,一个老师找到了一些简单的 BASIC 程序的打印输出让我们鼓捣玩耍。
电脑上的音频盒式磁带驱动器当时是坏掉的,所以每次我们想要运行一些代码的时候,我们不得不仔细的从头开始键入。这使得我们更喜欢那些只有几行代码的程序:
10 PRINT "BOBBY IS RADICAL!!!"
20 GOTO 10
注解
如果计算机打印足够多的次数,或许它会神奇的变成现实哦。(译者注:这里指的是计算机反复打印第10行代码的语句
BOBBY IS RADICAL!!!
,作者开玩笑的说会变成现实。)
即便如此,整个过程还是比较艰辛。我们不懂得如何去编程,所以一个小的语法错误便让我们感到很费解。程序出毛病是家常便饭,而那是我们只能重头再来。
在有了这些小程序的经验积累之后,我们遇到了个大BOSS:一个代码密密麻麻占去好几页纸的程序。我们光是鼓起勇气决定去尝试它就花了不少时间,光是它的标题“隧道与巨人”("Tunnels and Trolls")就令人捉摸不透。这听起来像是个游戏,而还有什么事比亲手编写一款电脑游戏更酷?
我们从没让它实际运行起来过。一年后,我们搬出了那个教室。(后来随着我更多地接触BASIC,才意识到它只是一个为桌面游戏使用的角色生成器,而并非整个游戏。)但木已成舟,从那之后,我立志要成为一个游戏开发者。
在我十几岁时,我的家人搞了一台装有 QuickBASIC 的 Macintosh,之后又装了 THINK C。我几乎整个暑假都在那上面倒腾游戏。自学是缓慢而痛苦的。我希望能让程序轻松地跑一些功能-一张地图或者是个小的猜谜游戏-但是随着程序的扩大,这越来越难了。
注解
我的许多夏天都是在路易斯安那州南部的沼泽中捕蛇和乌龟来渡过的。如果户外不是这样酷热,很有可能,这将是一本爬虫学的书,而不是编程书。
起初,我的挑战在于让程序跑起来。后来,我开始思考如何让程序做一些超越我脑袋所想的工作。除了阅读一些关于“如何用C++编程”的书籍,我开始试图寻找一些关于如何组织程序的书籍。
又过了几年,一个朋友给了我一本书:《设计模式:可复用面向对象软件的基础》。终于来了!这就是我从青少年开始便一直寻找的那本书!我们刚碰面,我就把书从头到尾读了一遍。我之前仍然在为我自己写的程序挣扎犯愁,但是看到别人也如此挣扎并提出了解决方案,我便解脱了。我感觉我终于有了一些武器用来挥舞而不再是赤手空拳了。
注解
这是我们第一次见面,5分钟自我介绍之后,我坐在他的沙发上,并在接下来的几个小时里,我聚精会神地阅读而完全忽视了他。我感觉那时候自己的社交能力还是稍有那么一丁点提升的。
在2001年,我得到了我梦想中的工作:EA(Electronic Arts) 的软件工程师。我迫不及待的想看下真正的游戏,以及工程师是如何组织它们的。像 Madden Football 这样的大型游戏到底是一个什么样的架构?他们是怎么让一套代码库在不同平台上运行的?
破解开放的源码是一个震撼人心和令人惊奇的体验。图形、人工智能、动画和视觉效果等各个方面的代码都十分出众。我们公司有人懂得如何榨取CPU的每一个周期并得以善用。甚至一些我认为不可能的东西,这些家伙一个早上就能搞定。
但这种优秀代码的结构往往是事后想出来的。他们太专注于功能以至于忽视了组织架构。模块之间耦合很严重。只要是有作为的新功能都会被扔进代码库里。我的幻想破灭了,在我看来,恐怕很多程序员,从没翻过_设计模式_,不曾了解单例模式。
当然,实际并非想象的那么糟。我曾设想游戏程序员们坐在放满白板的象牙塔中,从头到尾的几周时间里都在想当然地讨论代码架构细节。实际上,我所见到的代码是出自那些被上司催着进度的人之手。他们竭尽了全力,而且,我逐渐意识到,他们竭尽全力的结果往往是很棒的。我越深入这些代码,便越是这么觉得。
不幸的是,“隐藏”一词恰恰反映了这样的情况:宝藏埋在代码深处,而许多人只从地表踏过。我看到同事在努力重塑更好的解决方案时,他们所寻求的办法正藏在他们脚下的代码库之中。
这样的问题正是这本书所关注的。我挖掘并打磨出自己在游戏中所发现的最好的设计模式,在此一一呈现给大家,以便我们将时间节省下来发现新大陆,而不是重新造轮子。
目前市面已经有数十多本游戏编程的书籍。为什么还要再写一本?
我见过的大多数游戏编程书籍无非下列两类:
-
关于特定领域的书籍。这些针对性较强的书籍为你的游戏开发打开一个独特而深刻的视角。他们会教你3D图形,实时渲染,物理模拟,人工智能,或音频处理。这些是多数游戏程序员在自己的职业生涯中所专注的领域。
-
关于整个游戏引擎的书籍。相反,这些书尝试涵盖整个游戏引擎的各部分。它们被组织起来形成一个完整的引擎以适用于一些特定类型的游戏,通常是3D第一人称射击游戏。
我喜欢这两类书,但我觉得它们仍留有一些空白。特定领域的书很少会写你的代码块如何与游戏的其他部分交互。你可能擅长物理和渲染(译者注:这里指的是在某个领域特别擅长的人),是你知道如何优雅的将它们拼合起来?
第二类书籍写到了这些,但我通常发现这类书都太单一,太泛泛而谈。特别是随着移动和休闲游戏的兴起,我们正处在充斥着大量不同类型游戏的时代。我们不再只是克隆 Quake(译者注:雷神之锤,第一个真3D实时演算的FPS游戏)了。当你的游戏不适合这个模型时,这类阐述单个引擎的书籍就不再合适了。
相反,这里我想要做的,更倾向于“引导”。在这本书中,每个章节都是一个独立的思想,而你可以将它应用到你的代码里。藉此,你可以混用它们以令其在你制作的游戏中发挥最好的效果。
注解
这种“向导”风格的另外一个例子,就是广受大家喜爱的《游戏编程精粹》系列。
任何名字中带有“模式”的编程书籍都和经典图书《设计模式:可复用面向对象软件的基础》脱不了干系。这本书由 Erich Gamma,Richard Helm,Ralph Johnson 和 John Vlissides 完成。(俗称“Gang of Four”--四人组)
注解
设计模式一书本身也源自前人的灵感。使用模式语言来描述开放式解决问题的想法来自《A Pattern Language》,由 Christopher Alexander(以及Sarah Ishikawa,Murray Silverstein)完成。
他们的书是关于架构(就像真正的建筑结构有着建筑和围墙之类的东西),但他们希望他人会使用相同的结构来描述在其他领域的解决方案。设计模式(Design Patterns)是 Gang of Four 在软件领域的一个尝试。
本书以“游戏编程模式”命名,并不是说 Gang of Four 的书不适用于游戏。恰恰相反,在[再探设计模式](02-Design Patterns Revisited.md)一节中覆盖众多来自GoF著作的设计模式,同时强调了在游戏开发中的运用。
从另一面说,我觉得这本书也适用于非游戏软件。我也可以把这本书命名为 More Design Patterns,但我认为游戏制作例子更吸引人。难道你真的想要阅读的一本关于员工记录和银行账户例子的书么?
话虽这么说,这里介绍的模式在其他软件中是有用的,我觉得他们是特别适合于软件开发,就像在游戏中经常遇到的挑战一样:
-
时间和序列化往往是一个游戏的架构的核心部分。事情必须依照正确的顺序和正确的时间发生。
-
开发周期被高度压缩,程序员们需要能够快速构建和迭代一组丰富且相异的行为,同时不牵涉到他人或者弄乱代码库。
-
所有这些行为被定义后,游戏便开始互动。怪物撕咬英雄,药水混合在一起,炸弹炸到敌人和朋友...诸如此类。这些交互必须很好地进行下去,同时代码库需要保持干净不能纷乱无章得像个交织错乱的毛线球。
-
最后,性能是游戏的关键。游戏开发者们总在不断比赛着看谁能够充分利用平台的性能。游戏周期处理的不同可能意味着产品是成为数以百万计销售的A级游戏,或者满是掉帧且贴满愤怒评论的废铁。
_游戏编程模式_分为三大部分。第一部分是序言和书的概括。这正是你现在阅读的章节以及[下一章节](01.1-Architecture, Performance, and Games.md)。
第二部分,再探设计模式,回顾了 Gang of Four 中的一些设计模式。在每个章节中,我会提及自己对该模式的认识,及将该模式运用到游戏中的方法。
最后部分是这本书的重头戏。这部分代表了我认为十分有用的13种设计模式。它们分为四类:序列模式,行为模式,解耦模式,优化模式。
这些模式使用一致的文本组织结构来讲述,以便你将该书作为参考并能快速找到你所需要的内容:
-
目的 部分简述了此模式旨在解决的问题。这样你很容易根据自己遇到的问题来快速确定该用哪个模式。
-
动机 部分描述了一个示例、该示例存在问题、我们将要对之采用设计模式。不同于具体的算法,模式通常是无形的,除非针对一些特定的问题。学设计模式离不开示例正如学烘培离不开面团一样。这个部分提供面团,之后的部分将会教你如何烘培。
-
模式 部分会提炼出前面示例中的模式本质。如果你想了解该模式的书面描述,就是这部分了。如果你已经熟悉了,这部分也是一个很好的复习,确保你没有忘记该模式。
-
到目前为止,该模式只是就一个单一的例子来解释的。但你怎么该模式是否适用于你的问题呢?使用情境 针对模式使用的情境以及何时避免使用它提供一些指引。使用须知 部分会指出使用该模式时面临的后果和风险。
-
如果像我一样,需要借助具体的实例才能真正的理解,那么__示例__ 正满足你的需要。示例会一步步实现模式,所以你可以清楚的看到模式是如何工作的。
-
模式和单一的算法不同,因为模式是开放式的。每次使用模式的时候,你实现的方式有可能会不同。接下来__设计决策__ 部分,会探讨这个问题,并告诉你在应用模式时要考虑的不同因素。
-
结束部分,参考 部分会告诉你该模式和其他模式的关联并指出使用该模式的一些真实世界中的开源代码。
这本书中的示例代码用 C++ 编写,但是这并不意味着这些模式仅在该语言中有用或者说 C++ 比其他语言要好。几乎所有的语言都适用,虽然有些模式确实倾向于面向对象语言。
我选择 C++ 有几个原因。首先,它是商业游戏中最流行的语言,是该行业的通用语言。 另外,C++ 基于 C 的语法也是 Java,C#,JavaScript和许多其他语言的基础。即使你不懂 C++,也没有关系,你可以很轻松的明白示例代码的含义。
这本书的目的,不是教你学习 C++。示例会尽可能保持简单,但是这并不代表良好的 C++ 编码风格或使用就是这样。阅读代码时要理解代码所传达的思想,而不是代码本身的表达。
特别一提的是,示例代码没有采用“现代” C++ -- C++11 或更高版本风格。它没使用标准库并很少使用模板。这是“糟糕”的 C++ 代码,但我仍希望保留下来,这样会对那些从C,Objective-C,Java和其他语言转来的人们更加的友好。
为了避免浪费页面空间,你已经看到了,和模式不相关的代码,有时会在例子中省略,通常用省略号来表示省去的代码。
举个例子,有一个函数,它会处理一些工作,并且会返回一个值。被解释的模式是只关心返回值,不关心处理的工作。在这种情况下,示例代码看起来像这样:
bool update()
{
// Do work...
return isDone();
}
模式是软件开发中一个不断变化和扩展的部分。这本书从 Gang of Four 文献开始,并分享他们了解的软件设计模式,当书页发布之后过程仍然会继续。
你是这个过程的核心部分。只要你开发了你自己的模式并细化(或者反驳!)这本书中提到的模式,你就是在为软件社区贡献力量。如果你关于书中内容有任何建议,修正或者其他反馈,请与我联系。
=============================== 目录
[下一节](01.1-Architecture, Performance, and Games.md)