// selector.js — 游戏选择器 // 单击:切换到下一个游戏 // 双击:开始当前选中的游戏 const GAME_CATALOG = [ { title: '林夏', desc: '一部碎屏手机,一个北漂的夜晚。十六条消息,决定明天的自己。', get: () => GAME_LINXIA, }, { title: '一念', desc: '内心法庭。七个声音在等你,今晚必须做一个决定。', get: () => GAME_YINIAN, }, { title: '守夜', desc: '你是夜班保安,独自坐在监控室。楼里传来声音,去查,还是不动。', get: () => GAME_SHOUYE, }, { title: '候诊', desc: '等待检查结果的两个小时。等待本身就是一种体验。', get: () => GAME_HOUZHEN, }, { title: '遗声', desc: '一个陌生人的手机,二十二条录音。听,还是跳过——跳过就永远不知道了。', get: () => GAME_YISHENG, }, { title: '浮', desc: '感官漂流。声音漂过来,抓住,还是让它走。结束时你会听到你带走了什么。', get: () => GAME_FU, }, ]; class GameSelector { constructor(engine, input) { this._engine = engine; this._input = input; this._idx = 0; this._active = false; } async start() { this._active = true; this._idx = 0; this._input.onTap = () => this._next(); this._input.onDoubleTap = () => this._pick(); await Narrator.sayAndWait( '欢迎来到盲游。共六个游戏。单击听下一个介绍,双击开始当前游戏。' ); this._announce(); } _announce() { const g = GAME_CATALOG[this._idx]; const n = this._idx + 1; Narrator.interrupt( `第${n}个:《${g.title}》。${g.desc}单击换一个,双击开始。` ); } _next() { if (!this._active) return; this._idx = (this._idx + 1) % GAME_CATALOG.length; this._announce(); } async _pick() { if (!this._active) return; this._active = false; const g = GAME_CATALOG[this._idx]; Narrator.interrupt(`开始《${g.title}》。`); await new Promise(r => setTimeout(r, 1500)); this._engine.run(g.get(), this._input, () => { // 游戏结束后回到选择器 setTimeout(() => this.start(), 2000); }); } }