与 Ren'Py 的功能对等
Novella 的功能目标是与 Ren'Py 对等,同时采用它自己的 API 和编程风格。本页面记录第 1 次迭代中各功能领域的现状,依据的是引擎的代码,而不是计划。已支持表示其行为符合 Ren'Py 用户的预期;部分支持表示可以使用,但有所述限制;尚未支持表示没有该功能。有些差异是有意为之,标记为设计如此。
| 领域 | 已支持 | 部分支持 | 尚未支持 |
|---|---|---|---|
| 脚本语句 | 带属性的对话、临时 @ 属性、一次性说话者、台词 id,以及在台词出现之前播放的转场(with);旁白;extend;带 at、behind、zorder、as、onlayer 和内联 ATL 的 show、scene、hide;with;pause 和 pause hard;带标题、条件和 set 的 menu;具名菜单(menu name:),可以在故事的任何地方像标签一样被跳转或调用;jump、带实参的 call、带值的 return,以及 expression 目标;标签参数;if/elif/else;while;$ 赋值;play、queue、stop;voice 和 voice sustain;movie;input;window;nvl clear;notify;pass;define 和 default;带 ATL 块的 image name: |
自定义语句是用 C# 或 Divooka 实现的 run 命令,而不是新语法;call expression 不接受实参;在选择启用 Python 的游戏中,python: 和 init python: 通过 IronPython 运行真正的 Python,但 $ 是 Novella 自己的表达式语言,设计如此;代码块创建的、故事变量无法容纳的东西(对象、字典、集合)会被 pickle 到一个隐藏变量中,就像 Ren'Py pickle 它的 store 一样,而函数和类会在启动时重新定义,因此应放在 init python: 中;标准库随游戏一同提供 |
init 优先级;show expression;camera 和 show layer |
| 表达式 | 数字、字符串、布尔值、none、列表和索引;算术、链式比较、in、and/or/not、条件表达式;约三十个内置函数以及游戏自身的查询(visited、seen_label、seen_image、heard、achieved、showing);persistent. 变量;[expression] 插值;可由回滚重放的随机抽取 |
函数可以从 C#(RegisterFunction)、从 Divooka 图(Register Expression Function)添加,在选择启用 Python 的游戏中也可以从脚本通过 init python: 添加;在用 C# 故事构建器编写的故事中,条件或效果可以是作用于故事变量的 C# lambda,而在以节点编写的故事中,可以是交给 From Function 节点的 Function 图,二者都没有脚本形式 |
作为故事值的字典、对象和类(Python 可以创建它们并保留在存档中,但故事自身的表达式无法容纳它们) |
| ATL | 属性设置;使用 Ren'Py 的缓动函数(warper)和 Penner 系列进行插值;pause;带转场的图片行,用于逐帧动画;作为时间线的图像(image name:);repeat 和 repeat n;block;parallel;带权重的 choice;time;on show、on replace 和 on hide,变换处理 hide 的图像会一直保留到处理程序结束;contains;function,调用游戏在 C# 中注册的函数;按名称并带参数引入的变换;show 和 scene 下的内联时间线;标准位置;在读档或回滚后可精确重放的时间线(包括随机选择),因为每个显示的图像都保有一个已保存的种子 |
属性集涵盖位置、锚点、对齐、偏移、缩放、旋转、透明度、模糊、饱和度、亮度、色调和尺寸,但不包括 crop、极坐标、matrixcolor 或平铺;时间线表达式可以读取变换的参数,但不能读取游戏变量 |
event 语句(解析器将其报告为错误),以及用于图像自身的 show、replace 和 hide 之外其他事件的 on;样条和 circles |
| 转场 | dissolve、fade、flash、pixellate、move、ease;movein、moveout、easein、easeout 系列;四个方向的 slide、slideaway、push、wipe;irisin、irisout、zoomin、zoomout、vpunch、hpunch、blinds、squares、crossfade;带遮罩的 imagedissolve;带实参的具名转场;舞台语句、对话台词以及 show screen 和 hide screen 上的转场;关闭转场的偏好设置 |
带转场的 call screen 会在转场的时长内让被调用的界面淡入,无论转场是哪种类型,因为被调用的界面不属于舞台 |
MultipleTransition、ComposeTransition、AlphaDissolve 及其他转场类 |
| 图像和分层图像 | 由文件名定义的图像;内置的 black 和 white,无需定义;保留当前属性的属性解析;颜色图像;缺失美术素材的占位图;影片图像;滤镜(灰度、复古褐色、色调、翻转、缩放、裁剪、模糊、透明度、亮度、饱和度);composite;条件切换;侧边图像;带分组、multiple、默认值和条件的分层图像 |
分层图像缺少 if_any/if_all/if_not、逐层变换和偏移,以及 auto 属性 |
作为图像定义的文本、框架及其他可显示对象(displayable);动态可显示对象 |
| 舞台和图层 | master、transient、screens 和 overlay 图层,其中 transient 在每句台词、菜单、输入和点击继续的暂停之后清空;用 onlayer 以其他任意名称创建的图层,绘制在 master 之上、transient 之下,按名称排序;z 顺序和 behind;用 as 指定的标签 |
图层变换和镜头 | |
| 音频通道 | music、sound、voice、ambience 和 audio,以及带混音器、循环、默认淡出和 norestore 的自定义通道;淡入淡出、队列、单次播放音量、if_changed、别名和播放列表;音乐、音效和语音的音量及静音;读档和回滚时恢复通道;打字音效;WAV、MP3、AAC、FLAC、Vorbis 和 Opus 解码 |
音频滤镜和声像 | |
| 影片 | 带 noskip 和 keepmusic 的全屏 movie;舞台上的循环影片图像;经混音器输出的影片声音;无头游玩时对影片截图,并在影片可跳过时点击跳过 |
带 alpha 遮罩的影片 | |
| 语音 | voice、voice sustain,以及按台词 id 或角色根据文件模式自动配音 |
从历史记录重放某句台词的语音;按角色设置语音音量 | |
| 界面和界面语言 | 所有默认界面:主菜单、游戏菜单、存档、读档、偏好设置、历史记录、选项、输入、NVL、快捷菜单、确认、通知、画廊、音乐空间、成就、关于和帮助;启动画面标签;写成标签的主菜单;全部使用由主题生成的具名内置样式绘制;界面语言,可以在脚本中写成 screen 定义,也可以在 C# 中用 ScreenBuilder 或用 Screens 节点编写:容器 vbox、hbox、grid、frame、fixed,以及可裁剪、可滚动的 viewport;if/elif/else、for 和 use;界面变量(default);文本、图像、文本按钮和图片按钮(支持 sensitive)、进度条、输入框、空白、计时器和按键;用 at、align、pos 和 anchor 定位;动作 return、jump、set、toggle、notify、play、open(存档、读档、偏好设置、历史记录、画廊、音乐空间、成就、主菜单)、close、show、hide 和 run;每帧根据故事变量重新布局。界面用 show screen 显示,用 call screen 调用;玩家未作答就关闭的被调用界面返回 none |
界面语言无法表达的内容用 C# NovellaScreen 类实现,它优先于同名的已定义界面;主菜单之外的内置界面可以重新设置样式,但不能替换 |
拖放;图像映射(imagemap)的热点裁剪;界面元素上的变换 |
| 样式 | 带父样式的具名样式(style name is parent:),第二次定义会补充第一次;状态前缀 idle_、hover_、selected_ 和 insensitive_,外加用于在之前的游玩中选过的选项的 visited_,以及复合前缀 selected_idle_、selected_hover_ 和 selected_insensitive_,查找方式与 Ren'Py 相同(在每个样式上,先找最具体的前缀,再找不带前缀的属性,然后找父样式);背景可以是颜色、图片、frame(...)、solid(...) 或任何图像函数(Frame 和 Solid 两种写法均可);文本、容器、布局和声音属性;74 个内置样式(say_window、say_dialogue、choice_button、save_slot 等),每个内置界面都用它们绘制,它们由主题生成,因此主题的设置起到 Ren'Py 的 gui 变量的作用,而故事中的同名样式会对其进行细化;界面上的 style 和 style_prefix,以及直接写在元素上的属性;角色的 window_style、namebox_style、who_style 和 what_style,以及 what_size 40 这样的部件属性;{style=name} 文本片段;在 C# 和 Divooka 节点中同样可用;lint 会检查父样式、循环引用、属性名和值,以及所命名的每个样式 |
Novella 自己的属性集:outlines、xpadding 或 xminimum 等 Ren'Py 属性要写成 Novella 的属性(outline_width 和 outline_color、padding、xsize),或者没有对应项;背景是一个图像来源(图片、框架、颜色、合成图或经滤镜处理的图片),而不是任意可显示对象 |
Frame 的 tile,以及动画背景;在游戏运行时更改样式;文本片段的 {=style} 写法 |
| 存档、读档、回滚、快进、自动 | 带缩略图的分页存档位、删除存档、轮换的自动存档、快速存档和读档、Continue;以可读 JSON 格式保存的存档;after_load;带限制和 rollback_past_choices 的回滚与前进;快进已读文本、未读文本以及选项之后的内容;自动前进;隐藏对话框;截图 |
实时脚本(live script)不能存档、读档或回滚,用 Call Label 运行的故事标签也不能;存档的名称会被保存,但存档界面不会询问名称;pickle 无法写出的 Python 值(生成器、已打开的文件)不会被保留 | 从脚本阻止或固定回滚(block_rollback、固定回滚);云存档 |
| 历史记录 | 按显示内容记录的台词和选项,已翻译,带上限 | 语音重放;从历史记录返回到某句台词 | |
| 持久数据 | 默认值只应用一次的 persistent. 变量;已读台词、已见图像、已听音频和已到达的标签;之前游玩中做出的选择;成就;偏好设置,与存档分开保存 |
在多个游戏之间共享的数据(Ren'Py 的 MultiPersistent) | |
| 画廊和音乐空间 | 在其图像被看到时或按条件解锁的画廊条目,并附带查看器;被听到时或按条件解锁的音乐空间曲目 | ||
| 成就 | 定义、achieve、隐藏成就、通知、Achievements 界面、achieved() |
Steam 及其他平台后端 | |
| 翻译 | 按显式或推导出的 id 翻译台词;字符串表;在某种语言中删去一句台词;语言偏好设置;translate() 和 language();引擎界面的简体中文、繁体中文和日文版本;由 lint 报告的覆盖率 |
繁体中文和日文的界面表不完整,缺失部分回退为英文 | 按语言设置字体和样式;生成翻译文件的工具 |
| 文本 | Ren'Py 的文本标签,包括注音(ruby)、{w}、{p}、{nw}、{fast}、{cps}、内联图像和空白;{a=} 链接,在台词显示完毕后可点击,可以跳转到某个标签、调用某个标签后回到该台词,或打开网址;插值;NVL 页面;居中文本;按角色设置的字体、字号、颜色和引号 |
{vspace}、{k} 和 {clear} 会被接受并忽略 |
自定义文本标签 |
| 无障碍和自动朗读 | 文字大小和对话框不透明度偏好设置;转场开关;默认开启的文字阴影 | 自动朗读:该偏好设置会被保存,但偏好设置中没有对应开关,背后也没有语音合成器;无障碍菜单;字体和对比度覆盖 | |
| 开发者工具 | Lint(NovellaPlayer lint、Validate、控制台的 lint、Check Story 和 Check Game 节点);可以求值表达式、设置变量、列出问题并用 jump label 跳转的控制台(Shift+O);重新加载(Shift+R);从某个标签开始(--label);带描述截图的无头游玩;用 NovellaPlayer bench 测量帧时间 |
重新加载会从当前标签的开头重新开始,而不是从当前台词开始 | 跳转到某个文件和行;交互式导演工具;图像位置拾取器;变量查看器 |
| 不使用脚本的故事 | C# 故事构建器和 Divooka 节点都能表达脚本语言所能表达的内容,包括 Python 代码块、动画图像和使用容器布局的界面;Novella 的测试会用两种方式构建同一个故事,并比较各自打印出的脚本来验证这一点;用代码构建的标签不会落入下一个标签,lint 会在标签可能运行到末尾之外的地方给出警告 | 构建器和节点传给标签、命令或界面的实参是在构建故事时就固定的值,而脚本中的实参是在游玩时求值的表达式(Add Use Screen 接受表达式,因此列表的某一行可以把它的条目传下去);lambda 或 From Function 图没有脚本形式,因此使用了它们的故事无法从其脚本读回 | |
| 发行和构建 | 游戏可以作为 C# 程序运行(像任何 .NET 10 应用程序一样构建),可以作为用 NovellaPlayer 运行的脚本文件夹,也可以作为在 Divooka Compute 或 Explore 中的 Divooka 文档 |
打包游戏以供发行的命令;通过 Divooka 运行器模板一键发布到桌面;Android、iOS 和 Web 构建 | |
| 游戏手柄 | 用手柄操作每个界面,包括游戏自己的界面:A 继续和选择,B 返回或打开游戏菜单,Start 打开游戏菜单,方向键和左摇杆在按钮之间移动,肩键回滚和前进,X 隐藏对话框,Y 切换自动前进,Back 切换快进 | ||
| Live2D 和 3D | Live2D;3D 舞台 |
缺失功能的计划见 RFC 170。剩余的差距简要如下:界面中没有拖放或图像映射热点裁剪;不能在运行时更改样式;没有 ATL event;没有 Live2D、3D 舞台或自动朗读;没有移动端或 Web 构建;没有生成翻译文件的工具;也没有 block_rollback 或固定回滚。