LPAI 独立网页游戏 AI 社区指南

表现与音频

客户端音频

管理音频资产、程序化声音、会话生命周期和浏览器播放限制。

表现与音频

先决定声音何时结束,再决定播放什么

点击音、环境循环和背景音乐有不同生命周期。音频只表达结果,不修改玩家状态;浏览器拒绝播放时,规则仍必须完成。

# 文件资产还是程序化音频

需求 推荐
已有音乐、配音或样本 项目音乐资产库与场景/事件/控件音频字段
短提示音、合成器、节奏和程序化音乐 tools.runClientAudio

项目音乐资产统一上传、试听和复用 URL。不要为同一文件重复上传或在脚本中散落手写地址。

# 两层脚本与生命周期 API

外层 Worker 脚本读取状态并调用:

方法 作用
tools.runClientAudio(script, options?) 启动音频会话
tools.disposeClientAudio(label) 停止指定会话
tools.clearClientAudio() 停止当前页面所有客户端音频

内层字符串注入 Toneaudiopayloadruntimesessionpointer。脚本按原生 JavaScript 执行,不做浏览器全局遮蔽;不要借此绕过宿主资源管理或请求平台私有接口。运行时数据通过 payload 传入。

tools.runClientAudio(`
  await audio.resume();
  const synth = audio.createSynth({
    oscillator: { type: "triangle" },
    envelope: { attack: .005, decay: .08, sustain: .02, release: .12 }
  });
  synth.setVolume(-12);
  synth.triggerAttackRelease("C5", "16n");
`, { label: "ui-confirm" });

短音通常播放后自动销毁。循环和背景音乐在内层 await audio.keepAlive(),外层用稳定 label 停止或替换。不要假设场景切换会自动清理所有长音。

# 内层 API

类别 方法
基础 resumenowtoSecondswaitkeepAlivedisposecleanuplog
乐器 createSynthcreatePolySynthcreateNoiseSynthcreateMembraneSynth
调度 createLoopcreateSequencecreatePatternscheduleOnce
音乐工具 Tone.Frequency(...) 等 Tone 转换能力

宿主包装的乐器和调度器会跟随会话清理。裸 new Tone.Synth()new Tone.Pattern() 可能脱离宿主跟踪,不作为默认做法。

# 完整乐器与调度句柄

所有 create*Synth 方法都返回受跟踪乐器句柄:

方法/属性 用途
kindidtype 句柄身份和乐器类型
set(options?) 修改受支持的 Tone 乐器参数
setVolume(db) 设置分贝音量
triggerAttackRelease(note, duration, time?, velocity?) 播放完整音符/和弦
triggerAttack(note, time?, velocity?) 开始持续音符/和弦
triggerRelease(time?) / releaseAll(time?) 释放正在播放的声部
start(time?, offset?, duration?) 在类型支持时启动音源
stop(time?) 在类型支持时停止
seek(offset?, time?) 在类型支持时跳转位置
loaded() 可加载音源是否准备完成
dispose() 释放该受跟踪资源

createLoopcreateSequencecreatePatternscheduleOnce 返回调度句柄:

方法/属性 用途
kindidtype 句柄身份及 loop/sequence/pattern/schedule 类型
start(time?) 开始或安排资源
stop(time?) 停止后续迭代
cancel(time?) 从指定时间取消已调度事件
set(options?) 修改受支持调度参数
dispose() 停止并释放资源

audio.dispose(handle) 是通用安全释放入口,audio.cleanup(reason?) 会销毁整个当前音频会话。runtime 提供 sessionIdlabelnow()toneNow()getContextState();注入的 session 是前端脚本共享 session,不是玩家存档。

# 音高与并发规则

音符必须包含八度,例如 C4F#4Bb3。同一单音 synth 的开始时间必须严格递增;同一拍多个音使用 createPolySynth()

tools.runClientAudio(`
  await audio.resume();
  const poly = audio.createPolySynth();
  poly.setVolume(-14);
  poly.triggerAttackRelease(["C4", "E4", "G4"], "8n");
`, { label: "success-chord" });

程序化背景音乐使用稳定 label:

tools.runClientAudio(`
  await audio.resume();
  const synth = audio.createSynth();
  audio.createSequence(payload.notes, "8n", (time, note) => {
    if (note) synth.triggerAttackRelease(note, "8n", time);
  });
  await audio.keepAlive();
`, {
  label: "scene-theme",
  payload: { notes: ["C4", "E4", "G4", "B4"] }
});

停止时调用 tools.disposeClientAudio("scene-theme")

# 高频交互

js_enter 可以播放一次短音,js_leave 清理持续音,js_long 播放确认或蓄力反馈。js_move 不要每个事件创建新会话;复用稳定 label,或完全避免连续发声。

# 自动播放、音量和可访问性

第一次发声前通常需要 await audio.resume(),仍可能受浏览器用户手势策略限制。玩家可从悬浮设置调节或静音客户端音效。重要信息不能只靠声音表达,必须有视觉或文本反馈。

# 纯 AI 提示词与验收

说明资产、一次性/循环类型、label、开始、停止、淡出、场景切换、静音和失败行为。测试首次无手势、重复触发、同 label 替换、场景切换、后台恢复、静音、非法音符、单音并发错误和低性能设备。

返回:客户端视觉特效