2014年,我加入南京智精灵编写健脑小游戏。在这之前公司已有一堆前人留下的风格迥异的小作品,我们要参考这些作品开发一组新的风格统一的游戏产品。这些小游戏粗看画面简单,开发难度应该不大,但另一方面,游戏数量多,各有不同。一个一个的解决不是什么好办法。
我从众多的游戏中发现,这些游戏具备一种估值循环的逻辑,从这个认识可以推出一套适合每个小游戏的程序骨架。
但随后我意识到,开发中充满了繁琐乏味损坏开发乐趣的事情:切图、以及它的好伙伴测算精灵坐标。
注:游戏里的人物、棋子、按钮等等都统称为精灵。
我要用cocos2d制作这些小游戏。cocos2d 还有很多游戏框架使用称为精灵图集的东西。就像下面这样:
精灵图集:小图片拼成的大图和小图片在大图的位置索引 |
这些精灵图集怎么来呢?
游戏工序可以浅显而不失准确的理解为:第一步策划,第二步美工,第三步程序,第四步玩。
美工使用 Photoshop 画好游戏素材:
之后将游戏素材中精灵的位置尺寸一一测出,形成一个excel文件和一组小图片:
程序员用工具程序将小图片生成精灵图册,而excel转为程序代码中精灵的位置:
我意识到,必须能从Photoshop一步到位直接产生精灵图册,必须从Photoshop直接生成游戏精灵摆放位置大小的初始代码。也就是说,从Photoshop直接生成游戏原型。
代码生成器什么的对我来说驾轻就熟,在我加入智精灵之前利用业余时间敲敲打打,神器完成:
效果如何呢?数据说话:在此之前一款小游戏要开发一周左右,在我担纲的时期,可以做到一天出2到3个游戏。抛开开发能力方面的因素,效率提升至少也有一倍。
一方面效率大幅提升,另一方面美工和程序的痛苦程度大大降低。那些枯燥乏味的切图测算精灵位置尺寸的活消失了,只剩下如何编写游戏逻辑,工作变得直指本质,也不再那么乏味了。要是不存在其他一些因素,这个团队将是快乐工作的典范。
回顾我是如何取得这个成就的。首先是想象力,想象力能让人从无到有看到一个不存在的事物:从Photoshop这么一个美术软件直接生成游戏骨架的工具。有了这个目标再一点一点的丰富它的细节,形成可用的产品。谈想象力有点玄,除了想象力外还有一个很有意思的可以复制的因素发挥着重要效用。这个因素比所谓的“偷懒是发明的原动力”、“技术颠覆管理”等等正确的废话更能帮助我们实现真正的创新。这也是本文所要介绍的方法论:工序主义。
刚才我们看到,这款游戏生成器干掉了切图测位置等工序,这是否就是所谓工序主义呢?工序主义是否就是消掉一切可以消掉工序? NO。仅止步于此那工序主义就是奥卡姆剃刀的另一个版本而已。奥卡姆剃刀法则说,如无必要勿添实体。工序主义的内涵不止于此。
消除工序是工序主义的一项重要内容,却不是核心内容。
直接阐述工序主义是怎么回事是很乏味的,我希望能尽量让案例说话。
让我们继续谈谈这款游戏生成器。
这款游戏生成器随后带来一种新的美术和程序的结合,幸运的是当时的美工抓住了它。
有了这个神器,美工已经不需要切图测位置,而是直接给我Photoshop文件。我在收到Photoshop文件后,为了生成代码,会对Photoshop文件图层做一步极有用的人工编组工作。例如,我把同一个精灵的图层安排在一个图层组,以程序的方式命名为精灵名,这样Photoshop文件里就有一个事物(图层组)和游戏程序里的事物(精灵)是对应的了。
按程序里的事物重新组织Photoshop文件中的事物后,一个Photoshop文件往往变成这样:
上面的英文命名大多是为程序服务的。
这不是一款单向的游戏生成器。在设计时我要考虑一个问题:游戏编码完成并不是工作的终点,美工随时可能对Photoshop文件再做修改,设计中要考虑尽量无痛的将新的美术设计更新到游戏世界。
我在按上面的方法重新组织Photoshop文件图层后将文件交还给美工,他就以这份Photoshop文件为基础做下一次调整。通常他做出新改动后我只要重新生成代码即可。不久后,他甚至能猜到程序员会如何组织游戏事物主动将精灵编为图层组。他给的命名时常符合程序员的规范。赞美这位优秀的合作伙伴。他很早就是美术总监,不喜欢我当他是美工,其实我也不只是程序员 :)
从管理的角度看,这样一来迭代成本大幅降低,迭代速度和质量都更有保障了。
另外还带来一个益处:便于定位故障。例如精灵的初始大小不对,打开Photoshop文件就可以找出它在程序里的命名了。在工序割裂很强的模式里,每道工序的成果自成体系,Photoshop文件只满足美工的意图,和程序世界没有联系,定位某些故障很难。
这个游戏生成器的确是工序主义的经典案例。
注:上文援引的素材已征得智精灵许可,特此鸣谢。
下面的案例来自纯粹的软件开发方面。
网站开发人员经常需要在数据库语言SQL和网站自身的程序语言之间切换。切换的方式很多年前是这样的:
06-07年,我发明了一种表述方法。
我把它称为SQL块。SQL块是d2js的一项核心技术。除了SQL块d2js还包括不少其它工序主义的设计亮点,有兴趣的同仁可以访问https://github.com/inshua/d2js 进行了解。
SQL块是如何拯救乏味的工作并带来效率提升的呢?
在开发工序中,通常遵循先SQL后程序语言(如Java)的编写顺序。SQL有SQL编写工具,如Oracle有SQL Developer、PL/SQL Developer,PG有pgAdmin。程序员在SQL编辑器编制查询,达到意图后将它粘贴到程序语言开发工具中,按程序语言的要求将SQL加上双引号、断行、混入程序语言的变量,形成一个该语言中的字符串。就像这样:
这里将一段SQL赋值给了一个名为 sql 的变量。
将SQL嵌入程序代码后,当时的框架还要经过不少编码步骤才能给出一个能用的页面。不幸的是,祸根在这一步已经种下了。
我们看到,SQL代码已经变为程序语言内的SQL字符串,混杂着一堆程序变量和飞舞的单引号双引号转义符,看上去已经与SQL代码截然不同,程序可读性变得极差。一旦出现故障很难通过阅读代码定位问题,即使一条简单的查询也要付出不少心血认读排查。
而且一旦程序不能正常工作或者随着业务要做调整,而原始SQL已经转化为程序语言里的字符串,这种格式的文本粘贴回SQL编辑器已不是SQL,无法在SQL编辑器识别、运行和修改。
可见,这种做法操作繁琐,可读性差,不适合快速迭代。
SQL块给予SQL语言几近独立的地位,让SQL步骤的成果直接体现在程序中。正向来说,将SQL代码从SQL编辑器复制到程序语言中即可使用。逆向来说,将SQL代码从SQL块复制回SQL编辑器即可修改调整。
在程序语言给SQL块独立地位的同时,SQL块中也可以套入程序块。SQL块和程序块互相穿插,你中有我我中有你,形成递归的嵌套结构。这种设计让上一工序可以反过来混入下一工序。
SQL块提升了代码可读性,提升了迭代效率,定位问题也更容易了,甚至原来的做法带来的SQL注入问题也一道解决了。而这一切不仅不必付出额外劳动,反而减少了原来乏味的工作。
这里我透露一个心愿。如果我有精力改造IDE,我会在开发工具SQL块上显示一个Run SQL按钮,直接运行SQL代码。
从这两个案例我想我们可以触摸到结论了,工序主义是这样一种方法论:
1. 消除可消除的工序,让它消失或自动化。
2. 工序贯穿。
a) 上一步工序在下一步工序中得到充分尊重。
b) 上一步工序除了结果也将必要的针头线脑传递到下一步工序。
c) 在下一步工序给出的作品中简单的包装着上一步工序的作品,只要进行简单的拆箱就可以退化出上一步工序作品——甚至可以直接嵌入。
d) 上一步工序新的调整很容易再传播到下一步。
e) 下一步工序在上一步工序中也得到充分尊重。下一步工序为上一步工序准备好切入点。
f) 综上,工序贯穿让工序间信息共享、深层咬合,工序贯穿能有效的支撑快速迭代。
3. 工序贯穿导致最终成果浅显直接的暴露出各个主要工序。用哲学一点的说法,在共时性的产品中能看出历时性的工序。用比喻性的说法,就像树的横截面,树的年轮暴露了它的生长经历。
a) 暴露工序对于构建可维护的产品来说怎么强调都不过分。
b) 通过想象工序暴露后的最终产品形态,可以得出你梦寐以求的设计。实际上本文介绍的这两个设计都是这样出发的。这也是一种结果导向思维。
回顾一下上面两个案例是怎么围绕这三点进行的。
消除工序:游戏生成器消除了切图定点的工序,SQL块消除了粘贴SQL语句套双引号断行置入程序代码、将程序代码中的SQL字符串复制回SQL编辑器的工序。
工序贯穿:游戏生成器将游戏世界的精灵知识转为程序员和美工所共同持有的知识,程序步骤的知识甚至回馈到了美工步骤。d2js中SQL成果原原本本的转移到了第二步工序的程序代码中。
工序暴露:d2js的SQL块在最终代码中清晰的暴露了SQL 代码。游戏生成器在Photoshop文件中充分暴露了美术设计中的知识,在游戏代码中充分暴露了Photoshop文件中的知识。
除了d2js和前面的Ps2Game游戏生成器,molecule框架是一款工序主义的精致小巧的HTML组件框架。这个框架基于DOM-Prototype思想,在纯HTML基础上实现了HTML组件。其中工序主义是贯穿整个设计的方法论,使用molecule框架的人会发现包装为组件和拆箱回朴素HTML代码都极为简单。molecule的地址https://github.com/inshua/molecule 。
这套方法论特别适合迭代频繁的软件领域,除此之外在其它行业有没有用呢?至少就智力行业而言,如写书需引用知识库,画模型需引用其它模型等等,涉及到工序的,都可以从工序贯穿的角度进行思考。
除了用于设计,工序主义还可以用于评价技术框架、工具组合。这个话题留待日后铺陈。
让我们随着这个机械的运转领悟如何将时间序列转化为共时的空间组织: