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 onceonce 关键字
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="旁白"
endend 可省略
当 else 或下一个同级语句出现时,引擎自动推断块结束。但推荐显式写 end 以提高可读性。
循环
while 循环
dsl
set "_local_i" 0
while {_local_i < 3}
say "第 {_local_i} 次" speaker="系统"
set "_local_i" {_local_i + 1}
endfor 循环
dsl
for "i" in {1, 2, 3}
say "第 {i} 次" speaker="系统"
endbreak / 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" 12foreach 遍历
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"下一步
变量和逻辑掌握了!下一章学习背景立绘与视觉——让画面丰富起来。