# 米菲剧场

米菲剧场是一款运行在浏览器中的轻量级ADV游戏引擎。米菲剧场提供了一套适合开发ADV的游戏脚本系统,一套米菲立绘,以及一些简单的游戏特效。与主流的桌面ADV引擎相比,米菲剧场不支持音频和视频回放,不支持自定义背景和立绘,不支持存档。但是对于“轻松制作ADV”的预期用途而言,米菲剧场的功能已经足够强大。

# 系统界面

米菲剧场的系统界面类似于大多数ADV游戏。舞台[4]是显示立绘的位置,可以同时容纳五个角色,并且角色可以在舞台上左右移动。场景说明[1]用于显示故事发生的时间、地点等说明信息。幕布[2]用于改变界面的色调,可以用不同的颜色和透明度来模仿清晨、黄昏、夜晚等效果。对话框[5]用于显示角色的对话。提示消息[3]用于辅助对话框,显示一些额外的信息。

# 编写脚本

使用米菲剧场制作ADV时,用户唯一需要做的就是编写游戏脚本。脚本中可以包含指令、标签、注释和空行。按照脚本中指令出现的先后顺序,系统依次执行每条指令。

+ 指令 -----

指令用于调用系统提供的各项功能。指令按照“[对象][.方法] [参数]”的格式书写,一条指令占用脚本中的一行。一条指令过长时也可以分行书写。在行尾添加下划线 _ 之后,就可以另起一行接着书写。书写指令时,可以省略掉某部分来简化书写。省略[.方法]时,调用对象的默认方法。省略[对象]时,使用上一条指令中调用的对象。当[参数]不会与[对象]和[.方法]产生混淆时,可以省略[对象]和[.方法],使用上一条指令中调用的对象和方法。

+ 标签 -----

标签用于配合各种跳转指令,改变脚本的执行流程。一个标签单独占用脚本中的一行,以 @ 号开头。每个标签都按照“@[标签名]”的格式书写。[标签名]是每个标签的唯一标识符,同一个脚本中[标签名]不可以重复。[标签名]只能使用数字、大小写字母、下划线,并且不能以数字开头。

+ 注释 -----

注释用于给脚本添加说明。一条注释单独占用脚本中的一行,以 # 号开头。

+ 空行 -----

空行用于脚本的排版。在脚本中插入空行不会对脚本的执行产生影响。

# 使用对象

每条指令通过调用[对象]的[方法]来完成各项操作。有些[方法]在调用时需要提供[参数]。指令中可以使用的对象包括内建的系统对象,以及脚本中动态创建的角色对象。

+ msg 对象 -----

默认方法

用途:显示一条提示消息。

参数:msg [颜色],[延迟],[文本]

说明:[颜色]为可选参数,使用十六进制颜色值,详细资料请参考HTML颜色名。省略时,提示消息使用上一次使用的颜色。[延迟]为可选参数,使用以毫秒为单位的正整数。使用时,系统在延迟时间之后自动执行下一条指令。省略时,系统等待用户点击鼠标后执行下一条指令。[文本]为必需参数,在不与前两个参数混淆的情况下,可以使用任何内容。

示例:复制

# 用绿色显示提示,延迟1秒后自动执行下一条指令
msg #00FF00,1000,米菲是什么..

# 省略颜色和延迟,等待用户点击
msg 是什么..

# 用红色显示提示,等待用户点击
msg #FF0000,米菲就是爱..

clear 方法

用途:清除目前的提示消息。

参数:无

说明:清除之后,系统自动执行下一条指令。

示例:复制

# 显示一条提示
msg #00FF00,1000,系统设计:OranGes

# 显示一条提示
msg #00FF00,1000,米菲设计:paradise infinity

# 清除提示信息
msg.clear

+ mask 对象 -----

默认方法

用途:设置幕布的颜色和透明度。

参数:mask [颜色],[透明度]

说明:[颜色]为必需参数,使用十六进制颜色值,详细资料请参考HTML颜色名。[透明度]为必需参数,使用0到100之间的整数。0为完全透明,100为完全不透明。设置之后,系统自动执行下一条指令。

示例:复制

# 设置幕布的颜色和透明度
mask #0000FF, 10

msg 到了晚上..

clear 方法

用途:清除目前的幕布。

参数:无

说明:等价于用参数“#FFFFFF,0”设置幕布。清除之后,系统自动执行下一条指令。

示例:复制

# 设置幕布的颜色和透明度
mask #0000FF, 10

msg 1000,到了晚上..

# 清除幕布
mask.clear

msg 到了早晨..

+ info 对象 -----

默认方法

用途:显示场景说明。

参数:info [编号],[颜色],[文本]

说明:场景说明使用上下两行文字,分别对应编号1和编号2。[编号]为必需参数。[颜色]为可选参数,使用十六进制颜色值,详细资料请参考HTML颜色名。省略时,说明文字使用上一次使用的颜色。[文本]为必需参数,在不与前两个参数混淆的情况下,可以使用任何内容。显示之后,系统自动执行下一条指令。

示例:复制

# 显示上行说明
info 1,#FF0000,5月3日

# 显示下行说明
info 2,#00FF00,星期日

msg 1000,一天过去了..

msg.clear

# 省略颜色,使用上一次的颜色
info 1,5月4日

# 省略颜色,使用上一次的颜色
info 2,星期一

clear 方法

用途:清除目前的场景说明。

参数:info.clear [编号]

说明:[编号]为可选参数。省略时,同时清除上下两行说明。使用时,只清除指定行说明。清除之后,系统自动执行下一条指令。

示例:复制

# 显示上行说明
info 1,#FF0000,生命值:999/999

# 显示下行说明
info 2,#00FF00,魔法值:999/999

# 清除上行说明
info.clear 1

# 重新显示上行
info 1,#0000FF,生命值:000/999

# 清除所有说明
info.clear

+ jump 对象 -----

默认方法

用途:跳转脚本的执行位置。

参数:jump [位置]

说明:[位置]为必需参数,使用[标签名]或者[+/-][整数]。使用[标签名]时,跳转到对应标签之后的第一条指令的位置。使用[+/-][整数]时,跳转到当前指令[之后/之前]的第[整数]条指令的位置。

示例:复制

# 跳转到标签“label1”之后的第一条指令
jump label1

msg 1000,麻婆加上..

# 跳转到当前指令之后的第3条指令
jump +3

# 定义一个标签
@label1

msg 1000,麻婆豆腐的原料是..

# 跳转到当前指令之前的第3条指令
jump -3

msg 豆腐..

+ back 对象 -----

默认方法

用途:返回最后一次跳转之前的脚本执行位置。

参数:无

说明:系统会依次记录下每次跳转之前的脚本执行位置。每返回一次,系统就按照与添加记录相反的顺序移除最后一次的记录。当没有任何记录时,返回指令不改变脚本执行位置。系统接着执行当前指令之后的第一条指令。

示例:复制

jump label1

msg 1000,我想想..

@label1

msg 1000,你喜欢米菲吗..

# 返回最后一次跳转之前的位置
# 没有任何跳转记录时接着执行下边的指令
back

msg 喜欢..

+ eval 对象 -----

默认方法

用途:计算数学表达式。

参数:eval [表达式], [表达式], ...

说明:[表达式]为必需参数,使用由[变量名]和[运算符]组成的数学表达式。参数中可以包含多组[表达式],每组之间用逗号 , 分隔。[变量名]只能使用数字、大小写字母、下划线,并且不能以数字开头。[运算符]的详细资料请参考JavaScript运算符中适用于数学运算的部分。首次出现的变量的值初始化为0。名为“rnd”的变量为系统保留变量,每次计算时,其值随机等于0到1之间的任意小数。可以使用“%[变量名]”的格式给其它对象的方法使用的[文本]参数里添加模板变量。

示例:复制

# 初始化变量x
eval x = 2

# 使用模板变量显示x的值
msg x = %x

# 变量y首次出现,初始值为0
eval x = ( x + y ) *  2, i = rnd

# 使用模板变量显示x和i的值
msg x = %x, i = %i

+ switch 对象 -----

默认方法

用途:根据表达式计算结果跳转脚本的执行位置。

参数:switch [表达式]:[位置], [表达式]:[位置], ...

说明:[表达式][位置]为必需参数。[表达式]:[位置]构成一组跳转条件,每组之间用逗号 , 分隔。指令执行时,从左到右依次计算每组跳转条件中的表达式。当某组中的[表达式]计算结果为非零的数字,或者为计算结果为真时,脚本执行位置跳转到该组中的[位置]。当所有跳转条件都不满足时,系统自动执行当前指令的下一条指令。

示例:复制

eval x = 2

msg 1000, 从前有%x根萝卜..

eval x = x - 1

msg 1000, 吃掉一根..

msg 1000, 还剩下%x根..

# 根据萝卜数量跳转脚本执行位置
switch x > 0 : -3

msg 最后萝卜没了..

+ branch 对象 -----

默认方法

用途:显示选折枝,根据用户的选择跳转脚本的执行位置。

参数:branch [文本]:[位置], [文本]:[位置], ...

说明:[文本]为必需参数,在不引起参数混淆的情况下,可以使用任何内容。[位置]为必需参数。[文本]:[位置]构成一组选择枝,每组之间用逗号 , 分隔。根据用户的选择,脚本执行位置跳转到对应的[位置]。

示例:复制

msg 1000,你喜欢米菲吗..

# 显示选择枝
branch 喜欢.. : +3 , 不喜欢.. : +1 

msg 1000, 但是米菲喜欢你.. 这样的话..

jump -3

msg 欢迎来到米菲乐园..

+ chara 对象 -----

默认方法

用途:创建一个角色对象。

参数:chara [对象名],[颜色],[角色名]

说明:[对象名]为必需参数,只能使用数字、大小写字母、下划线,并且不能以数字开头,并且不能与系统对象和已有角色对象重复。角色对象创建后,就可以在脚本中使用[对象名]来调用该角色对象。[颜色]为必需参数,使用十六进制颜色值,详细资料请参考HTML颜色名。[颜色]用于设定角色名和对话的颜色。[角色名]为必需参数,显示在角色的立绘上。

示例:复制

# 创建一个角色对象
chara miffy,#000000,米菲

# 使用新创建的角色
miffy.move 3

# 使用新创建的角色
miffy Happy~

角色.默认方法

用途:控制角色说话。

参数:角色 [表情],[延迟],[文本]

说明:[表情]为可选参数。使用时,在说话的同时切换表情。[延迟]为可选参数,使用以毫秒为单位的正整数。使用时,系统在延迟时间之后自动执行下一条指令。省略时,系统等待用户点击鼠标后执行下一条指令。[文本]为必需参数,在不与前两个参数混淆的情况下,可以使用任何内容。

示例:复制

chara miffy,#000000,米菲

# 移动角色
miffy.move 3

# 使用指定表情和延迟说话
miffy lovelove,1000,萝卜什么的..

# 省略表情和延迟
miffy 最喜欢了..

角色.face 方法

用途:切换角色表情。

参数:角色.face [表情]

说明:[表情]为必需参数,使用下列表情之一。切换之后,系统自动执行下一条指令。

angry
angry
ase
ase
back
back
fufu
fufu
happy
happy
kira
kira
kiss
kiss
love
love
lovelove
lovelove
no
no
orz
orz
sad
sad
silent
silent
sleepy
sleepy
thx
thx
yes
yes

示例:复制

chara miffy,#000000,米菲

# 移动角色
miffy.move 3

# 更改表情
miffy.face orz

miffy 萝卜没了..

角色.move 方法

用途:控制角色移动。

参数:角色.move [编号]

说明:[编号]为必需参数,使用0到5之间的整数,用于控制角色从当前位置移动到[编号]的位置。舞台按从左到右的顺序,提供编号1到5的五个位置用于显示立绘。当[编号]的位置空余时,角色开始移动。当[编号]的位置被其他角色占用时产生一个错误。编号0表示离开舞台。新创建的角色的初始位置编号为0。

示例:复制

chara yuuiti,#0000FF,佑一

chara ayu,#FF0000,阿由

# 佑一上场
yuuiti.move 2

# 阿由上场
ayu.move 4

# 移动阿由
ayu.move 3

ayu no,前面的人快闪开~~

yuuiti kira,啊?

# 位置2被佑一占用,以下指令产生一个错误
ayu.move 2

角色.tmpl 方法

用途:设置角色的对话模板。

参数:角色.tmpl [模板]

说明:[模板]为必需参数,可以使用任意内容,并且必须包含模板变量“%s”。对话模板设置后,角色说话时,使用[文本]参数替换掉“%s”,用替换后的模板作为说话的内容。

示例:复制

chara miffy,#000000,米菲

# 设置对话模板
miffy.tmpl 米菲「%s」

miffy 欢迎加入米菲乐园演剧部~

# 调试脚本

米菲剧场具有简易的调试功能。推荐用户使用带行号显示功能的文本编辑器编写游戏脚本。编写好之后,可以把脚本复制到本页面顶部的脚本输入框里,执行并查看实际运行效果。脚本中包含错误时,系统会显示简易的错误描述,以及发生错误的指令所在的行数。用户可以根据这些信息来查找和修改错误。另外,脚本执行过程中点击系统界面的“skip”按钮可以关闭各种动画特效,便于快速检查脚本。

# 完整示例

以下示例演示了米菲剧场的所有特性,供用户学习和参考。

示例:复制

# Miffy_Show Sample Script Chinese Ver.
# 小白兔大冒险
# by 悠久ノ風
# written at 2009/06/20


# 初始化角色 ---------------------------------------------------------

chara pb, #777777, 旁白
baitu, #FF6600, 小白兔
xiong, #7F0000, 熊大爷

baitu.tmpl 小白兔「%s」
xiong.tmpl 熊大爷「%s」


# 故事开始 -----------------------------------------------------------

mask #FFFFFF, 70
msg #FF6600, 2000, 这是某个兔子星的某只小白兔的故事..
.clear
mask.clear

eval day = 0, carrot = 3
info 1, #0033FF, 第%day日
info 2, #33FF00, 萝卜%carrot根

baitu.face back
baitu.move 3

形式已经相当严峻了…接下来要怎么办呢?
家里的萝卜也只剩下三天的份了。

pb 终于有一天,小白兔带上最后的三根萝卜,踏上了不归路。
到达堆满了萝卜的乐园需要七天时间。
但是每天都需要吃掉一根萝卜。
只靠三根萝卜的话,旅途会变得相当艰险。

baitu kira, 总会有办法的吧~
pb 于是,小白兔的旅途开始了。

baitu.move 0
eval day ++


# 七天循环开始 -------------------------------------------------------


# 早晨
@morning

mask #FFFFFF, 30
info 1, 第%day日
pb 到了早晨。

baitu.move 5
今天也加油哦~
mask.clear

baitu.face happy
pb 1000, 走啊走…
baitu.move 4
pb 1000, 走啊走…
baitu.move 3

# 随机事件发生。熊遭遇事件(40%),种萝卜事件(40%),平安无事(20%)。
switch i = rnd < 0.4 : bear, i < 0.8 : field


# 平安无事
pb 今天什么也没发生,平安地度过了。
jump evening


# 熊遭遇事件
@bear

baitu.face no
xiong.face kira
.move 1

pb 遇到熊大爷了!
xiong 嗷嗷嗷!把萝卜交出来!
pb 怎么办?

# 没有萝卜的话就拼了吧
switch carrot == 0 : +2
branch 交出一根萝卜…:give, 与熊大爷战斗!:battle
branch 与熊大爷战斗!:battle, 与熊大爷战斗!:battle

@give

eval carrot--
info 2, 萝卜%carrot根
xiong 哦呵呵呵呵!你是只好兔子!
.move 0
msg #FF0000, 1000, 失去了一根萝卜…
.clear
jump evening

@battle

pb 1000, 惊天动地的战斗之后…

# 战胜成功率20%
switch rnd > 0.2 : battle_fail

baitu.face yes
xiong.face orz
.move 0
pb 熊大爷奇迹般地被打败了!
eval carrot += 2
info 2, 萝卜%carrot根
msg #FF3300, 1000, 战利品萝卜两根入手!
.clear
jump evening

@battle_fail

baitu.face sad
xiong.face kira
pb 你只是一只小白兔…毫无悬念地被秒杀了…
switch carrot < 2 : +5

eval carrot -= 2
info 2, 萝卜%carrot根
msg #FF0000, 1000, 两根萝卜被夺走了!
jump +4

eval carrot = 0
info 2, 萝卜%carrot根
msg #FF0000, 1000, 一根萝卜都没有了!

msg.clear
xiong.move 0
jump evening


# 种萝卜事件
@field

baitu.face kira
pb 发现了希望的田野!
switch carrot > 0 : +4

baitu.face sad
pb 但是一根萝卜都没有了…
jump evening

pb 要种一根萝卜试试看吗?
branch 种一根:+1, 算了:evening

eval carrot--
info 2, 萝卜%carrot根
pb 种了一根萝卜。
1000, 接下来小白兔等了好久好久…

# 种植成功率60%
switch rnd > 0.4 : +4

baitu.face sad
pb 到最后什么都没发生…
jump evening

baitu.face lovelove
eval carrot += 2
info 2, 萝卜%carrot根
msg #FF0000, 1000, 长出来两根萝卜!
.clear
jump evening


# 晚上
@evening

mask #000033, 30
baitu.face fufu
pb 晚上到了。

switch carrot == 0 : bad_end

baitu 来吃萝卜吧。
eval carrot--
info 2, 萝卜%carrot根
msg #FF0000, 1000, 萝卜又少了一根…
.clear
pb 接下来夜深了…
baitu.move 0
.face kira

# 检查是否撑了七天了
switch day == 7 : good_end, day++ : morning


# 故事结束 -----------------------------------------------------------

@good_end

mask #FF6600, 10
pb 七天的旅途过去了,小白兔终于来到了米菲乐园。
堆得像山一样高的萝卜印入眼帘。
baitu 啊啊啊!太了不起了!
pb 于是小白兔的幸福生活再次开始了。
mask #FFFFFF, 70
msg #FF6600, _
于是故事到这里也就结束了…
jump end

@bad_end

baitu.face sad
baitu 已经一根萝卜都没有了。看来俺的日子也到头了…
mask #000000, 70
msg #FFFFFF, _
谁也不知道的寒冷的深夜里,小白兔去了天国…

@end