-
Notifications
You must be signed in to change notification settings - Fork 3
快速开始
一组剧本有多个 场景 组成,一个场景可以用于表示一段剧本或者一幕UI,以下例子定义了一个名为main
的场景:
- scene "main"
同一个文件可以定义多个场景,例如:
- scene "main"
- scene "abc"
- scene "def"
对于-
开头的定义,被称作 顶级定义 。
YukimiScript可以使用#
符号来表示行注释,如以下例子:
# 这是一段注释
- scene "main" # 这里定义了场景main
# 注释
在场景下可以定义一段文本,以下例子定义了一个名为main
的场景,里面有一段旁白:
- scene "main"
这里是一段旁白。
如果对话特别长的话,可以使用\
符号换行:
- scene "main"
这是一段特别特别长的文本,\
特别特别长~~~~~~~~~\
然后到这里就结束了。
如果需要表示一个角色,则可以编写这样的一段对话:
- scene "main"
今天也是金砂镇和平的一天呢。
杰西卡:早上好啊!苏紫。
苏紫:早上好啊,杰西卡。
说时迟,那时快,只见杰西卡将燧发枪抵在了苏紫的脑袋上。
如果你需要使用半角“:”符号,那么你可以使用空的角色名称来表示这是一段旁白:
- scene "main"
:这里是关于:符号的一个例子。
:正如你所看到的,可以使用一个“空角色”来表示对话角色,之后便可以自由使用“:”符号了。
你也可以不使用前导冒号,但是这样的话对话中就不能出现前导冒号了。
一般情况下我们可以省略前导冒号的“空角色”语法,但如果需要使用半角冒号,\
那么就应该前导冒号表示旁白,以和后面的冒号作出区分。
文本必须写在场景定义的下方,否则我们不知道这条文本到底属于哪个场景,比如以下的例子是错误的:
# 错误的例子
今天也是金砂镇核平的一天呢。
这段例子并没有定义场景,因此编译器会报错“在第1行找到了悬浮操作”。
以@
开头可以调用一个命令,比如以下例子:
- scene "main"
@textwindow.hide # 调用了textwindow.hide命令
@textwindow.show # 调用了textwindow.show命令
有的命令可能会具有参数,比如以下例子:
- scene "main"
# 调用命令并传入file参数和effect参数
@bg.play --file "bg/background.png" --effect fade
有的参数名字可能会非常长,因此可以省略参数名,没有参数名的参数将会按顺序传入:
- scene "main"
@bg.play "bg/background.png" fade
或者也可以一部分参数传入参数名,另一部分不使用参数名,在这种情况下,不带参数名的参数必须放在左边:
- scene "main"
@bg.play "bg/background.png" --effect fade
有的命令的某些参数可能具有默认值,当省略时将会采用默认值传入:
- scene "main"
@bg.play "bg/background.png" # 此命令的effect参数默认值是fade的话,可以不传入
@bg.play --file "bg/background.png"
例如以下例子,是错误的,因为带参数名的参数被放到了不带参数名的参数左边:
- scene "main"
# 错误的例子
@bg.play --file "bg/background.png" fade
与文本相同,命令也必须写在场景定义的下面。
参数具有以下几种类型:
- 字符串(需要使用半角双引号包住,例如
"a"
、"super"
等) - 实数(其中一定含有一个点号,例如
1.0
、-12.5
等) - 整数(一定不带点号,例如
1
、-12
等) - 符号(一个不被半角双引号包住的串,例如
true
、false
、S
、J
等) - 特别地,在宏中可使用类似
$"a={a}"
的字符串格式化语法
如果你需要关于类型的详细信息,或者需要进行类型检查,请参见“类型检查器”一节。
可以在文本内嵌入命令,以在文本中执行,文本中嵌入的命令使用[
和]
包裹:
- scene "main"
A:惊![wait --time 5]你们在做什么!
E:快把枪放下![wait 5]你们不要打了啦!
可以用<
和>
包裹一段被某个符号标记的文本,比如我们有一个符号bold
表示粗体,那么我们可以作如下标记:
- scene "main"
这一段文本中,<bold 这几个字>是粗体。
标记可以嵌套,比如现在我们还有斜体标记ita
,就可以写出这样的代码:
- scene "main"
这一段文本中,<bold 这几个字>是粗体,<ita 这几个字>是斜体,<bold <ita 这几个字>>是粗体斜体。
以上文本命令将会被编译为 文本命令 ,可以通过手动调用文本命令来实现某些功能。
文本命令已经被预定义为系统外部定义,参见本章“外部命令”的部分。
关于文本命令如何使用,参见“编译”中“展开文本命令”的部分。
如果一个场景,它的初始状态继承于另一个场景(比如从某个场景跳转到这里但是背景、音乐等状态不发生改变的时候),则使用scene
声明后跟inherit
来声明状态继承。
inherit
声明仅用于编辑器创建实时预览,编译器和剧情图生成器并不关心inherit
声明。
# 一些外部命令的声明
- extern select.add text target
- extern select.do
- extern goto
- macro select.add text target # 重载select.add外部方法以在图生成器中创建连接
@__diagram_link_to target # 指示剧情图生成器生成对应的图
@select.add text target # 调用外部命令select.add
- macro goto target # 同上
@__diagram_link_to target
@goto target
- scene "场景A 起始"
@select.add "选择支1" "场景A 分支1"
@select.add "选择支2" "场景A 分支2"
@select.do
- scene "场景A 分支1" inherit "场景A 起始" # 指示编辑器,此场景起始状态为"场景A 起始"的终末状态
@goto "场景A 结束"
- scene "场景A 分支2" inherit "场景A 起始" # 指示编辑器,此场景起始状态为"场景A 起始"的终末状态
@goto "场景A 结束"
- scene "场景A 结束" inherit "场景A 分支1" # 指示编辑器,此场景起始状态为"场景A 分支1"的终末状态
如果你已经安装了.NET,那么可以使用这种方式安装编译器:
dotnet tool install -g YukimiScript.CommandLineTool
如果需要将其作为独立的可执行文件使用,需要自行从源码执行dotnet publish
命令。
如果你没有安装.NET,那么可以使用这种方式安装编译器。
Windows平台和macOS平台为AOT编译生成的可执行文件。
Linux平台为.NET单文件发布的可执行文件。
- 在Github Release下载对操作系统的包。
- 将其复制到PATH目录,使其可在终端使用。
- 确认命令
ykmc
可用。
除此之外,它也可以作为独立的可执行文件使用。
使用以下命令即可将单个YukimiScript编译为单个Lua文件:
ykmc ./main.ykm --target-lua ./main.lua
其中./main.ykm
为待编译的YukimiScript,./main.lua
则为编译生成的Lua代码。
如果需要附加额外的库,可以传入-L
参数和-l
参数。
ykmc ./main.ykm --target-lua ./main.lua -L../my_engine/ykmlib -lmy_engine
使用-L
参数添加库搜索目录,使用-l
添加要链接的库。
如-L../my_engine/ykmlib -lmy_engine
,将会从目录../my_engine/ykmlib
中搜索libmy_engine.ykm
作为库导入。
另外你也可以设置环境变量YKM_LIB_PATH
来添加搜索目录而不必从-L
参数指定,YKM_LIB_PATH
环境变量可以用;
进行分割。
YukimiScript一般需要和其目标码写成的其他代码或宿主语言代码交互(如使用Lua作为编译目标时,需要与Lua进行交互)。
可以通过“外部定义”语法,定义来自其他语言的命令:
- extern system_call
extern
定义内部不能出现任何内容,其后只能出现新的顶级定义,如以下内容是错误的:
# 错误的例子
- extern system_call
@wait 5 # 错误!extern不能包含内容
如果出现顶级定义的话是没问题的:
- extern system_call
- extern system_call2
- scene "main"
这里是场景main的内容。
外部定义可以声明参数,这些参数将会被传递给与其交互的语言编写的代码:
- extern bg.play file effect # 定义了一个bg.play命令,它含有两个参数file和effect
也可以定义一个默认值:
- extern bg.play file effect=fade # 为effect参数定义了默认值fade
- extern bg.play2 name filename=$"{name}.png" # 默认值也可以使用字符串格式化语法
之后便可调用这个命令:
- extern bg.play file effect=fade
- scene "main"
@bg.play "bg/background.png"
关于对外部定义的调用如何传递给目标语言,参见“目标代码”部分 。
外部定义一般在lib
文件夹下,或引擎提供的额外附加库中,用于实现脚本与引擎的交互。
为了支持YukimiScript语言本身,存在一些语言预定义的系统外部定义。
如果需要集成YukimiScript,则宿主语言必须实现这些系统外部定义。
关于系统外部定义的列表,参见“系统外部定义参考”。
YukimiScript编译后的目标代码只包含对外部定义的调用。
对于重复的代码,可以使用宏来化简,可以使用这种方式来定义宏:
- macro bg.play file effect=fade # 名称和参数的定义同外部定义一致
@system.set_bg file # 宏的内容
@system.set_effect effect
@system.start_bg_transform
如果在宏中需要加入文字,则需要使用“系统外部定义参考”中“文字相关”部分的命令,不可以直接使用文本语法。
对宏的调用同外部命令一致。
宏可以调用其他宏,但不能递归,也不能多个宏之间相互递归。
宏将会在编译期被展开,形式参数会在编译期被替换为传入的实际参数。
如果宏的名称与某个系统宏或外部定义一致,则视为对那个系统宏或外部定义的重载,重载版本的参数列表不必一致。
在宏内使用这个宏的名称即可调用重载前的宏,以下是对__diagram_link_to
系统宏的重载:
- macro __diagram_link_to target
@__diagram_link_to target # 这里调用的是重载前的版本
可以扫描某个文件夹下所有的YukimiScript,并将其场景及其跳转关系绘制成DGML格式存储的有向图。
对于需要生成图的场景,则需要使用__diagram_link_to
命令表示这个场景可能跳转到的所有目标场景。
__diagram_link_to
是一个系统宏,参见“系统宏参考”。
Examples/Diagram
目录下已经有写好的关于剧情图的Demo,可使用其生成一个用于测试的剧情图。
- scene "a"
@__diagram_link_to --target "b1"
@__diagram_link_to --target "b2
- scene "b1"
@__diaram_link_to --target "b2"
- scene "main"
@__diagram_link_to --target "a"
之后对编译器调用diagram子命令即可对一个文件夹中的所有YukimiScript生成图。
ykmc diagram dgml ./my_project ./my_project.dgml --lib ~/my_engine/lib1 --lib ~/my_engine/lib2
该有向图文件可以使用Visual Studio中的DGML编辑器打开,或者使用Visual Studio Code的DGML Viewer插件打开。
同样,你也可以生成Mermaid Flowchart图文件,具体参考README.md
中的“Usage部分”。
如果普通编译时需要传入lib
参数,则生成剧情图时也应当传入相同的lib
参数。
__diagram_link_to
命令一般不被直接使用,它一般是包裹在一个跳转宏中,当用户执行跳转命令时,__diagram_link_to
会被自动展开到调用处。
__diagram_link_to
命令会在“展开系统宏”阶段被消除,参见“编译”。