为什么采用这个架构?
接下来你将了解末语视觉小说引擎的设计思想和主要功能。
在设计初期,我们有两个目标:
- 支持尽可能多的平台
- 引擎的使用应是简单的、渐进的
将其展开,问题很容易变成:
- 如何让引擎本身的开发与维护成本足够低,同时不对未来的扩展构成障碍?
- 用户以何种方式简单地使用引擎、拥有什么样的功能;当他们需要更多能力时,如何让他们能够深入进来,我们又该如何提供这些能力?
围绕这些问题,我们最终确立了当前的架构。
引擎使用 Rust 编写,基于 winit 和 wgpu 提供跨平台的图形渲染能力,并在此之上构建了图形渲染、音频播放、事件处理等核心模块。它是一个 native 的程序,这最大限度保证了我们对特性的掌控,也为未来支持更多平台奠定了基础。所有实质性的引擎功能都在这一层实现,因此我们在这里提供了可插拔的渲染器和插件系统。
在此之上,我们引入了 JavaScript 作为脚本语言,使用 QuickJS 作为解释器,在引擎内部提供一个 JavaScript 运行环境。这是一个有意限制的环境——它并非类似 Node.js 或 Bun 那样全方位的运行平台,而是纯粹的 JavaScript 运行时。引入外部模块或访问网络这类操作均不被支持,一方面出于安全性考虑,另一方面也是希望它始终保持轻量。
通过 QuickJS,我们向运行时环境暴露了引擎层的各种 API,因此运行时这一层才是真正面向用户的接口。用户可以通过编写 JavaScript 脚本来控制引擎行为,进而实现各种功能。
然而,仅提供简单的命令式 API 还不足以让引擎真正易用。为此,我们引入了 React——是的,我们在非浏览器环境中使用了 React。这并非首创,我们从 AVG.js 项目中汲取了经验与教训,重新实现了这一特性。有了 React,我们可以提供更加声明式的 API,用户能够以组件化的方式构建视觉小说的界面,从而更便捷地组织代码与实现功能。这也意味着可以充分利用 React 现有生态中的丰富工具,例如路由、状态管理等。
如果你是一位有经验的开发者,或许会觉得这个架构有些奇怪。但我们相信这样的架构是有意义的——它帮助我们更好地分层:这里所说的分层,并非软件架构意义上的分层,而是功能与用户接口的分层。这使得引擎层可以承载更多功能,同时又不会给用户带来额外的负担。
因此,对于初次接触本引擎或经验尚浅的用户,我们更推荐首先使用我们提供的模板,专注于视觉小说的内容与交互,而不必深入了解引擎底层。在实践过程中按需学习定制化与扩展的方法,会更容易上手。
而对于有经验的开发者,我们提供了更丰富的自定义能力——从调用额外的 JS API,到从头实现一套完整的模板,乃至开发可插拔的渲染器和插件。我们提供了一个渐进式的连续体,让你可以根据自身需求和投入来自由选择。