bindbox-game/docs/前端对接指南_对对碰.md
邹方成 e2782a69d3 feat: 添加对对碰游戏功能与Redis支持
refactor: 重构抽奖逻辑以支持可验证凭据
feat(redis): 集成Redis客户端并添加配置支持
fix: 修复订单取消时的优惠券和库存处理逻辑
docs: 添加对对碰游戏前端对接指南和示例JSON
test: 添加对对碰游戏模拟测试和验证逻辑
2025-12-21 17:31:32 +08:00

4.6 KiB
Raw Blame History

对对碰Matching Game前端对接指南

1. 核心流程概述

本版本采用 "预计算 + 客户端渲染" 模式,以确保流畅体验并防止网络延迟影响游戏节奏。

交互时序

  1. 开始游戏 (API): 用户点击开始 -> 调用 PreOrder 接口 -> 服务器扣费并返回完整游戏剧本
  2. 动画播放 (Frontend): 前端根据返回的 timeline 数据,按顺序播放每一轮的 消除、填补、重洗 动画。
  3. 游戏结算 (API): 动画播放完毕(或用户点击跳过) -> 调用 Check 接口 -> 服务器确认结束并发放奖励。

2. 接口调用详解

2.1 第一步:下单并获取数据 (Start)

  • 接口: POST /api/app/matching/preorder
  • 参数: { "issue_id": 123 }
  • 核心响应:
    {
      "game_id": "MG_123456",        // 保存此ID用于结算
      "initial_board": [ ... ],      // 初始9宫格数据 (用于渲染第一帧)
      "timeline": [ ... ],           // 关键!动画剧本数组
      "total_pairs": 5               // 预计总消除对数 (可用于显示"目标")
    }
    

2.2 第二步:前端渲染循环 (Render)

前端拿到 timeline 后,不需要再请求服务器,直接在本地执行以下逻辑:

// 伪代码示例
async function playFullGame(data) {
    // 1. 渲染初始棋盘
    renderBoard(data.initial_board);
    
    // 2. 遍历时间轴,逐回合播放
    for (const round of data.timeline) {
        
        // --- 阶段 A: 消除动画 ---
        if (round.pairs.length > 0) {
            // 高亮要消除的卡牌
            highlightCards(round.pairs);
            await wait(500); // 停顿
            
            // 播放消除特效(根据 slot_indices 找到对应格子)
            for (const pair of round.pairs) {
                // pair.slot_indices 数组包含了所有要消除的格子下标 (0-8)
                playEliminateEffect(pair.slot_indices); 
            }
            await wait(500); // 等待特效结束
            
            // 从界面移除卡牌 DOM
            removeCardsFromBoard(round.pairs);
        }
        
        // --- 阶段 B: 填补动画 ---
        if (round.drawn_cards.length > 0) {
            // 播放发牌/飞入动画
            for (const draw of round.drawn_cards) {
                // draw.slot_index 是目标格子
                // draw.card 是新卡牌数据
                flyCardToSlot(draw.card, draw.slot_index);
            }
            await wait(500);
        }
        
        // --- 阶段 C: 死局重洗 (如果有) ---
        if (round.reshuffled) {
            showToast("死局重洗中...");
            playShuffleAnimation(); // 播放所有卡牌重新排列的动画
            // 动画结束后,根据 round.board 更新整个棋盘状态,确保位置正确
            updateFullBoard(round.board); 
            await wait(1000);
        }
        
        // 每一轮结束后稍作停顿
        await wait(300);
    }
    
    // 3. 全部播放完毕,调用结算
    doCheck(data.game_id);
}

2.3 第三步:结算与领奖 (Check)

  • 接口: POST /api/app/matching/check
  • 参数: { "game_id": "MG_123456" }
  • 作用: 告知服务器动画已播完触发最终奖励发放虽然服务器在PreOrder时已经计算好了但这个调用作为完整的业务闭环

3. 数据结构字典

MatchingRoundResult (时间轴中的每一项)

字段 类型 说明 前端处理建议
round int 回合数 用于UI显示"第几轮"
pairs array 消除列表 关键:遍历此数组,读取 slot_indices 来决定哪些格子要播消除动画
drawn_cards array 填补列表 关键:遍历此数组,读取 slot_index 来决定新卡牌飞入哪个格子
reshuffled bool 是否重洗 若为 true必须播放全屏洗牌特效并强制刷新棋盘数据
can_continue bool 是否继续 若为 false播放完本轮后显示"游戏结束"弹窗

MatchingPair (消除详情)

字段 类型 说明
card_type string 消除的卡牌类型
count int 消除数量 (通常是2连消可能是4,6)
slot_indices int[] 核心:被消除的格子下标列表,如 [0, 1]

DrawnCardInfo (填补详情)

字段 类型 说明
slot_index int 核心:填入的目标格子下标 (0-8)
card object 新卡牌的完整数据 (id, image_url, name)