也是去年的差不多这个时间,工作之余接触了inky,一时惊艳。inky专门为了互动小说设计了一套简易的逻辑语言,然后可以decode为js代码,对于非软件背景出身的人却又做文字AVG的心来说,这是将无可能变成有可能的质变。
于是花了一个周末研习语法,然后又花了一个周末移植 了一个经典文字AVG《潜伏之赤途》,做的十分稚嫩:
本以为这会是自己业余开发文字AVG的开始,谁料工作中接连出现了2个紧急的项目,且都需要本人下场救火,成为一个业余AVG作者的计划无奈只能不断后延。恍惚一年过去,老的工作已经结束,新的工作还未落定,这才想起,原来一年前的今日还有过这样的闲情逸致。
可能是能力不济,也可能是患得患失,人总是陷入不自由的境地。陈寅恪在《答北客》里说:“柳家既负元和脚,不采蘋花即自由”。对于陈寅恪,不采蘋花意味着拒绝涉足政界,而对于我等打工人而言,不采蘋花大抵意味着从过于没有work-life-balance的地方默默出走,去到一个可以让自己做点自由且无用的事情的安静地带。
总之,希望新的一年自己做个业余文字AVG作者的爱好可以继续下去。
附录:inky学习笔记
一个节点/选项=<div> ,每一行都是一个<p>。节点必须为英文名
inky语法对换行符敏感、对大小写敏感,如果出现语法错误,建议先在换行符上下点功夫。然后部分语法识别中,空格也是必要的。
1元素:节点
-子节点
节点至少要用==表示,而其子节点用=表示,引用子节点需要相对路径,具体看引用位置和被引用子节点的相对位置,和css的引用一致
2元素:选项
选项通常用*表示,子选项用**、***表示。
->END是一个特殊节点,进入后游戏结束
-备用选项
有的时候可能所有选项都是条件判断,在全部条件判断都失败的情况下,故事应该被判定死局进入end,但是这样意味着我们要在每个选项下写一个死局判定,太过麻烦,inky用
*->
表示备用选项,会在前面的所有*选项都被选择过的情况下自动选择
-固定选项
一般选项用*表示,只能选择一次,可重复点击的选项用+。(可重复点击意味着必然存在循环结构)
通过标签跳转到选项等于选择了该选项,也会用掉选项的选择次数。
-不输出到内容的选项
用[]表示,
在它前面的内容,会成为选项且输出到内容;
在它里面的内容,会成为选项但不会输出到内容;
在它后面的内容,只会输出到内容
很多时候[]里面直接不写内容
之所以有这个东西,是为了让跳转节点干净一些,in case还有其他选项会跳转到对应节点
3元素:收束
-收束
选项不一定要跳转到新的平级节点,可以用- 表示收束到一起。为收束位置添加标签则是常见的做法
*A
选A后发生的事情,可以包括子选项、跳转子节点
*B
选B后发生的事情
-xxxx
-子收束
如果子选项也有收束,那么可以用--表示子收束。-的数量和*的数量一致。
-标签
可以用-()添加标签,节点、子节点和标签的性质相同。标签的概念在选项{}中很重要。
引用标签需要用相对路径,节点.标签。
有的地方并不需要约束,但为了加标签,也可以加--前缀。
1逻辑:条件
为了避免混淆,不允许在条件中添加-约束点。
-运算符
逻辑运算符,非not !,与and &&,或or ||,相等==,不等!=,子字符串?,()修饰
-默认:是否经过某个标签
{标签A:执行|执行}
实际上标签名是一个数字变量,记录了其被显示的次数,{标签A:}其实是{标签A>0:}的简略。
执行内容至少需要一字符,如果是不执行,也需要输入一个空格
-更普遍情况:在{}用表达式写条件
选项开头{a<3}选项,内容:{a<3:显示内容|else显示}
-条件语句
if用-代替,else前需要加-
{
- clue == 0:
you died
- clue > 0 and clue <=2:
~fear+=3-clue
->challenge
- else:
->challenge
}
如果只有两种情况,直接用{条件:执行|否则执行}即可,不需要-和else
第一行必须是空的
-选择语句
{ clue:
- 0: you died
- 1: ~fear+=2
- 2: ~fear++
- else: ->challenge
}
第一行必须非空。inky用这种方式识别条件和选择语句。
-实际使用
可以直接在条件语句中包括选项。最常见的如{条件:
*选项->xxx
}
(注意换行的必要性)
不符合就等于没这个选项。复杂的如
{ door_open:
* 我大步走出车厢 [] 并且我仿佛听见我的主人在低声地自言自语。->outside
- else:
* 我请求离开 [] 主人礼貌的和我再见。 -> open_door
* 我站起来打开了门 [],并和主人告了别。 -> open_door
}
2逻辑:变量
VAR定义全局变量,VAR记得大写,函数/指令同。不能在定义阶段直接采取运算。
{变量表达式}在内容中对其值进行引用,(变量)在标签/选项中进行引用,在运算时则无需{}、()
~ temp 定义临时变量,仅在当前节点下生效。temp必须小写。
-极简变量引用案例(原理看不懂,照猫画虎)
* [Accuse Hasting]
-> accuse("Hastings")
* [Accuse Mrs Black]
-> accuse("Claudia")
* [Accuse myself]
-> accuse("myself")
=== accuse(who) ===
"我控诉 {who}!" 波洛宣布。
“真的吗?” Japp 回道。 “{who == "myself":你要这么做?|{who}?}”
“为什么不可以?” 波洛回击道。
-可变文本
随机文本:{~A|B|C}会等比例随机呈现其中一个文本
序列文本:{A|B|C}第一次点击该节点,显示A,第二次B,之后全部C
一次性序列文本:{!A|B|C},第三次C,之后空白,相当于最后一个是空白的序列文本
循环文本:{&A|B|C}略
可变文本用于那些需要多次进入的节点。如果同一节点下,有两个序列文本,里面的内容也会根据次序匹配着呈现,比如
=== turn_on_television ===
我打开电视{一次|两次|三次|更多次},但电视上 {没啥有意思的东西,所以关上了电视|依旧没什么有意思的东西|比以前更不能吸引我的兴趣了|只有垃圾|演关于鲨鱼的节目我并不喜欢鲨鱼|什么都没有}。
+ [再试试] -> turn_on_television
* [去外面] -> go_outside_instead
=== go_outside_instead ===
-> END
序列文本中都可以插入跳转,从而避开后面的文本,这可以实现循环一个节点一定次数后再呈现后续内容,并每次都呈现新的反映。比如在下面,我们试图实现在3个选项中至多选2个的效果:
==opts
{loop: |暗影长老只会回答你两个问题:}
* [了解高玮宁的情况]
{loop<2:“他曾经是我以外最优秀的吸血鬼,它已经死了。”}
* “告诉我安防系统”
{loop<2:“他很老,” 暗影长老缓缓说, ”就像古董一样老。但它依然可以工作。"}
* “你妈还活着吗?”
{loop<2:“……”长老没有回答你。}
* {loop} [问够了]
-> done
- (loop)
{ -> opts | “又是问题。再问就给我去死。”长老缓缓说。-> opts | }
暗影长老抬起眼睛看向你。<br/>“不,等等!”就在你出声的瞬间,它瞬间杀死了你。
->END
==done
你谢过暗影长老,离开了洞穴。->END
可变文本的作用很大,你可以其中插入跳转,但是你无法插入选项。
-运算
~运算标志,例如~luoxiaohan++,可表示在选择某选项后,罗小涵的好感度+1
随机文本也可以参与运算,比如~a="{~shit|fart|pee}"
3细节:修饰
-图像
让图像文件夹保持在项目文件夹下,采用相对路径访问
#IMAGE:relative path
-css
#CLASS: 名称A
css选择器,在项目文件夹下的style.css中添加 .名称A{自定义style内容}(常用color:red, color:yellor}
之前也玩过一小段时间的 ink,挺喜欢里面的灵活的书写方式,不过由于对多语言的支持不太好就放弃了,然后最近吸收了一些剧情管理软件的特点撸了一个满足自己使用习惯的软件,现在还在试坑中