# 技术设计 ## 1. 当前原型架构 当前版本采用微信小程序原生 JavaScript,不依赖 npm 包和远程服务。 ```text 页面层 pages/* ↓ 本地游戏服务 services/game-service.js ↓ wx Storage(房间、玩家、事件和结果) ``` `game-service.js` 将页面与数据源隔离。接入真实后端时,页面调用接口可以尽量保持不变,只需将服务实现替换为网络请求和实时订阅。 ## 2. 推荐生产架构 初期建议采用微信云开发,减少登录、部署和运维成本;验证规模后可迁移为自有服务。 ```text 微信小程序 ├─ HTTPS API:创建、加入、抓捕、技能、结算 ├─ WebSocket:房间状态和事件推送 └─ 定位模块:低频位置上报与边界判断 ↓ 应用服务 ├─ 身份与权限 ├─ 房间状态机 ├─ 游戏规则引擎 ├─ 位置模糊化 ├─ 口令与防作弊 └─ 安全事件 ↓ 数据层 ├─ 持久数据库:用户、房间、结果 ├─ Redis:在线状态、口令、房间实时状态 └─ 短期位置存储:设置自动过期时间 ``` ## 3. 核心实体 ### User ```js { id, openId, displayName, avatarUrl, safetySettings, createdAt } ``` ### Room ```js { id, code, hostId, name, mode, status, settings: { maxPlayers, durationMinutes, prepareMinutes, clueIntervalMinutes, seekerCount, radiusMeters, skillsEnabled }, center, phaseEndsAt, version, createdAt } ``` ### Player ```js { id, roomId, userId, displayName, role, status, ready, caughtBy, caughtAt, joinedAt, lastSeenAt } ``` ### GameEvent ```js { id, roomId, type, actorId, targetId, visibility, payload, createdAt } ``` ### LocationPing ```js { roomId, playerId, latitude, longitude, accuracy, capturedAt, expiresAt } ``` 生产环境中 `LocationPing` 不应作为永久战绩保存。 ## 4. API 草案 - `POST /rooms`:创建房间。 - `GET /rooms/:code`:读取可公开的房间摘要。 - `POST /rooms/:code/join`:加入房间。 - `POST /rooms/:id/ready`:切换准备状态。 - `POST /rooms/:id/start`:房主开始游戏。 - `POST /rooms/:id/location`:上报位置。 - `POST /rooms/:id/skills/:skill`:使用技能。 - `POST /rooms/:id/captures`:提交抓捕凭证。 - `POST /rooms/:id/pause`:暂停游戏。 - `POST /rooms/:id/assemble`:发起全员集合。 - `POST /rooms/:id/finish`:结束游戏。 - `GET /rooms/:id/result`:读取结算结果。 所有改变游戏状态的接口都应: - 校验用户身份和房间成员关系。 - 校验当前房间状态和角色权限。 - 使用服务端时间。 - 支持幂等键,避免弱网重试造成重复事件。 - 更新房间版本号并广播事件。 ## 5. 实时同步 WebSocket 消息建议仅发送必要状态变化: ```js { eventId, roomId, roomVersion, type: "PLAYER_CAUGHT", payload: {}, serverTime } ``` 客户端策略: 1. 进入候场或游戏页后建立连接。 2. 按 `eventId` 去重。 3. 检测版本跳跃时重新拉取房间快照。 4. 退到后台后按微信能力选择保活或恢复时重连。 5. UI 倒计时基于 `phaseEndsAt - serverTimeOffset` 计算。 ## 6. 位置和地理围栏 - 客户端获取坐标并附带定位精度和采集时间。 - 服务端校验坐标新鲜度、速度异常和精度阈值。 - 使用服务端保存的场地中心和半径判断越界。 - 向寻找者发送的线索由服务端完成网格化或随机偏移。 - 不将躲藏者原始坐标发送给其他普通玩家。 - 位置记录设置短期 TTL,游戏结束后触发删除任务。 线索模糊化可采用: - H3/Geohash 网格降级。 - 以真实点为中心生成受边界约束的随机圆。 - 仅返回目标与玩家的距离档位,如“很近、附近、较远”。 ## 7. 抓捕防作弊 动态口令建议由服务端生成: ```text token = HMAC(roomSecret, targetPlayerId + timeWindow + nonce) ``` - 口令窗口建议 30 秒。 - 提交时校验寻找者与目标的最近位置距离。 - 校验双方都在线、角色正确且目标尚未被抓。 - 使用事务写入抓捕结果,防止两个寻找者同时抓到同一目标。 - 口令只作为相遇证明之一,不能替代安全规则。 ## 8. 安全设计 - 房主开始前必须完成场地和规则确认。 - 服务端保留暂停、集合和取消的高优先级事件通道。 - 客户端进入后台、定位失效、低电量或离线时产生状态提示。 - 精确位置访问纳入服务端审计,不允许普通运营后台随意查看。 - 公开组局上线前必须具备举报、封禁、内容安全和年龄策略。 ## 9. 测试策略 - 单元测试:房间状态机、身份分配、倒计时、抓捕和结算。 - 属性测试:不同人数与寻找者数量下角色数量始终合法。 - 集成测试:多人并发加入、重复抓捕、断线重连和版本冲突。 - 真机测试:前后台切换、弱网、定位精度、耗电和不同微信版本。 - 户外测试:边界提醒时机、线索节奏、屏幕使用时间和安全流程。 ## 10. 迁移顺序 1. 保留页面与服务接口,先把本地房间读写替换为云函数。 2. 接入微信登录并使每个玩家拥有稳定服务端 ID。 3. 引入实时房间事件和服务端倒计时。 4. 接入地图选区、定位上报和模糊线索。 5. 将抓捕、技能和结算全部迁到服务端裁决。 6. 增加日志、监控、隐私删除和运营安全能力。