方块世界(Tetris World)是在尝试 fantasy console 的过程中实现的一个小作品,虽然小,但是在体验上进行了仔细考量,这里将设计过程记录成文。
起源
差不多去年这个时候,我开始涉足游戏开发,并在机缘巧合之下选择制作一款俄罗斯方块的变种,采用的是捏合不同类型游戏的思路。由于想捏和的东西越来越多而开发只能在部分业余时间进行,这个项目断断续续进行了一年还尚未完成。在大概 9 个月的时候,我渐渐觉得这种捏和的方式未能回到交互和体验的本源上来考虑问题,创新性还是被类型游戏局限住了。也大概是那个时候,突然有一个场景浮现在我脑中:一片开阔的原野上,若干俄罗斯方块缓缓飘落。这个场景的气氛与当今越发竞技化的俄罗斯方块迥然不同。大概 1 个月前我在读 indienova 的博文时发现了 fantasy console 这一门类,把玩之下发现似乎颇为适合实现这个创意,出乎意料的是,这个游戏很快地做完了。
设计
游戏的核心即为上文所述的场景,体验上要足够放松,可以相对佛系地游玩。首先确定的是需要宽大的地图,并可能同时下落多个方块,为了在这个前提下维持俄罗斯方块的玩法,有两个问题必须首先解决:1.如何切换方块?2.如何在宽大地图下消行?问题 1 仿佛比较简单,只需要增加两个切换按钮就可以了,问题 2 比较核心:由于行太长,实在是太容易发生失误了,而一旦失误想通过消上面的行来补救几乎是不可能的,解决这个问题是游戏能够成立的关键。
方块实现
在解决两个核心问题之前,我先确定了方块实现的方案。一般用 Tilemap 实现俄罗斯方块,都会把每种方块建模成四个 Tile 的组合,在 TIC80 里这意味着一个方块会有 24 或 32 个像素宽。由于 TIC80 总共只有 240x136 的分辨率,这显然会使得地图显得很小。为此,我将方块建模成四个 2x2 方块的组合,这样地图尺寸就大大扩大。在这种逻辑下,我舍弃了原先以 Sprite 为单位的 Tilemap 计算,全部采用像素运算与操作,特别是写了碰撞检测的逻辑。
我曾经纠结于多个方块在空中的碰撞问题,为此设想过多个方案都既不好玩又不好实现,最后决定专注核心体验避免复杂性,干脆在空中不做碰撞。
降雪机制
在早期设想的时候我曾经考虑过小精灵这个概念:小精灵定期出现,搬运方块帮助玩家填空。然而这个概念并不能在我脑中形成一幅和主场景相容的画面,显得非常刻意。我也考虑过别的机制,比如特殊方块可以形成有耐久的围栏,允许在局部形成更短的行并消除,又比如在 t-spin 等接触面积大于一定值的落地事件时触发同色消除等。但最后我觉得这些都太复杂了,“穿透”成为最可行的关键词,在考虑了几个穿透物的方案后,我回到了最初的比喻:既然方块像雪片一样从空中落下,那雪花便是最合适的可穿透降落物。在试玩的过程中,从最低空隙开始堆积的雪花确实能冲抵大地图带来的问题。此外,降雪单纯随时间递增的效用使得玩家即使不做操作也可以慢慢消行,加上融洽的视觉效果,几乎超出预期地解决了游戏核心体验的问题。
受控标识与色彩设计
在具体实现的过程中,本以为已经解决的问题 1 又冒了出来。虽然控制的切换只是两个按键的事,受控方块的标识却有很多选项。最直白的就是加框,但是由于我格外醉心于方块在夜空中落下的意象,并不能容忍加框这种明显的人造物来破坏沉浸感。为此只能使用不同的颜色来标识,而这需要和色彩设计综合考虑。
传统俄罗斯方块的色彩系统非常简单:每个方块一个色彩。在实际试玩的过程中,我发现这样会使得堆积的方块非常花哨凌乱,方块过多时显著破坏场景的宁静感。我希望方块堆积起来具有相对和谐的颜色,为此限制了色彩的个数,这使得方块开始形成更和谐的更大色块。突然我意识到玩家可能想有意识地用方块堆出一些形状——这是宽大地图带来的意外效果,而当前颜色与方块绑定的做法使得玩家“涂色”时会受限于可用方块的种类。
经过一番考虑我重新设计了色彩系统,让色彩随时间而不是方块变化,每隔一段时间,系统会更换新下落方块将具有的颜色,这样玩家总是有一批同色而形状各异的方块来用,更加容易搭建自己喜欢的图案。
方块的色彩选择的是明亮的暖色系,与之对应,受控方块的色彩自然就要选用亮色的蓝或绿。遗憾的是,这样我喜爱的亮黄+夜空的色彩对比就无法出现在视野的中央。后来我实现了下落标识的功能,这时蓝色就可以只标识在下落标识上,方块本身则保持原有颜色,但是我又发现在这种模式下玩家的眼睛会集中在底部,同样不会关注亮黄+夜空的色彩对比。最后这个感受只能留给任由方块下落的佛系玩家,这是游戏设计的一点遗憾。
粒子系统
在游戏设计过程中我经常克服实现一些花哨特效的诱惑,部分是因为 TIC80 的机能和表现力有限,这种限制其实也是 fantasy console 这类开发环境的好处。但是我还是决定在消行这里作出最棒的视觉效果——消行相比普通俄罗斯方块太难了,必须要给玩家以惊喜,同时,这个视觉效果应当既华丽又同样宁静,具有“不为人知地悄悄发生”的感觉。最后我选择了飘散的效果,通过控制速度可以同时呈现出能量和轻盈感。
TIC80 没有自带粒子系统,我在之前的开发中也并没有用过其它引擎的粒子系统,大概参考了一下网上的常规设计后就干脆开始动手实验。按照单粒子单方向移动->消散->多粒子移动->分批移动->速度扰动的顺序逐渐实现一个自然的粒子效果。在实际操作时,我意外地发现最大的挑战来自像素本身。开始时我用浮点数按帧积累 x 和 y 的值,x 和 y 变化达到一个整数时就结算到位置上,结果导致移动方向只有两种:45 度和水平,形成非常难看的折线。为此需要让 x 和 y 协调变化,在固定时间后或移动超过一定距离后才结算距离。
粒子移动完成后,整体分布效果的处理反而意外顺利,引入了随机速度扰动后,只需要控制随机的区间就可以实现效果的微调。比如根据 x 的位置改变粒子的基准速度,就可以呈现出向右方开口的效果。这里还有一个窍门是为了使随机数被压缩在靠近 0 的区间,可以简单使用两个甚至三个均匀分布的随机数相乘,我用这种处理防止散逸的粒子扎堆。
声音系统
我希望游戏大部分时间是无声的,但一度考虑在下雪和消行时播放一句音乐。TIC80 支持 SFX 的定制,但是折腾了好半天后我基本确信无法使用 8bit 达成我心中的音效。我希望下雪时的音乐有一种回忆色彩,而消行时的音乐明亮而轻盈,这需要类似于钢琴的音色和类似于三角铁的音色。放弃音乐后游戏就完全无声了,作为补偿,我突然意识到可以给方块本身配上音符,就像玩家可以不管消行只是堆图案,他/她也应当可以不管所有积累的东西只进行即逝的创造。于是我为切换控制的按键加上了声音,如果下落的方块比较合适,通过横向摆布方块的相对位置玩家就可以编排出趣的乐句。虽然可能根本不会有人这么玩,这个想法还是让我非常兴奋。实际试玩过程中意外的旋律可能令旁边的人会心一笑,算是一个不错的副产品。
音符选择上,我选择了 C 大调和 F 大调给前两种颜色,高八度的 D 大调给最亮的黄色,红色则用 C 大调的关系小调 a 小调(和声小调)来衔接。音阶的设计理应更花心思,但那已经超过了我的能力范围。
配置与交互设计
我在交互上一度有过稍显奇怪的困扰。比如,我执着于不实现游戏内菜单,实现的枯燥是一方面,另一方面,我觉得这样一个世界不应该有菜单这种完全控制的意象,更何况 TIC80 的游戏自带一个游戏外菜单。但是为了不同目的的玩家能有最佳体验,我还是设计了指示物的开关(开便于游戏,关更有漂浮感),时间和分数的开关(开便于记录刷分,关避免干扰),把交互简化成两个专用的键。
键位上,TIC80 默认 a 对应 XBOX 手柄上的 X 而 x 对应 B,这使得手柄上正常的左右操作变成了 a 和 x 的奇怪操作,因而我增加了 q 和 w 来切换方块,这样的话立即下落对应的 z(手柄上的 A)就显得干扰太多了,于是我增加了回车来立即下落。
结语
我想我还会使用 fantasy console,可能是 TIC80,也或者购入 PICO-8,这些工具当然不是没有问题,比如自带的代码编辑器对习惯了 vim 的程序员来说过于痛苦,几乎没有什么用,Sprite 编辑器也仅仅够用,与 Aseprite 这种神器相距甚远。但是它们的限制和高度集成的特点会潜移默化地塑造开发进程,迫使开发者不断回到游戏的核心玩法,是一个非常安适的工作环境。
有一种说法是 fantasy console 适合快速开发原型,这点我之前一直不太明白。由于缺少太多游戏引擎的便利功能且工作在十分低的抽象上(sprite、map、甚至像素),实现一个在其它引擎里拖拖拽拽的简单任务都可能颇费周章。现在我开始理解它可能并非适合任何游戏的原型开发。对于一个相对复杂的类型游戏,仅仅建立类型的要件可能就要浪费大量时间,但是对于玩法特殊、渲染特殊的游戏,所有引擎提供的功能都会变成桎梏——对于这类游戏没有什么比直接画像素更自在了。
不长的开发时间却让我感触颇多。作为一个全包型且只能在业余时间进行开发的个人开发者,应当更多地坚持创新的独立玩法。去实现成熟的类型游戏机制当然是有益的,那些机制创立之初本身也极富创意,但是由于珠玉在前,很容易陷入繁琐的细节,反而无法充分体现创意。至少对我而言,理想的游戏开发是一种接近艺术创作的状态,寻求的是触动,而不那么关心传统意义上的“好玩”和“吸引力”,还是应当对目标进行精简,坚持做游戏的初衷,尽快抓住和发展自己的灵感。
游戏目前已经移植到 Love2d 引擎上,后续开发将基于这个版本进行,TIC80 的版本已经上传到 itch.io,可以免费游玩。Love2d 版也放到了 itch.io 上,目前只是加了封面、彩蛋和一点音乐,收费 2 刀,也希望大家支持。
暂无关于此日志的评论。