IntegrationPULSE · WEB / HTML5 游戏接入指南 · 对应 @clxgame/pulse-game v0.1.0
游戏开发者:5 分钟接入 .pulse
Updated 2026-07-19This document is currently available in Chinese only
这份指南只面向 Web / HTML5 游戏开发者。目标只有一个:让制作好的 .pulse 音乐包开始播放,并跟随游戏切换音乐状态。
你不需要理解素材、片段、Layer、DSP 或转场编排。第一次接入只需要三个动作:① 加载音乐包 → ② 播放 → ③ 切换游戏音乐状态。
如果你负责制作音乐包,请改看 Pulse Designer 手册。不确定角色时,从文档入口开始。
从 Pulse Desktop 帮助页复制 pulseContract,然后:
pnpm add @clxgame/pulse-game
const music = await loadPulseGame("/packs/forest-combat.pulse");
await music.play();
music.setGameState(pulseContract.states.combat);
只调用合同公开的 ID;场景销毁时 music.dispose()。细节和陷阱见下文。
规范交付的新 .pulse 文件应在包内携带一份开发者接入合同:它只公开游戏真正需要调用的 state ID 和 parameter ID。在 Pulse Desktop 的帮助页中打开这个包,复制自动生成的 pulseContract 和接入示例即可,不要自己翻 manifest 猜 ID。
export const pulseContract = {
initialStateId: "exploration",
states: {
exploration: "exploration",
combat: "combat",
},
parameters: {
tension: { id: "tension", min: 0, max: 1, defaultValue: 0.2 },
},
} as const;
| 游戏含义 | Pulse 调用值 |
|---|
| 探索音乐 | state · exploration |
| 战斗音乐 | state · combat |
| 紧张程度 | parameter · tension(范围 0..1) |
合同里没有出现的状态和参数也都属于包内实现,不应由游戏调用。resource、segment 和 layer ID 永远属于音乐包内部实现。
⚠️ 旧包未声明接入合同怎么办?
如果帮助页显示「旧包未声明接入合同」的警告,SDK 为兼容旧包会暂时把所有状态和参数推断为公开;请让内容方确认后再接入。这个推断不会被悄悄写回 .pulse。
⛔ 合同损坏或版本不受支持时的行为
如果包已经声明合同但合同损坏或版本不受支持,SDK 不会退回「全部公开」,而会停止生成调用代码并明确报错。
pnpm add @clxgame/pulse-game
public/
└─ packs/
└─ forest-combat.pulse ← 浏览器中的地址:/packs/forest-combat.pulse
游戏事件驱动状态切换与参数调节;音乐如何过渡由 .pulse 内容决定
import { loadPulseGame } from "@clxgame/pulse-game";
import { pulseContract } from "./pulse-contract";
const music = await loadPulseGame("/packs/forest-combat.pulse");
for (const warning of music.contract.warnings) console.warn(warning);
startButton.addEventListener("click", async () => {
await music.play();
});
gameEvents.on("encounter:start", () => {
music.setGameState(pulseContract.states.combat);
});
gameEvents.on("encounter:end", () => {
music.setGameState(pulseContract.states.exploration);
});
gameEvents.on("danger:changed", (value: number) => {
music.setGameParameter(pulseContract.parameters.tension.id, value);
});
scene.( music.());
💡 startButton、gameEvents 和 scene 代表你项目里已有的按钮、事件系统和场景生命周期,不是 Pulse 新增的框架。
做到这里,开发者接入就完成了。音乐怎么循环、何时在小节边界切换、战斗状态里有哪些分层音轨,都由 .pulse 内容决定。
loadPulseGame() — 负责下载、校验并准备音乐,但不会绕过浏览器自动播放限制。
play() — 应从 Start、Continue 或点击画面等用户操作中调用。
setGameState() — 只能传入接入合同公开的 state ID;不存在或仅供包内使用的 ID 会立即报错。
setGameParameter() — 只能传入合同公开的 parameter ID;未知、内部参数或非数字会立即报错;有限数值超出范围时,SDK 会限制到音乐包定义的最小值或最大值。
- 一个场景一个 runtime — 一个场景通常只创建一个 runtime,不要在每次战斗事件中重新加载。
dispose() — dispose() 之后不要继续使用这个 runtime。
如果还没有声音,优先检查文件 URL、浏览器控制台、用户点击是否真正触发了 play(),以及 state ID 是否和交付合同完全一致。
🚧 上面的示例代码只验收 happy path。上线前还要在游戏的启动边界捕获 loadPulseGame() / play() 失败,并回退到普通 BGM 或静音;这部分放在完整说明的加载与部署部分,不塞进第一次接入代码。
📌 当前版本没有真正的 Stinger;trigger() 只是状态切换兼容别名,不要把它当作叠加播放的一次性音效。Unity、Godot 和 Unreal runtime 也还不是当前生产承诺。
游戏开发者:5 分钟接入 .pulse | Soundbook DocsonDestroy
() =>
dispose