- 屏幕3列×2行六区鼓组(列=声像左中右/行=音高上亮下沉),六件程序合成打击乐,三重冗余蒙眼可辨
- 无鼓伴奏BGM上跟随领奏 call&response + 加花句;3曲90/105/120 BPM解锁制,BPM实测89.99/105.00/120.01
- 引擎后向兼容扩展:onGesture补{x,y}坐标(单参回调零感知,15游戏+3引擎测试全量回归零失败)
- 判定简化:全部音符=分区点按零延迟,旧双击补偿/下滑折中退役;键盘Digit1-6+空格=家区
- 教学摸鼓认区(摸哪报哪,8s无触摸自动进阶)+重教≤2+降速DDA+归因真话律
- 保留旧作好评:跟随领奏核心/S~C评级/解锁制/判定口径/guide工程遗产
- 语音49id双性别+8key;R1+R2连续2轮4/4愿意玩P0=0裁定可交付;live直证33 Perfect dt≈0.00s
- 03号文档仅文末加取代指针;新设计24号;档案research/rhythm-drummer/;Mureka累计$1.35
12 KiB
12 KiB
03 · 《节拍行者》重构施工稿(rhythm rebuild,R3 施工依据)
给开发者的实现要点摘要
- 玩法 = 跟随领奏(call & response):系统奏 1 小节节奏型(2-4 个手势乐器音),玩家在下一小节的相同拍点用相同手势跟打。3 首曲目(90/105/120 BPM)解锁制。完整谱面见 §3(每首前 8 句全部写出,后续句按 §3.5 规则生成)。
- 判定沿用现版常量:PERFECT ±0.12s / GOOD ±0.25s / TAP_DELAY 0.30s 补偿 / LOOKAHEAD 0.6s / 调度泵 40ms;tap 只允许出现在第 1、3 拍(强拍)。
- 判定反馈全改震动(
engine/haptics.js):出手震动引擎 gesture.js 已内置(swipe/confirm),游戏层只加 Miss=error、16 连击=success、乐句全 Perfect=自定义 [20,40,20];领奏音符锚点自定义 BEAT=[8]。judge_*提示音删除。- 语音台词全表在 03-rhythm-voice-ids.md(音频总监照录):旁白 female=Vivian / male=Uncle_Fu(R1 音色分配表),准确率分档整句播报。
- 进度 data:
{ summary, unlocked, grades, bestCombo }(§7),大厅卡片显示 summary。
1. 现版问题与重构方向(结论,不再展开)
现版"听令行动"(指令音→下一拍做手势)认知负荷四层(认音色→忆映射→换算拍点→精确出手),且 judge 提示音制造"考试感"。重构为跟随领奏:记忆负荷压到 ≤4 音短句,负荷转移到节奏精度;玩家动作触发与 BGM 同调性的乐器音,做对时听到自己在演奏。现版的 AudioContext 预排程泵(_pump/_scheduleSfx/tap 补偿)工程质量好,保留复用,只重写谱面与判定逻辑。
2. 常量与判定(施工契约,直接抄)
const PERFECT = 0.12; // Perfect 窗口 ±120ms
const GOOD = 0.25; // Good 窗口 ±250ms(蓝牙延迟由它吸收)
const TAP_DELAY = 0.30; // 引擎 tap 回调延迟补偿(沿用现版)
const LOOKAHEAD = 0.6; // 调度前瞻(秒)
const PUMP_MS = 40; // 调度泵周期
- tap 补偿:判定时
if (g === 'tap') t -= TAP_DELAY;tap 音符的 Miss 超时检查放宽TAP_DELAY + 0.08,其他手势放宽0.05(现版 game.js:159-164 原样保留)。 - tap 位置约束:谱面中 tap 只允许落在第 1、3 拍(强拍),给补偿留足余量;doubletap 不落在 x.5 反拍(曲目三之前)。
- 判定结果:
- 手势对 + |dt|≤0.12 → Perfect:玩家手势乐器音 + accent 亮音层叠加。
- 手势对 + |dt|≤0.25 → Good:只播乐器音。
- |dt|>0.25 或手势错 → Miss:不播乐器音(错过=没出声,本身就是反馈)+
vibrate('error')。 - 手势对但窗口内找错音符归属:按现版"最近未判定音符"归属逻辑(game.js:278-293)保留。
- 计分:Perfect=2 / Good=1 / Miss=0;
rate = 得分 / (2 × 总音符数);评级 S≥0.95 / A≥0.85 / B≥0.70 / C<0.70。不掉血、不中断,歌照唱完。 - 连击:每 16 连击
vibrate('success')(不打断演奏,不播报);乐句全部 Perfect 时乐句末vibrate([20,40,20])。
3. 谱面
3.1 记号与结构
- 拍点记号:
拍号:手势,1 小节 = 4 拍(1, 2, 3, 4),x.5= 八分音符反拍。 - 手势:
tap(T)doubletap(D)left(L)right(R)up(U)down(N)。 - 每个乐句 = 领奏 1 小节 + 应答 1 小节(应答拍点 = 领奏拍点 + 4 拍)。
- 曲目流程:
数拍 1 小节(BGM 内鼓点,无独立节拍器)→ 逐乐句 → 结算。 - 乐句间休止:曲目一前 4 句应答后各休 1 小节;曲目二前 2 句各休 1 小节;曲目三不休。
3.2 曲目一《启程》90 BPM(SPB=0.667s,10 句,≈70s)
定位:教学曲。全强拍,2→4 音,无反拍。
| 句 | 领奏节奏型 | 音符数 |
|---|---|---|
| 1 | 1:tap, 3:tap |
2 |
| 2 | 1:left, 3:right |
2 |
| 3 | 1:tap, 2:doubletap, 3:tap |
3 |
| 4 | 1:left, 2:doubletap, 3:right |
3 |
| 5 | 1:tap, 3:left, 4:doubletap |
3 |
| 6 | 1:right, 3:tap, 4:doubletap |
3 |
| 7 | 1:up, 3:down, 4:doubletap |
3 |
| 8 | 1:tap, 2:up, 3:right, 4:doubletap |
4 |
| 9 | 1:left, 2:right, 3:tap, 4:doubletap |
4 |
| 10 | 1:tap, 2:doubletap, 3:tap, 4:doubletap |
4(终句,全鼓组收束) |
3.3 曲目二《追风》105 BPM(SPB=0.571s,12 句,≈75s)
定位:引入反拍(第 5 句起)与 4 音密集句。
| 句 | 领奏节奏型 | 音符数 |
|---|---|---|
| 1 | 1:tap, 3:right |
2 |
| 2 | 1:left, 2:doubletap, 3:tap |
3 |
| 3 | 1:up, 3:down, 4:doubletap |
3 |
| 4 | 1:tap, 2:right, 3:left, 4:doubletap |
4 |
| 5 | 1:tap, 2.5:right, 3:tap |
3(首个反拍 2.5) |
| 6 | 1:left, 2:up, 3.5:right, 4:doubletap |
4 |
| 7 | 1:tap, 2:doubletap, 3:down, 3.5:up |
4 |
| 8 | 1:right, 1.5:left, 3:tap, 4:doubletap |
4 |
| 9 | 1:tap, 2.5:left, 3:tap, 4:doubletap |
4 |
| 10 | 1:up, 2:right, 3:down, 3.5:left |
4 |
| 11 | 1:tap, 2:doubletap, 2.5:right, 3:tap |
4 |
| 12 | 1:left, 1.5:right, 2:doubletap, 3:tap, 4:doubletap |
5(终句) |
3.4 曲目三《星爆》120 BPM(SPB=0.5s,12 句,≈70s)
定位:4-6 音密集句、切分、doubletap 上反拍。不设十六分音符(盲玩极限)。
| 句 | 领奏节奏型 | 音符数 |
|---|---|---|
| 1 | 1:tap, 2:doubletap, 3:tap, 4:doubletap |
4 |
| 2 | 1:left, 2:right, 3:left, 4:doubletap |
4 |
| 3 | 1:up, 2:down, 3:up, 4:doubletap |
4 |
| 4 | 1:tap, 2.5:left, 3:tap, 4:right |
4 |
| 5 | 1:left, 1.5:right, 2.5:left, 3:tap |
4 |
| 6 | 1:tap, 2:up, 2.5:down, 3:tap, 4:doubletap |
5 |
| 7 | 1:right, 2:doubletap, 3:left, 3.5:right, 4:up |
5 |
| 8 | 1:tap, 1.5:doubletap, 2.5:left, 3:tap, 3.5:right, 4:doubletap |
6(高潮句) |
| 9 | 1:left, 2:doubletap, 2.5:up, 3:right, 4:doubletap |
5 |
| 10 | 1:tap, 2.5:down, 3:tap, 3.5:up, 4:doubletap |
5 |
| 11 | 1:right, 1.5:left, 2:right, 3:tap, 4:doubletap |
5 |
| 12 | 1:tap, 2:doubletap, 2.5:left, 3:tap, 3.5:right, 4:doubletap |
6(终句) |
3.5 难度曲线规则(谱面设计约束,续作/改谱遵守)
- 乐句长度:曲目一 2→4 音,曲目二 2→5 音,曲目三 4→6 音;同曲内单调不减(终句允许 +1 爆发)。
- 反拍(x.5)引入:曲目一禁用;曲目二第 5 句起、每句至多 1 个反拍音;曲目三不限。
- tap 只落 1/3 拍(全曲目铁律);doubletap 曲目一/二只落整拍,曲目三可落反拍。
- 同一手势连续出现 ≤2 次(跨音符);同一乐句内手势种类 ≥2(第 1、10 句的全鼓句除外)。
- up/down 作为"音高对"尽量成对出现在同一乐句(↑↓ 或 ↓↑),利于听觉记忆。
- 左右声道手势不放在相邻反拍连续位(如
1:left, 1.5:right只允许曲目三)——声像跳变过快在耳机上易混。
4. 手势 → 乐器音映射(sfx 资产)
| 手势 | 乐器音 | sfx id | 声像/音高 |
|---|---|---|---|
| tap | 底鼓 kick | sfx/inst_kick |
中央,低频 |
| doubletap | 军鼓 snare | sfx/inst_snare |
中央偏上 |
| left | 闭合镲 closed hat | sfx/inst_hat_l |
极左 |
| right | 开放镲 open hat | sfx/inst_hat_r |
极右 |
| up | 高通 tom | sfx/inst_tom_hi |
中央,升调感 |
| down | 低通 tom | sfx/inst_tom_lo |
中央,降调感 |
| (叠加层) | Perfect accent 亮音 | sfx/accent |
共用 1 个,叠在乐器音上 |
全部与 BGM 同调性(曲目一/二/三 BGM 根音需在 Mureka prompt 里统一,建议 A minor)。乐器音时长 ≤0.4s,起音要硬(盲玩靠起音对拍)。生成方式:Stable Audio 3(打击乐短采样质量足够)或程序合成兜底;accent 可用程序合成(高频短琶音)。
5. 流程与教学(30 秒上手)
5.1 状态机
idle → intro(语音) → tut(3 步教学) → select(选曲,二周目起) → countin → main(逐乐句) → end(结算)
↑_________________|
select:左右滑切曲目(播曲目名 + 已解锁状态),单击进入,下滑回大厅。未解锁曲目播报"上一首拿到 B 级以上解锁"。- 教学只在首次进游戏出现(
progress.data.tutorialDone);之后 intro 缩减为一句"跟着音乐,我奏一句,你跟一句。"
5.2 教学 3 步(台词见 voice-ids 文档 T 组)
| 步 | 内容 | 机制 |
|---|---|---|
| T1 | 领奏 1:tap(第 1 拍单底鼓)→ 玩家在第 2 小节同位置跟打 |
做错:error 震动 + 纠正语音(早了/晚了/不是这个手势,按 dt 与手势选句)→ 重播领奏重试;2 次失败跳过进 T2 |
| T2 | 领奏 1:left, 3:right → 跟打 |
同上 |
| T3 | 领奏 1:tap, 2:doubletap, 3:tap → 跟打 |
通过后进曲目一 |
纠正判定复用正式判定窗口,只是不计分。教学期间 BGM 已在播(从 intro 第 6 秒起),数拍感来自 BGM 本身。
6. 震动与语音在流程中的落点
| 时机 | 震动 | 语音 |
|---|---|---|
| 领奏每个音符 | [8](BEAT,自定义) | — |
| 玩家出手 | (引擎内置 swipe/confirm,游戏层不重复) | 乐器音 |
| Miss | error | — |
| 16 连击 | success | — |
| 乐句全 Perfect | [20,40,20] | — |
| 曲目过半 | — | mid_song("过半了,保持。") |
| 结算 | success(S/A)/ 无(B/C) | grade_* + restart_hint |
| 解锁新曲 | success + [20,40,20] | unlock_song2/3 |
7. 进度存储
{
"schema": 1,
"updatedAt": "2026-08-29T12:00:00Z",
"summary": "《追风》B级 · 已解锁2/3首",
"tutorialDone": true,
"unlocked": 2,
"grades": { "song1": "a", "song2": "b" },
"bestCombo": 42
}
- 评级提升(如 b→a)、解锁变化、bestCombo 刷新时在结算后 PUT;
summary格式:《曲名》X级 · 已解锁N/3首(取最高评级的曲目)。 - 解锁规则:曲目 n 拿到 B 级以上 → 解锁 n+1。
8. 实现要点(给开发 agent)
- 保留现版:
AudioContext.currentTime预排程、40ms 泵、LOOKAHEAD、TAP_DELAY补偿与 Miss 放宽(现 game.js:26-30, 149-176, 267-293)、BGM 手动src.start(t0)对网格(game.js:221-239)。 - 重写:谱面数据从 40 指令流改为
phrases: [{ notes: [{ beat, gesture }] }](本文 §3 表格直接转 JSON);调度时领奏音符排第 k 小节、应答_cues期望时刻 = 领奏时刻 + 4 拍;间奏休止按曲目参数插入空小节。 - 玩家乐器音不走预排程:出手即播(sfx 即发即弃),Perfect 时叠播
sfx/accent。 - BGM:3 首重生成(Mureka,90/105/120 BPM 精确、鼓组清晰、A minor、60-90s 无缝循环,沿用现版 groove 归一化工艺);现版
bgm/groove弃用。数拍融入 BGM,删独立 tick 节拍器。 - 震动接
engine/haptics.js;BEAT 用自定义数组vibrate([8]),领奏音符在调度时同步排一个setTimeout对齐(或用 pump 在音符时刻触发,误差 <40ms 可接受)。 - 语音全表见 03-rhythm-voice-ids.md;现版
voice/welcome/rules/tut_start/tut_done弃用,grade_*/restartid 沿用但文案变更(重录)。 - 结算画面:单击=再来一遍(同曲),右滑=下一首(若已解锁),下滑=回大厅。
- 更新
web/rhythm/README.md(玩法、手势表、进度结构)。
取代指针(2026-09-14,24 号裁定):本文档(及 03-rhythm-voice-ids.md)的 施工依据地位已被 24-rhythm-drummer.md + 24-rhythm-voice-ids.md 取代——《节拍行者》重构为 屏幕分区鼓手模式(6 区打击乐 + 无鼓伴奏,跟随领奏核心/评级/解锁/BPM 精确性 延续)。本文仅作历史档案保留,正文一字不改;13 号文档 §4 rhythm 断言段 同理冻结,新断言见 24 号文档 §11。