Skip to content

04 · 分支与导航 ​

本章讲解如何用 menu 制造选择,用 navigate / jump / call 控制剧情走向。

label 标签 ​

label 是剧情的锚点,用 navigate 跳转:

dsl
label forest:
  say "你来到了森林。" speaker="旁白"
  navigate "town"

label vs scene

  • scene——含 UI 元素的完整画面
  • label——纯脚本片段,不含 UI 元素

navigate 两者都能跳。引擎会在所有 .story 文件中查找匹配的名字。

dsl
navigate "chapter1"       // 跳到场景或标签
navigate "forest_battle"  // 跳到另一个标签

navigate 是最常用的跳转方式。跳转后,当前标签的后续代码不再执行。

dsl
menu "你要怎么做?"
  "战斗" -> wolf_battle
  "逃跑" -> wolf_flee
  • 第一行是提示文字(可选)
  • 每行一个选项:"显示文字" -> 目标标签

玩家选择后,跳转到对应标签。

无提示文字的 menu ​

dsl
menu
  "选项一" -> option1
  "选项二" -> option2

完整分支结构 ​

dsl
label encounter:
  say "一只野狼挡住了去路!" speaker="系统"
  menu "你要怎么做?"
    "战斗" -> wolf_battle
    "逃跑" -> wolf_flee

label wolf_battle:
  say "你拔出武器!" speaker="旁白"
  if {player.hp > 20}
    say "你战胜了野狼!" speaker="系统"
    set "player.exp" {player.exp + 30}
  else
    say "你太弱了,被野狼击退。" speaker="系统"
    set "player.hp" 1
  navigate "town"

label wolf_flee:
  say "你转身跑开了。" speaker="旁白"
  navigate "town"

jump 跳转 ​

jump 与 navigate 类似,但不创建回溯检查点:

dsl
jump "shared_ending"   // 跳转,但回溯时跳过这一步

jump vs navigate

  • navigate——创建检查点,可回溯
  • jump——不创建检查点,回溯时跳过

大多数情况用 navigate。jump 适用于跳转到共用代码段(如结局判定),不需要单独回溯。

call / return 子过程调用 ​

call 调用子过程,return 返回调用点:

dsl
label main:
  say "开始" speaker="旁白"
  call "heal_full"      // 调用子过程
  say "回到主线" speaker="旁白"   // return 后继续执行
  navigate "next"

label heal_full:
  set "player.hp" {player.maxHp}
  say "HP 完全恢复!" speaker="系统"
  return                // 返回调用点

适用于重复的逻辑片段(如恢复 HP、显示系统提示)。

scene 切换 ​

跳转到 scene 会重建画面:

dsl
// 文件 A
label go_to_town:
  navigate "town_entrance"   // 跳到另一个 .story 文件中的 scene

// 文件 B
scene "town_entrance"
  image "Images/town.jpg" x=0 y=0 width=100% height=100%
  text "小镇入口" x=50% y=10% size=32
  button "进入酒馆" x=50% y=50% nav="tavern"

场景堆栈:back / forward ​

引擎维护一个场景堆栈,支持后退 / 前进:

dsl
// 从 town 调用 tavern,tavern 可以 back 回 town
scene "town"
  button "进入酒馆" x=50% y=50% nav="tavern"

scene "tavern"
  button "返回" x=50% y=80% nav="back"   // 回到上一个场景
命令说明
back回到上一个场景
forward前进到下一个场景(back 之后用)

back 的用途

适用于 UI 面板层级(如 设置 → 音频设置 → 返回设置)。剧情分支中通常用 navigate 显式跳转。

call_screen 调用 UI 场景 ​

call_screen 调用一个 UI 场景并等待返回值:

dsl
label main:
  call_screen "save_panel" store="save_result"
  if {save_result == "saved"}
    say "存档成功!" speaker="系统"
  navigate "next"
  • store="key"——将 UI 场景的返回值存入变量
  • with "k=v"——传参(可选)

跨文件导航 ​

引擎自动在所有 .story 文件中查找场景名和标签名。你可以把不同章节放在不同文件中:

Stories/
├── title/
│   └── title_main.story      # scene "title_main"
├── chapter1/
│   └── chapter1.story        # scene "chapter1_intro"
├── chapter2/
│   └── chapter2.story        # scene "chapter2_start"
dsl
// title_main.story
button "开始游戏" nav="chapter1_intro"

// chapter1.story
scene "chapter1_intro"
  ...
  navigate "chapter2_start"   // 跨文件跳转

动手练习 ​

制作一个三选一的分支:

dsl
label crossroad:
  say "你站在岔路口。" speaker="旁白"
  menu "走哪条路?"
    "森林小径" -> path_forest
    "山间道路" -> path_mountain
    "河边小路" -> path_river

label path_forest:
  say "你走进了幽暗的森林。" speaker="旁白"
  call "gain_exp"
  navigate "town"

label path_mountain:
  say "你攀登陡峭的山路。" speaker="旁白"
  call "gain_exp"
  navigate "town"

label path_river:
  say "你沿着河边前行。" speaker="旁白"
  call "gain_exp"
  navigate "town"

label gain_exp:
  set "player.exp" {player.exp + 10}
  say "获得 10 经验值!" speaker="系统"
  return

下一步 ​

分支掌握了!下一章学习变量与表达式——让游戏记住玩家的选择。

基于 .NET 10 + Avalonia 12 · Apache-2.0 License