§2.2游戏构思
对于一个像Pong的游戏,讨论游戏内容似乎有点儿可笑,但是我试着尽可能保持事物的常规。在你开始编码前,考虑游戏应该看上去怎样和玩起来感觉怎样是重要的。越大的游戏项目,设计阶段越是重要。我不是说没有任何概念你就不可以写游戏或者应用程序。实际上,大多数初学者都是以写东西开始,然后再一遍遍地改进直到它看起来非常好。问题在于,要在第一次尝试的时候就找到最好的解决方案是几乎不可能的。
Pong游戏逻辑非常简单,也不需要太多的文字内容或者图像(如图2-1所示)。这使得编写代码和游戏构思都很简单。只要考虑该游戏需要的所有组件(比如球、球拍和屏幕边框等)以及你的最初想法。
写下你的创意
写下创意概念并不意味着你必须疯狂地写下所有想法、画UML图,直到所有东西都计划好了才开始工作。我完全反对这种方式,因为您不可能把一切东西都想到。另外,初学者很可能不知道如何以最好的方式预先设计整个游戏。取而代之,可能在您的脑海中对您的游戏有一个非常清晰的画面,并且当您在脑海中花了足够多的时间来设计之后,你就可以开工了。
如果在您的游戏项目中还有其他人一起工作,那么解释游戏构思以及让其保持每个人思想上的同步将变得比较困难。仅仅因为这个原因您就应该养成一个习惯,只用一页纸写下您的游戏构思。
您不但可以把这个展示给其他人看,也可以书写更多内容,但是您还得考虑其他的东西——当你书写游戏构思的某个部分时,你会看到纸上的东西比脑海中想的更加复杂,而且您不得不考虑额外的从属物。
例如,在Pong游戏中,您知道您需要两个球拍和一个球,该球在球拍之间运动。但或许只有当您写下最初的构思以及考虑到精灵的纹理之后,您才会想到更多的游戏细节。
每个玩家有几条命?怎样检测球碰到了球拍的边缘,以及如何处理它?球拍的速度会影响球的速度和运动方向吗?当两边玩家都觉得无聊的时候,是不是要每隔一段时间就增加游戏的速度呢?当然,当您完成第一个游戏版本之后,许多方面都可以改进。但是,在您开始编写复杂的代码之前把所有这些都加入考虑会让事情容易得多,而且后来你会发现你甚至不需要这么做。
作为一个例子,我会写下您将在本章中开发的Pong游戏的设计构思。您可能想花5到10页的篇幅来写更加复杂的游戏,但是不要一行代码都没有写就写了100页的构思文本。这会花太多时间而且很难管理这些构思。使用“敏捷方法学”您将经常更新想法并修改一些细节,我一般都是在代码至少完成了50%之后才开始画UML图,而概览图和文档直到项目快结束的时候才进行更新。
游戏构思:Pong
这个游戏是一个简单的Pong游戏克隆版,它支持一或二个玩家。在单人模式中,计算机会控制另一个球拍。在多人模式中,两个玩家既可以使用游戏手柄玩,也可以在PC上使用同一个键盘的不同按键来操作,还可以在Xbox 360控制台上玩。
游戏会为球和球拍使用一些2D图片,以及一些声音文件来支持当球撞到球拍或者丢了一条命的特效。还有一个非常简单的菜单允许你如下选择:
单人模式、多人模式、退出游戏
菜单使用一个简单的纹理图片,背景就是一块黑暗空间,而大多数的图片是明亮的。您要试着把游戏尽可能做得有趣。
游戏特点及玩法
游戏有两个屏幕模式:菜单Menu和游戏Game。菜单就是之前提到过的,包含几个菜单条目,游戏主要由球、两个球拍以及一个简单的计分系统组成。
看一下这张简单的草图,您将试着完成的任务(图2-2):
技术
很明显,您将使用XNA Game Studio Express;不需要使用其它的额外类库,因为你只是渲染一些简单的sprite精灵,这里也不涉及3D模型或者Shaders。游戏应该在Windows平台和Xbox 360控制台上都可以运行。
如您所见,我设法将所有东西都放到一页纸的篇幅内,这是我在写游戏构思时候的一条规则:首先把所有东西都放在一页篇幅内,然后写一些代码,如果您的团队或者外部合作伙伴(比如,如果您想展示概念给一个游戏出版商)需要的话,可以写一份5-10页的白皮书,包含一些最初的想法和草图。
我从来不会在游戏构思的阶段谈论编码,我只要确定将使用什么技术。现在是时候考虑执行的问题了。不要在你写游戏构思的时候考虑您的实际能力,因为这会限制您太多。把它们抛之脑后吧。
有关游戏构思的一个更完整的例子是Rocket Commander的构思(参见图2-3)。您可以查看本章文件夹中的相关PDF文件。它包含4页篇幅和一个封面,它描绘了Rocket Commander的所有构想。就想您从封面看到的,游戏看起来和它的构思非常不同,但是大体上的游戏想法都体现出来了。
敏捷方法学
对软件开发来说,敏捷方法学是个概念框架。其基本思想是避免大的计划阶段,因为这经常会带来危险的和不切实际的项目进度表,以至于难以遵从。对于较小的项目,您可能只要短时间的反反复复,但随着项目的增大,您可能会发现你总是把自己放在问题的面前,而这些问题可能要花费几个月甚至几年才能解决,并且这些是很难计划到的。
取代把所有东西都规划到最细节的水准,只要一些粗略的构思就可以了。在整个敏捷开发过程中,构思的每个部分被逐步细节化的反复多次,在单元测试的帮助下设计代码,然后编写实际的代码来实现,最后测试并写该部分的文档。这样的反复应该不会超过几个星期,而且大项目的所有部分都会重复这样的过程。
敏捷方法还包含其它的一些思想,关于让开发人员和客户、测试人员、项目管理人员以及设计人员等,更好地在一起协作。有几条规则可以用到敏捷框架中来避免整体的混乱。因为被缩短了的设计阶段,看起来好像没有为项目进行详细的计划,和混乱的强力编码相类似。但实际上,设计过程贯穿于更个项目,并且比在开始就设计好一切,并且不得不忍受在那个为整个项目计划阶段所产生的所有错误,要更有用得多。
我不会在本书中过多地讨论敏捷方法学,不过我首先会使用单元测试以及简略的概念,单元测试设计,然后反复地编码将贯穿本书的所有项目。如果您想了解单元测试的更多信息,我推荐您访问Martin Fowler的站点http://martinfowler.com 。
Martin也写了好几本书,并且我推荐《重构:改善既有代码的设计》(Refactoring: Improving the Design of Existing Code)这本书。您也可以在网站上找到它。您还可以在他的站点上找到更多的有关敏捷软件开发过程的链接及信息。
解决最初的困难
好了,游戏的构思您已经有了,但您还没有花时间在得到图片和声音文件上,以及如何实现它们。球撞击球拍边缘的问题又如何处理呢?您是否需要为球而设计一个简单的物理引擎呢?
在设计阶段之后,所有这些问题都会冒出来,而对于更复杂的项目来说,可能要花几个星期甚至几个月的时间来解决一些基本问题。比如,我做的第一个.Net 2.0游戏Rocket Commander,我有一个美好的想法就是在屏幕上显示上千颗小行星,并且总体上有数百万个。我有一个很酷的想法是让它们相互碰撞并反弹,但如何最优化地实现它并不是很清楚。在最初的测试之后,我发现,我甚至不能在没有明显降低性能的前提下渲染超过100个小行星。此时,我并没有重写我的游戏构思,也没有做一个根本没有几颗小行星,令人厌烦的游戏(如果没有很多小行星那它就不是一个真正的游戏——这就是Rocket Commander的游戏原则),而是试着通过把小行星按照Shaders和材质设置(Material Settings)分类,然后渲染它们来解决这个问题。如果小行星不可见,就尽早把它们清空,并且只把物理过程的处理应用于相邻的小行星上。
虽然经过一周的工作和最优化处理,直到小行星能以不错的执行效能渲染出来,但是物理过程的处理仍然太慢了。即使应用了最好的优化处理,只是在每一帧的可视范围内更新5,000到10,000个小行星来看,它们相互碰撞仍然显得太多。我依然想让小行星相互撞击,并且在碰撞后运行正常。如果每一帧我只检查某一数量的小行星,算法经常会错过碰撞,而且只捕获到当2个小行星都已经彼此渗透的时候。带来的麻烦甚至比完全移除物理过程还多。我几乎快要放弃了,因为我已经花了整个项目的50%的时间来解决这一个问题。但后来我又有了一个想法,把整个空间分割成若干个区域。每个区域都有特定数量的小行星,每当一个小行星离开一个区域的时候就把它从这个区域移除,并添加到新的区域。这样小行星只需要检测它们自己的以及所有邻近区域的碰撞,这听起来好像还有很多碰撞检测,但是使用区域逻辑(sector logic)的确把物理过程的性能提高了100倍之多,并且经过优化处理后还会更多。
在我现在参与的大多数游戏项目中,我会花一半还多的时间来解决最初的问题,并且把它们分化成较小的问题,这些问题再次被解决。
稍后,通过把这些小的碎片一起正确放置,游戏自身被组合起来,大约几天时间,就像变魔法,整个游戏完成了。
虽然这可能是尽可能快的方式来完成一个游戏,但是很长一段时间看不到游戏运行的结果会有一种挫败感。在过去,我总是反复地修改游戏,直到我对结果满意为止。这也的确会花很长时间。多亏了敏捷开发过程,现在我可以解决这些问题并且再也不用反复几乎没有止境的改进循环了。
这对您的Pong游戏意味着什么呢?好了,游戏非常简单,并且您不需要花很多时间对它改进100次,不过说起来你只要实现一个基础版本的Pong,为计算机硬编码(hard-coded)一个球拍,在左边随着球的位置上下移动,并且要控制右边的球拍。
经过改进和测试单人模式的游戏之后,您或许想添加双人对战的支持,但这非常难,因为您硬编码了。您可能会把这部分代码注释掉,或者甚至删除之,并重新构造游戏玩法的代码。后来测试了双人对战模式之后,您可能又想添加一个菜单,并且您又再一次调整代码位置,重新实现游戏编码等等。
虽然所有这些是一个好的实践方式,并且迫使您不断地重构您的代码(重构的意思是在不改变功能的前提下,修改代码层,使之容易维护;参看Martin Fowler的书,Refactoring),每次只聚焦在游戏的一个部分上,并且使用几个版本并行测试会容易得多。在本章接下来的部分,您将要这么做,并且希望您能领会我的意思。归功于单元测试,代码重构会更自然,并让您的代码更易使用,还能让您更快地看到运行结果。
接下来的部分,您要解决的问题之一是如何处理球的物理运动,以及如何检测撞击了球拍的哪个部位。
创建纹理
在您开始编码之前,您需要一些纹理显示在屏幕上。即使在这里您使用虚拟位图(dummy bitmap),或者一些从其他地方得到的图片,考虑最终的图像还是很重要的,比如球和球拍的尺寸等等诸如此类的东西。
再说一次,您的Pong游戏相当地简单,但更加复杂的游戏可能需要一个美术创意、很多草图以及一个能管理这些艺术作品并能及时地完成它们,以便于游戏编程人员实现它们的人。回顾计算机游戏早期,几乎所有的游戏都是靠一个人单独完成的,虽然这是最容易的方式,但今天没有一个正规的游戏可以只靠一个人来开发。大多数优秀的艺术设计师都不是编程人员,并且大多数编程人员也不是好的艺术设计师。如果您只做一个简单的游戏这样倒无所谓,但是您的项目变得越大,您就需要更多的时间来找合作伙伴、熟练的的艺术设计师和模型制作人员,并且组织这一切。
看一下游戏图片(见图2-4),
您将用到三个纹理文件:(1)SpaceBackground.dds 作为背景;(2)PongMenu.png,它包含了Logo,菜单项以及游戏需要的其他文本;最后是(3)PongGame.png,用于球拍和球。
另外,你将导入两个声音文件(PongBallHit.wav和PongBallLost.wav)到项目中,并添加一个简单的XACT工程项目来播放声音。要学习更多关于声音和XACT的内容,请阅读第九章。
发布时间:2008/6/17 下午4:23:12 阅读次数:9802