方案 A 已拍板 · MVP-VISUAL-001 → 资产落地

搭子竞技场 · 2 周验证 Demo(可直接跑)

三款自研玩法(手速 / 策略 / 合作)+ 三局两胜场次 + 场终战报 + MatchCore 统一内核 + 结算契约 v1。同屏上下分区、P2 区倒置为两人对坐的设计意图。全部素材自研,零竞品复用。

逻辑 390 × 844 pt @1x浅色底 #F4F7FB黏土 + 白瓷 · 五要素 5/5 批次 2026-11-10 · v1离线可跑 · 同屏零网络

怎么玩 / 怎么测

触屏:上半区归 P2、下半区归 P1,双指并发互不串扰。
键盘:极速回弹 A / D(P1)、← / →(P2);三格连珠 1~9 落子;同步开关 F(P1)+ J(P2)在 0.8 秒内同时按。
推荐路径:点「开一场 · 三局两胜」→ 打完一局 →「下一局」→ 场终战报 →「再来一局」/「发给搭子(纯自愿)」。
玩法配置化:GameDefRepo.override('rebound_rush', {target_score: 3}) 可改目标分而不发版;白名单外字段显式抛错。
远端权威源(默认关闭):?authority=remote&endpoint=http://127.0.0.1:18765 让每局结算真实 POST 到 Java 服务; 默认仍是本地内存结算、同屏零网络。远端超时 / 断网 / 非 2xx 一律显式入队待补报,绝不回退本地结算伪装成功。

结算契约 v0 → v1 对照

项基线 v0定稿 v1(本 Demo 实现)
入口submitResult(uid, gameId, score)submitMatchResult(SubmitMatchResultReq)
返回{ok: bool},失败静默MatchSettlement,失败显式抛 3 类异常
幂等无client_match_id unique,重放返回首次结算
玩家槽单 uid,同屏无 uid 直接丢局双槽 slot 0/1,支持 guest_id / is_ai / uid
模式无区分local / ai / online / async 共用状态机,只在 InputAdapter 与 AuthorityProxy 分化
过程只看最终分数events 摘要 + events_hash 签名校验,脏摘要抛 RiskFlaggedError
场次 / 关系无session_score 聚合、pair_key 排序拼接、默契 / 对抗值与 WAP 判定

7 处关联调用点全部按 v1 契约一次性建齐,业务层不并存两套契约;老客户端 v0 由网关 /v0/result 适配 30 天后下线。

「黏土 + 白瓷」五要素 · 落地自检

自检项实现位置 / 手法
① 大卡浮层--card-shadow:双层柔影 + inset 0 1px 0 #fff 顶缘高光
② 黏土钮三层影--clay-shadow:4px 底部厚度 + 外投影 + 内顶高光 + 内底暗缘;:active 下沉 3px
③ 输入框内凹--sunk-shadow:上暗下亮 inset 对偶 + 外底亮线
④ 球面径向高光.sphere / .ball / .cell .m:32%/26% 高光点 + 内暗缘
⑤ 相框 + 接触阴影.report-card 9px 白框 + 0 10px 20px 接触影;.frame-card .thumb 白框 + 接触影

合规硬约束(写进代码,不靠自觉)

• 局内零广告:MatchCore.finish() 调 assertNoInGameAd() 扫描广告位,命中即抛 RiskFlaggedError;CSS 另设 .ad-slot{display:none!important}。
• 无分享解锁 / 无奖励:玩法解锁只由 applyUnlocks() 在「对局达成」触发;分享按钮只记埋点 + toast,share_card_url 恒为 undefined(运营规范 5.1.1 / 5.1.2 / 5.1.4)。
• 再来一局无遮挡:场终主按钮四周无任何广告位或跳转层(特别规范 2.10.2)。
• 未知 ≠ 正常:未知玩法、脏摘要、未知 session、滞后数据一律抛错或显式标记 stale / unavailable,绝不返回看起来正常的默认值。

批次 MVP-RUNTIME-001 · 方案 A 已拍板落地 · 产出目录 双人竞技场_MVP_A/ · 评审阶段效果图与截图仍保留在 evidence/ui_preview/ 供对照 · 本 Demo 为浏览器原型,微信小游戏移植需补分包与平台适配。