软件工程界有个术语,鲁棒三世,意思是说优秀的代码经过三代人维护,依然像油纸包着的零件一样可靠易懂。要做到这一点,必须依靠设计模式。那么什么时候开始学呢?我是自学编程的,因为遇到了急需解决、但是靠现有知识应付不了的问题,所以用三个月时间初步掌握了设计模式。学习资料包括两本书和一套视频:
首先,我建议快速通读 C# 设计模式。这本书把设计模式从简单到复杂分为三大类(Structual,Creational 和 Behavioral);在每一类内部,把功能相近的模式组成一章(详见下表)——比如一开始讲解了最容易实现的三种模式:Decorator,Proxy 和 Bridge。针对每种模式,先讲应用场景和涉及到的 C# 语法,再画 UML 图,然后提供两份代码:一份是简短的理论代码,另一份更长,牵涉到更复杂的业务逻辑。通常来说,我只看应用场景、UML 图和理论代码,读不懂的时候参考一下 Head First 这本书。C# 和 Head First 同时详细讲解的设计模式,在图 3 中标记为浅绿色。
Head First 是我读的第一本书,但是我觉得太罗嗦了,当词典翻翻还行,完整读一遍意义不大。
读完 C# 设计模式,开始看视频(感谢 UP 主搬运到 B 站)。讲课的瑞典博士小哥肢体语言丰富,非常抓人。每集视频短的半小时,长的九十分钟。小哥用一半时间仔细解释每个设计模式的适用场合,接下来四分之一时间画 UML 图,然后写示例代码,最后两分钟回顾与总结。视频全部剪辑过,没有一分钟冷场。我强力推荐。
先前发现一个问题:NPC 超过二十个,游戏开始卡顿;超过五十个,游戏几乎玩不下去。俺寻思了整整一周,最后注意到两点:
换句话说,如果有 50 个 NPC,每一轮都要调用 50 次 Update()。问题是否出在这里呢?于是略作修改:
问题顺利解决。背后的技术细节我不太懂,但是从现象看,Update() 太多了会拖慢游戏速度。
敌人是资源转换器,但这种转换往往是不平衡的。可能是数量上不平衡:消耗 5 瓶药水杀死敌人,但是对方只掉落了 1 瓶药水;也可能是时间上不平衡:消耗 5 瓶药水,对方掉落了最终战斗才有用的誓约胜利之剑。
由此出发,我设计敌人的第一步是列出 PC 拥有的资源:
怎样理解“伤害”是“资源”?不妨把“攻击”看作是支付三个“伤害”筹码,购买对方的三个“生命值”筹码。“伤害”筹码在每次行动前自动补充到最大值(三个),“生命值”筹码很难得到补充。
接下来,我们假定每种资源都有一个对应的原型敌人,他的攻击能力是直接改变(减少或增加)这种资源,比方说生命值原型能够减少 PC 的生命值。感染有两个原型:提高 PC 遭到攻击时的感染率,或者延长感染的持续时间。它是敌人强制赠送给 PC 的筹码(或者说负面资源),遵循两条规则:
在 PC 资源列表和原型敌人列表的基础上,根据 SSD 原则设计出实际的敌人。SSD 原则是指:
所谓完全相同,从编程的角度讲,是让 PC 和 NPC 继承同一个接口 IAction,但是具体的实现方法不同——PCAction 监听键盘事件,NPCAction 根据 AI 算法决定下一步行动;从纸面设计的角度讲,是让原型敌人拥有 PC 的一切资源,包括(上文提到的)基础资源以及高级资源(改变资源的资源)。《真菌洞窟》的高级资源是能力(Power)。PC 有九种能力,三组防御,三个攻击,分别影响生命值、感染和能量:
简化有两层含义。第一,把浮动数值变成固定数值。比方说,PC 的最大生命值随着等级提升而提升,但是某个 NPC 的最大生命值始终是固定的。第二,删除或合并部分资源。详见下表。
与 PC 相比,NPC 只有四种能力,而且都表现为固定数值。
免疫,快速治疗:删除免疫,保留快速治疗(Defense-Duration)。
活力,肾上腺素:删除肾上腺素,保留活力(Defense-Energy)——每轮额外恢复 X 点能量。
每种敌人应当努力带来截然不同的游戏体验。不能指望玩家注意到细微的数值差异,比如大地精的伤害比地精高出 5%,可以这样修改:地精攻击 3 次才能击杀 PC,大地精攻击 1 次就能重伤重甲 PC。这种不同除了来自数值,也可以来自游戏元素——地精造成 3 点伤害,大地精造成 4 点伤害,并且能够晕眩 PC。
以上是我目前的设计心得。这张纸还剩点空白,我来写个证明。
评论区
共 9 条评论热门最新