Files
youle_cocos/cocoscreator_projects/docs/framework/protocol/00-框架架构设计.md
T
joywayer 35216f75e7 feat: integrate room framework and isolated subgame bundles
Complete room UI and protocol integration, move game definitions and resources behind bundle entries, publish authoritative version XML, and document single-game builds. Include all current resource changes and experiment artifacts.
2026-09-09 03:13:18 +08:00

15 KiB
Raw Blame History

00 · 框架架构设计(子游戏框架总览)

本章说明 Game_Surface_3 的整体架构与设计思想。它不是某一款游戏,而是一套 「子游戏框架」:平台壳(Surface)把登录、大厅、房间、网络、UI、社交等通用能力全部做好, 一款具体游戏(SubGame)只需在固定的接入点里实现自己的对局逻辑。

理解这套分层,是用 CocosCreator 重写前端的前提——新前端应复刻"平台通用层 + 子游戏对局层"的边界, 这样才能与服务器无缝对接(服务器只认协议,不关心前端用什么引擎)。


1. 框架定位

┌───────────────────────────────────────────────────────────────┐
│                        一个可发布的游戏                          │
│                                                                 │
│   ┌─────────────────────────┐   ┌───────────────────────────┐  │
│   │   Surface 平台壳 (00_)   │   │   SubGame 子游戏 (01_)     │  │
│   │  登录/大厅/房间/网络/UI   │◄─►│  仅实现「对局逻辑」        │  │
│   │  社交/支付/战绩/排行...   │钩子│  发牌/出牌/结算/界面       │  │
│   └─────────────────────────┘   └───────────────────────────┘  │
│                  ▲                                               │
│                  │ 引擎回调分发 (gamemain.js)                    │
│   ┌──────────────┴──────────────────────────────────────────┐  │
│   │  gameabc 自研精灵引擎 (gameabc.min.js) + Spine 骨骼动画   │  │
│   │  Canvas 渲染 / 触摸 / 定时器 / 资源加载 / WebSocket       │  │
│   └─────────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────────┘
  • 平台壳和子游戏用同一套代码骨架;换游戏时只替换 01_SubGame/ 与美术布局数据。
  • 平台壳通过**钩子(Hook)**反向调用子游戏;子游戏通过调用平台 API(Net.Send_*、GameUI.*、Desk、C_Player、set_self)使用平台能力。

2. 四层结构

层 载体 职责
引擎层 gameabc.min.js、spine-canvas.js、SpineMgr.js Canvas 精灵渲染、触摸/绘制/定时/资源/网络底层回调、Spine 骨骼动画
桥接层 gamemain.js(gameabc_face) 把引擎回调统一分发给上层三个消费者(GameUI / Game_Modify / gameCombat)
平台层 js/00_Surface/*(12 个文件) 登录、大厅、房间、解散、网络协议、玩家数据、UI、聊天、支付、战绩、排行、敏感词等
子游戏层 js/01_SubGame/*(3 个文件) 子游戏配置、对局逻辑、自定义输入处理(接入点)

3. 引擎层:自研精灵(Sprite)系统

渲染不是 DOM,也不是常规游戏引擎,而是一套基于**精灵编号(spid) + 标签(tag) + 组(group)**的自研系统。 美术界面在编辑器里排版后导出为 output/gameabc_data.min.js(精灵布局数据),运行时引擎据此渲染。

3.1 核心 API(子游戏与平台都用它操作界面)

API 作用
set_self(spid, attr, value, ...) 设置某精灵的属性
get_self(spid, attr, ...) 读取某精灵属性
set_group(groupid, attr, value, ...) 对一组精灵批量操作(常用于整页显隐)
play_ani(...) 播放属性动画(位移/缩放/帧动画)
set_clip(...) 设置裁剪区域(滚动列表用)
ifast_addtospritefromspritecopy(fSpid, srcSpid, x, y, tag) 以模板精灵为原型,动态复制出带 tag 的子精灵(实现动态列表,如战绩/排行行项)
ifast_dllpritefromspritecopy(fSpid, tag) 删除动态复制的子精灵
ifast_check_add(spid, x, y) 命中检测,返回被点中的子精灵 tag(动态列表点击)
ifast_mydrawbmp(...) 在 gamemydraw 回调里自绘位图(如勾选框的对勾)

3.2 常见 attr 属性码(由源码用法归纳)

attr 含义
7 文本内容(set_self(spid,7,"文字"))
18 / 19 x 坐标 / y 坐标
20 / 21 宽 / 高
37 显示/隐藏(1 显示 0 隐藏)
43 按钮状态/帧索引(多态按钮切换外观)
1 资源/图片绑定(set_self(268,1,资源号),预加载/换图)

这是平台与子游戏共享的"界面操作语言"。CocosCreator 重写时,这一层用 Cocos 的 Node/Sprite/Label/Widget 取代, 不需要复刻 spid 体系——只要最终把同样的协议数据展示出来即可。


4. 桥接层:gamemain.js(引擎 → 上层 的总分发)

引擎对象 gameabc_face 的所有回调都在此广播给三个消费者,顺序固定为 GameUI → Game_Modify → gameCombat:

引擎回调 时机 分发去向
gamestart(gameid) 引擎就绪 Logic.AppStart()(应用总入口)
mousedown / mousedown_nomove / mouseup / mousemove 触摸 GameUI.utl* + Game_Modify.utl*/mouseup + gameCombat.utl*
gamemydrawbegin / gamemydraw 每精灵绘制前/绘制 同上三方(子游戏在此自绘)
gamebegindraw / gameenddraw 每帧开始/结束 GameUI
ontimer 定时器 GameUI.utlontimer
ani_doend 动画结束 GameUI + gameCombat
onloadurl 图片/资源加载完成 GameUI.onloadurl
onresize 屏幕尺寸变化 (预留)
tcpconnected/tcpmessage/tcpdisconnected/tcperror 引擎自带 TCP 空(实际网络走 00_minhttp.js 的 WebSocket 封装,不用引擎 TCP)

关键:子游戏不直接向引擎注册回调,而是由 gamemain.js 转发。新前端可保留这种"统一事件总线 → 平台/子游戏"的模式。


5. 平台层模块清单(js/00_Surface/)

文件 模块 职责
02_Const.js ConstVal / AppList / RouteList / RpcList 全局常量、协议名、UI 布局常量
04_Data.js GameData 全局运行时状态(服务器地址、连接状态、各种缓存)
08_Utl_Output.js Utl 工具函数、本地存储、退出房间、部分发包
07_Desk.js Desk 牌桌/房间状态机 + 几乎所有房间类接收处理
05_Func.js Func 通用功能(HTTP、语音录制、截图分享、创建房间渲染等)
10_Game.js Game 定位等少量游戏级杂项
11_GameUI.js GameUI 平台所有界面(大厅/房间/聊天/战绩入口/弹窗/列表),最大文件
12_Logic.js Logic 应用生命周期 + 连接管理 + 消息分发 + 重连 + 桥接
00_minhttp.js min_tcp / min_http WebSocket 与 HTTP 底层封装
09_Net.js Net 协议收发层(Send_* 发包 / Net.<rpc> 收包路由到 Desk/Player)
06_Player.js Player / C_Player 玩家数据结构与玩家相关接收处理
03_Banwords.js banwords 敏感词库(聊天过滤)

网络协议、数据结构的字段细节见 01–04 章。


6. 子游戏层(js/01_SubGame/)—— 这是开发一款游戏唯一要写的部分

文件 模块 职责
00_SubGame_Config.js Game_Config 子游戏配置:房间人数、聊天/语音气泡位置、分享、客服、声音、调试开关等
01_SubGame_modify.js Game_Modify / gameCombat 子游戏实现:输入处理、创建房间界面、战绩界面、对局渲染
02_SubGame_Input.js Game_Modify(接口桩) / gameHallImport 平台会回调、子游戏需实现的钩子接口默认空实现

6.1 两类接入点

A. 业务回调钩子(平台 → 子游戏;定义在 02_SubGame_Input.js,子游戏按需重写):

钩子 调用时机(平台侧)
Game_Modify._ReceiveData(msg) 收到游戏内协议包(route 非 platform/agent/room)
Game_Modify.StartWar(msg) 开局(收到 makewar)
Game_Modify.Reconnect(deskinfo) 登录/进房响应含 deskinfo 时触发(还原牌局;模板为空实现,由子游戏自定义)
Game_Modify.DeskInfo(deskinfo) 进房响应含 deskinfo 但未自动开战(deskwar 假)时,传入 deskinfo
Game_Modify.createRoom / onCreateRoom 创建房间成功
Game_Modify.myJoinRoom / playerJoinRoom(seat) / playerLeaveRoom(seat) 进/离房
Game_Modify.playerOffline/Online(seat) / playerphonestate 在线/电话状态
Game_Modify.onReady(seat) / changeSeat(s1,s2) / onSurrender(msg) / Free(msg) 准备/换座/投降/解散
Game_Modify.updateScene / closeGameScene / onEnterMainScene / onExitMainScene / stopAllSounds 场景/声音管理
Game_Modify.getRoomInfo/getFullRoomInfo/getStarLimit/getMult/getVideoByRoomType/getRoomMode... 平台向子游戏取房间展示信息(返回值)

B. 引擎事件钩子(引擎 → 子游戏;定义在 01_SubGame_modify.js):

钩子 用途
Game_Modify.utlmousedown / mouseup / utlmousemove / utlmousedown_nomove 子游戏自己的触摸交互
Game_Modify.gamemydraw / utlgamemydrawbegin 子游戏自绘

6.2 子游戏能调用的平台能力

  • 发包:Net.Send_*(data)(平台层 RPC,见 02/03 章);游戏内自定义包用 Net._SendData(app, route, rpc, data)
  • 房间/玩家状态:Desk.*(roomcode、PlayerList、stage…)、C_Player.*、Desk.GetPlayerBySeat(seat)
  • 界面:set_self/get_self/set_group/play_ani + GameUI.*(弹窗、提示、聊天气泡等)
  • 座位换算:Logic.ChangeToStatus(myseat, targetseat)(把服务器绝对座位转成"以我为视角"的相对位置)
  • 配置:Game_Config.*

7. 应用生命周期

引擎就绪 → gameabc_face.gamestart()  (gamemain.js)
        → Logic.AppStart()           (12_Logic.js:313)
            ├─ 读取 URL/app 参数:渠道(channelid)、代理(agentid)、市场(marketid)、启动模式(LaunchMode)
            ├─ Logic.setGameServer()  → 仅解析配置(Game_Config.Debugger.gameserver);配置服 update_json 回调 ServerUrl_Succ → GameData.Server = urlserver
            ├─ Desk.Create()          → 建空牌桌(PlayerList)
            ├─ C_Player = new Player(-1)
            ├─ 加载敏感词、音频、定位(cityjson IP)
            └─ 连接:Logic.firstConnect/Connect → new WebSocket(ws://Server)
                    → onopen → Net.Send_login(...)(有条件:isLogin 重连,或读到 wxinfo cookie;见 01 章)
                    → Desk.login(资产+房间恢复)             (见 04 章)
                        ├─ 有 roomcode:恢复房间;响应含 deskinfo → Game_Modify.Reconnect(deskinfo)
                        └─ 无 roomcode:进大厅 GameUI.JumpMenuScene()
大厅 → 创建/加入房间 → 房间(准备/开局) → 对局(游戏内协议) → 结算(over_game) → 回房间/大厅
       期间断线 → onclose → Logic.TryConnect()(轮换服务器)→ 重连后重发 login 恢复状态

8. 游戏内对局协议的通道(子游戏自定义)

平台层协议(01–04 章)是固定的;对局协议由子游戏定义,复用同一条 WebSocket 与同一套信封:

  • 下行:服务器发 route 非 platform/agent/room 的包 → Game_Modify._ReceiveData(msg) → 子游戏按 msg.rpc 自行分发
  • 上行:Net._SendData("youle", "<游戏route>", "<游戏rpc>", {agentid,gameid,playerid,roomcode,seat, ...对局字段})
  • 结算:over_game;重连快照:登录/进房响应里的 deskinfo(结构由子游戏定义)

Game_Surface_3 是模板工程:02_SubGame_Input.js 里 _ReceiveData/StartWar/Reconnect 等为空实现 (即未含具体玩法),所以本工程取不到某款游戏的对局字段。需从真实子游戏工程或抓包补全(见 05 章)。

真实数据结构样例(战绩,平台层 get_player_grade1 响应)

01_SubGame_modify.js 的 gameCombat 揭示了一个真实嵌套结构,可作为对局数据风格参考:

data = {
  asetcount: 总局数,
  gradeinfo: [                         // 每场对局
    {
      overtime: "结束时间",
      roomcode: "房号",
      idx: 翻页索引,
      gameinfo1: {                     // 可能是 JSON 字符串,需二次 parse
        roundsum: 小局数,
        playerlist: [ [昵称, 总分], ... ],
        round: [ [ [座位, 该局分], ... ], ... ]   // 每小局每人得分
      }
    }, ...
  ]
}

9. 给 CocosCreator 重写的架构映射

原框架 CocosCreator 对应 说明
gameabc 精灵引擎 + spid/tag/group Cocos 场景/Node/Prefab/Label/Sprite 不复刻 spid 体系,只还原界面与协议数据展示
gamemain.js 事件总线 Cocos 输入事件 + 自建 EventBus 统一把交互/帧更新派发到 UI 与对局模块
00_Surface/* 平台层 一个"平台 SDK"模块(登录/大厅/房间/网络) 按 01–04 章协议 1:1 实现,是与服务器对接的关键
Net._SendData + 双层解包 Cocos 的 WebSocket 封装 严格保持信封 {app,route,rpc,data}、双层包装、心跳识别(01 章)
Game_Modify 钩子 对局模块对外接口 平台模块在相应时机回调对局模块
Desk / C_Player 房间状态/玩家数据模型 按 04 章字段建模
01_SubGame/* 具体游戏对局场景 自由用 Cocos 实现,只需吃平台给的数据、按对局协议收发

核心结论:与服务器"完美适配"只取决于**平台层协议(01–04 章)+ 对局协议(05 章,需补全)**的字节级一致; 渲染引擎、UI 实现方式可以完全替换。把"平台 SDK"和"对局逻辑"在新前端里分清边界,就复刻了这套子游戏框架的精髓。