Desktop 接入指南
本文档面向 Windows、macOS、Linux 桌面应用开发者,介绍如何将 NovaMark 运行时接入桌面端应用。
1. 架构选型
桌面端有两种主流接入方式,根据你的项目需求选择:
方案 A:嵌入式 WebView + WASM
将 NovaMark 编译为 WebAssembly,在桌面应用中嵌入 WebView 运行。
适合场景:
- 已有 Web 前端团队
- 需要快速验证原型
- 渲染逻辑复用 Web 模板
- 需要热更新能力
实现要点:
- 使用平台原生 WebView 控件
- NovaMark WASM 模块通过 JS 桥接与宿主通信
- 宿主提供文件系统、存档等原生能力桥接
注意事项:
- WebView 渲染性能略低于原生
- 需要处理跨平台 WebView 差异
- 原生能力调用需要额外的桥接层
方案 B:原生渲染
直接使用 C API 集成 NovaMark VM,在原生层实现渲染。
适合场景:
- 追求最佳性能
- 需要深度定制渲染管线
- 需要直接访问原生能力
- 已有成熟的原生 UI 框架
实现要点:
- 通过 C API 加载
.nvmp包并控制 VM - 宿主轮询或监听 NovaState 变化
- 自行实现所有 UI 渲染逻辑
注意事项:
- 需要自行实现文本渲染、图片显示、音频播放
- 多平台可能需要多套渲染代码
- 开发周期相对较长
2. 接入步骤
第一步:准备运行时
无论选择哪种方案,都需要:
获取 NovaMark 运行时
- WebView 方案:编译 WASM 模块
- 原生方案:编译 C API 静态库 / 动态库
准备测试包
- 使用
nova-cli build构建一个简单的.nvmp测试包 - 确保包可以正常加载
- 使用
第二步:实现基础控制流
实现以下核心功能:
加载包
加载 .nvmp 文件到 VM
初始化运行时状态推进剧情
调用 advance(),让 VM 推进到下一个需要宿主处理的状态点。
处理选择
调用 choose(choiceId),告诉 VM 玩家选择了哪个选项。
验证标准:
- 能够加载包并显示初始对话
- 能够推进对话直到出现选择
- 能够选择选项并继续剧情
第三步:接入运行时状态
将 NovaState 的关键字段接入你的渲染层:
| 状态字段 | 用途 |
|---|---|
dialogue | 当前对话文本、说话角色 |
choices | 可选选项列表 |
bg | 背景图资源引用 |
sprites | 立绘资源引用 |
bgm / sfx | 音频资源引用 |
variables | 变量值(用于 UI 显示) |
inventory | 物品背包状态 |
状态读取原则:
- 宿主只读取状态,不直接修改
- 所有状态变更由 VM 驱动
- 宿主根据状态决定如何渲染
第四步:实现渲染提示处理
NovaMark 脚本中可能包含渲染提示字段:
| 字段 | 含义 | 宿主处理建议 |
|---|---|---|
transition | 过渡效果类型 | 解析并实现过渡动画 |
position | 元素位置 | 映射到布局坐标 |
opacity | 透明度 | 控制元素淡入淡出 |
loop | 是否循环播放 | 控制音频/动画循环 |
volume | 音量 | 控制音频播放音量 |
重要:这些字段是渲染提示,不是引擎自动执行的行为。宿主负责解释和实现。
第五步:实现存档功能
NovaMark 提供两种存档格式:
正式存档(二进制)
- 用于生产环境
- 体积小、加载快
- 通过 C API 的存档接口操作
调试快照(JSON)
- 用于开发和调试
- 可读性好
- 方便排查状态问题
建议:
- 开发阶段先用 JSON 快照验证存档逻辑
- 生产环境切换到二进制格式
3. 状态驱动渲染
NovaMark 的核心设计是状态驱动,理解这一点对桌面端接入至关重要。
什么是状态驱动
┌─────────────┐ 状态变化 ┌─────────────┐
│ NovaMark │ ───────────────▶ │ 宿主 │
│ VM │ │ 渲染器 │
└─────────────┘ └─────────────┘
│
▼
更新 UI 显示引擎维护 NovaState,宿主负责"观察"这个状态并渲染。
事件循环模式
典型的桌面端事件循环:
1. 用户输入(点击/按键)
│
▼
2. 宿主调用 advance() 或 choose()
│
▼
3. VM 更新 NovaState
│
▼
4. 宿主读取新状态
│
▼
5. 宿主更新渲染
│
▼
6. 等待下一次用户输入宿主的渲染职责
根据 NovaState,宿主需要决定:
- 对话如何显示:文本框样式、打字机效果、角色名显示位置
- 选项如何呈现:按钮样式、布局、动画
- 背景/立绘如何切换:过渡效果、动画时长
- 音频如何播放:BGM 切换、音效触发
- UI 何时出现:菜单、存档界面、设置面板
这些全部由宿主控制,脚本不干预。
4. 输入处理
核心输入动作
桌面端需要处理以下输入:
| 输入类型 | 对应 VM 操作 | 说明 |
|---|---|---|
| 点击/回车 | advance() | 推进到下一个状态点 |
| 选择选项 | choose(choiceId) | 玩家做出选择 |
扩展输入(可选)
除了核心输入,宿主可以自行决定是否支持:
- 快捷键:存档/读档/快进/自动播放
- 历史回看:显示之前的对话
- 菜单按钮:打开设置/存档界面
这些功能由宿主自行实现,VM 不感知。
输入时机
只在特定状态允许输入:
- 有对话时:允许
advance() - 有选项时:禁止
advance(),只允许choose() - 空闲状态:允许打开菜单
宿主需要根据 NovaState 判断当前允许的输入类型。
5. 存档管理
存档数据内容
NovaMark 存档包含:
- 当前执行位置(场景/标签)
- 所有变量值
- 物品背包状态
- 已触发的结局/事件标记
存档操作流程
保存:
1. 调用 VM 的存档接口获取快照数据
2. 将数据写入本地文件
3. 可选:生成存档元信息(时间戳、截图等)加载:
1. 从文件读取快照数据
2. 调用 VM 的读档接口恢复状态
3. 根据恢复的 NovaState 更新渲染多存档槽位
如果需要多存档槽位:
- 由宿主管理槽位列表和元信息
- 每个槽位对应一个独立的存档文件
- VM 只负责生成/消费单个存档数据
6. 调试建议
使用 JSON 快照
开发阶段建议使用 JSON 快照格式:
- 可以直接查看状态内容
- 方便定位渲染问题
- 易于自动化测试
状态变化日志
建议在开发版本中记录:
- 每次
advance()/choose()调用 - NovaState 关键字段的变化
- 渲染提示字段的值
与 Web 模板对照
如果渲染结果不符合预期:
- 使用相同包在 Web 模板中运行
- 对照 Web 模板的状态显示
- 找出差异点定位问题
常见问题排查
| 问题 | 排查方向 |
|---|---|
| 对话不显示 | 检查 dialogue 字段是否正确读取 |
| 选项无法选择 | 检查 choices 列表和 choiceId 映射 |
| 背景不切换 | 检查 bg 字段和资源加载 |
| 存档无法恢复 | 检查快照数据完整性 |
7. 总结
桌面端接入 NovaMark 的关键要点:
- 理解状态驱动模型:VM 管状态,宿主管渲染
- 选对架构方案:WebView 快速验证,原生渲染性能最优
- 按步骤接入:先跑通流程,再完善细节
- 重视存档分离:开发用 JSON,生产用二进制
- 善用调试工具:快照日志和 Web 模板对照
接入完成后,你的桌面应用就能运行 NovaMark 游戏内容了。