Branch
branch 指令可以创建分支流程,根据条件判断跳转到不同的执行路径。
branch({ Condition() { if (this.atk > 10) return "win"; if (this.hp > 10) return "alive"; return "gameOver"; },
// jump 到 chapter-2 这个 flag win: "chapter-2",
// 执行这些内容。 alive() { text`something wrong`; },
// 使用 `likely` 来标记更可能发生的分支 gameOver(likely) {},});- 条件判断,返回希望前往的分支。
- 分支目标
win - 分支目标
alive - 分支目标
gameOver
首先在 branch 指令中,定义一个名为 Condition 的函数(这个名称不可修改),用于控制分支。
branch({ Condition() { if (this.inGame.atk > 10) return "win"; if (this.inGame.hp > 10) return "alive"; return "gameOver"; },});this指向了游戏内可以访问的变量(见 World 变量)。win、alive、gameOver是分支目标的名称,可以任意指定。
这个示例 Condition 的逻辑为:当攻击力大于 10 时跳转到 win 分支,当血量大于 10 时跳转到 alive 分支,否则跳转到 gameOver 分支。
随后在 branch 中,定义每个分支的目标。目标可以是跳转到某个 flag,也可以是播放一段剧本。
branch({ Condition() { /* ... */ }
// 跳转到 chapter-2 这个 flag win: "chapter-2",
// 执行这些内容 alive() {
text `stay alive!`; Natsume.enter()
text `something wrong`; Natsume.leave()
jump("chapter-2") },
// 使用 `likely` 来标记更可能发生的分支,以便编译器进行优化 gameOver(likely) {},});Branch 支持嵌套,例如:
branch({ Condition() { /* ... */ },
alive() { text `看来我还活着!喝瓶可乐压压惊!`; branch({}); // 嵌套分支 },});尝试减少嵌套
Section titled “尝试减少嵌套”复杂的嵌套分支会导致剧本变得难以阅读与维护。
最简单的方法是使用 jump 指令跳转到不同的分支,避免嵌套。
此外,还可以利用 JavaScript 的特性,将分支写在一个函数中,然后在分支目标中使用这个函数。通过这种方法可以大量减少嵌套层数。
branch({ Condition() { /* ... */ },
// 执行 aliveResult 这个函数 alive: aliveResult,
// 或是在半当中调用 gameOver(likely) { aliveResult(); text `哎哟!力竭倒下!...`; },});
function aliveResult() { text `something wrong`; SomeBody.enter();
text `something wrong`; SomeBody.leave();}具有副作用的 Conditon
Section titled “具有副作用的 Conditon”默认情况下,你无法在 Condition 函数中执行具有副作用的操作(特别是赋值操作)。
branch({ Condition() { if (this.inGame.atk > 10) { this.inGame.money += 10; return "win"; } if (this.inGame.hp > 10) { this.inGame.hp -= 10; return "alive"; } return "gameOver"; },});如果你确信需要在 Condition 中执行副作用操作,可以使用 TypeScript 的类型绕过 as any。
Condition() { (this.inGame.love as any) = 10;}这将暂时禁用类型检查。
回忆 概览 中强调的,所有的控制流指令,都会强制结束目前的语段。
text `语段 1`;yohane.leave();
branch({ Condition() { /* ... */ }, alive() { text `语段 2`; yohane.leave();
text `语段 3`; yohane.leave(); },});
text `语段 4`;yohane.leave();在一些时候,我们可能希望在进入分支的时候,不强制结束语段,这个时候就轮到 directive.SceneBindNext 指令出场(语段分割逻辑不变,但连续播放)。
text `语段 1`;yohane.leave();directive.SceneBindNext;
branch({ Condition() { /* ... */ }, alive() { text `语段 2`; yohane.leave();
text `语段 3`; yohane.leave(); },});
text `语段 4`;yohane.leave();