http://www.flashcat.com.cn/blog/read.php?49
酝酿了一下,决定写一篇《口袋战士NOVA》的开发心得,其实是把我所遇到和解决的问题做个整理,也希望对大家以后开发游戏有帮助。
由于是第一次写这么复杂的游戏,我前面写的那一堆小游戏的总开发长度都没这一个游戏开发周期长。
项目变大之后,很多以前不是问题的事情成了问题。现在只能做一件事就是,改正,下次不犯了。
好切入正题。(注:仅代表个人观点,请选择性接收,欢迎指正错误)
1.了解你将要开发的游戏
恩,你要开发哪一类的游戏,先要对那一类的游戏比较熟悉,如果不熟悉,请连续玩一段时间,对游戏整体有个感觉了再开始构架游戏。如果你是这一类游戏的资深玩家,开发出来的游戏可玩性将大增,你知道在什么地方该注意以增加游戏可玩性。
结论,请多玩你要开发的同类型的游戏。
2.编码规范
如果是个很小,几个类就解决问题的项目,可能看不出问题,可是一旦项目规模达到一定规模,一个规范,结构清晰的代码将给维护带来很大的便利,否则代码很有可能会失控。
首先是命名规范。
变量名,采用“类型”+“名称”的方式命名
常用的命名参考:
mc : MovieClip (影片)
bt : Button (按钮)
b : Boolean()
n : Number
s : String
a : Array
bmd: BitmapData
pic : Bitmap
类名,采用“名词”,函数名采用“动词”
例如,有个“坦克”的类,里面有“创建坦克”,“装弹”,“开炮”等函数,很容易让人理解。
库里面的元件,尽力用英文来命名,导出名和元件名称相同,非常便于管理。尽量不要使用拼音。
你也许和我命名习惯不一样,这个也没关系,你自己习惯就行,团队合作的话,需要将编码规范统一起来
自文档化编程(重点)
一个类文件里,多少注释合适呢?答案是,不知道。
没有规定说多少注释是好或者不好,但是,有个原则是,你尽可能的“自文档化的编程”思想来写你的代码。
什么是“自文档化编程”呢?(我是从《编程匠艺》上学的,有兴趣的话,请看原版),意思就是编写可读性很强的代码,机器能读懂,人也能读懂,即使没有注释一看也能明白写的是什么。
在关键的地方使用注释,大部分时候请用代码描述代码自己。
这么做的目的就是方便,代码规模变大之后,你还能轻松的掌控住自己的代码。
《口袋战士NOVA》一共34700行代码。168个类,不算太大,我也是遵循这个原则来开发的,可控性还好。
3.效率or代码可读性
FLASH是有效率问题的,有时候为了效率,会牺牲掉代码的可读性,用最高效的方式去写一个算法。
但请注意,大部分时候,都不要做为了效率牺牲可读性的事情,否则,代码是非常难维护的。
只有当你确定,那个关键点是整个游戏的效率瓶颈,改善了那里的效率就能使整个游戏效率有很大的提高,并且不得不用人难懂,但机器执行效率高的方式去写的时候,你才可以牺牲一点可读性。并且尽可能的维持在一个函数中处理算法,注释清楚,方便修改。
不要为了效率放弃代码可读性,这一点怎么强调都不为过。当代码规模变大的时候,越可读的代码,越让你觉得轻松。
4.mc or bitmapData
开发游戏的角色使用mc(影片)还是BitmapData?
我以前用AS2开发过很多的游戏,都是使用mc的,mc的优点是很直观,所见即所得,占用内存很少,缺点是效率不高(当效率是瓶颈的时候是缺点,其他时候可能也不算)。BitmapData的优点是效率高,管理有些麻烦,占用内存高。
小问题,为什么mc效率没Bitmap高呢?
mc中的位图在编译后,是以shape形式存在,也就是说,使用的是矢量渲染器渲染,进行位图填充,效率很低。
mc中的矢量图片,也是用矢量渲染器渲染,负责的图像,非常耗cpu。
BitmapData的是将数据存在内存中,真正的位图渲染,效率非常高。
你可以用一个影片内放一个hitarea(检测范围)的方式做角色
也可以将整个角色的动画以bitmapData的形式存进数组中,模拟mc的方式做角色。
当效率不是问题的时候,前者非常容易开发。
当效率很重要的时候,可以选择后者来做,《口袋战士NOVA》是采用Bitmap+Araay来控制角色动画的,效率很高。
5.显示和数据检测分离
接上面,用mc做角色的问题还在于,显示和数据检测是联在一起的,单机游戏可能也没什么问题,因为在本地基本上代码执行是实时的,不存在大延迟现象,就算延迟了几十毫秒,也不会有什么问题。
但是要做联机对战的话,问题就来了,两个客户端通过网络传递数据后,有延迟,数据并不是实时的,但显示是实时的,不同步了,这个时候,就需要将显示和数据分离,适当的时候可以让角色做过渡性的动作弥补数据的延迟(其实就是电脑骗一下玩家),保持画面的流畅,这个是很有必要的。Bitmap+Araay+数据队列方式,可以很好的做联机应用。
注:上述理论对于及时对战游戏更贴切些,社区类的,等非即时的联机游戏,影响会稍微小一些。
口袋战士是要开发成联机对战版本的,目前还没写完,所以这个不展开讨论了,以免误导大家。
6.创建资源和释放资源
用C语言写东西的时候,需要自己管理内存,创建什么,后面还要自己释放什么。用as开发一般可以不用自己管理内存了。
但是注意了,当你游戏中使用大量的内存的时候(Bitmap+Araay),你需要管理好你的内存。
写类的时候,你创建了什么资源,数组、BitmapData,更改了什么属性,你要写个函数,释放资源,恢复属性。这个事前要想好,否则,后面在一堆代码里去找那些该释放,哪些改恢复,是非常头疼的事情。
我写《口袋战士NOVA》的是前面没注意,后面花了几天时间专门整理这个,而且还提心吊胆的,害怕有遗漏就麻烦了。
以后的编码我自己会注意这个问题啦,特别是大项目。
7.格斗游戏原理
格斗游戏原理挺简单,就是两个角色,有自己的bodyArea(被攻击范围)和hitArea(攻击范围),有个格斗检测器,传双方的动作过去,格斗检测器判断是否是攻击动作,谁攻击谁,攻击有没成功,返回结果给两个角色,然后角色再切换反应动作。
8.数据队列
队列是个思想,AS3里貌似没有队列一说,我使用数组模拟队列。
为什么要使用队列?
恩,是个问题,单机游戏的时候,我们要要更改数据,只需要执行一下相关函数就行了。及时联机对战的游戏不能这么做,因为网络有延迟,实时更改数据会使游戏变得不可控。
比如,我出个拳,对方掉血,自己加能量,这个3个动作,在本地实时更改是没问题的,没有延迟。但是在网络上,你出个拳,还要等对方是什么反应才能决定是该不该加血,该不该加能量。所以要用队列来控制更改数据,出拳后,将拳加入队列,等数据齐全了再去判断需要做什么,再将要操作的事情,写入另一个队列,按顺序执行,不会出错。
仅理论,待实践。
9.一个类只做一件事情(重要)
随时在心里告诉自己,一个类只能做一件事情!
我在写《口袋战士NOVA》的时候,本来打算创建一个类来管理一个角色所有的事情,后面发现天真了,一写就几千行,是我低估了这个类的大小,后面硬着头皮,将角色类拆成,属性管理,动作创建,动作管理3个类,其实还能细分的,暂时还可控。
这个故事告诉我们,一个类只能做一件事情,不要将不同的功能写在一个类里,越写越复杂,最后崩溃。
幸好,我在崩溃前,耐着性子将类拆分了,拆分类那几天感觉是世界末日,大家要引以为戒。
10.多模块开发
一个fla文件里东西装多了之后呢,就会出现崩溃现象,加个东西要等半天才有反应,甚至是改个名字都要等半天。
什么,你没有这样的经历?恭喜,可能你的电脑足够快,或者你的fla文件没加的足够多的东西(flsah道:为什么你一定要玩死我?呵呵)。
我将6个角色的文件都加在一个fla文件中时,已经达到了60M,文件基本上不可编辑,改任何一样的东西都会等半天,编译一次,我要到周围转悠一下,再回来看看有没有编译完成。
好吧,再次拆分,将角色,场景,道具,界,声音都拆分成不同的模块,导出SWC组件,然后再拼成一个游戏。
这种方式开发,应该说对付一般的大项目足够了,SWC是编译好的,整个游戏编译一次快多了,各模块资源管理都在可控范围内。
当然多人开发的话,请协调好,各自写好各自的模块,不在讨论范围内。
11.万恶的文档类
看标题绝对是对文档类的污蔑,事实上我确实对这个文档类的作用很不理解(板砖!)。
因为我的游戏,编译的时候,光代码就有1M的大小,所以如果代码在第一帧导出的话,玩家在网页上加载的时候会很长时间看不到游戏内容,这是不能允许的事情(至少对于我个人来说是这样。)。可是当我将类改成在其他的帧导出时,问题来了,找不到对象。
我总结了一下,应该是我将文档类作为游戏的主类的问题,写得太复杂,牵涉太多类,而游戏在第一帧初始化,就会首先执行文档内,而文档内牵涉的其他类又还没初始化好,所以就会出问题。
我后面解决方案是,用as2的老办法,重新用一个mc作为游戏主类,文档类彻底弃用了。
现在游戏第一帧进60K,一般1秒钟就可以见到游戏画面。
注,这仅个人解决方案,文档类应该是有好处的(我暂时没发现),而且和flex通用方面比较好,谨慎选择此方案。
建议写游戏的时候,重新写个游戏主类,有文档类的话,尽量不要牵涉到太多的其他类。
12.正确的估计开发时间
有人问你多长时间能做完这个项目?你心里在打鼓,多长时间呢?不知道,说个数字也是不准的,后面肯定延期。
如果你能很准确的说出项目的时间,那么你已经能很好的把控自己的项目了,这点非常好。
如果不能,也没关系,其实每个人都有一个特殊的系数,比如,你估计这个项目1周能完成,后面看看最终完成需要多长时间,如果是2周,那么,你的系数是2,做很多事情的时候,都来评估一下这个系数,后面会整理到一个比较接近实际的系数。以后,你每次评项目时间的时候,就是:
真实时间 = 乐观估计时间 × 自己的系数。
我的系数是3,也就是说,这个项目我本来打算3个月完成了,结果用了10个月,但这并不是说我不努力,我相当的努力,因为人估计时间的时候总会乐观些,但实际上你可能会遇到问题、需要休息、或者有突发事情发生,这些会使你的实际开发时间变长,乘以自己的系数就是比较接近的实际时间了。
13.最后的最后:坚持
恩,前面说了那么多,其实最实在的就是踏踏实实的坚持将自己计划的项目做完,做完就是个小胜利。
个人耐心还可以,呵呵。
好吧,就写这么多啦,谢谢大家!
最后,大家去我的游戏《口袋战士NOVA》官方去开心一下吧:http://pf.gedou.com