Novella
类型: 视觉小说框架
包: Divooka.Novella(Novella 工具箱),位于 Divooka Compute 的 Game Development 工作负载中;C# 程序集 Novella.Core 和 Novella
上下文: 过程式(Routine 和 Events 图)、数据流(Flows 和 Function 图)、C#,以及纯脚本文件夹
设计: RFC 170
状态: 第 1 次迭代,即改版版本。本次迭代中,引擎、其脚本语言、其 Divooka 包、Explore 示例以及示例游戏均已就绪。

Novella 是 Parcel NExT 的视觉小说框架。游戏就是数据:一个由标签和语句组成的故事,故事所引用的定义(角色、图像、变换、转场、音频),一份配置和一个主题。同一个游戏可以从脚本文件夹、C# 程序、Divooka 过程式图或 Divooka 数据流图的预览中运行,并且在每种方式下的游玩效果都相同。
它的功能目标是与最广泛使用的视觉小说引擎 Ren'Py 对等,因此熟悉 Ren'Py 的作者一眼就能认出这种脚本语言。它的 API 和编程风格则是自己的:条件和赋值使用一种小巧、安全的表达式语言;故事需要的除此之外的任何东西,都是用 C# 或 Divooka 实现的命令;需要 Python 的游戏可以选择启用它,以代码块的形式通过 IronPython 运行真正的 Python。故事甚至完全不必是脚本:C# 和 Divooka 节点可以写出相同的故事数据,包括条件和对变量的更改。
制作游戏的方式
| 方式 | 你编写的内容 | 运行方式 |
|---|---|---|
| 脚本文件夹 | .novella 脚本文件,与游戏的图像、声音和字体放在一起 |
NovellaPlayer run <folder> |
| C# | 一个 NovellaGame 或其派生类,故事写在脚本中、用 C# 故事构建器编写,或写成实时脚本 |
game.Run() 打开一个窗口 |
| Divooka | 创建并运行游戏的 Routine 或 Events 图,或者把游戏描述为数据(直到其条件、效果和场景)的 Function 图 | 运行图,或从其 Custom Preview 中游玩某个定义 |
故事本身可以用四种方式编写:写成脚本;在 C# 中用故事构建器编写,无需脚本;在 C# 中写成实时脚本,即一个本身就是故事的过程;以及写成 Divooka 节点,可以是函数式的(把序列、条件、效果和场景构建为数据),也可以是过程式的(Events 图中的实时脚本)。它们最终殊途同归:无论用什么编写游戏,产生的都是一个故事及其定义,并由同一个运行时来播放。脚本文件夹只需几行代码就能变成 C# 程序,Divooka 图可以从文档自己的库中加载同样的脚本,而脚本、构建出的标签和场景可以混合在同一个故事中。
define config.title = "The Garden"
character q "Qinglan" color "#c0392b" image qinglan
label start:
scene bg garden with fade
show qinglan smile at right with dissolve
q "You came."
menu:
"I did.":
q "Then sit with me a while."
"I was passing.":
q smile "Of course you were."
return
功能
- 类似剧本的脚本语言。 缩进构成代码块;对话就是说话者加一句带引号的台词。支持标签、跳转、带参数的调用、带条件的菜单、
if/elif/else、while、变量和持久变量。参见脚本语言参考。 - 无需登记的图像。 图像文件按其路径命名(
sprites/qinglan/smile.png即qinglan smile);缺失的图像会绘制为占位图,因此在任何美术素材完成之前就能游玩故事;分层图像可以组合服装和表情,而不必为每种组合准备一个文件。 - 舞台。 带位置、z 顺序和图层的 show、hide 和 scene;ATL 风格的动画时间线(属性、缓动函数、暂停、用于帧动画的图片行、
repeat、block、parallel、choice、time、on show/replace/hide、contains、function),在读档或回滚后会精确重放;能够自行播放动画的图像,例如闪烁的蜡烛;近五十种内置转场,从dissolve和fade到pixellate、irisin、pushleft,以及通过遮罩实现的图像溶解。 - 文本。 Ren'Py 的文本标签(粗体、颜色、字号、字体、用于假名注音和拼音的 ruby、
{w}、{p}、{nw}、{fast}、{cps})、[variable]插值、NVL 页面、居中文本、侧边图像和打字音效。 - 声音和视频。 音乐、音效、语音和环境音通道,支持淡入淡出、队列和循环;按台词 id 自动配音;全屏影片和影片精灵。
- 游戏自己的界面。 一种界面语言,包含容器、网格、框架和可滚动视口,
if、for和use,界面变量、按钮、进度条、文本字段、计时器和按键,每一帧都根据故事的变量重新布局:物品栏、状态栏、地图、谜题板。它可以显示在故事上方,也可以被调用来向玩家提问;可以在脚本中写成screen,也可以用 C# 或节点编写;更复杂的需求可以使用 C# 类。 - 键盘、鼠标和手柄。 每个界面,包括游戏自己的界面,既可以用键盘和鼠标操作,也可以用手柄操作。
- Python,如果游戏需要的话。
python:和init python:代码块通过 IronPython 运行真正的 Python,并可使用其标准库;它们设置的内容(包括对象和字典)会随故事一起存档、读档和回滚,它们定义的函数可以在任何表达式中调用。 - 玩家期望的每一个界面。 主菜单、游戏菜单、带缩略图的存档和读档、偏好设置、历史记录、画廊、音乐空间、成就、关于、帮助、确认和通知,全部由一个主题设置样式——主题是纯数据,即使不用任何一张图像也能工作。
- 样式。 与 Ren'Py 一样,样式是带有父样式以及
hover_、selected_、insensitive_和visited_变体的具名外观。每个内置界面都用样式绘制,主题也由样式组成,因此故事可以细化游戏外观的某一部分,给某个角色一个专属的对话窗口,把选项按钮做成带悬停图片的图片,或者用{style=name}给一句台词中的某个词着色。参见样式。 - 无需脚本的故事。 流畅的 C# 故事构建器和 Divooka 节点,每一种都能表达脚本语言所能表达的内容,从台词、菜单、条件和效果,到动画、分层图像、翻译、界面和 Python 代码块;场景,即 Novella One 的配置模型(一个背景、音乐、台词以及故事接下来的去向);以及用于实现节点无法组合出的逻辑的 Function 图。它们产生的故事都与脚本产生的相同,因此存档和回滚的方式也相同;唯一的区别是,它们传给标签、命令或界面的实参是在构建故事时就固定下来的值,而脚本传递的实参是表达式。
- 存档、读档和回滚。 每句台词、每个菜单和每次输入都是一个检查点;玩家可以向后和向前回滚、跳过已读文本、自动前进、快速存档和读档,而读档会精确还原画面,包括随机抽取的结果。
- 翻译。 逐句翻译和字符串翻译直接写在脚本中,引擎自身的界面已翻译为简体中文、繁体中文和日语。
- 面向作者的工具。 根据文件检查故事的 lint 工具,带有标签跳转功能的开发者控制台,游玩时重新加载脚本,以及为每一步保存一张带说明的屏幕截图的无头通关测试。



页面
- 安装:在 Divooka 和 C# 中从哪里获取 Novella。
- 入门:分别从脚本文件夹、C# 和 Divooka 制作第一个游戏。
- 概念:故事、标签、场景、角色、图像、舞台、运行器、检查点、存档、用代码编写的故事、实时脚本,以及键盘和手柄控制。
- 脚本语言:完整的参考,附带示例。
- 主题设置:每一项配置和主题设置、它们所对应的内置样式、字体、九宫格图像和界面翻译。
- 样式:带父样式和状态的具名外观、内置样式,以及在脚本、C# 和节点中应用于界面、角色和台词片段的样式。
- 在 Divooka 中使用 Novella:工具箱、过程式图和函数式图,以节点形式呈现的条件、效果、场景、动画、界面和样式,Function 图中的逻辑、预览和嵌入的资源。
- 开发:C# API、故事构建器、自定义命令、作为数据和作为类的界面,以及无头测试。
- 示例:Explore 示例和示例游戏 The Red Thread。
- 与 Ren'Py 的功能对等:哪些已支持、哪些部分支持、哪些尚未提供。
参考资料
- RFC 170 - Framework - Novella:设计文档。
- DevLog 20250512 Visual Novel Game Framework (Highlights),作者 Charles Zhang(dev.to),介绍最初的设计 Novella One。
- DevLog 20250516 NovellaOne, A Visual Novel Game Framework - Early Introduction,作者 Charles Zhang(dev.to)。