用户系统(B,游戏零改动): - POST /api/device 首访 0 交互静默建档(自动玩家一/二…,per-IP 频控);断网降级纯本地照玩 - 大厅档案切换器(切换=flush 上云→快照回灌→倒灌→服务器回拉,profileId 分桶修同设备串档;aria menu 编号可听) - claim 可选认领(命名+scrypt PIN);旧 users/sessions 单向迁移(PIN 明文即刻哈希,已真实数据验证);login 兼容+claim-merge 桶级 LWW;logout;/server/ 静态封禁 - PUT baseUpdatedAt 守卫(legacy 放行+警告);GET 无参全桶回拉(修 7/8 游戏跨设备只 PUT 不 GET) - web/profiles.js 分桶纯函数 + api-smoke.mjs 7/7(建档/LWW/claim-merge/迁移/频控/封禁/分桶 H1-H4) 键盘双端(A,游戏代码零改动): - gesture.js 键盘通道 +137 行:←↑↓→/WASD=滑动、空格=单击(走 300ms 双击窗与触摸共享虚拟指针)、回车=即时 doubletap、按住空格 ≥450ms=长按;repeat 抑制/表单守卫/方向键 preventDefault - settings.input(auto/touch/key)+ gesture.inputMode();遮罩键盘解锁与文案自适应(按空格开始/轻触开始) - 8 游戏遮罩改用自适应默认文案;大厅设置面板「操作方式」+页脚键位提示 - live control.mjs 键盘注入通道(CDP dispatchKeyEvent);engine-input.test 61 断言 回归:12 套件全绿(8 playtest + guide + engine-voice + engine-input + api-smoke 7/7);8001 服务器已重启加载新 API,/api/device 端到端验证通过 P1 待排:153 句×双性 TTS 键盘语音变体 / 6 位配对码跨设备 / 认领 UI 打磨(research/platform/00-synthesis.md §3)
36 lines
1.1 KiB
HTML
36 lines
1.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<!-- viewport 锁缩放,viewport-fit=cover 适配刘海屏 -->
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
|
|
<title>暗室 · SoundGame Web</title>
|
|
<link rel="stylesheet" href="../engine/style.css">
|
|
</head>
|
|
<body>
|
|
<!-- 全屏根元素:手势全屏捕获层,封面图放里面 -->
|
|
<div id="game-root">
|
|
<img class="cover" src="cover.png" alt="">
|
|
</div>
|
|
|
|
<script type="module">
|
|
import { WebAudioEngine } from '../engine/audio.js';
|
|
import { attachGestures } from '../engine/gesture.js';
|
|
import { EscapeGame } from './game.js';
|
|
|
|
async function main() {
|
|
const root = document.getElementById('game-root');
|
|
const audio = new WebAudioEngine('audio/');
|
|
const game = new EscapeGame(audio, root);
|
|
|
|
await audio.showStartOverlay({ cover: 'cover.png' });
|
|
// 走到这里 AudioContext 已解锁,可以出声了
|
|
game.start();
|
|
attachGestures(root, (g) => game.onGesture(g));
|
|
}
|
|
|
|
main();
|
|
</script>
|
|
</body>
|
|
</html>
|