Files
SoundGame/docs/design/24-rhythm-drummer.md
T
2026-10-01 23:26:47 +08:00

311 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 24 · 《节拍行者》鼓手模式(26 号对齐)
> **给开发者的实现要点摘要**
> 1. **玩法保留**:3×2 分区鼓组、跟随领奏、PERFECT ±0.15 / GOOD ±0.35、S~C 评级、B 级解锁下一首、无鼓伴奏、BPM 网格。本文取代 03 号作为施工依据。语音表仍见 [24-rhythm-voice-ids.md](24-rhythm-voice-ids.md)。
> 2. **演奏期 = Floor `ACTION`**:不起等待声;点按即敲。Miss = 不按「敲对」计、该音符无领奏应答感 + 闷镲/回执 + 真话归因。禁止只震。
> 3. **新手期无双击手势**(`doubleTapWindow: 0`)。同区两记连续点按是两下敲击,不是「双击手势」。菜单禁止双击确认。双击手势直至阶段 3 才存在,且不绑音符类型。
> 4. 分区点按是核心;选曲/结算/暂停说明的**帮助=长按**(上半屏点按是鼓,上滑易混)。暂停恢复必须 **count-in**。
> 5. 第一句就摸鼓或跟打;第一次成功 ≤10s。
---
## 0. 设计单(26 号附录 C)
### 0.1 一句话核心动作
**屏幕是一面 3×2 鼓组。领奏敲一小节,你在下一小节同一拍点敲同一面鼓。**
### 0.2 玩家可感知的状态(3 个)
| 状态 | Floor | 听感 | 第一次教 |
|---|---|---|---|
| 演奏 / 教学跟打 | `ACTION` | 无鼓伴奏 + 鼓声音色(声像+音高) | 「敲屏幕。摸到哪是哪。」 |
| 选曲 | `YOUR_TURN` | `bgm/menu` + 等待声 | 「左右滑选歌。单击开始。」 |
| 结算 | `YOUR_TURN` | menu pad + 评级句 | 「单击,再来一遍。」 |
暂停:音乐停,不叠 menu pad。恢复先 count-in,再进窗。
### 0.3 新手手势与解锁
| 手势 | 演奏 ACTION | 选曲 / 结算 | 解锁 |
|---|---|---|---|
| 单击(含分区坐标) | 敲该区 | 开始 / 再来 | 阶段 0;演奏期 `immediateTap` |
| 左 / 右滑 | 不作为音符(可 `invalid` 或忽略为非敲) | 切曲 / 右滑下一首 | 阶段 0 |
| 长按 | 死输入:`invalid` 或闷镲,不判定 | **帮助一句** | 阶段 1 |
| 下滑 | 阶段 2 前=`invalid`「现在只要敲。」;阶段 2 后无条件暂停菜单 | 菜单 | 阶段 2(第一局结束) |
| 双击手势 | **不存在**;300ms 内两下=两次 tap | 当单击 | 阶段 3 仅重听选曲说明/评级,禁止绑重开 |
键盘:Digit1–6 = 六区,按下即发。空格落 BC(家区)。选曲态数字键无效。
### 0.4 状态 × 手势矩阵(新手期)
| 状态 \ 手势 | 分区单击 | 左右滑 | 长按 | 下滑(未解锁菜单) | 双击 | 连点 |
|---|---|---|---|---|---|---|
| intro/tut 讲解 SPEAKING | 跳句 或 摸鼓(T0 探索) | 打断 | 帮助 | `invalid`+解释 | 当单击 | 400ms `busy`(讲解);T0 每下都出声 |
| 教学跟打 ACTION | 敲区判定 | `invalid` | 死输入 | `invalid` | 当两次单击 | 两下两击 |
| 演奏 ACTION | 敲区判定 | 非音符 | 死输入 | 未解锁=`invalid` | 两次单击 | 合法连击 |
| 选曲 | 开始当前曲 | 切曲报名 | 帮助 | 阶段 2 菜单 | 当单击 | `busy` |
| 暂停菜单 | 确认当前项 | 左右切换 | 重听说明 | 关闭菜单 | 当单击 | `busy` |
| 结算 | 同曲再来 | 右=下一首 | 重听评级 | 菜单 | 当单击 | 只处理第一下 |
### 0.5 等待点
| id | 期待 | `_full` | `_short` | 静默 | L2 / L3 |
|---|---|---|---|---|---|
| `tut_probe` | 任意敲 ≥1 | 「随便摸,听鼓在哪。」 | 「摸一下。」 | 8s 自动进 T1 | — |
| `tut_kick` | 应答敲 BC | 「家区在下中。点一下。」 | 「点下中。」 | Miss | 降速重演 → 演示 |
| `tut_sides` | BL 然后 BR | 「左下,再右下。」 | 「左右下。」 | Miss | 同上 |
| `select` | 单击 | 「单击,开始。」 | 「单击。」 | 18s | — |
| `settle` | 单击 | 「单击,再来一遍。」 | 「单击。」 | 20s | — |
演奏 ACTION 不挂等待声、应答小节内零语音。
### 0.6 首 3 分钟逐秒脚本
| 时间 | 游戏说 / 播 | 期待 | 没做 | 做错 |
|---|---|---|---|---|
| 0~3s | 「点一下屏幕。」或直接「随便摸。」 | 任意敲 | 8s 自动进 T1 | — |
| 3~10s | 区音色 + 区名(第一次成功)→ T1 数拍 → 领奏 BC | 应答敲家区 | 「这拍没接。」 | 错区:报名实际区 +「敲家区。」 |
| 10~30s | T2 左右下排 | 跟打 | 短句;2 败降速 | 真话归因 |
| 30~60s | T3 上排三音或进曲目一句 1 | 跟打 | 接管 | Miss 无「假成功」乐器归属 |
| 60~180s | 曲目一前句(无双击手势、反拍仅加花) | 敲对区 | 连 2 Miss 才 `gd_miss` 一次 | 早/晚/没接/错鼓分档 |
### 0.7 失败表
| 类型 | 判定 | 归因 | 回到 | 新手代价 |
|---|---|---|---|---|
| 没出手 | expected+GOOD+0.10s 无应答 | 「这拍没接。」 | 教学重来;正片歌继续 | 不中断 |
| 早 / 晚 | 同区超 Perfect 但仍在 Good | 教学事后「早了/晚了」;正片 Good 出声 | 教学重来 | 无 |
| 错鼓 | 异分区音符半窗内被敲 | 教学:区名+「敲错鼓了」;正片:错区音色本身(配额不叠语音) | 同上 | combo 清零 |
| 教学 2 败 | 同一步 | 「我放慢一些。」×0.75 | 该步 | 再败跳过不卡死 |
| 长按演奏期 | 按下≥450ms | 闷镲 + `invalid` | 不归属 | 无 |
### 0.8 台词类别
- `critical`:开场动手句 ≤3s。
- `content`:曲名、评级、解锁、`tut_map` 拆句后非关键段。
- `hint`:`gd_answer`、`gd_count`、区名、短教学。
- `feedback`:`gd_miss_none` / early / late / `retry_wrong`。
应答小节内:hint/feedback 播不出则丢。曲尾 3s 内不插 `gd_miss`。
### 0.9 断点复述
暂停:泵停、BGM 记 offset。恢复:cue.expected / `_bgmT0` 平移 = 暂停时长 + **count-in 小节**;guide full 先播 `gd_count`(每曲 1 次)。退出写进度 schema 1。
### 0.10 测试
§12 断言清单(已按新手无双击、菜单单击确认、ACTION、count-in 修订)。乱点:无声操作 0;被动原句重复 0。
---
## 1. 可行性决策(保留)
引擎 `onGesture(g, info?: {x,y})` 后向兼容扩展;键盘 `keyCenter` 免费得坐标。打击乐 numpy 合成。BGM 硬性 `no drums`。回归义务见 `research/rhythm-drummer/round0/`。
---
## 2. 屏幕分区与音色(保留)
```
┌─────────┬─────────┬─────────┐
│ TL 左上 │ TC 上中 │ TR 右上 │ 上排:清亮 pan -0.6 / 0 / +0.6
│ 踩镲 │ 高嗵 │ 吊镲 │
├─────────┼─────────┼─────────┤
│ BL 左下 │ BC 下中 │ BR 右下 │ 下排:低沉
│ 军鼓 │ 底鼓 │ 低嗵 │
└─────────┴─────────┴─────────┘
```
| 区 | 乐器 | sfx | pan | 合成要点 |
|---|---|---|---|---|
| TL | 闭合踩镲 | `dm_hat` | -0.6 | 6–10kHz 噪声,0.06s |
| TC | 高音嗵 | `dm_tomhi` | 0 | 200→140Hz,0.25s |
| TR | 吊镲 | `dm_crash` | +0.6 | 长尾 ≤1.2s |
| BL | 军鼓 | `dm_snare` | -0.6 | 鼓皮+带通噪声,0.2s |
| BC | 底鼓 | `inst_kick` | 0 | 130→45Hz,0.25s |
| BR | 低音嗵 | `dm_tomlo` | +0.6 | 120→75Hz,0.3s |
Perfect 叠 `dm_accent`。`zoneOf(x,y)` 以 `#game-root` 为界;缺 payload 落 BC。领奏与玩家同一批 sfx。
**同区连击**:谱面上 `1:BC, 2:BC` 是两记点按。新手 `doubleTapWindow: 0` 时两下都是 `tap`,各自判定。不要再走「双击改判 / 序曲撤销账簿」——只保留 immediateTap 的 `tapcancel`(转滑动/长按时撤销这一下的认领,ghost 音收不回,统计必须回滚且不计 Miss)。
---
## 3. 循环与状态机(保留)
```
选曲 → 数拍(1 小节底鼓×4 + 每拍轻震)→ 逐乐句 → 过门/加花 → 终句吊镲 → 结算
idle → intro → tut → select → countin → main → end
```
- 正片数拍:`inst_kick`×4(guide.test G3 `_sched` 锚点保留)。
- 教学数拍:木鱼 `dm_accent`(G2:教学 `_sched` 里 kick=领奏音)。
- 每曲第一个应答窗前 1 小节:`gd_answer` + `turn`。
- **模态菜单**(阶段 2):下滑呼出;**左右滑切换、单击确认**;长按=重听菜单说明;再下滑关闭。暂停真冻结。恢复全网格平移 + **4 拍 count-in**。
---
## 4. 谱面与难度(保留;新手无「双击手势」需求)
记号 `拍:区码`。加花尾音恒 TR。
### 4.1 曲目一《启程》90 BPM(8 句 + 终曲加花,≈65s)
| 句 | 领奏节奏型 | 音符数 |
|---|---|---|
| 1 | `1:BC, 3:BC` | 2 |
| 2 | `1:BL, 3:BR` | 2 |
| 3 | `1:BC, 2:BC, 3:BL` | 3(同区两记点按,不是双击手势) |
| 4 | `1:BL, 2:BR, 3:BC` | 3 |
| 5 | `1:BC, 2:BL, 3:BC, 4:BR` | 4 |
| 6 | `1:TL, 3:BL, 4:BC` | 3 |
| 7 | `1:BC, 2:TL, 3:BC, 4:TR` | 4 |
| 8 | `1:BL, 2:BR, 3:TL, 4:BC` | 4 |
| 终曲加花 | `1:BC, 1.5:BC, 2:BC, 2.5:BL, 3:BL, 3.5:BC, 4:TR` | 7 |
前 4 句应答后各休 1 小节。曲目一普通句无反拍;反拍仅加花。
### 4.2 曲目二《追风》105 BPM
| 句 | 领奏节奏型 | 音符数 |
|---|---|---|
| 1 | `1:BC, 3:BR` | 2 |
| 2 | `1:BL, 2:BL, 3:BC` | 3 |
| 3 | `1:TL, 3:BL, 4:BR` | 3 |
| 4 | `1:BC, 2:BL, 3:BC, 4:TL` | 4 |
| 5 | `1:BC, 2.5:BR, 3:BC` | 3(首个反拍) |
| 中途加花 | `1:BL, 1.5:BL, 2:BC, 2.5:BC, 3:BR, 3.5:BR, 4:TR` | 7 |
| 6 | `1:BL, 2:TL, 3.5:BR, 4:BC` | 4 |
| 7 | `1:BC, 2:BL, 3:BR, 3.5:TL` | 4 |
| 8 | `1:BR, 1.5:BL, 3:BC, 4:TR` | 4 |
| 9 | `1:BC, 2.5:TL, 3:BC, 4:BL` | 4 |
| 10 | `1:BL, 2:BR, 3:TL, 4:BC` | 4 |
| 终曲加花 | `1:BC, 1.5:BL, 2:BC, 2.5:BL, 3:BC, 3.5:BR, 4:TR` | 7 |
前 2 句应答后各休 1 小节。
### 4.3 曲目三《星爆》120 BPM
| 句 | 领奏节奏型 | 音符数 |
|---|---|---|
| 1 | `1:BC, 2:BL, 3:BC, 4:BL` | 4 |
| 2 | `1:TL, 2:BL, 3:TL, 4:BC` | 4 |
| 3 | `1:BR, 2:TR, 3:BR, 4:BL` | 4 |
| 4 | `1:BC, 2.5:TL, 3:BC, 4:BR` | 4 |
| 5 | `1:BL, 1.5:BR, 2.5:BL, 3:BC` | 4 |
| 6 | `1:BC, 2:TL, 2.5:BL, 3:BC, 4:TR` | 5 |
| 中途加花 | `1:TL, 1.5:TL, 2:BL, 2.5:BL, 3:BC, 3.5:BC, 4:TR` | 7 |
| 7 | `1:BR, 2:BC, 3:BL, 3.5:BR, 4:TL` | 5 |
| 8 | `1:BC, 1.5:BC, 2.5:BL, 3:BC, 3.5:TL, 4:TR` | 6 |
| 9 | `1:BL, 2:BC, 2.5:BR, 3:TL, 4:BL` | 5 |
| 10 | `1:BC, 2:BR, 3:BC, 3.5:TL, 4:BL` | 5 |
| 终曲加花 | `1:BC, 1.5:BL, 2:BC, 2.5:BL, 3:BC, 3.5:BC, 4:TR` | 7 |
全曲不休。
### 4.4 改谱规则
1. 曲目一 2→4 音、曲目二 2→4、曲目三 4→6;加花不计。
2. 反拍:曲目一只允许加花;曲目二第 5 句起普通句每句 ≤1;曲目三不限。
3. 同一分区连续 ≤2(两连合法,三连禁止)。
4. 乐句内分区种类 ≥2(仅曲目一句 1 允许纯底鼓)。
5. 相邻反拍禁止左列↔右列大跳(仅曲目三允许 BL↔BR)。
6. 加花尾音恒 TR。
7. **谱面不得要求「双击手势」**;只需连续 tap。
---
## 5. 判定与计分(数字保留)
```js
const PERFECT = 0.15;
const GOOD = 0.35;
const LOOKAHEAD = 0.6;
const PUMP_MS = 40;
```
- 判定时刻 = 触摸/数字键按下(immediateTap 零补偿)。
- 同分区最近未判定音符 \|dt\|≤GOOD → 出该区音;Perfect 叠 accent。
- 异分区音符 \|dt\|≤GOOD×0.5 被敲 = Miss(错鼓)。
- 窗外同区 = 自由演奏(出声不判定)。
- Miss 超时:expected+GOOD+0.10s → 闷镲(`dm_hat` 0.5×)+ `invalid` 回执 + 可选 error 震。**主反馈是声音。**
- 计分/评级/16 连击震/全 Perfect 震:数字沿用;震是补充。
退役:TAP_DELAY / SWIPE_DELAY / DOUBLE_DELAY、双击序曲撤销账簿、超时复活窗、滑动音符。
---
## 6. 教学(分区心智,保留四步)
零惩罚,单步重教 ≤2,第 2 次失败降速 25%,再败跳过。
| 步 | 内容 |
|---|---|
| T0 摸鼓 | 双轴模型一句 → 探索:敲哪区出哪音+区名。摸 ≥3 区进 T1;**8s 无触摸自动进 T1** |
| T1 家区 | 数拍 → 领奏 `1:BC` → 应答 |
| T2 左右下 | `1:BL, 3:BR` |
| T3 上排 | `1:TL, 2:TC, 3:TR` → `tut_done` → 曲目一 |
教学 Miss 归因真话。下滑跳过教学仅阶段 2 以后;新手回访者用开场「点一下开始」跳过。`tut_fill` 在曲目一终曲加花前 1 小节,每账号一次。
---
## 7. 反馈与语音配额(保留数字)
应答小节内零语音。教学失败至多 1 条纠正链。正片连 2 Miss 才 `gd_miss`,同曲一次。探索区名每区每轮一次。结算链 = grade + [new_best_combo] + [unlock] + restart。引擎 3s/5 次保险丝不得绕过。
---
## 8. 资产规格(保留)
打击乐 7 件程序合成,QC:去直流、8ms 淡化、真峰值 ≤−3 dBFS。BGM 三首 prompt 仍要求 **no drums no percussion**,90/105/120 BPM,A minor,`bpm_precise.py` 误差 >0.5 则 atempo。`bgm/menu` 保留。旧含鼓 track 删除。
---
## 9. 进度
key `soundgame.rhythm.progress`,schema 1:`tutorialDone, unlocked, grades, bestCombo, summary`(`《曲名》X级 · 已解锁N/3首`)。B 级解锁下一首。
结算:单击=同曲;右滑=下一首(未解锁播 `song_locked`;song3 右滑播 restart);阶段 2 下滑=菜单。
---
## 10. 断言清单(修订)
A1–A5、A7–A5、A8–A25 原编号保留,交互口径改:
- **A6**:新手期 300ms 内同区两 `tap` = 两次独立敲击(可认领两音),**不产生 `doubletap` 手势、无撤销账簿**。阶段 3 若引擎仍发 `doubletap`,游戏层当第二次 `tap`。
- **A10 菜单**:main 中阶段 2 后下滑呼菜单;**单击确认当前项,不是双击确认**;恢复后平移量 = 暂停 + count-in;`gd_count` 每曲 1 次。
- **A21**:演奏期单击是演奏;讲解期单击跳句,400ms 内再点=`busy`。
- 增补 **A26**:新手谱面/教程不依赖 `g==='doubletap'`。
- 增补 **A27**:演奏期 Floor=ACTION,无等待声;选曲 YOUR_TURN 有等待声或 menu pad。
- 增补 **A28**:无声操作 0;Miss 有闷镲或回执。
其余 A1 分区、A2 窗、A3 错鼓、A4 超时、A5 tapcancel、A9 数拍、A11 加花、A12–A16 评级进度、A17 配额、A18 键盘、A19 guide 签名、A20 资产、A22 全局、A23–A25 R1 修复:**保留**。
13 号旧 §4 手势模式断言不回改;鼓手验收以本节 + 13 号 §5 为准。
---
## 11. 预算台账(保留)
语音 49 id×2;打击乐 7 件;BGM 上限见原文工艺。开发零 API 费。
---
## 12. 废止清单
| 废止 | 改为 |
|---|---|
| 双击手势=一种音符;双击确认菜单 | 只有分区点按;菜单左右滑+单击 |
| 新手 `doubleTapWindow` 300ms | 0;两下两击 |
| 演奏期等待声 / 帮助插播 | ACTION;应答内零语音 |
| 暂停恢复无 count-in | 4 拍 count-in |
| Miss 只震 | 闷镲 + 回执 + 真话归因 |
| 帮助用上滑(与上排鼓冲突) | 非演奏期长按 |
| 开场长规则 | T0 先摸鼓 |
| 03 号手势乐器谱作为现行施工 | 以本文为准 |
引擎坐标第二参、分区布局、时值、曲目表、合成与 BGM 工艺:**全部保留**。