Files
SoundGame/web/harness/sessions/simon.mjs
T
SoundGame Dev 79dffac01e guide层v1: 全局向导交互层落地(状态签名earcon/turn cue/静默看门狗/纠错) + 6游戏接线 + 8句向导语音 + 测试全绿
- engine/guide.js 运行时合成8个签名earcon(方法论L2硬参数),off档零定时器,插播queue不顶对白
- settings: guide三档(full/standard/off默认full) + 语速2.2视障档;audio: isVoicePlaying()/setRateBoostEnabled() 清两个已知问题
- 6游戏按schemes§2接线: storyline看门狗+无效手势纠错、simon免扣重听看门狗、escape turn cue+提前卡关提示、rhythm gd_answer/gd_miss+结算看门狗+快进豁免、space首撞指令提示+结算看门狗、rpg格挡纠错+60s催促+状态签名
- 大厅设置面板+向导文档(14-guide-layer.md)+00-global-ux §6;R5台词表补4条一致性
- 试玩转写含向导事件;6 playtest(guide=off断言零改动)+guide.test(34断言)+资产终检全绿
2026-08-30 22:46:05 +08:00

71 lines
3.4 KiB
JavaScript
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.
/**
* 《音序回响》新手会话剧本:教学六音一步一步学(中间故意做错一次听纠错)、
* 第 1 轮答对、第 2 轮中途忘序列僵住 11 秒(触发向导「双击可重听」提示)、
* 第 3 轮故意答错第一下(消耗机会自动重播),然后答对完成第 3 轮收工。
*/
export function describe(game) {
const GN = { up: '上滑', down: '下滑', left: '左滑', right: '右滑', tap: '单击', doubletap: '双击' };
const GESTURES = ['up', 'down', 'left', 'right', 'tap', 'doubletap'];
switch (game.phase) {
case 'tutorial':
return game.teachAwait
? `教学:该做「${GN[GESTURES[game.teachIdx]]}」了`
: '教学旁白在播,先听着';
case 'announce': return `第 ${game.round} 轮报数呢,听好了`;
case 'playback': return `第 ${game.round} 轮序列演奏中(${game.sequence.length} 个音),记住顺序,先别动手`;
case 'input': return `第 ${game.round} 轮轮到你了:已对上 ${game.inputIdx}/${game.sequence.length},照原顺序做手势`;
case 'roundend': return game.chances < (game.round > 4 ? 2 : 1) ? '答错了,正在重播刚才的序列' : '刚答完,播报中';
case 'gameover': return `游戏结束,完成 ${game.round - 1} 轮。单击再来一局,下滑开菜单`;
case 'menu': return '菜单里:单击切选项,双击确认,上滑听规则';
default: return '开场,稍等一下';
}
}
export async function session(ctx, mock) {
const { game } = ctx;
const G = ['up', 'down', 'left', 'right', 'tap', 'doubletap'];
// 教学 T0-T6:教一个练一个
for (let i = 0; i < G.length; i++) {
await ctx.waitCond(() => game.phase === 'tutorial' && game.teachAwait);
ctx.status(`教学第 ${i + 1}/6 个音色`);
if (i === 2) {
ctx.note('把「左滑」记混了,先来了个右滑');
await ctx.gesture('right'); // 听纠错语音(t_wrong_left)
await ctx.waitCond(() => game.phase === 'tutorial' && game.teachAwait);
}
await ctx.gesture(G[i]); // 照指令做对
await ctx.waitIdle();
}
// 正式对局:打到完成第 3 轮
let wrongDone = false;
let stallDone = false;
while (mock.now < 12 * 60 * 1000 && game.phase !== 'gameover' && game.round < 4) {
if (game.phase === 'input') {
// 第 2 轮开局先失忆僵住 11 秒:触发向导「双击可以重新听一遍序列」提示
if (game.round === 2 && game.inputIdx === 0 && !stallDone) {
stallDone = true;
ctx.status('序列有点长,先僵一会儿');
ctx.silence(11, '想不起来序列了');
await ctx.waitVirtual(11000);
ctx.status('听到提示:需要的话,双击可以重新听一遍序列');
}
// 第 2 轮第二拍故意答错:触发"用一次机会,再听一遍"(复活重听)
if (game.round === 2 && game.inputIdx === 1 && !wrongDone) {
wrongDone = true;
ctx.note('这一下故意点错,听听游戏怎么说');
await ctx.gesture(G[(G.indexOf(game.sequence[game.inputIdx]) + 1) % G.length]);
await ctx.waitIdle(); // retry_use + 自动重播同一序列
continue;
}
ctx.status('轮到我复现了');
await ctx.gesture(game.sequence[game.inputIdx]);
continue;
}
await ctx.waitIdle();
}
ctx.status(`收工:完成了 ${game.round - 1} 轮`);
}