题外
订的 ClariS 的首专 Birthday 终于到了,圆通在北京市耽搁了一整天…… 好吧虽然里面的歌已经听一周多了……
昨晚一点半就早早躺下了,本想好好休息一下今天鼓足精神干上一天,结果被一只蚊子每隔半小时叫醒一次,九点才起床而且各种呵欠,今天一整天都颓过去了……FML
下午孙老师的 Model Checking 整节课都在离线状态,虽然孙老师因为老婆刚生孩子也睡眠不足离线中。小师妹和 leo 酱倒是表示情绪稳定,何其学术……
因为担心下雨早早回来了,然后回宿舍定然是继续颓了,结果这雨还是憋着不下……
看这个帖子有感。 感觉自己这么个N久不碰移植而且碰的时候对ONS也不算太熟的家伙也没啥可说的,算是吐吐积怨吧。
首先应该明白的是,ONScripter 是一个基于 SDL 的以模拟 NScripter 为首要目标的开源模拟器。 所以我想要是对其评价的话,是应该分给 SDL, NScripter 和 ONScripter 三边的。
SDL & ONScripter: 可移植性。
ONScripter 最大的优点就是其高度可移植性,这不仅是由于它基于移植性极佳的 SDL,更是因为它自身就是以高度可移植性为目标编写的。
ONScripter 的作者原先使用的设备是 Sharp 的 Zaurus. 这台跑 Linux 的设备性能非常有限,还是很佩服作者下决心去做这件事情的。 假如它只能跑在 Zaurus 上的话,那么随着 Zaurus 的离去,它也会逐渐化为尘土。 但是开源和可移植性带给了它更长久的生命力。
ONScripter 选择 SDL 为其基础是一个很好的决策——SDL 大概是目前能跑的设备最多的图像引擎之一。 ONScripter 使用的其他库基本也都是移植性比较好的库,对比用了 boost 的 rlvm,移植了后者的设备就少了很多。
开源的好处就是大家都可以贡献自己的力量。 在大家的支持下,ONScripter 现在支持的设备越来越多。 就我所知,国内的设备一但移植上了 SDL,接下来最常见的被移植的游戏就是 opal(开源版仙剑,同样基于 SDL) 和 ONScripter 了。 这也是为什么十年过去了,ONScripter 仍然被我们所使用的原因。
对于移植者来说,大家选择 ONScripter 最大的理由就是它实在是太能跨平台了。 纵使它有这样那样的缺点,很多时候也没有更好的选择。 对比 ONScripter 一次写成造福万设,能做到这一点的其他引擎实在是找不到了。
NScripter: 完善的基本功能。
ONScripter 的另一大成功之处在于,它的目的在于模拟 NScripter.
高桥的 NScripter 在当年大受欢迎,现在也有作品在出。 虽然现在看来功能还是欠缺不少,但不得不承认, NScripter 的确是一个合格的 Galgame 引擎。 它具备实现一个 Galgame 所需要的全部基本功能的能力。
并且,假如你依照它给的框架走,实现起来也非常精炼。
大量原版 NScripter 引擎的游戏被移植也使得 ONScripter 大受欢迎,同时也焕发了那些老游戏以及 NScripter 自身的第二生命。
性能。
性能问题一方面是 SDL 的问题,一方面是 ONScripter 自己编写的问题。
SDL 的主要问题在于最初移植过去的时候一般是基于软解的。 当然该来的总是会来的,硬件加速还是会来的。
ONScripter 的代码里的确有些写的很“素”的地方。 平芜泫的评价一语中的:
该说不愧是日本人的思维么?在指定环境下面能够非常好地工作,不是这个环境就糟糕了。。。。
顺提,该贴里的 bug 是 Arch 里的 SDL_ttf 的问题,其实和 ONScripter 关系不大,现已修复。
我倒不觉得性能是极度重要的问题。当然它确实重要。
一方面,只要总的框架没有大问题,先保证正确再优化也不为过,毕竟过早优化是万恶之源,开源对这种问题也是一种好的解决方案。
另一方面,ONScripter 很大的瓶颈还是在 IO 和显示上。 对于那些 label 用链表 lookup 之类的,倒也真不是什么性能问题。
NScripter 的表达能力。
我想这部分才是我对 ONScripter 意见最大的部分——尽管这部分应该归到 NScripter 的问题上。
平芜泫的评价在这里仍然适用: 如果你照着高桥佬的想法走,NScripter 是非常爽快的; 但如果不是这样的话,你就会觉得 NScripter 处处捆人手脚。
不幸的是,移植的目的是模仿另一款游戏重新实现它,想完全照着 NScripter 的思路走往往没那么容易。
高桥是很清楚一款 Galgame 引擎需要什么的,但是除此之外的事情他就懒得管了。NScripter 的语言设计明显是混乱的。命令式的风格,一些计算上的东西又明显是汇编的样式,很多函数明显是后头擦屁股添上的,最终发现这事没法弄了又开始支持 lua……
总之,NScripter 自己从语言角度而言还是很不灵活的。 说实在的,很多事情不是不能实现,而是实现太麻烦。
动画效果实现繁琐。
NScripter 的动画基本要靠自己写循环控制。不讲究时间精确性可以用 for 循环,追求时间卡准可以 while(即 if-goto) 循环靠 timer 精确控制,当然可以抽象到自定义过程中,总归还是麻烦的很。更别提缩放和旋转了。
要是实现全屏雨点效果呢?那就不得不依赖插件,而那是平台相关的,移植性很差。
顺提,msp 的移动效率不咋样。
NScripter 语言的混乱之处还在于,它竟然有lsp、lsp2、drawsp、blt等不同体系的功能去做类似的事情。
并行动画实现困难。
怎样让两个移动共同实现?你不得不在一个循环中同时做两个移动。 如果你已经把移动抽象到一个过程中了呢? 如果是全屏震动的同时移动呢? 如果是移动同时缩放呢? 上面这些 Fate 里都不少,而且我希望抽象到一个过程中。我当时很头疼。
对比 Kirikiri2 里解析脚本默认不阻塞动画执行,这边表达起来的确费劲的多。
但还好,上面起码还算是好表达的。如果想表达类似秽翼序章窗外的雨滴落下,或者魔法使之夜里人物对话时背景缓缓移动的效果呢?
我目前知道的 NScripter 对话过程中同步画面移动的方法只有利用多帧图片动画,这得做多少张?对魔夜这种大背景图缓慢移动的,恐怕图片都载入不进去。
画面再加工能力匮乏。
很多引擎会对图片加效果,比如通过色调和光线变化可以将一张图重复利用在多个场景。 也有图片直接翻转和旋转使用的。
NScripter 倒是支持黑白和反色。如果不需要考虑统一处理,也可以做旋转。 除此之外就很有限了。
当然总可以靠图像处理软件预先处理,然后替换文件名(fate 移植时是这么做的)。只是,麻烦。
声音部分的控制能力简单。
一些其他引擎的游戏,有时会将一段音乐分为两段, 一段是 head 只播放一次,一段是 loop 只循环这部分。 有些引擎干脆就把两段合并为一个文件,设定好 loop 的时间段即可。
对语音有时需要更精确的控制时间,比如语音结束的时候触发 XX 效果。
NScripter 中很难实现这些部分。最大的难点还是在“如果当前正在对话,将无法控制其他部分”。
语言表达能力缺乏。
NScripter 从语言特性上和 php 有部分地方挺有共同之处的, 比如它们在自己的领域表现都不错,但是语言设计的都挺不考量的。
NScripter 里真正有的是过程而非函数,注意它定义过程用的是 defsub.
比如说,对于类似 $2 = str(int($1) + int($0))
这种东西,你就不得不一堆 atoi/itoa 过去,还要产生一堆临时变量,简洁度大打折扣。
NScripter 最缺乏的是临时变量。 NScripter 里的所有变量都是全局相关的。 假如你需要实现很多过程的时候,你就不得不担心变量分配问题了。这实际上是很恶心的。
NScripter 里没有自定义结构。你需要自己设计地址分配,自己设计接口。
NScripter 缺乏一些反射功能(也许用这个词不妥),比如,某层加载的图片文件名是什么?在什么位置?是否真的加载了文件(而不是加载但不显示)? 如果你需要,那就只好自己保存下来——用自定义的结构。
拿 NScripter 计算是一件痛苦的事情。
ONScripter 已经走过十年了。它的优点无可替代,它的缺点也日益显著。 假如有其他的选择,我心目中的理想的移植引擎应该是什么样子的?
高度可移植性的开源引擎。
这条实际上是维持引擎生命力的重要因素。
我们真的不缺 PC 平台的 Galgame 引擎,真的。
也许为每个平台单独优化也是可以的,但是我想,基于一个高度可移植的基础上优化会更吸引人。 就像 ONScripter 自己的进化历程一样,先求有,再求优。 毕竟,硬件我们还有摩尔定律,软件想从头改架构,成本还是太大。
国产引擎中兼顾(尤其是数据文件易于跨平台维护) Win、Mac、Android、iOS手机、Linux 的我还没想到,这些算常见的,我这还没提 WM/CE、Symbian、PSP、NDS、MP4 和诺亚舟。当然是不是需要这么跨平台也许每个人有自己的看法,但 ONScripter 已经做到了。
这样的话,实现上可选择的余地就不是很大了。也许 C/Cpp/Lua + SDL 还是最好的选择。国产的 NGE 也许也值得期待。
当然还有 Web,这条路对 Gal 是否合适还有待探索,毕竟 CG 和音乐对 Gal 来说是很重要的部分,这部分要保证高质量,对流量是一个考验。
当然,开源是保证可移植性的重要要求,毕竟能一个人/团队精通众多设备并长期维护的并不多。
完善的 Gal 全套功能。
特别的,它一定要是一个合格的 PC平台的 Galgame 引擎。 这句话看上去像是废话,但是应该是值得强调的,因为一些出于移植目的写成的引擎反而并不注重这一点。
按理说,高度可移植的引擎,至少应该能移植到 PC 上。 而一个在 PC 平台上的 Galgame 引擎,至少应该有实现一个 Galgame 游戏的全套(基本)要素的能力,比如快进、回想、鉴赏、存读档界面。
对比 ONScripter,你在写游戏的时候并不需要考虑设备是使用鼠标/触屏还是键盘/按键,这些事情引擎都替你包办了。 如果你需要基本的回想和快进,都可以利用引擎自己默认的设置。 虽然很多时候这些东西肯定还是要自己定制,但是起码当你需要一个快速原型的时候,这些原装支持可以让你少操些心。 对 PC 平台作者也是友善的,它的基本功能的指令集并不复杂,最常见的输出文本也不需要指令,直接打字就是。
最关键的是,一个有 PC 版实现的引擎才能吸引更多的 Galgame 制作者,毕竟 PC 平台上的 Galgame 作品还是占优势的。 而一个有丰富的 PC 原版游戏支持的引擎显然会比其他竞争者更具吸引力。 ONScripter 很吸引人的一点是,至少你可以毫不费力的将基于 NScripter 的 PC 游戏移植过去,并且在 PC 上也可以玩。 要知道万事开头难,一个移植游戏引擎早期的移植作品数量是很关键的。这一点上很佩服 PyMO 的作者 Chen 大,他独自完成了该引擎的全部早期移植作品。
表达力丰富的语言。
由上一条,最好是一种面向普通 Galgame 制作者的语言。 最好是基于一种现代语言。现在看到的实现中比较常见的是 lua 或 python.
这里的“基于”不是“完全借用”。Kirikiri2的 tjs + ks 就是很好的方案, ks 面向普通制作者,tjs 实现高级功能。
它需要有比较好的时间控制模型和高度的可定义性。
说实在的,Galgame 界最不缺的就是引擎,然而移植 Galgame 最缺的恰恰又是引擎,这是一个很微妙的现象。 开源跨平台、完善功能和表达灵活是移植最需要的功能,只可惜现在没有引擎真正做好这些。 如果有一天有一个引擎能做好这些,这肯定是一件值得高兴的事情。