Skip to content

Latest commit

 

History

History
146 lines (80 loc) · 13.8 KB

01-Introduction.md

File metadata and controls

146 lines (80 loc) · 13.8 KB

序言

在五年级的时候,我和我的小伙伴们被获准使用一个容放着一些非常破旧的 TRS-80s (译者注:见维基百科TRS-80s) 的废弃教室。为了激励我们,一个老师找到了一些简单的 BASIC 程序的打印输出让我们鼓捣玩耍。

电脑上的音频盒式磁带驱动器当时是坏掉的,所以每次我们想要运行一些代码的时候,我们不得不仔细的从头开始键入。这使得我们更喜欢那些只有几行代码的程序:

10 PRINT "BOBBY IS RADICAL!!!"
20 GOTO 10

注解

如果计算机打印足够多的次数,或许它会神奇的变成现实哦。(译者注:这里指的是计算机反复打印第10行代码的语句BOBBY IS RADICAL!!!,作者开玩笑的说会变成现实。)

即便如此,整个过程还是比较艰辛。我们不懂得如何去编程,所以一个小的语法错误便让我们感到很费解。如果程序不工作了,通常都会这样,我们便会重新开始。

在这些书页的后面,我们遇到了一个真正的怪物:一个程序,它密密麻麻的代码占去了好几页。我们过了一会终于鼓足勇气来尝试它,但是它实在让人无法接受-列表的标题是“隧道与巨人”("Tunnels and Trolls")。我们不知道它是做什么的,但是听起来像是个游戏,还有什么比你自己编写一款电脑游戏更酷么?

我们从来没有让它运行起来过,一年后,我们搬出了那个教室。(很久之后,我才真正了解了一点BASIC,我意识到它只是一个为桌面游戏使用的字符产生器,本身并不是游戏。)但木已成舟,从那之后,我立志要成为一个游戏开发者。

在我十几岁时,我的家人搞了一台装有 QuickBASIC 的 Macintosh,之后又装了 THINK C。我几乎整个暑假都在 hack games。自学是缓慢而痛苦的。我学到了一些东西并顺手会运行起来-或许是个地图又或者是个小的猜谜游戏-但是随着程序的扩大,它越来越难了。

注解

我的许多夏天都是在路易斯安那州南部的沼泽中捕蛇和乌龟来渡过的。如果户外不是这样酷热,很有可能,这将是一个爬虫学的书,而不是编程书。

起初,让一些东西显示在屏幕上对我来说是个挑战。后来,我想搞清楚如何写出更大点的程序。除了阅读一些关于“如何用C++编程”的书籍,我开始试图寻找一些关于如何组织程序的书籍。

又过了几年,一个朋友给了我一本书:《设计模式:可复用面向对象软件的基础》。终于来了!这就是我从青少年开始便一直寻找的那本书!在一次会面中,我从头到尾读了一遍。我之前仍然在为我自己写的程序挣扎犯愁,但是看到别人也如此挣扎并提出了解决方案,我便解脱了。我感觉我终于有了一些武器用来挥舞而不再是赤手空拳了。

注解

这是我们第一次见面,5分钟自我介绍之后,我坐在他的沙发上,并在接下来的几个小时里,我在聚精会神的阅读,完全忽视了他。从那时起,我想我的社交应该至少要提高一点点了。

在2001年,我得到了我梦想中的工作: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)一节中覆盖了众多设计模式,但强调了他们是如何被应用到游戏开发中的。

相反,我觉得这本书也适用于非游戏软件。我也可以把这本书命名为 More Design Patterns,但我认为游戏制作例子更吸引人。难道你真的想要阅读的一本关于员工记录和银行账户例子的书么?

话虽这么说,这里介绍的模式是在其他软件中是有用的,我觉得他们是特别适合于软件开发,就像在游戏中经常遇到的挑战一样:

  • 时间和顺序往往是一个游戏的架构的核心部分。事情必须发生在正确的顺序和正确的时间。

  • 开发周期被高度压缩,一些程序员需要能够快速构建和迭代一组丰富的不同的行为,而不牵连到他人或者查遍整个代码库。

  • 所有这些行为被定义后,它便开始互动。怪物撕咬英雄,药水混合在一起,炸弹炸到敌人和朋友类似这样。这些交互必须被很好的完成,同时代码库需要保持干净不能纷乱无章犹如交织错乱的毛线球一样。

  • 最后,性能是游戏的关键。游戏开发者是在不断比赛着看谁能够充分利用平台的性能。游戏周期处理的不同可能意味着数以百万计销售的A级游戏或者掉帧以及愤怒的评论的区别。

如何阅读这本书

_游戏编程模式_分为三大部分。第一部分是序言和书的概括。这正是你现在阅读的章节以及[下一章节](01.1-Architecture, Performance, and Games.md)。

第二部分,再探设计模式,回顾了 Gang of Four 中的一些设计模式。在每个章节中,我会提到我对该模式的认识,以及我觉得如何将该模式运用到游戏中。

最后部分是这本书的重头戏。这部分代表了我认为十分有用的13种设计模式。它们分为四类:序列模式,行为模式,解耦模式,优化模式。

这些模式使用一致的文本组织结构来讲述,以便你将该书作为参考并能快速找到你所需要的内容:

  • 意图(Intent)部分提供了该模式旨在解决的问题的快照描述。这样你很容易浏览全书快速找到你想要的模式来帮助你解决遇到的难题。

  • 动机(Motivation)部分描述了一个示例,该示例存在问题,我们将要对之采用设计模式。不同于具体的算法,模式通常是无形的,除非适用于一些特定的问题。教授一个设计模式却不提供示例就像教授烘培却没有面团一样。这个部分提供面团,之后的部分将会教你如何烘培。

  • 模式(Pattern)部分会提炼出前面示例中的模式本质。如果你想了解该模式的书面描述,就是这部分了。如果你已经熟悉了,这部分也是一个很好的复习,确保你没有忘记该模式。

  • 到目前为止,该模式只是就一个单一的例子来解释的。但你怎么该模式是否适用于你的问题呢?使用情境(When to Use It)就模式使用的情境以及何时避免使用会提供一些指引。使用须知(Keep in Mind)部分会指出使用该模式时面临的后果和风险。

  • 如果像我一样,需要借助具体的实例才能真正的理解,那么__示例__(Sample Code)正满足你的需要。示例会一步步实现模式,所以你可以清楚的看到模式是如何工作的。

  • 模式和单一的算法不同,因为模式是开放式的。每次使用模式的时候,你实现的方式有可能会不同。接下来__设计决策__(Design Decisions)部分,会探讨这个问题,并告诉你在应用模式时要考虑的不同因素。

  • 结束部分,参考(See Also)部分会告诉你该模式和其他模式的关联并指出使用该模式的一些真实世界中的开源代码。

关于示例代码

这本书中的示例代码用 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)