- 新增 web/ 纯音频 HTML5 平台:共享引擎(手势/WebAudio 三层/设置/震动)、 Node 零依赖服务器(静态 + 注册登录 + 进度存档 API) - 游戏:剑与声(RPG 新作)、声命线、暗室(重设计)、音序回响(重设计)、 节拍行者(跟随领奏重构)、盲航(同向闪避重构);声东击西删除 - 全局功能:男声/女声双套 TTS 资产、三档语速、BGM 音量三档、 震动反馈语言(10 种震型)、服务器进度同步 - 资产:899 ogg + 899 m4a(Qwen3-TTS 双性别语音、Stable Audio 3 音效、 Mureka BGM 4+3 首),终检零缺失 - 文档:docs/design/ 13 篇设计审查文档、docs/audio/ 资产管线、 web/server/README.md API 文档
239 lines
15 KiB
Markdown
239 lines
15 KiB
Markdown
# 05a · 《剑与声》第一章施工稿(rpg chapter 1,R4 资产 / R5 开发依据)
|
||
|
||
> **给开发者的实现要点摘要**
|
||
> 1. 本文件 + [05-rpg-ch1-voice-ids.md](05-rpg-ch1-voice-ids.md)(台词表)+ [05-rpg.md](05-rpg.md)(总设计)三者齐全即可施工。场景图、战斗状态机、数值表、存档结构全部定死,不允许实现时自由发挥。
|
||
> 2. 战斗是**定时器驱动的回合状态机**(§3 状态转换表):敌方前摇 1.0s 内双击=格挡(双击即时回调,规避 tap 延迟);指令循环 攻击→技能→防御→道具。
|
||
> 3. 第一章 8 场景、5 场固定遭遇战(明雷)、2 件装备 + 道具在商店/宝箱/支线获取(§5)。
|
||
> 4. 存档 data 结构 §6(含大厅卡片要显示的 `summary` 字符串);保存时机:场景切换/战斗结束/商店交易后。
|
||
> 5. 资产清单 §7:5 首 BGM(Mureka prompt 草稿)+ 35 个 sfx(Stable Audio 3 prompt 草稿 / 程序合成标注)。语音 ~114 句见台词表文件。
|
||
|
||
---
|
||
|
||
## 1. 第一章场景图(数据表,直接转 JSON)
|
||
|
||
```js
|
||
const CH1 = {
|
||
start: 'village',
|
||
scenes: {
|
||
village: { name: '雾口村', amb: 'amb_village', options: ['go_path', 'shop', 'rest', 'status'] },
|
||
path: { name: '林间小路', amb: 'amb_path', options: ['go_fork', 'investigate', 'back'] },
|
||
fork: { name: '岔路口', amb: 'amb_fork', options: ['go_chest', 'go_stream', 'back'] },
|
||
chest: { name: '枯树洞', amb: 'amb_chest', options: ['open_chest', 'back'] },
|
||
stream: { name: '溪流', amb: 'amb_stream', options: ['drink', 'go_hunter', 'back'],
|
||
encounter: 'enc_teach_wolf' }, // 首次进入先触发教学战
|
||
hunter: { name: '猎人小屋', amb: 'amb_hunter', options: ['talk_hunter', 'go_deepwood', 'back'] },
|
||
deepwood: { name: '密林深处', amb: 'amb_deepwood', options: ['go_gate', 'back'],
|
||
encounter: 'enc_bandits' }, // 首次进入触发山贼连战
|
||
gate: { name: '黑风寨门前', amb: 'amb_gate', options: ['assault', 'sneak', 'back'] },
|
||
boss1: { name: '聚义厅', amb: 'amb_hall', options: [],
|
||
encounter: 'enc_boss1' }, // 由 gate 两个选项分别进入
|
||
},
|
||
};
|
||
```
|
||
|
||
选项语义(选项 id → 行为):
|
||
|
||
| 选项 id | 播报语音 | 行为 |
|
||
|---|---|---|
|
||
| `go_*` | `opt_go_<场景>` | 切换场景(播脚步 sfx + 新场景 desc) |
|
||
| `back` | `opt_back` | 回上一场景 |
|
||
| `shop` | `opt_shop` | 进商店子菜单(§4) |
|
||
| `rest` | `opt_rest` | HP/MP 回满,播 `sys_rest`;仅 village |
|
||
| `status` | `opt_status` | 角色状态播报(同上滑) |
|
||
| `investigate` | `opt_investigate` | 一次性:+15 金币(flag `chest_path`),播 `evt_gold15`;之后播 `evt_nothing` |
|
||
| `go_chest` | `opt_go_chest` | 岔路左支线 |
|
||
| `open_chest` | `opt_open_chest` | 一次性:金疮药×2(flag `chest_fork`) |
|
||
| `drink` | `opt_drink` | HP 回满,播 `sys_drink` |
|
||
| `talk_hunter` | `opt_talk_hunter` | 支线对话(flag `hunter_quest`:金疮药×1 + 商店九折 flag `shop_discount`) |
|
||
| `assault` | `opt_assault` | 战 `enc_elite` → 胜后进 boss1 |
|
||
| `sneak` | `opt_sneak` | 战 `enc_sneak`(较弱)→ 进 boss1 且 HP/MP 回满 |
|
||
|
||
## 2. 遭遇战表(第一章,全部明雷固定)
|
||
|
||
| 遭遇 id | 敌人 | 触发 | 特殊 |
|
||
|---|---|---|---|
|
||
| `enc_teach_wolf` | 教学野狼 ×1 | stream 首次进入 | 教学战:玩家 HP 锁底 1(不败),分步教学(台词表 B 组) |
|
||
| `enc_wolf` | 野狼 ×1 | 教学战后 stream 再入 50% 刷新一次 | 可逃 |
|
||
| `enc_bandits` | 山贼 ×2(连战两场) | deepwood 首次进入 | 不可逃;两场间不回血 |
|
||
| `enc_elite` | 寨丁头目 ×1 | gate 选 assault | 不可逃 |
|
||
| `enc_sneak` | 山贼 ×1 + 毒蛛 ×1(连战) | gate 选 sneak | 不可逃;胜后进 boss 前回满 |
|
||
| `enc_boss1` | 黑风寨主 ×1 | boss1 进入 | Boss 战,不可逃;半血进二阶段 |
|
||
|
||
## 3. 战斗状态机(完整状态转换表)
|
||
|
||
状态:`B_START → (回合循环) → VICTORY | DEFEAT | FLED`
|
||
|
||
| 状态 | 进入时副作用 | 出口转换 |
|
||
|---|---|---|
|
||
| `B_START` | 播 `btl_start_<enemy>` + 敌方登场 sfx; init 回合数=1 | 自动 → `ENEMY_TELEGRAPH`(敌方先攻的蛊师类)或 `PLAYER_SELECT`(默认玩家先攻)。第一章全部玩家先攻 |
|
||
| `PLAYER_SELECT` | 播当前指令名(`cmd_attack`),左右滑循环切换(攻击→技能→防御→道具),单击执行;上滑播战场状态;下滑请求逃跑 | 单击 → `PLAYER_EXECUTE`;下滑 → `FLEE_CHECK` |
|
||
| `PLAYER_EXECUTE` | 按指令结算:攻击=伤害公式;技能=atk×2 耗 mp3(mp 不足播 `btl_nomp` 留在本状态重选);防御=置 halfDamage 标记;道具=金疮药回 40%maxHp(无药播 `btl_noitem` 重选)。播对应 sfx + 敌方受击音 | 结算完 → `CHECK_ENEMY_DEAD` |
|
||
| `CHECK_ENEMY_DEAD` | 敌 HP≤0:播 `btl_enemy_die`;连战则拉下一个敌人回 `B_START`(不重置玩家状态) | 敌死 → `VICTORY`(无下一只);敌活 → `ENEMY_TELEGRAPH` |
|
||
| `ENEMY_TELEGRAPH` | 播敌方前摇音(`tel_<enemy>`,1.0s);启动格挡窗口 1.0s | 窗口内双击 → 格挡标记=true(`vibrate('confirm')` + `sfx/parry`),→ `ENEMY_RESOLVE`;窗口结束 → `ENEMY_RESOLVE`;窗口内其他手势 → `vibrate('error')`,留在窗口 |
|
||
| `ENEMY_RESOLVE` | 结算敌方伤害:`dmg×0.3`(格挡)/`×0.5`(防御)/全值;播受击音 + `vibrate([80])`(格挡成功不震 HIT,已震 confirm);血量档位变化时播 `btl_hp_*` | 玩家 HP≤0 → `DEFEAT`;否则回合数+1 → `PLAYER_SELECT` |
|
||
| `FLEE_CHECK` | 非 Boss 战:播 `btl_flee` 脱离;Boss/剧情战:播 `btl_noflee` 回 `PLAYER_SELECT` | → `FLED`(回场景,遭遇不消失)或 `PLAYER_SELECT` |
|
||
| `VICTORY` | 播 `btl_win` + 经验/金币获得句(整句分档,见台词表)→ 结算升级(升级播 `btl_levelup` + `vibrate('success')`)→ 写存档 | → 场景探索态 |
|
||
| `DEFEAT` | 播 `btl_lose` + 死亡归因句 → 章首(village)重生:HP/MP 回满,等级/金币/装备/flags 保留,本章非 Boss 遭遇重置 | → village 探索态 |
|
||
|
||
半血叙事钩子:敌人 HP 首次 ≤50% 时在 `CHECK_ENEMY_DEAD` 前插播 `btl_half_<enemy>`(无此语音的敌人跳过)。
|
||
|
||
## 4. 数值表
|
||
|
||
### 4.1 玩家
|
||
|
||
```
|
||
maxHp = 20 + 8*(lv-1) // lv1=20, lv3=36, lv5=52
|
||
atk = 5 + 2*(lv-1) + 武器atk
|
||
def = 护甲def
|
||
mp = 3 + lv // 破空斩耗 3
|
||
expToNext = lv * 20
|
||
dmg = max(1, round((atk攻 - def守) * (0.85~1.15)))
|
||
```
|
||
|
||
### 4.2 敌人(全游戏 8 种 + 3 Boss;第一章用前 4 种 + Boss1)
|
||
|
||
| 敌人 | 章 | HP | ATK | DEF | EXP | 金币 | 前摇音 sfx id | 前摇特征 | 半血句 |
|
||
|---|---|---|---|---|---|---|---|---|---|
|
||
| 教学野狼 | 1 | 6 | 3 | 0 | 5 | 0 | `tel_wolf` | 扑击前低吼 | 无 |
|
||
| 野狼 | 1 | 10 | 4 | 0 | 8 | 5 | `tel_wolf` | 低吼 | 无 |
|
||
| 山贼 | 1 | 16 | 6 | 1 | 12 | 12 | `tel_bandit` | 脚步+拔刀 | `btl_half_bandit` |
|
||
| 毒蛛 | 1 | 12 | 7 | 0 | 12 | 8 | `tel_spider` | 高频肢节摩擦 | 无 |
|
||
| 寨丁头目 | 1 | 24 | 8 | 2 | 20 | 25 | `tel_elite` | 重甲碰撞 | `btl_half_elite` |
|
||
| **Boss 黑风寨主** | 1 | 45 | 10 | 2 | 50 | 100 | `tel_boss1` | 双刀互击两声 | 二阶段:ATK→12,播 `boss1_phase2` |
|
||
| 沼泽鳄 | 2 | 30 | 11 | 2 | 22 | 18 | `tel_croc` | 水花+低吼 | 无 |
|
||
| 蛊师 | 2 | 22 | 12 | 1 | 26 | 30 | `tel_shaman` | 吟唱(敌方先攻) | 有 |
|
||
| 剑傀 | 3 | 38 | 14 | 3 | 40 | 45 | `tel_puppet` | 机括咔哒 | 无 |
|
||
| 影卫 | 3 | 30 | 16 | 2 | 45 | 50 | 无声(震动 DANGER 代替) | 寂静 | 有 |
|
||
| **Boss 腐沼祭主** | 2 | 70 | 14 | 3 | 90 | 200 | `tel_boss2` | 人声哼鸣 | 二阶段召唤 2 毒蛛 |
|
||
| **Boss 白无瞳** | 3 | 110 | 18 | 5 | 150 | 500 | 三阶段完全无声 | 寂静+DANGER | 三次阶段转换 |
|
||
|
||
经验校验:第一章可得 exp = 5+8+12×2+20+12+12+50 = 131+(教学狼 5 + 野狼 8 + 山贼 24 + 头目/偷袭线 20~24 + Boss 50)≈ 110-135 → 打完第一章玩家 lv3(20+40+60=120 可到 lv4 门槛前),数值节奏成立。
|
||
|
||
### 4.3 装备与道具(获取节点)
|
||
|
||
| 物品 | 效果 | 获取 |
|
||
|---|---|---|
|
||
| 铁剑 | atk+3 | village 商店 100 金(开局 50 金 + 小路调查 15 + 若干战斗;猎人支线后九折 90) |
|
||
| 皮甲 | def+2 | village 商店 80 金(九折 72) |
|
||
| 金疮药 | 回 40% maxHp | 商店 30 金;枯树洞宝箱 ×2;猎人支线 ×1;叠加上限 5 |
|
||
| 青钢剑 | atk+6 | 第二章商店 300 |
|
||
| 铁鳞甲 | def+4 | 第二章商店 250 |
|
||
| 听风剑 | atk+9,格挡窗口 1.0s→1.3s | 第三章商店 600 |
|
||
|
||
### 4.4 商店子菜单(village)
|
||
|
||
进入播 `shop_open` → 左右滑循环:铁剑/皮甲/金疮药/离开 → 单击购买(播物品名+价格档句 `shop_price_<item>`;钱不够播 `shop_poor`;已购装备播 `shop_owned`)→ 购买成功 `sfx/coin` + `vibrate([15,40,15])` → 写存档。
|
||
|
||
## 5. 探索态手势(复读总设计,施工口径)
|
||
|
||
左右滑=切选项(播选项名)/ 单击=确认 / 双击=重听场景描述+环境音 / 上滑=状态播报(`st_lv`、`st_hp_*`、`st_gold_*`、`st_equip` 链播,全整句分档)/ 下滑=菜单(继续 / 保存并回大厅 / 重听帮助)。血量档位:>70% `btl_hp_high`("你状态很好")、30-70% `btl_hp_mid`("你受了伤")、<30% `btl_hp_low`("你伤势很重")。
|
||
|
||
## 6. 存档 JSON(精确定义)
|
||
|
||
`PUT /api/progress { game: 'rpg', data: ... }` 的 `data`:
|
||
|
||
```json
|
||
{
|
||
"schema": 1,
|
||
"updatedAt": "2026-08-29T12:00:00Z",
|
||
"summary": "第一章·溪流 · Lv3 · 金币120",
|
||
"chapter": 1,
|
||
"scene": "stream",
|
||
"player": {
|
||
"lv": 3, "exp": 45,
|
||
"hp": 28, "maxHp": 36, "mp": 6,
|
||
"gold": 120,
|
||
"weapon": "iron_sword",
|
||
"armor": "leather",
|
||
"potions": 2
|
||
},
|
||
"flags": {
|
||
"tutorial_battle_done": false,
|
||
"chest_path": false,
|
||
"chest_fork": false,
|
||
"hunter_quest": false,
|
||
"shop_discount": false,
|
||
"enc_bandits_done": false,
|
||
"enc_elite_done": false,
|
||
"enc_sneak_done": false,
|
||
"boss1_done": false
|
||
},
|
||
"chapters": { "1": "open", "2": "locked", "3": "locked" },
|
||
"stats": { "kills": 0, "deaths": 0, "parries": 0, "playSec": 0 }
|
||
}
|
||
```
|
||
|
||
字段规则:
|
||
|
||
| 字段 | 默认 | 说明 |
|
||
|---|---|---|
|
||
| `schema` | 1 | 升版时 R5+ 写迁移或丢弃重来 |
|
||
| `summary` | `"新的旅程"` | 大厅卡片显示;格式 `第X章·场景名 · LvN · 金币M` |
|
||
| `chapter`/`scene` | 1 / `village` | 继续游戏落点 |
|
||
| `player.*` | lv1 exp0 hp20 maxHp20 mp4 gold50 weapon null armor null potions 1 | 开局 50 金为村长赠送剧情款 |
|
||
| `weapon`/`armor` | null | `iron_sword`/`steel_sword`/`wind_sword`;`leather`/`iron_scale` |
|
||
| `flags.*` | false | 一次性事件锁 |
|
||
| `chapters` | 见上 | `locked`/`open`/`cleared` |
|
||
| `stats.*` | 0 | 只增不减,新游戏也保留 |
|
||
|
||
- 保存时机:场景切换后、战斗结算后、商店交易后、菜单"保存并回大厅"。localStorage `soundgame.progress.rpg` 与服务器双写。
|
||
- 进游戏有存档时:播 `sys_continue_ask`("继续上次的旅程?单击继续,右滑开始新游戏。");新游戏清空 data 保留 `stats` 累计。
|
||
|
||
## 7. 资产需求清单
|
||
|
||
### 7.1 BGM(5 首,Mureka instrumental,60-90s 无缝循环,沿用归一化工艺)
|
||
|
||
| id | 用途 | Mureka prompt 草稿(英文) |
|
||
|---|---|---|
|
||
| `bgm/explore` | 第一章探索底 | "Atmospheric Chinese wuxia ambient, bamboo forest mist, sparse guzheng plucks over low drone, slow tempo 60 bpm, mysterious but calm, no vocals, seamless loop" |
|
||
| `bgm/battle` | 普通战斗 | "Tense wuxia battle music, driving taiko drums 100 bpm, sharp erhu stabs, urgent but not chaotic, no vocals, seamless loop" |
|
||
| `bgm/boss` | Boss 战 | "Epic dark wuxia boss theme, heavy taiko 120 bpm, dissonant strings, dramatic tension, no vocals, seamless loop" |
|
||
| `bgm/village` | 村庄/安全区 | "Warm peaceful Chinese village ambiance music, soft dizi flute melody, gentle plucked strings, cozy 70 bpm, no vocals, seamless loop" |
|
||
| `bgm/ending` | 章结算/剧情 | "Melancholic wuxia emotional theme, solo erhu over soft pads, bittersweet, slow, no vocals, seamless loop" |
|
||
|
||
### 7.2 SFX(35 个;SA3 = Stable Audio 3 生成,SYN = 程序合成)
|
||
|
||
| 类别 | id | 方式 | prompt 草稿 / 说明 |
|
||
|---|---|---|---|
|
||
| 敌方前摇 | `tel_wolf` | SA3 | "wolf growl then lunge, short, dry, close mic" |
|
||
| | `tel_bandit` | SA3 | "footsteps on dirt then sword unsheathing shing, 1 second" |
|
||
| | `tel_spider` | SA3 | "insect legs skittering, high frequency chitin clicks, eerie, 1 second" |
|
||
| | `tel_elite` | SA3 | "heavy armor plates clanking, menacing, 1 second" |
|
||
| | `tel_boss1` | SA3 | "two metal blades striking each other twice, dramatic ring" |
|
||
| | `tel_croc` | SA3 | "water splash with low reptile growl" |
|
||
| | `tel_shaman` | SA3 | "low guttural chant humming, ritualistic, dark" |
|
||
| | `tel_puppet` | SA3 | "wooden mechanism clicks and winding gears" |
|
||
| 战斗 | `atk_swing` | SA3 | "sword whoosh through air, fast, clean" |
|
||
| | `atk_hit` | SA3 | "sword hitting flesh, dull impact, not gory" |
|
||
| | `parry` | SA3 | "metal parry clang, bright ring, short" |
|
||
| | `skill_slash` | SA3 | "powerful sword slash with air rip, dramatic" |
|
||
| | `hurt` | SYN | 低频闷击(程序合成,避免与 atk_hit 混淆) |
|
||
| | `enemy_die` | SA3 | "body falling to ground with weapon clatter" |
|
||
| | `potion` | SA3 | "drinking liquid gulps, glass bottle" |
|
||
| | `flee` | SYN | 渐远脚步 |
|
||
| 探索/系统 | `step` | SYN | 单步脚步(复用 escape 工艺) |
|
||
| | `coin` | SYN | 硬币叮当(短合成) |
|
||
| | `chest` | SA3 | "old wooden chest creaking open" |
|
||
| | `drink_water` | SA3 | "scooping and drinking stream water" |
|
||
| | `rest` | SA3 | "settling down by campfire, fabric rustle" |
|
||
| | `levelup` | SYN | 上行钟声琶音(内容音非提示音,允许) |
|
||
| | `door_heavy` | SA3 | "heavy wooden gate slowly opening, deep creak" |
|
||
| | `ui_deny` | — | **不做**(反馈走震动 error) |
|
||
| 场景环境 | `amb_village` | SA3 | "night village ambience, campfire crackle, distant chatter, crickets, loop" |
|
||
| | `amb_path` | SA3 | "forest path ambience, wind through leaves, birds distant, loop" |
|
||
| | `amb_fork` | SA3 | "forest crossroads ambience, wind split feel, crows, loop" |
|
||
| | `amb_chest` | SA3 | "hollow tree hole ambience, drips, muffled wind, loop" |
|
||
| | `amb_stream` | SA3 | "flowing stream over rocks, gentle water, loop" |
|
||
| | `amb_hunter` | SA3 | "wood cabin ambience, firewood crackle, knife sharpening occasionally, loop" |
|
||
| | `amb_deepwood` | SA3 | "deep forest ambience, insects, distant wolf howl, ominous, loop" |
|
||
| | `amb_gate` | SA3 | "bandit camp outside gate ambience, torches burning, rowdy distant voices, loop" |
|
||
| | `amb_hall` | SA3 | "large hall ambience, fire brazier, echoing space, tense, loop" |
|
||
| 二/三章备用 | `tel_croc/tel_shaman/tel_puppet`(已列) + `amb_swamp`、`amb_peak`、`tel_boss2` | SA3 | 沼气泡/山峰风/哼鸣,R4 一起生成 |
|
||
| 格挡无声敌人 | (无 sfx,震动 DANGER) | — | 影卫/白无瞳三阶段 |
|
||
|
||
计数:前摇 8 + 战斗 9 + 探索系统 8 + 环境 9 + Boss2 前摇 1 = **35**(`ui_deny` 不做,无声敌人不占 sfx)。环境音 amb_* 走 bgm 层 loop(低音量 volume 0.5),不占 sfx 并发。
|
||
|
||
## 8. 与台词表的对应
|
||
|
||
语音 id 共 114 个(旁白双性别 ~70 + NPC 平铺单音色 ~44),见 [05-rpg-ch1-voice-ids.md](05-rpg-ch1-voice-ids.md)。场景 desc、选项名、战斗播报、商店、状态档位、教学全部覆盖;开发 agent 只许引用表内 id。
|