本书详细综述了应用在许多重要视频游戏编程中的算法和技术。书中采用了一种独立于平台和结构的方法,能协助开发几乎任何风格、语言和框架的游戏,并展现2D和3D图像、物理、人工智能、相机等工作的基本技术。书中的每个概念都是用C#、Java或 C++程序员直观明白的伪代码阐述的,并且作者已经改进和证实过这些伪代码。本书最后作者详细分析了两个完整的游戏,清楚展现了前面章节讲到的很多技术和算法。
腾讯专家倾情翻译,全面介绍游戏行业中会用到的算法和技术,专注于实际应用
推荐序
当瀚阳让我为他的译作作序的时候,我还是有些吃惊的。我并非业界名人,虽然在游戏行业摸爬滚打了十几年,但并没有多少建树,为了配得上译者所散发出的光芒,我多少也要发掘出自己的一些亮点。如果资历也算亮点的话,我倒是有些的。1993 年我有了自己的第一台电脑,那时的电脑还处于386 的时代,硬盘不过200MB,内存不过4MB,用着5 英寸的软驱,光驱还在萌芽状态。当时我一心想做游戏,玩着《Wolf3D》、《Doom》,仰望着id Soft的成就。2001 年我终于如愿进入了游戏行业,有幸赶上了西山居《月影传说》的后期开发。之后在三大游戏公司转了一圈,如今沉浮于手机游戏开发的大潮中。其间也曾参与了两款3D引擎的早期开发工作,其中的成果已融合在两三款早已上市的游戏当中。我参与程度最深,也算稍微有点名气的游戏就是《斗战神》了。
我和瀚阳相识缘于我们现在共同参与的这个项目,我是项目的第一个客户端程序员,瀚阳是第二个。当项目还只有我一个前台程序员的时候,我一个人要面对十几个美工产出的资源和四五个策划提出的需求,真是压力很大。瀚阳的加入仿佛给项目增加了第二台引擎,各种架构迅速完善起来,功能也越来越完整,项目顺利度过了Demo 期,得以立项。瀚阳在游戏开发方面涉猎广泛,精通多种语言,做过端游,写过手游,参与过3D 引擎开发。游戏开发之外瀚阳也有着广泛的兴趣,他的博客就是自己搭建的,跑在租用的服务器上,可以称得上是全栈程序员。游戏行业加班是出了名的,对于瀚阳能在繁忙的工作之余抽出时间来翻译这本书,我是十分佩服的,每一个程序员都不应该局限于自己所在的公司与工作,而应该在更广阔的空间拓展自己的职业生涯。
最后回到本书。如果你想进入游戏开发行业,或者对于游戏开发你已经入门但还缺乏一个全面的了解,本书可以作为不错的入门书籍。本书读起来不会那么累,能够使你快速了解游戏开发所涉及的众多领域,建立一个较为全面的认识。在此之后你可以针对感兴趣的方面购买学习更加深入的书籍。
腾讯互娱前台程序技术指导
陈鹏
译者序
我与本书的一些缘分
我自己是多年的玩家了。在中学时期就暗自下定决心,一定要做游戏。于是不顾反对,大学选择了游戏专业,后来通过一套类似XNA 的框架进行开发,在学习的过程中一边写游戏,一边扩展框架。从最初的使用DirectX 绘制2D 精灵开发俄罗斯方块,到写3D 骨骼蒙皮动画做3D 射击游戏,慢慢地学会了很多技术,比如AI、网络、物理、脚本等。这些知识是“成长”起来的,于是每学到一点新技术都可以往里面塞,逐渐地形成了自己系统的理解。
雕爷有一篇文章说的好,临摹是最好的学习方法。因为临摹不仅需要你拆解分析对象作为输入,还需要以自己的理解作为输出。这种带着主动思考的输入/输出,无形中就对临摹对象有了深刻的理解,这不是走马观花那种被动的学习效率能比拟的。这种经过充分思考的练习,最能够将知识“内化”,而只有站在前人的基础之上,创新才会比较靠谱。在我看来,本书的内容,属于手把手地对各种GamePlay 拆解,然后实现,让知识一点一点地成长起来。更加难得的是,因为作者从业界转向了教育界,所以本书不仅内容上系统全面,而且语言上简单清晰,让人易于理解。
兴趣是最好的老师,GamePlay 不像操作系统、渲染引擎、物理引擎那么“枯燥”,本书可以很轻松就读完。初学者完全可以从GamePlay 入手,在XNA 框架上实现书中的内容,然后在深入的过程中补全游戏开发中各个系统的知识。而有经验者也可以从本书中补全对游戏软件的系统理解,比如一开始作者就阐明了游戏程序的三要素:游戏时间、游戏对象、游戏循环,还有一些有意思的诀窍,比如用xyzzy 口诀记住叉乘运算,也有一些案例分析——《魔兽世界》的UI 插件系统,以及工作中的教训——《指环王》中音频引擎的设置。
除此之外,本书还提供了专业方向上的参考资料,让读者在感兴趣的话题上深入学习。每章都会提出关键问题并列出有深度的参考资料,这些资料大部分是行业经典,比如像《游戏引擎架构》、Real-Time Rendering 这样的神作当然没有错过。
游戏行业是一个很有意思、充满朝气的行业,有很多真正热爱游戏的人。当然,同时有很多问题,但这何尝不是机会呢?
刘瀚阳
前言
不久之前,开发商业游戏的知识还只有少数游戏界精英才知道。在那时候,学习真正用于AAA 游戏的算法就像学习一些黑暗禁忌的魔法一样(比如Michael Abrash 的Graphics ProgrammingBlack Book)。如果一个人想要接受游戏编程教育,那么只能去为数不多的培训学校。可是10 多年过去之后,游戏编程教育发生了非常大的变化。现在一些顶尖的大学也提供了游戏编程的课程和学位,而且每年加入这个领域的人数也越来越多。
游戏开发课程爆发的结果就是,游戏产业更容易招到需要的人员。21 世纪早期的时候,大多数想参与游戏开发的年轻人都拥有着很强的计算机科学背景及创造游戏的热情。这些有着良好基础的年轻人,会在后续工作中不断学习更加高级的游戏编程技巧。今天,有了更多的专注于游戏教育的地方,大量的游戏公司希望他们的年轻程序员可以拥有游戏编程相关的丰富阅历。
为什么需要这么一本游戏编程的书
游戏课程的增长也激发出大学课程设计的需求。可是现在市场上大多数的书都只面向两种读者:希望利用业余时间做点小游戏的爱好者和有着多年经验的专业人员。两种书都会让在校学生感到迷惑。爱好者系列图书不够系统严谨,太过专业的书学生又看不懂。
我在南加利福尼亚大学讲的其中一门课程是ITP 380:游戏编程。课堂上的学生大多数都是大二或者大三的,懂一点编程。有些学生已经能很熟练地运用GameMaker 或者Unity 开发游戏原型了。但ITP 380 是学生们第一门正式的游戏编程课程。我希望本书能够成为这种课程的最佳补充。虽然受众是在校学生,但是其他对游戏编程感兴趣的人也能获得很大价值。
本书的一个特色就是前12 章与任何平台和框架无关。这就是说,本书适用于大部分语言和平台。这与市场上其他书籍不一样,那些书往往因为适用某个版本的框架导致几年之后就没用了。正因为这种独立性,本书将会长期适用。这对大学课程设置来说很有帮助,因为他们运用不同的开发框架和语言。这就是说,示例代码总是有价值的。也因此,最后两章会使用两种不同的框架去开发游戏,之前的示例代码会在这些游戏上体现。
谁应该读这本书
本书认为读者已经掌握一门面向对象编程语言(C++、C#、Java),同时也能熟练运用各种数据结构,比如链表、二叉树及哈希表。这些内容通常在计算机科学的前两个学期就会学到,因此对于那些已经完成这些课程的人来说阅读本书是没问题的。更进一步来讲,如果能够掌握微积分,那么后面的线性代数和物理章节读者会更容易理解。
虽然不是必需的,但如果读者提前掌握了基础的游戏策划或者有熟悉的游戏会有不少帮助。同时,本书会专门讨论某种特定的编程机制,所以阅读参考资料会有更多收获。有过GameMaker 制作游戏原型经验的话会更好,但仍然不是必需的。
虽然本书意在为学校而写,但是对于已经掌握了通用编程技巧而又对游戏专业感兴趣的人来说,会很有帮助。不像一些学院派的理论书籍,书中的话题总是通过例子形象地展开。
最后,因为本书涵盖非常多话题,对希望掌握游戏编程多个方面的人来说也很有帮助。还有一点需要说明,资深游戏开发者不会在本书中找到太多的最新技术。
本书是怎么组织的
本书的前12 章在游戏实战中演示了许多算法与技术。这些话题涵盖2D 到3D、物理学、人工智能、摄像机等。虽然设计上第1 章到第12 章是顺序阅读的,但是有些章节可以直接阅读。图P.1 把各章节的依赖关系罗列了出来。所以,最好先阅读依赖章节。
最后两章的游戏示例是为了运用前面12 章所学到的算法和技术。两个示例游戏分别是2D滚轴iOS 游戏(用Objective-C 在Cocos2D 上开发)和PC/Mac/Linux 平台的3D 塔防游戏(用C# 在XNA/MonoGame 上开发)。两个游戏的源码可以在本书的网站上下载:http://gamealgorithms.net。
本书演示风格
这节讲本书的一些演示约定,比如代码和公式。
侧边栏和注意
在本书某些位置你能看到一些“侧边栏”和“注意”版块,像下面这样。
(图P.1 前12 章的依赖关系)
侧边栏
在侧边栏中,会讨论某些运用在某款游戏中特定的算法和技术。有时候会是一些我所开发的游戏中的趣闻轶事,也有时候会是其他游戏的。不管怎样,这里会更加深入地讨论这些在真实游戏开发中会遇到问题的概念。
注意
注意里更多的是不相关的有趣内容。虽然它们不是那么相关,但可能会让我们对话题有更加深刻的认识。
伪代码
为了保持语言的中立性,算法已经以伪代码的形式展现。伪代码的语法与Lua 比较近似,虽然也有点像C++ 和C#。代码展示会像这样:
function Update(float deltaTime)
foreach Object o in world
// 注释
o.Update(deltaTime)
loop
end
代码高亮与IDE 近似。关键词用蓝色,注释用绿色,类名用蓝绿色,变量用斜体。在所有的示例中,访问都是通过点成员方法和变量实现的。
有些情况下,代码要被多次讨论。在这种情况下,展示的不是代码的最终版本。通常最后会将所有代码再展示一次,像清单P.1 那样。
清单P.1 示例代码清单
function Update(float deltaTime)
foreach Object o in world
// 注释
if o is alive
o.Update(deltaTime)
end
loop
end
注意,上面伪代码中简单地检查Object“is alive”,而不是直接调用某个函数。这样写会更加清晰。
还有就是,一些代码可能会由于篇幅原因省略。通常是由于前面刚演示过,中间有大段重复的部分,我们用省略号替代。
function Update(float deltaTime)
// 更新代码
...
end
公式
一些章节(主要是线性代数、3D 渲染、物理学)会通过公式来解释。这么做会比使用伪代码更加清晰易懂。公式会居中处理如下:
?? (??) = ?? + ??
本书网站
本书的网站是http://gamealgorithms.net,内含第13 章和第14 章中游戏的源码及本书的勘误。最后,网站中有一个论坛,读者可以上去提与本书内容或游戏编程相关的问题。
在60FPS的帧率下,敌人每秒(实际应该为每帧)只会移动2.5个像素,但总共还是每秒150个像素