入门
本页面用三种方式制作同一个小游戏。选择适合你的一种即可;游戏本身,以及你学到的有关脚本语言的一切,都可以沿用到其他方式中。各个工具从哪里获取,参见 安装。
开始时你不需要任何美术素材。故事中提到但找不到的图像会以占位图绘制(角色为剪影,背景为渐变),而引擎会用主题的颜色自行绘制对话框和菜单,因此故事从第一行起就可以游玩。
故事
下面的每个版本都播放这个脚本。将它保存为 game.novella(UTF-8):
define config.title = "The Garden"
character q "Qinglan" color "#c0392b" image qinglan
default met_before = false
label start:
scene bg garden with fade
"Plum blossom, and nobody in the garden but one girl with a guqin."
show qinglan smile at right with dissolve
q "You came."
menu:
"I did.":
q "Then sit with me a while."
"I was passing.":
$ met_before = true
q annoyed "Of course you were."
q "Listen, then."
return
从头读起:define config.title 为游戏命名;character 声明一个说话者,其名字以红色显示,图像标记为 qinglan;default 为变量指定初始值。游戏从 label start 开始。scene 清空舞台并显示背景 bg garden;单独一行带引号的文本是旁白;show 让 Qinglan 出现在右侧;q "..." 是她在说话;menu 提供两个选项;q annoyed "..." 在她说话时把她的表情换成 qinglan annoyed,并且此后保持不变;在无处可返回时,return 会结束游戏并回到主菜单。
方式 1:脚本文件夹
新建一个名为
The Garden的文件夹,把game.novella放进去。如果你有美术素材,就添加进来。图像按其路径命名,因此下面这些文件正好就是脚本所要求的图像:
The Garden/ game.novella bg/garden.jpg -> bg garden sprites/qinglan/smile.png -> qinglan smile sprites/qinglan/annoyed.png -> qinglan annoyed名为
images、sprites或characters的顶层文件夹不计入名称,路径的其余部分成为一个个单词,名称一律小写。运行它:
NovellaPlayer run "The Garden"主菜单随即打开。点击 Start。
检查它:
NovellaPlayer lint "The Garden"会列出故事引用了但并不存在的任何东西,例如没有对应文件的图像名称。
编写时,NovellaPlayer run "The Garden" --developer 会打开开发者工具:Shift+R 重新加载脚本并重新开始你所在的标签,Shift+O 打开一个控制台,在其中用 jump label_name 可以直接跳转到某个标签。
方式 2:C#
创建一个引用 Novella 项目的 .NET 10 控制台程序(参见 安装),把方式 1 中的文件夹以 Assets 为名放在它旁边,然后编写:
using Novella;
NovellaGame game = new("The Garden", 1920, 1080);
game.AddAssetFolder("Assets");
game.LoadScriptsFromAssets();
game.Run();
AddAssetFolder 告诉游戏它的文件在哪里,LoadScriptsFromAssets 按路径顺序加载其中的每个 .novella 文件,Run 打开窗口,并在玩家退出时返回。脚本中的 define config.width 和 define config.height 会覆盖这里给出的分辨率。
代码能做脚本做不到的事。下面故事用 run 向程序请求一些东西:
$ answer = "moon"
run riddle answer
if _return:
q "Correct."
using Novella.Values;
game.RegisterCommand("riddle", arguments => Value.FromBoolean(arguments[0].AsText() == "moon"));
命令的结果会放入 _return。开发 完整介绍了 C# API,包括把游戏写成一个类。
不使用脚本
故事也可以用 C# 编写。故事构建器写出的标签与上面的脚本相同,因此该游戏的存档、读档和回滚与脚本版完全一样;此时 Assets 文件夹中只需要美术素材:
using Novella;
using Novella.Building;
NovellaGame game = new("The Garden", 1920, 1080);
game.AddAssetFolder("Assets");
game.WriteStory(story =>
{
story.Character("q", "Qinglan", color: "#c0392b", image: "qinglan")
.Default("met_before", false);
story.Label("start", s => s
.Scene("bg garden", with: "fade")
.Narrate("Plum blossom, and nobody in the garden but one girl with a guqin.")
.Show("qinglan smile", at: "right", with: "dissolve")
.Say("q", "You came.")
.Menu(m => m
.Choice("I did.", c => c.Say("q", "Then sit with me a while."))
.Choice("I was passing.", c => c.Set("met_before", true).Say("q", "Of course you were.", "annoyed")))
.Say("q", "Listen, then.")
.Return());
});
game.Run();
条件可以是 C# lambda,例如 .If(v => v.Flag("met_before"), ...),也可以是构建出来的、能读回为脚本的值。完整的构建器参见 开发。
方式 3:Divooka
作为过程(Routine 图)
- 创建一个带有 Routine 图的文档。
- 打开文档的资源库(在 Divooka Compute 中为 Asset library 工具或 Ctrl+Shift+A),使用 Import files… 导入
game.novella和所有美术素材,并保持脚本所依赖的文件夹名称。 - 从 Novella 工具箱中,在执行路径上依次串联以下节点:
- Make Novella Game,标题为
The Garden,宽度为1920,高度为1080。 - Add Library Assets,连入游戏。它的库输入由文档提供,因此不需要连线。
- Load Scripts From Assets,文件夹留空,以加载库中的所有脚本。
- Run。
- Make Novella Game,标题为
- 运行该图。游戏会在自己的窗口中打开。

你也可以不导入脚本文件,而是把脚本输入到 Load Script 节点中;或者完全不用脚本,用 Define Character 和 Set Config 等节点来定义内容。
作为数据(Function 图)
故事也可以完全不用脚本,而写成节点:
- 创建一个 Function 图。
- 串联 Start Sequence → Scene(
bg garden,使用fade)→ Show(qinglan smile,位于right,使用dissolve)→ Say(角色q,文本You came.)。 - 用名称
start和该序列创建 Make Label。 - Start Story → Add Label(该标签)→ Add Character,由 Make Character(
q、Qinglan、#c0392b、图像qinglan)提供输入。 - 用标题和故事创建 Make Game Definition。
- 选中 Make Game Definition 节点,在 Properties 面板中打开它的 Custom Preview。游戏会在窗口中运行,存档保存在内存中,开发者控制台处于开启状态。
链上的任何节点都可以预览:序列以单标签故事的形式播放,没有 start 标签的故事从其第一个标签开始。条件和对变量的更改也是节点(If 搭配 Variable At Least,Apply Effect 搭配 Add To Variable);游戏还可以用 Make Scene 写成一个个场景,每个场景包含背景、音乐、台词以及故事接下来的去向。不使用自定义预览时,这些值会以它们所对应的脚本形式预览,因此你可以读到一串节点写出了什么。
在 Divooka 中使用 Novella 讲解了每个节点、用 Events 图编写游戏的方式,以及如何从 Flows 图调用描述游戏的 Function 图。