Files
mini-zmc/docs/TECHNICAL_DESIGN.md
2026-07-29 10:50:33 +08:00

5.5 KiB
Raw Permalink Blame History

技术设计

1. 当前原型架构

当前版本采用微信小程序原生 JavaScript不依赖 npm 包和远程服务。

页面层 pages/*
    ↓
本地游戏服务 services/game-service.js
    ↓
wx Storage房间、玩家、事件和结果

game-service.js 将页面与数据源隔离。接入真实后端时,页面调用接口可以尽量保持不变,只需将服务实现替换为网络请求和实时订阅。

2. 推荐生产架构

初期建议采用微信云开发,减少登录、部署和运维成本;验证规模后可迁移为自有服务。

微信小程序
├─ HTTPS API创建、加入、抓捕、技能、结算
├─ WebSocket房间状态和事件推送
└─ 定位模块:低频位置上报与边界判断
        ↓
应用服务
├─ 身份与权限
├─ 房间状态机
├─ 游戏规则引擎
├─ 位置模糊化
├─ 口令与防作弊
└─ 安全事件
        ↓
数据层
├─ 持久数据库:用户、房间、结果
├─ Redis在线状态、口令、房间实时状态
└─ 短期位置存储:设置自动过期时间

3. 核心实体

User

{
  id,
  openId,
  displayName,
  avatarUrl,
  safetySettings,
  createdAt
}

Room

{
  id,
  code,
  hostId,
  name,
  mode,
  status,
  settings: {
    maxPlayers,
    durationMinutes,
    prepareMinutes,
    clueIntervalMinutes,
    seekerCount,
    radiusMeters,
    skillsEnabled
  },
  center,
  phaseEndsAt,
  version,
  createdAt
}

Player

{
  id,
  roomId,
  userId,
  displayName,
  role,
  status,
  ready,
  caughtBy,
  caughtAt,
  joinedAt,
  lastSeenAt
}

GameEvent

{
  id,
  roomId,
  type,
  actorId,
  targetId,
  visibility,
  payload,
  createdAt
}

LocationPing

{
  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 消息建议仅发送必要状态变化:

{
  eventId,
  roomId,
  roomVersion,
  type: "PLAYER_CAUGHT",
  payload: {},
  serverTime
}

客户端策略:

  1. 进入候场或游戏页后建立连接。
  2. eventId 去重。
  3. 检测版本跳跃时重新拉取房间快照。
  4. 退到后台后按微信能力选择保活或恢复时重连。
  5. UI 倒计时基于 phaseEndsAt - serverTimeOffset 计算。

6. 位置和地理围栏

  • 客户端获取坐标并附带定位精度和采集时间。
  • 服务端校验坐标新鲜度、速度异常和精度阈值。
  • 使用服务端保存的场地中心和半径判断越界。
  • 向寻找者发送的线索由服务端完成网格化或随机偏移。
  • 不将躲藏者原始坐标发送给其他普通玩家。
  • 位置记录设置短期 TTL游戏结束后触发删除任务。

线索模糊化可采用:

  • H3/Geohash 网格降级。
  • 以真实点为中心生成受边界约束的随机圆。
  • 仅返回目标与玩家的距离档位,如“很近、附近、较远”。

7. 抓捕防作弊

动态口令建议由服务端生成:

token = HMAC(roomSecret, targetPlayerId + timeWindow + nonce)
  • 口令窗口建议 30 秒。
  • 提交时校验寻找者与目标的最近位置距离。
  • 校验双方都在线、角色正确且目标尚未被抓。
  • 使用事务写入抓捕结果,防止两个寻找者同时抓到同一目标。
  • 口令只作为相遇证明之一,不能替代安全规则。

8. 安全设计

  • 房主开始前必须完成场地和规则确认。
  • 服务端保留暂停、集合和取消的高优先级事件通道。
  • 客户端进入后台、定位失效、低电量或离线时产生状态提示。
  • 精确位置访问纳入服务端审计,不允许普通运营后台随意查看。
  • 公开组局上线前必须具备举报、封禁、内容安全和年龄策略。

9. 测试策略

  • 单元测试:房间状态机、身份分配、倒计时、抓捕和结算。
  • 属性测试:不同人数与寻找者数量下角色数量始终合法。
  • 集成测试:多人并发加入、重复抓捕、断线重连和版本冲突。
  • 真机测试:前后台切换、弱网、定位精度、耗电和不同微信版本。
  • 户外测试:边界提醒时机、线索节奏、屏幕使用时间和安全流程。

10. 迁移顺序

  1. 保留页面与服务接口,先把本地房间读写替换为云函数。
  2. 接入微信登录并使每个玩家拥有稳定服务端 ID。
  3. 引入实时房间事件和服务端倒计时。
  4. 接入地图选区、定位上报和模糊线索。
  5. 将抓捕、技能和结算全部迁到服务端裁决。
  6. 增加日志、监控、隐私删除和运营安全能力。