Skip to content

05 · 变量与表达式 ​

变量是游戏状态的基石。本章讲解变量的定义、修改、作用域和表达式系统。

define 全局变量 ​

define 在启动时注册全局变量:

dsl
define "player.name" "旅人" once
define "player.hp" 50 once
define "player.maxHp" 100 once
define "player.gold" 100 once
define "story.met_elder" false once

once 关键字 ​

once 表示只在变量不存在时设置。再次执行 define ... once 不会覆盖已有值:

dsl
define "player.gold" 100 once   // 第一次:设为 100
// ... 玩家花了 50 金币,player.gold = 50
define "player.gold" 100 once   // 不会覆盖!player.gold 仍然是 50

何时不用 once

不加 once 的 define 每次执行都会覆盖。但 define 通常用于初始化,推荐始终用 once。

点分路径 ​

变量名用 . 分隔表示嵌套结构:

dsl
define "player.name" "旅人"
define "player.hp" 50
define "player.inventory.gold" 100

引擎内部用嵌套 Dictionary 组织,player.hp 等价于 player 字典下的 hp 键。

set 修改变量 ​

dsl
set "player.gold" {player.gold - 10}       // 减 10
set "player.hp" {player.hp + 20}           // 加 20
set "story.met_elder" true                 // 设为 true
set "player.name" "勇者"                   // 改名

复合运算(自增 / 自减) ​

set 支持复合赋值 += -= *= /= %=,无需花括号,直接做自增 / 自减 / 取模:

dsl
set "player.gold" += 50      // player.gold = player.gold + 50
set "player.hp"   -= 15      // player.hp = player.hp - 15
set "player.exp"  *= 2       // player.exp = player.exp * 2
set "player.gold" /= 10      // 整除
set "player.turn" %= 7       // 取模

与花括号写法等价

复合赋值等价于花括号表达式 set "player.gold" {player.gold + 50},两者结果相同,可任选其一。注意 / 和 % 在除零 / 模零时返回 0,不会抛异常。

set 表达式必须包花括号

set 的第二个参数若不是数字、也不是以 += -= *= /= %= 开头,会被当作纯字符串原样存储,不会计算:

dsl
set "player.gold" {player.gold + 50}   // ✅ 计算后存 150
set "player.gold" player.gold + 50     // ❌ 存成字符串 "player.gold + 50"

let / local 局部变量 ​

let 和 local(别名)定义局部变量,以 _local_ 前缀存储,场景切换时自动清除:

dsl
label battle:
  let "enemy_hp" {random(30, 50)}
  say "敌人 HP: {_local_enemy_hp}" speaker="系统"
  set "_local_dmg" {random(10, 30)}
  set "_local_enemy_hp" {_local_enemy_hp - _local_dmg}
  if {_local_enemy_hp <= 0}
    say "敌人被击败!" speaker="系统"
  return

局部变量的优势

  • 场景切换自动清除,不污染全局状态
  • 适合临时计算、战斗 HP、随机骰子等
  • local 是 let 的别名,两者完全等价

undef 销毁变量 ​

dsl
undef "temp_data"

从状态容器中彻底移除变量。

表达式语法 ​

用 {} 包裹表达式:

算术运算 ​

dsl
{a + b}    {a - b}    {a * b}    {a / b}    {a % b}

比较运算 ​

dsl
{a > b}    {a < b}    {a >= b}   {a <= b}   {a == b}   {a != b}

逻辑运算 ​

dsl
{a && b}   {a || b}   {!a}

三元运算 ​

dsl
{a > b ? "大于" : "小于等于"}

random 函数 ​

dsl
{random(1, 6)}        // 1~6 随机整数
{random(20, 50)}      // 20~50 随机整数

格式化 ​

dsl
{player.hp:0.0}       // 保留 1 位小数
{player.gold:#,##0}   // 千分位分隔

表达式不支持的写法

  • 单 & 与单 |:位运算符未实现,误用会静默返回 false(不报错!)。逻辑运算请用 && / ||。
  • 链式比较:{a < b < c} 不被支持,请拆成 {a < b && b < c}。
  • === / !== / ++ / --:均不支持;比较请用 == / !=,自增请用 += 1。

条件分支 ​

if / else if / else ​

dsl
if {npc.trust < 3}
  say "新来的?坐吧。" speaker="老张"
  set "npc.trust" {npc.trust + 1}
else if {npc.trust < 6}
  say "又是你啊。" speaker="老张"
else
  say "老朋友!" speaker="老张"

缩进规则 ​

if / else if / else / end 需要正确缩进:

dsl
if {condition}
  say "真" speaker="旁白"
else
  say "假" speaker="旁白"
end

end 可省略

当 else 或下一个同级语句出现时,引擎自动推断块结束。但推荐显式写 end 以提高可读性。

循环 ​

while 循环 ​

dsl
set "_local_i" 0
while {_local_i < 3}
  say "第 {_local_i} 次" speaker="系统"
  set "_local_i" {_local_i + 1}
end

for 循环 ​

dsl
for "i" in {1, 2, 3}
  say "第 {i} 次" speaker="系统"
end

break / continue ​

dsl
while {true}
  set "_local_x" {random(1, 10)}
  if {_local_x == 7}
    say "中了!" speaker="系统"
    break
  say "没中,再试。" speaker="系统"
end

数据结构 ​

array 数组 ​

dsl
array "inventory" ["剑", "盾", "药水"] once
array_push "inventory" "钥匙"
array_pop "inventory" store="last_item"

dict 字典 ​

dsl
dict "npc.stats" {"str": 10, "dex": 15, "int": 8}
dict_set "npc.stats" "str" 12

foreach 遍历 ​

dsl
foreach "item" in "inventory"
  say "你有:{item}" speaker="系统"

switch 多分支 ​

dsl
switch {player.level}
  case 1
    say "新手" speaker="系统"
  case 5
    say "老手" speaker="系统"
  default
    say "等级 {player.level}" speaker="系统"

func 函数 ​

dsl
func greet(name)
  say "你好,{name}!" speaker="系统"
  return "greeted"

label main:
  call "greet" with "name=旅人"

动手练习 ​

综合运用变量和条件:

dsl
define "player.gold" 50 once
define "npc.trust" 0 once

label shop:
  say "欢迎光临!你有 {player.gold} 金币。" speaker="商人"
  menu "买什么?"
    "药水 (20金)" -> buy_potion
    "武器 (50金)" -> buy_weapon
    "离开" -> leave_shop

label buy_potion:
  if {player.gold >= 20}
    set "player.gold" {player.gold - 20}
    set "npc.trust" {npc.trust + 1}
    say "谢谢惠顾!好感度 +1。" speaker="商人"
  else
    say "金币不够。" speaker="商人"
  navigate "shop"

label buy_weapon:
  if {player.gold >= 50}
    set "player.gold" {player.gold - 50}
    set "npc.trust" {npc.trust + 2}
    say "好眼力!好感度 +2。" speaker="商人"
  else
    say "再攒攒钱吧。" speaker="商人"
  navigate "shop"

下一步 ​

变量和逻辑掌握了!下一章学习背景立绘与视觉——让画面丰富起来。

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