- 剧本在
application/static/scripts中,ending.js为结局列表,stage1.js为目前的剧本。 - 图片放在
application/static/image中。 - 主要的代码是
application/static/app.js和application/static/scripting.js,前者负责逻辑,后者负责解析剧本。 - 网站只有一个网页,在
application/templates/index.html中。
pip install flask # install Flask (in Python 3.6)
npm install -g bower # install bower
bower install # download static files for the webpages
python run.py # start the server之后,便可通过http://127.0.0.1:8000/访问网页。
- @xllend3 指出,iOS 10.3的WebKit不支持CSS grid layout,而页面中选项的display样式设为
inline-grid,故无法显示。
剧本语法基于JavaScript,使用类似JSON的格式存储。
一个事件包含以下域:
type:事件类型,可以为main(剧情事件)或者random(随机事件)。目前的系统尚未区分两者。name:事件名称。这一名称会显示在剧情卡片的顶部。stage:事件阶段,即事件发生的时间在大学的那一年。可以是大一到大四,当然也可以是入学前、大二暑假之类的。pages:事件的各页面。
一个页面包含以下域:
id:页面的唯一标识,一个事件中所有页面的标识必须不同。事件会从id为start的页面开始。image:页面图片的链接。text:页面的文本内容。这个域应当是一个字符串的数组,每个字符串代表一段。此处也支持表达式和嵌套的数组,详情见样例剧本。input:如果包含了这个域,则页面会显示文本框,并在玩家进入下一页面前将文本框的内容存入这一域指定的变量中。actions:在玩家做出选择之后执行的动作。actionsBefore:在页面显示前执行的动作。choices:玩家可以做出的选择。如果不为空,则每个选项会显示为一个按钮;如果为空,则会显示一个"继续"的按钮。deadline:代表页面是一个QTE游戏。当存在这一域时,会忽略image、text、input,和choices。详情见后文。
一个选项包含以下域:
text:选项的文本内容。此处支持表达式,但其值必须是单个字符串。actions:选择选项后执行的动作。condition:使得选项可选的前提条件。这个域应当是一个求值后为布尔值的表达式。
动作有以下一些:
flag(var)、unflag(var):将布尔变量var设为真或假。set(var, value):将变量var的值设为value。increase(var, value)、decrease(var, value):令整型变量var的值增加或减少value。- 条件表达式:举个例子,大家体会一下:
可用的条件表达式包括:
ge("$魅力", 1).and(lt("$魅力", 3)).then( flagged("$送花") .then("她笑着谢谢你为她带的花,之后转身向门口走去。") .else(flagged("$载人").then()) )
- 比较:
ge、le、gt、lt、eq、ne,均接受两个参数。参数可以是具体值、表达式,或者是变量名; flagged(var):判断布尔变量var是否为真;not(cond):将条件表达式cond的值取反。
- 比较:
jump(id):跳转到标识为id的页面;如果页面中有多条jump动作,那么只有最后一条会生效。请参考动作执行顺序。achieve(name):达成名称为name的成就。ending(name):达成名称为name的结局。如果页面中有多条ending动作,那么只有最后一条会生效,而且跳转动作不生效。
关于跳转:如果一个页面不包含任何跳转动作,那么会进入下一个事件。
游戏中有两类变量:全局变量与局部变量。
- 全局变量: 以
#开头的变量,在整局游戏的所有事件中均生效。 - 局部变量: 以
$开头的变量,只在当前事件中有效。
变量有字符串、布尔、整型三种类型。变量不需要提前定义,会在第一次被使用时被赋值为默认值(布尔为假,整型为0,字符串为空串)。变量的类型也会在第一次使用的确定,之后无法更改。
变量可以在文本中显示,文本中形如{$局部变量}和{#全局变量}的部分都会被替换为对应变量的值。
动作执行与页面加载的顺序为:
- 执行页面的
actionsBefore中的动作; - 载入页面文本内容与选项;
- 玩家做出选择或点击"继续";
- 执行页面的
actions中的动作; - 如果玩家做出了选择,那么执行选项的
actions中的动作。
当页面中有deadline域时,代表进入QTE游戏。可以进行如下设置:
targets:一个数组,按钮单击次数的各个目标。最小的数字代表及格目标。建议将其按照从小到大的顺序排序。数组至少包含一个整数,最多包含三个。title:这次肝的项目名称。time:时间限制。moving:布尔值,代表按钮是否会移动。目前还没有实现。badChoices:迷惑按钮的数量。这些按钮是干扰玩家的,会减小已单击次数。
在游戏结束后,会设置局部变量$__QTE__,代表玩家达成的目标的最高编号(从1开始)。如果$__QTE__$为0,则代表玩家没有达成及格目标。
举个例子,如果目标为[40, 50, 60]:
- 单击了39次:
$__QTE__ = 0; - 单击了45次:
$__QTE__ = 1; - 单击了56次:
$__QTE__ = 2; - 单击了666次:
$__QTE__ = 3。
感谢李林翼(@llylly)、李晓涵(@lxhAtTHU)、潘星宇(@pxxgogo)、高童(@tonygaosh)提供剧本。
感谢黄家晖(heiwang1997)提供结局图片。
游戏中的其它图片均从互联网上收集,成就图标来源于Nova by Webalys。仓库所有者并不拥有其版权。
感谢所有参与测试和提供反馈的同学。