Skip to content

02 · 对话系统 ​

对话是视觉小说的灵魂。本章深入讲解 say 语句、角色定义、内联标记和打字机控制。

say 语句详解 ​

dsl
say "对话文本" speaker="说话者" clickable=true
参数类型默认值说明
speakerstringnull说话者名字
clickableboolfalse对话期间允许点击 UI 元素
instantboolfalse跳过打字机效果
noskipboolfalseSkip 模式下仍需手动点击
typewriterbooltrue是否启用打字机
templatestringnull指定对话框模板(见第 03 章)

character 角色定义 ​

用 character 预定义角色,统一管理样式:

dsl
character "lao_zhang" name="老张" color="#FFAA00" font="Microsoft YaHei" side="Images/old_man.png"
参数说明
name显示名
color说话者名字颜色
font字体
side侧脸图路径(对话框左侧显示)
screen对话框模板名(角色级绑定)

定义后,say 用 key 引用即可自动应用样式:

dsl
character "keeper" name="守塔人" color="#88CCFF"

say "欢迎到来。" speaker="keeper"     // 自动显示"守塔人",颜色 #88CCFF
say "请进。" speaker="keeper"

speaker 的两种模式

  • speaker="老张"——字面字符串,不应用 character 样式
  • speaker="keeper"——character key,自动查找 name/color/side

推荐用 character key。

内联标记 ​

对话文本支持富文本标记,用 {} 包裹:

基础标记 ​

dsl
say "这是{b}粗体{/b},这是{i}斜体{/i},这是{u}下划线{/u}。" speaker="旁白"
标记效果
{b}...{/b}粗体
{i}...{/i}斜体
{u}...{/u}下划线

颜色和字号 ​

dsl
say "{color=#FFD700}金色文字{/color},{color=#FF4444}红色文字{/color}。" speaker="旁白"
say "{size=24}大字{/size},{size=12}小字{/size}。" speaker="旁白"

字体 ​

dsl
say "{font=Consolas}等宽字体{/font},{font=Microsoft YaHei}雅黑{/font}。" speaker="旁白"

嵌套 ​

标记支持任意嵌套:

dsl
say "{b}{color=#FFD700}{size=24}金色粗体大字{/size}{/color}{/b}" speaker="旁白"

标签暂停 ​

用 {w} / {p} / {fast} 控制打字机节奏:

dsl
say "前半句{w}后半句" speaker="旁白"
标签效果
{w}暂停打字机,点击后继续逐字显示
{p}同 {w},常用于段落分隔
{fast}跳过后续打字机,直接显示到末尾

{w} 的点击行为

{w} 暂停后点击:打字机从暂停处继续逐字推进(不是跳到末尾)。 如果打字机已完成,点击则进入下一句。

变量插值 ​

对话文本中用 {变量名} 引用变量,用 {表达式} 写表达式:

dsl
define "player.name" "旅人" once
define "player.gold" 100 once

say "你好,{player.name}!你有 {player.gold} 金币。" speaker="商人"
say "总共价值 {player.gold * 2}。" speaker="系统"

格式化 ​

用 {变量:格式} 格式化数字:

dsl
say "你的 HP 是 {player.hp}/{player.maxHp}" speaker="系统"

对话历史 ​

引擎自动记录对话历史,玩家可通过工具栏的「历史」按钮查看。历史记录包含说话者和文本内容。

回溯不重复记录

当玩家回溯(滚轮上滚)重新查看之前的对话时,不会重复记录到历史列表中。

say 的交互行为 ​

默认行为 ​

  • 打字机逐字显示文本
  • 显示期间,透明遮罩(ZIndex=50)拦截点击,防止误触 UI 元素
  • 点击 / 空格 / 回车推进

clickable=true ​

dsl
say "选择一个物品" speaker="系统" clickable=true

禁用遮罩,对话期间允许点击场景中的 UI 元素。适用于"对话 + 选择"同时存在的场景。

instant=true ​

dsl
say "(系统提示:你获得了 50 金币)" speaker="系统" instant=true

跳过打字机,直接显示完整文本。

noskip=true ​

dsl
say "这段剧情很重要,不能跳过。" speaker="旁白" noskip=true

即使在 Skip 模式下,这句话也需要手动点击才能推进。

侧脸图 ​

通过 character 的 side 参数或状态键设置侧脸图:

dsl
character "hero" name="勇者" color="#FFD700" side="Images/hero_face.png"

say "我出发了!" speaker="hero"   // 对话框左侧显示 hero_face.png

也可以用 sprite 命令动态切换:

dsl
sprite "hero" src="Images/hero_smile.png"
say "太好了!" speaker="hero"

动手练习 ​

综合运用本章内容:

dsl
character "narrator" name="旁白" color="#AAAAAA"
character "hero" name="勇者" color="#FFD700" side="Images/hero_face.png"

label dialog_practice:
  say "勇者来到了岔路口。" speaker="narrator"
  say "{w}左边是森林,右边是山脉。" speaker="narrator"
  say "我选择{b}{color=#FFD700}森林{/color}{/b}!" speaker="hero"
  say "(HP: {player.hp}/{player.maxHp})" speaker="系统" instant=true
  say "森林深处传来{size=24}{color=#FF4444}低吼{/color}{/size}声{p}点击继续..." speaker="narrator"

下一步 ​

对话掌握了!下一章学习对话框模板——让不同场景用不同风格的对话框。

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