初始化仓库:友乐/gameabc 房卡游戏平台脚手架(client + server + docs)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
* ============================================================================
|
||||
* GameView_Sprites.template.js - 精灵 ID 定义规范
|
||||
* ============================================================================
|
||||
*
|
||||
* 使用方式:
|
||||
* 将此文件复制到游戏项目中,按实际精灵 ID 填写。
|
||||
* 建议按界面拆分为多个文件,例如:
|
||||
* RoomView_Sprites.js (房间等待界面)
|
||||
* GameView_Sprites.js (游戏主界面)
|
||||
* PopupView_Sprites.js (弹窗/结算界面)
|
||||
* 所有 ID 值必须与 gameabc 编辑器中实际配置的精灵/图层/群组 ID 完全一致,
|
||||
* 不可自行编造数字。
|
||||
*
|
||||
* ============================================================================
|
||||
* ID 分配规范
|
||||
* ============================================================================
|
||||
*
|
||||
* 精灵 ID:子游戏使用 1001+(框架保留 1–1000)
|
||||
* 图层 ID:普通图层 101–200,弹窗图层 301+(框架保留 1–100)
|
||||
* 群组 ID:子游戏使用 201+(框架保留 1–200)
|
||||
*
|
||||
* ============================================================================
|
||||
* 文件结构规范
|
||||
* ============================================================================
|
||||
*
|
||||
* 顶层变量对应一个"界面",每个界面包含:
|
||||
*
|
||||
* VAR_NAME.VIEW_NAME = {
|
||||
* LAYER: <图层ID>, // 必填,该界面挂载的图层
|
||||
*
|
||||
* SOME_GROUP: {
|
||||
* GROUP_ID: <群组ID>, // 必填,该功能区的群组
|
||||
* SPRITES: {
|
||||
* SPRITE_KEY: <精灵ID>, // 每个精灵
|
||||
* ...
|
||||
* }
|
||||
* },
|
||||
*
|
||||
* // 也可不用群组,直接列精灵
|
||||
* SIMPLE_SPRITE: <精灵ID>
|
||||
* };
|
||||
*
|
||||
* ============================================================================
|
||||
* 每个精灵条目必须包含的注释字段
|
||||
* ============================================================================
|
||||
*
|
||||
* 类型:图片精灵 / 文字精灵 / 容器精灵 / 热区精灵
|
||||
* 用途:一句话说明该精灵在游戏中的作用
|
||||
* 资源:引用的 ImageResources 键名(图片精灵必填)
|
||||
* 帧说明:初始帧及切换时机(如有多帧)
|
||||
*
|
||||
* ============================================================================
|
||||
* 精灵类型说明
|
||||
* ============================================================================
|
||||
*
|
||||
* 图片精灵:显示图片/帧动画,用 SpriteManager.setFrame() 切换画面
|
||||
* 文字精灵:显示动态文字,用 SpriteManager.setText() 修改内容
|
||||
* 容器精灵:作为 SpriteCopyUtils 的父容器,本身不显示内容
|
||||
* 热区精灵:仅用于点击检测,透明不显示
|
||||
*
|
||||
* ============================================================================
|
||||
* 注意事项
|
||||
* ============================================================================
|
||||
*
|
||||
* - 玩家信息 UI(头像/昵称/分数/准备标识/房主标识)由平台框架提供,
|
||||
* 子游戏无需也不应在此重复定义
|
||||
* - GlobalUI(加载界面、消息弹窗、确认对话框)由框架提供,
|
||||
* 子游戏弹窗从 Layer 302+ 开始定义
|
||||
*
|
||||
* @see ImageResources.template.js 图片资源 ID 定义规范
|
||||
* @see SoundResources.template.js 音效资源 ID 定义规范
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// ============================================================================
|
||||
// 房间界面精灵定义 (Layer xxx)
|
||||
// ============================================================================
|
||||
|
||||
// /**
|
||||
// * RoomView_Sprites - 房间等待界面精灵定义
|
||||
// * 图层:Layer <在编辑器查到的图层ID>
|
||||
// * 用途:显示等待玩家加入、规则配置、准备/开始状态
|
||||
// */
|
||||
// var RoomView_Sprites = {};
|
||||
//
|
||||
// RoomView_Sprites.ROOM_VIEW = {
|
||||
// LAYER: <图层ID>,
|
||||
//
|
||||
// // 规则配置群组
|
||||
// // 用途:创建房间时的玩法选项(圈数、人数、特殊规则等)
|
||||
// ROOM_CONFIG_GROUP: {
|
||||
// GROUP_ID: <群组ID>,
|
||||
// SPRITES: {
|
||||
// // 图片精灵:第1行标题图片,资源=ImageResources.XXX,帧=1
|
||||
// ROW1_TITLE: <精灵ID>,
|
||||
//
|
||||
// // 图片精灵:第1行选项1图标,资源=ImageResources.XXX,帧1=未选中 帧2=已选中
|
||||
// ROW1_OPTION1: <精灵ID>,
|
||||
//
|
||||
// // 文字精灵:第1行选项1文字说明
|
||||
// ROW1_OPTION1_TEXT: <精灵ID>,
|
||||
//
|
||||
// // ... 按实际选项行数继续定义
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// ============================================================================
|
||||
// 游戏主界面精灵定义 (Layer xxx)
|
||||
// ============================================================================
|
||||
|
||||
// /**
|
||||
// * GameView_Sprites - 游戏主界面精灵定义
|
||||
// */
|
||||
// var GameView_Sprites = {};
|
||||
//
|
||||
// /**
|
||||
// * 牌桌主体
|
||||
// * 图层:Layer <在编辑器查到的图层ID>
|
||||
// */
|
||||
// GameView_Sprites.GAME_VIEW = {
|
||||
// LAYER: <图层ID>,
|
||||
//
|
||||
// // 中央信息群组
|
||||
// // 用途:牌桌中央区域,方向指示器、剩余牌数、倒计时等
|
||||
// CENTER_INFO_GROUP: {
|
||||
// GROUP_ID: <群组ID>,
|
||||
// SPRITES: {
|
||||
// // 图片精灵:方向面板背景,资源=ImageResources.XXX,4帧(帧1–4对应庄家方向)
|
||||
// DIRECTION_PANEL_BG: <精灵ID>,
|
||||
//
|
||||
// // 图片精灵:倒计时数字,资源=ImageResources.XXX,10帧(帧1–10对应数字0–9)
|
||||
// COUNTDOWN_NUMBER: <精灵ID>,
|
||||
//
|
||||
// // 图片精灵:剩余牌数数字,资源=ImageResources.XXX,10帧(帧1–10对应数字0–9)
|
||||
// REMAIN_COUNT: <精灵ID>
|
||||
// }
|
||||
// },
|
||||
//
|
||||
// // 玩家1手牌群组(下方/自己)
|
||||
// // 用途:显示自己手牌,支持点击选牌出牌
|
||||
// PLAYER1_HAND_GROUP: {
|
||||
// GROUP_ID: <群组ID>,
|
||||
// SPRITES: {
|
||||
// // 图片精灵×13:手牌1–13,资源=ImageResources.CARD_FACE,帧=当前牌值对应帧
|
||||
// HAND_CARD_1: <精灵ID>,
|
||||
// // ... HAND_CARD_2 至 HAND_CARD_13
|
||||
// HAND_CARD_13: <精灵ID>,
|
||||
//
|
||||
// // 图片精灵:摸牌(最右端,与手牌略有间距)
|
||||
// DRAW_CARD: <精灵ID>
|
||||
// }
|
||||
// },
|
||||
//
|
||||
// // 玩家2手牌群组(右方)
|
||||
// // 用途:显示右方玩家牌背(侧面透视角度)
|
||||
// PLAYER2_HAND_GROUP: {
|
||||
// GROUP_ID: <群组ID>,
|
||||
// SPRITES: {
|
||||
// HAND_CARD_1: <精灵ID>,
|
||||
// // ...
|
||||
// DRAW_CARD: <精灵ID>
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 玩家3(上方)、玩家4(左方)结构同上...
|
||||
// };
|
||||
//
|
||||
// /**
|
||||
// * 游戏操作按钮
|
||||
// * 图层:Layer <在编辑器查到的图层ID>
|
||||
// * 用途:玩家可操作时显示的吃/碰/杠/胡/过/听按钮
|
||||
// */
|
||||
// GameView_Sprites.GAME_ACTIONS_UI = {
|
||||
// LAYER: <图层ID>,
|
||||
//
|
||||
// ACTION_BUTTONS_GROUP: {
|
||||
// GROUP_ID: <群组ID>,
|
||||
// SPRITES: {
|
||||
// // 图片精灵:吃牌按钮,资源=ImageResources.BTN_CHI,1帧
|
||||
// BTN_CHI: <精灵ID>,
|
||||
// BTN_PONG: <精灵ID>,
|
||||
// BTN_KONG: <精灵ID>,
|
||||
// BTN_HU: <精灵ID>,
|
||||
// BTN_PASS: <精灵ID>,
|
||||
// BTN_TING: <精灵ID>,
|
||||
//
|
||||
// // 图片精灵:操作文字弹出动画,资源=ImageResources.OPERATION_EFFECT_XXX
|
||||
// ACTION_EFFECT_CHI: <精灵ID>,
|
||||
// ACTION_EFFECT_PONG: <精灵ID>,
|
||||
// ACTION_EFFECT_KONG: <精灵ID>,
|
||||
// ACTION_EFFECT_HU: <精灵ID>
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// ============================================================================
|
||||
// 弹窗界面精灵定义 (Layer 301+)
|
||||
// ============================================================================
|
||||
|
||||
// 子游戏自定义弹窗从 Layer 302+ 开始定义
|
||||
// Layer 301 建议预留给最高优先级的全局弹窗(如断线重连提示)
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* ============================================================================
|
||||
* ImageResources.template.js - 图片资源 ID 定义规范
|
||||
* ============================================================================
|
||||
*
|
||||
* 使用方式:
|
||||
* 将此文件复制到游戏项目中,重命名为 ImageResources.js。
|
||||
* 所有 ID 值必须与 gameabc 编辑器中实际配置的资源 ID 完全一致,
|
||||
* 不可自行编造数字。
|
||||
*
|
||||
* ============================================================================
|
||||
* ID 分配规范
|
||||
* ============================================================================
|
||||
*
|
||||
* 框架保留范围:1–500(平台框架使用,子游戏严禁占用)
|
||||
* 子游戏范围:501+(按项目实际需要自行规划分段,在代码注释中记录)
|
||||
*
|
||||
* ============================================================================
|
||||
* 每个资源条目必须包含的注释字段
|
||||
* ============================================================================
|
||||
*
|
||||
* 用途:该资源在游戏中的具体用途(一句话)
|
||||
* 帧数:资源包含的帧数量
|
||||
* 帧说明:每帧的内容,数字序号一一列出,例如:
|
||||
* 帧1=未选中 帧2=已选中
|
||||
* 帧1–9=1万–9万 帧10–18=1条–9条 ...
|
||||
* 尺寸:宽×高(像素)
|
||||
*
|
||||
* ============================================================================
|
||||
* 按钮资源规范
|
||||
* ============================================================================
|
||||
*
|
||||
* 所有按钮只需提供 1 帧普通状态图片,无需按下状态图片。
|
||||
* 点击效果(缩放 + 透明度)由框架统一处理。
|
||||
*
|
||||
* ============================================================================
|
||||
* 帧动画资源说明
|
||||
* ============================================================================
|
||||
*
|
||||
* 帧动画资源(操作效果动画、倒计时数字等)在此文件中只记录资源 ID,
|
||||
* 帧区间、帧间隔、循环模式等播放参数统一在 AnimationConfigs.js 中配置,
|
||||
* 不在此文件重复定义。
|
||||
*
|
||||
* @see GameView_Sprites.template.js 精灵 ID 定义规范
|
||||
* @see SoundResources.template.js 音效资源 ID 定义规范
|
||||
* @see AnimationConfigs.js 帧动画播放参数配置
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var ImageResources = {
|
||||
|
||||
// 按项目自行规划分段,每段在注释中记录 ID 起止范围和用途
|
||||
// 注意:底部操作面板、玩家信息头像等 UI 由平台框架提供,子游戏无需定义
|
||||
|
||||
// /**
|
||||
// * 用途:...
|
||||
// * 帧数:N 帧 帧1=... 帧2=...
|
||||
// * 尺寸:W×H
|
||||
// */
|
||||
// RESOURCE_NAME: <在编辑器中查到的实际资源ID>,
|
||||
|
||||
// 帧动画资源注意:帧播放参数(帧区间、帧间隔、循环次数)在 AnimationConfigs.js 中配置,不在此重复定义
|
||||
// 按钮资源注意:每个按钮 1 帧,点击效果由框架统一处理,无需按下状态帧
|
||||
// 麻将牌帧布局建议:帧1–9=万, 帧10–18=条, 帧19–27=筒, 帧28–31=东南西北, 帧32–34=中发白, 最后1帧=牌背
|
||||
// 不同显示区域(手牌/弃牌/副露)尺寸不同,各自用一个独立资源 ID
|
||||
|
||||
};
|
||||
@@ -0,0 +1,500 @@
|
||||
/**
|
||||
* ============================================================================
|
||||
* LayoutConstants.template.js - 游戏布局常量规范模板
|
||||
* ============================================================================
|
||||
*
|
||||
* 使用方式:
|
||||
* 将此文件复制到游戏目录,重命名为 LayoutConstants.js,
|
||||
* 然后按游戏实际分辨率和精灵编排修改各项数值。
|
||||
*
|
||||
* 如布局配置过多,可拆分为多个文件(如 PopupLayoutConstants.js),
|
||||
* 每个文件都向同一个全局对象 LayoutConstants 挂载属性。
|
||||
*
|
||||
* 加载顺序(index.html 中只需保证在 CardLayoutManager.js 之前加载即可):
|
||||
* <script src="js/01_SubGame/codes/game/constants/sprites/LayoutConstants.js"></script>
|
||||
* <script src="js/01_SubGame/codes/game/constants/sprites/PopupLayoutConstants.js"></script>
|
||||
* <script src="js/01_SubGame/codes/game/managers/CardLayoutManager.js"></script>
|
||||
*
|
||||
* 文件不依赖框架,可单独加载。
|
||||
*
|
||||
* ============================================================================
|
||||
* @guide 核心设计理念
|
||||
* ============================================================================
|
||||
*
|
||||
* LayoutConstants 是一个 **纯数据文件**(无函数、无副作用),
|
||||
* 所有坐标/尺寸/偏移量都在这里集中定义,供各 Manager / View 读取。
|
||||
*
|
||||
* 原则:
|
||||
* 1. 只包含常量对象,不包含业务逻辑
|
||||
* 2. 每个布局区域单独一个顶层属性(HAND_CARD_LAYOUT, DISCARD_LAYOUT …)
|
||||
* 3. 4人麻将用 PLAYER_1..4 子对象;其他游戏可用 SELF/OPPONENT 等命名
|
||||
* 4. 透视偏移量(PERSPECTIVE_OFFSET_X/Y)用于 2D 模拟 3D 效果,正对视角均为 0
|
||||
* 5. DIRECTION 枚举:'horizontal' | 'horizontal-reverse' | 'vertical' | 'vertical-reverse'
|
||||
* 6. ALIGN_MODE 枚举:'start' | 'center' | 'end'
|
||||
*
|
||||
* ============================================================================
|
||||
* @guide 透视偏移量说明
|
||||
* ============================================================================
|
||||
*
|
||||
* gameabc 以 2D 图片模拟 3D 透视效果。每张牌在排列时叠加一个累积偏移:
|
||||
*
|
||||
* 最终X = 基准X + 牌索引 × PERSPECTIVE_OFFSET_X
|
||||
* 最终Y = 基准Y + 牌索引 × PERSPECTIVE_OFFSET_Y
|
||||
*
|
||||
* 正值向右/向下,负值向左/向上。
|
||||
* 玩家1(正对屏幕)通常 PERSPECTIVE_OFFSET = 0。
|
||||
* 玩家2/4(侧视角)需要配置非零值形成倾斜效果。
|
||||
*
|
||||
* ============================================================================
|
||||
* @guide 如何拆分为多文件
|
||||
* ============================================================================
|
||||
*
|
||||
* // LayoutConstants.js(主游戏界面)
|
||||
* var LayoutConstants = {};
|
||||
* LayoutConstants.HAND_CARD_LAYOUT = { ... };
|
||||
* LayoutConstants.DISCARD_LAYOUT = { ... };
|
||||
*
|
||||
* // PopupLayoutConstants.js(弹窗界面,另一个文件)
|
||||
* var LayoutConstants = LayoutConstants || {}; // 保护性声明
|
||||
* LayoutConstants.ROUND_RESULT_LAYOUT = { ... };
|
||||
* LayoutConstants.GAME_RESULT_LAYOUT = { ... };
|
||||
*
|
||||
* 两个文件加载后,LayoutConstants 包含所有属性。
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @see LayoutConstants.js 金仙麻将实际实现
|
||||
* @see CardLayoutManager.js 使用 LayoutConstants 计算精灵坐标
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* LayoutConstants - 布局常量对象
|
||||
* 所有布局配置挂载在此全局对象下
|
||||
*/
|
||||
var LayoutConstants = {};
|
||||
|
||||
// ============================================================================
|
||||
// 设计分辨率
|
||||
// ============================================================================
|
||||
|
||||
/** 设计稿宽度(px) */
|
||||
LayoutConstants.DESIGN_WIDTH = 1280;
|
||||
|
||||
/** 设计稿高度(px) */
|
||||
LayoutConstants.DESIGN_HEIGHT = 720;
|
||||
|
||||
// ============================================================================
|
||||
// 手牌区布局(示例:4人麻将)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 手牌区布局配置
|
||||
*
|
||||
* DIRECTION 值:
|
||||
* 'horizontal' - 从左到右(PLAYER_1 常用)
|
||||
* 'horizontal-reverse' - 从右到左(PLAYER_3 常用)
|
||||
* 'vertical' - 从上到下(PLAYER_4 常用)
|
||||
* 'vertical-reverse' - 从下到上(PLAYER_2 常用)
|
||||
*
|
||||
* ALIGN_MODE 值:
|
||||
* 'start' - 从 START_X/Y 开始,按索引递增方向铺开
|
||||
* 'center' - 手牌整体居中于 START_X/Y
|
||||
* 'end' - 最后一张牌落在 START_X/Y,向前排列
|
||||
*/
|
||||
LayoutConstants.HAND_CARD_LAYOUT = {
|
||||
|
||||
// 玩家1 (下方 - 自己) - 正视角,无透视
|
||||
PLAYER_1: {
|
||||
START_X: 164, // 第1张牌的左边界X
|
||||
START_Y: 613, // 手牌区Y坐标
|
||||
CARD_WIDTH: 74, // 单张牌宽度(含视觉厚度)
|
||||
CARD_HEIGHT: 102, // 单张牌高度
|
||||
CARD_SPACING: -2, // 牌间距(负值=重叠)
|
||||
DRAW_CARD_GAP: 15, // 摸牌与手牌的额外间隔
|
||||
SELECT_OFFSET_Y: -20, // 选中牌向上偏移量
|
||||
MAX_CARDS: 13, // 最大手牌数
|
||||
DIRECTION: 'horizontal',
|
||||
ALIGN_MODE: 'end',
|
||||
PERSPECTIVE_OFFSET_X: 0,
|
||||
PERSPECTIVE_OFFSET_Y: 0
|
||||
},
|
||||
|
||||
// 玩家2 (右方) - 侧视角,竖排,透视向左上
|
||||
PLAYER_2: {
|
||||
START_X: 1205,
|
||||
START_Y: 537,
|
||||
CARD_WIDTH: 52,
|
||||
CARD_HEIGHT: 72,
|
||||
CARD_SPACING: 0,
|
||||
DRAW_CARD_GAP: 0,
|
||||
MAX_CARDS: 13,
|
||||
DIRECTION: 'vertical-reverse',
|
||||
ALIGN_MODE: 'center',
|
||||
PERSPECTIVE_OFFSET_X: -8,
|
||||
PERSPECTIVE_OFFSET_Y: -37,
|
||||
DRAW_CARD_PERSPECTIVE_X: -12,
|
||||
DRAW_CARD_PERSPECTIVE_Y: 18
|
||||
},
|
||||
|
||||
// 玩家3 (上方) - 对面视角,横排,无透视
|
||||
PLAYER_3: {
|
||||
START_X: 820,
|
||||
START_Y: 44,
|
||||
CARD_WIDTH: 43,
|
||||
CARD_HEIGHT: 58,
|
||||
CARD_SPACING: -3,
|
||||
DRAW_CARD_GAP: 6,
|
||||
MAX_CARDS: 13,
|
||||
DIRECTION: 'horizontal-reverse',
|
||||
ALIGN_MODE: 'end',
|
||||
PERSPECTIVE_OFFSET_X: 0,
|
||||
PERSPECTIVE_OFFSET_Y: 0
|
||||
},
|
||||
|
||||
// 玩家4 (左方) - 侧视角,竖排,透视向左上
|
||||
PLAYER_4: {
|
||||
START_X: 139,
|
||||
START_Y: 74,
|
||||
CARD_WIDTH: 52,
|
||||
CARD_HEIGHT: 72,
|
||||
CARD_SPACING: 0,
|
||||
DRAW_CARD_GAP: 12,
|
||||
MAX_CARDS: 13,
|
||||
DIRECTION: 'vertical',
|
||||
ALIGN_MODE: 'center',
|
||||
PERSPECTIVE_OFFSET_X: -8,
|
||||
PERSPECTIVE_OFFSET_Y: -37,
|
||||
DRAW_CARD_PERSPECTIVE_X: -9,
|
||||
DRAW_CARD_PERSPECTIVE_Y: -35
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// 弃牌区布局(示例)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 弃牌区布局配置
|
||||
*
|
||||
* CARDS_PER_ROW / MAX_ROWS:弃牌按行/列分组排列(DIRECTION 为 vertical 时按列)。
|
||||
* ROW_PERSPECTIVE_X/Y:每换一行的累积透视偏移,用于模拟牌桌中央的深度感。
|
||||
*/
|
||||
LayoutConstants.DISCARD_LAYOUT = {
|
||||
PLAYER_1: {
|
||||
START_X: 500,
|
||||
START_Y: 345,
|
||||
CARD_WIDTH: 45,
|
||||
CARD_HEIGHT: 55,
|
||||
CARDS_PER_ROW: 9,
|
||||
ROW_SPACING: 2,
|
||||
CARD_SPACING: 1,
|
||||
MAX_ROWS: 3,
|
||||
CARD_PERSPECTIVE_X: 0,
|
||||
CARD_PERSPECTIVE_Y: 0,
|
||||
ROW_PERSPECTIVE_X: 2,
|
||||
ROW_PERSPECTIVE_Y: -3
|
||||
},
|
||||
PLAYER_2: {
|
||||
START_X: 755,
|
||||
START_Y: 175,
|
||||
CARD_WIDTH: 28,
|
||||
CARD_HEIGHT: 36,
|
||||
CARDS_PER_ROW: 3,
|
||||
ROW_SPACING: 1,
|
||||
CARD_SPACING: 1,
|
||||
MAX_ROWS: 9,
|
||||
DIRECTION: 'vertical',
|
||||
CARD_PERSPECTIVE_X: -1,
|
||||
CARD_PERSPECTIVE_Y: 0,
|
||||
ROW_PERSPECTIVE_X: -2,
|
||||
ROW_PERSPECTIVE_Y: 1
|
||||
},
|
||||
PLAYER_3: {
|
||||
START_X: 720,
|
||||
START_Y: 95,
|
||||
CARD_WIDTH: 36,
|
||||
CARD_HEIGHT: 28,
|
||||
CARDS_PER_ROW: 9,
|
||||
ROW_SPACING: 2,
|
||||
CARD_SPACING: 1,
|
||||
MAX_ROWS: 3,
|
||||
DIRECTION: 'horizontal-reverse',
|
||||
CARD_PERSPECTIVE_X: 0,
|
||||
CARD_PERSPECTIVE_Y: 0,
|
||||
ROW_PERSPECTIVE_X: -2,
|
||||
ROW_PERSPECTIVE_Y: 2
|
||||
},
|
||||
PLAYER_4: {
|
||||
START_X: 200,
|
||||
START_Y: 280,
|
||||
CARD_WIDTH: 58,
|
||||
CARD_HEIGHT: 41,
|
||||
CARDS_PER_ROW: 3,
|
||||
ROW_SPACING: 1,
|
||||
CARD_SPACING: 1,
|
||||
MAX_ROWS: 9,
|
||||
DIRECTION: 'vertical-reverse',
|
||||
CARD_PERSPECTIVE_X: 1,
|
||||
CARD_PERSPECTIVE_Y: 0,
|
||||
ROW_PERSPECTIVE_X: -3,
|
||||
ROW_PERSPECTIVE_Y: -12
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// 副露区布局(吃/碰/杠)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 副露区布局配置
|
||||
*
|
||||
* 透视偏移量(组内 + 组间):
|
||||
* CARD_PERSPECTIVE_X/Y - 同一副露组内,每张牌相对前一张的额外偏移(累加)
|
||||
* GROUP_PERSPECTIVE_X/Y - 不同副露组之间,每组相对前一组的额外偏移(累加)
|
||||
*
|
||||
* 坐标计算公式(CardLayoutManager.js 负责实现):
|
||||
* 透视X = cardIndex × CARD_PERSPECTIVE_X + meldIndex × GROUP_PERSPECTIVE_X
|
||||
* 最终X = 基准X + 透视X
|
||||
*/
|
||||
LayoutConstants.MELD_LAYOUT = {
|
||||
PLAYER_1: {
|
||||
START_X: 105,
|
||||
START_Y: 639,
|
||||
CARD_WIDTH: 64,
|
||||
CARD_HEIGHT: 84,
|
||||
CARD_SPACING: 0,
|
||||
GROUP_SPACING: 8,
|
||||
DIRECTION: 'horizontal',
|
||||
MAX_GROUPS: 4,
|
||||
KONG_STACK_OFFSET_X: 0,
|
||||
KONG_STACK_OFFSET_Y: -20,
|
||||
CARD_PERSPECTIVE_X: -5,
|
||||
CARD_PERSPECTIVE_Y: 0,
|
||||
GROUP_PERSPECTIVE_X: -3,
|
||||
GROUP_PERSPECTIVE_Y: 0
|
||||
},
|
||||
PLAYER_2: {
|
||||
START_X: 1115,
|
||||
START_Y: 509,
|
||||
CARD_WIDTH: 65,
|
||||
CARD_HEIGHT: 48,
|
||||
CARD_SPACING: 0,
|
||||
GROUP_SPACING: 0,
|
||||
DIRECTION: 'vertical-reverse',
|
||||
MAX_GROUPS: 4,
|
||||
KONG_STACK_OFFSET_X: 6,
|
||||
KONG_STACK_OFFSET_Y: -20,
|
||||
CARD_PERSPECTIVE_X: -7,
|
||||
CARD_PERSPECTIVE_Y: 35,
|
||||
GROUP_PERSPECTIVE_X: -25,
|
||||
GROUP_PERSPECTIVE_Y: 35
|
||||
},
|
||||
PLAYER_3: {
|
||||
START_X: 930,
|
||||
START_Y: 48,
|
||||
CARD_WIDTH: 43,
|
||||
CARD_HEIGHT: 58,
|
||||
CARD_SPACING: 0,
|
||||
GROUP_SPACING: 4,
|
||||
DIRECTION: 'horizontal-reverse',
|
||||
MAX_GROUPS: 4,
|
||||
KONG_STACK_OFFSET_X: 0,
|
||||
KONG_STACK_OFFSET_Y: -9,
|
||||
CARD_PERSPECTIVE_X: 3,
|
||||
CARD_PERSPECTIVE_Y: 0,
|
||||
GROUP_PERSPECTIVE_X: -3,
|
||||
GROUP_PERSPECTIVE_Y: 0
|
||||
},
|
||||
PLAYER_4: {
|
||||
START_X: 198,
|
||||
START_Y: 91,
|
||||
CARD_WIDTH: 63,
|
||||
CARD_HEIGHT: 49,
|
||||
CARD_SPACING: 0,
|
||||
GROUP_SPACING: 0,
|
||||
DIRECTION: 'vertical',
|
||||
MAX_GROUPS: 4,
|
||||
KONG_STACK_OFFSET_X: -7,
|
||||
KONG_STACK_OFFSET_Y: -17,
|
||||
CARD_PERSPECTIVE_X: -6,
|
||||
CARD_PERSPECTIVE_Y: -30,
|
||||
GROUP_PERSPECTIVE_X: -25,
|
||||
GROUP_PERSPECTIVE_Y: -30
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// 玩家信息 UI 布局(支持 2/3/4 人)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 玩家信息 UI 布局配置
|
||||
*
|
||||
* 座位映射(seatToInd):
|
||||
* 不同人数局中,座位号(0-3)映射到屏幕显示位置(ind 0-3)。
|
||||
* ind = -1 表示该座位在此人数局中不显示。
|
||||
*
|
||||
* 约定:ind0=下方(自己) ind1=右方 ind2=上方 ind3=左方
|
||||
*
|
||||
* 位置配置(POSITIONS[ind]):
|
||||
* FRAME_* 底框精灵的绝对坐标和尺寸
|
||||
* AVATAR.* 头像相对于底框左上角的偏移量(OFFSET_X/Y + WIDTH/HEIGHT)
|
||||
* NAME_OFFSET_X/Y 昵称相对于头像左上角的偏移
|
||||
* SCORE_OFFSET_X/Y 分数相对于头像左上角的偏移
|
||||
*/
|
||||
LayoutConstants.PLAYER_INFO_LAYOUT = {
|
||||
DESIGN_WIDTH: 1280,
|
||||
DESIGN_HEIGHT: 720,
|
||||
|
||||
// 座位号 → 显示位置 ind 的映射
|
||||
SEAT_MAPPING: {
|
||||
4: [0, 1, 2, 3],
|
||||
3: [0, 1, 3, -1], // 3人局:北位(ind2)不显示
|
||||
2: [0, 2, -1, -1] // 2人局:只有南北两位
|
||||
},
|
||||
|
||||
VISIBLE_POSITIONS: {
|
||||
4: [0, 1, 2, 3],
|
||||
3: [0, 1, 3],
|
||||
2: [0, 2]
|
||||
},
|
||||
|
||||
POSITIONS: {
|
||||
// ind=0: 南位(下方) - 玩家自己
|
||||
0: {
|
||||
FRAME_X: 6, FRAME_Y: 592,
|
||||
FRAME_WIDTH: 90, FRAME_HEIGHT: 115,
|
||||
AVATAR: {
|
||||
OFFSET_X: 5, OFFSET_Y: 5,
|
||||
WIDTH: 80, HEIGHT: 80,
|
||||
NAME_OFFSET_X: -400, NAME_OFFSET_Y: 888,
|
||||
SCORE_OFFSET_X: 0, SCORE_OFFSET_Y: 88
|
||||
},
|
||||
NAME_CENTER_ALIGN: true
|
||||
},
|
||||
// ind=1: 东位(右方)
|
||||
1: {
|
||||
FRAME_X: 1186, FRAME_Y: 85,
|
||||
FRAME_WIDTH: 90, FRAME_HEIGHT: 115,
|
||||
AVATAR: {
|
||||
OFFSET_X: 5, OFFSET_Y: 5,
|
||||
WIDTH: 80, HEIGHT: 80,
|
||||
NAME_OFFSET_X: 905, NAME_OFFSET_Y: -888,
|
||||
SCORE_OFFSET_X: 0, SCORE_OFFSET_Y: 88
|
||||
},
|
||||
NAME_CENTER_ALIGN: true
|
||||
},
|
||||
// ind=2: 北位(上方)
|
||||
2: {
|
||||
FRAME_X: 1006, FRAME_Y: 5,
|
||||
FRAME_WIDTH: 90, FRAME_HEIGHT: 115,
|
||||
AVATAR: {
|
||||
OFFSET_X: 5, OFFSET_Y: 5,
|
||||
WIDTH: 80, HEIGHT: 80,
|
||||
NAME_OFFSET_X: 905, NAME_OFFSET_Y: -888,
|
||||
SCORE_OFFSET_X: 0, SCORE_OFFSET_Y: 88
|
||||
},
|
||||
NAME_CENTER_ALIGN: true
|
||||
},
|
||||
// ind=3: 西位(左方)
|
||||
3: {
|
||||
FRAME_X: 7, FRAME_Y: 59,
|
||||
FRAME_WIDTH: 90, FRAME_HEIGHT: 115,
|
||||
AVATAR: {
|
||||
OFFSET_X: 5, OFFSET_Y: 5,
|
||||
WIDTH: 80, HEIGHT: 80,
|
||||
NAME_OFFSET_X: -605, NAME_OFFSET_Y: -888,
|
||||
SCORE_OFFSET_X: 0, SCORE_OFFSET_Y: 88
|
||||
},
|
||||
NAME_CENTER_ALIGN: true
|
||||
}
|
||||
},
|
||||
|
||||
TEXT_STYLE: {
|
||||
NAME_FONT_SIZE: 14,
|
||||
NAME_MAX_LENGTH: 6,
|
||||
SCORE_FONT_SIZE: 12,
|
||||
CHAR_WIDTH: 9
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// 庄家标识布局
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 庄家图标布局
|
||||
*
|
||||
* POSITION_TYPE 决定图标与头像底框的对齐方式:
|
||||
* 'top-left' - 图标左上角 = 底框右上角(图标显示在底框右侧)
|
||||
* 'top-right' - 图标右上角 = 底框左上角(图标显示在底框左侧)
|
||||
*/
|
||||
LayoutConstants.DEALER_ICON_LAYOUT = {
|
||||
ICON_WIDTH: 32,
|
||||
ICON_HEIGHT: 32,
|
||||
SEAT_MAPPING: {
|
||||
4: [0, 1, 2, 3],
|
||||
3: [0, 1, 3, -1],
|
||||
2: [0, 2, -1, -1]
|
||||
},
|
||||
POSITIONS: {
|
||||
0: { POSITION_TYPE: 'top-left' },
|
||||
1: { POSITION_TYPE: 'top-right' },
|
||||
2: { POSITION_TYPE: 'top-right' },
|
||||
3: { POSITION_TYPE: 'top-left' }
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// 操作倒计时布局
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 操作倒计时布局
|
||||
*
|
||||
* 数字图片居中显示在 CENTER_X:
|
||||
* actualX = CENTER_X - (digitCount × CHAR_WIDTH / 2)
|
||||
*/
|
||||
LayoutConstants.COUNTDOWN_LAYOUT = {
|
||||
CENTER_X: 640, // 水平居中锚点
|
||||
Y: 296,
|
||||
CHAR_WIDTH: 31,
|
||||
CHAR_HEIGHT: 33
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// 操作按钮布局(吃/碰/杠/胡/听/过)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 操作按钮动态水平布局
|
||||
*
|
||||
* 从右锚点 ANCHOR_X 向左排列,按钮数量变化时整体右对齐:
|
||||
* totalW = count × BUTTON_WIDTH + (count-1) × BUTTON_SPACING
|
||||
* firstX = ANCHOR_X - totalW
|
||||
* nthX = firstX + (n-1) × (BUTTON_WIDTH + BUTTON_SPACING)
|
||||
*/
|
||||
LayoutConstants.ACTION_BUTTON_LAYOUT = {
|
||||
ANCHOR_X: 1180, // 右对齐锚点
|
||||
Y: 560, // 按钮Y坐标(统一)
|
||||
BUTTON_WIDTH: 100,
|
||||
BUTTON_HEIGHT: 80,
|
||||
BUTTON_SPACING: 10
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// 最后出牌指示器布局
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 最后出牌指示器偏移量(相对于该牌的坐标)
|
||||
*/
|
||||
LayoutConstants.LAST_DISCARD_INDICATOR_LAYOUT = {
|
||||
OFFSET: {
|
||||
0: { X: 8, Y: -20 },
|
||||
1: { X: 15, Y: -25 },
|
||||
2: { X: 6, Y: -20 },
|
||||
3: { X: 15, Y: -23 }
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* ============================================================================
|
||||
* SoundResources.template.js - 音效资源常量定义规范
|
||||
* ============================================================================
|
||||
*
|
||||
* 使用方式:
|
||||
* 将此文件复制到游戏项目中,重命名为 SoundResources.js。
|
||||
* 所有文件名必须与实际音效文件完全一致,不可自行编造。
|
||||
*
|
||||
* ============================================================================
|
||||
* 文件命名规范
|
||||
* ============================================================================
|
||||
*
|
||||
* 音效文件名 = 5位数字补零 + .mp3,例如:
|
||||
* ID=101 → '00101.mp3'
|
||||
* ID=151 → '00151.mp3'
|
||||
*
|
||||
* ============================================================================
|
||||
* ID 分配规范
|
||||
* ============================================================================
|
||||
*
|
||||
* 框架保留:00001–00100(平台系统音效,子游戏严禁占用)
|
||||
* 子游戏范围:00101+(EFFECTS / VOICE / MUSIC 的具体分段按项目自行规划)
|
||||
*
|
||||
* ============================================================================
|
||||
* 性别语音规则(AudioManager 依赖此规范)
|
||||
* ============================================================================
|
||||
*
|
||||
* 男性语音 ID = 基础 ID(151+)
|
||||
* 女性语音 ID = 男性语音 ID + FEMALE_VOICE_OFFSET(默认 100)
|
||||
* 规律:男性 '00151.mp3' 对应 女性 '00251.mp3'
|
||||
*
|
||||
* AudioManager.playActionVoiceBySeat(seat, action) 会根据该座位的
|
||||
* sex 字段(sex===2 为女性)自动选择正确的语音文件,
|
||||
* MALE 和 FEMALE 两组键名必须保持一一对应。
|
||||
*
|
||||
* ============================================================================
|
||||
* 调用示例(供理解结构,不代表实际值)
|
||||
* ============================================================================
|
||||
*
|
||||
* AudioManager.playSound(SoundResources.EFFECTS.DISCARD);
|
||||
* // 游戏侧 GameAudio 封装 ID 映射,再调用框架层通用 API:
|
||||
* AudioManager.playVoiceBySeat(seat, ACTION_VOICE_BASE_ID['chi']); // 自动按性别选语音
|
||||
* AudioManager.playVoiceBySeat(seat, CARD_VOICE_BASE_ID[cardValue]); // 自动按性别选报牌语音
|
||||
* AudioManager.playMusic();
|
||||
*
|
||||
* @see AudioManager.js 音频播放管理(gameabc-framework/system/)
|
||||
* @see GameAudio.js 游戏专属 ID 映射(子游戏目录,如 game/managers/GameAudio.js)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var SoundResources = {
|
||||
|
||||
// ========================================================================
|
||||
// EFFECTS - 通用音效
|
||||
// ========================================================================
|
||||
EFFECTS: {
|
||||
|
||||
// 操作动效音 ≠ 操作语音:
|
||||
// 操作动效音 = 文字弹出时的短促音效(在 EFFECTS 中定义)
|
||||
// 操作语音 = 玩家喊出操作词的人声(在 VOICE 中定义)
|
||||
|
||||
// DISCARD: '<实际文件名>',
|
||||
// DRAW: '<实际文件名>',
|
||||
// GAME_START: '<实际文件名>',
|
||||
// WIN: '<实际文件名>',
|
||||
// CHI_EFFECT: '<实际文件名>',
|
||||
// ...
|
||||
},
|
||||
|
||||
// ========================================================================
|
||||
// VOICE - 语音(按性别分组)
|
||||
// 规则:女性语音文件 ID = 对应男性语音文件 ID + FEMALE_VOICE_OFFSET(默认100)
|
||||
// MALE 和 FEMALE 两组键名必须完全一一对应,AudioManager 依赖此结构
|
||||
// ========================================================================
|
||||
VOICE: {
|
||||
|
||||
MALE: {
|
||||
// 操作语音键名(固定,AudioManager 按此查找):
|
||||
// CHI / PONG / KONG / HU / TING / PASS / ZIMO
|
||||
// CHI: '<实际文件名>',
|
||||
// ...
|
||||
|
||||
// 报牌语音键名建议统一为 <SUIT>_<VALUE>
|
||||
// 示例:WAN_1, WAN_2, ... TIAO_1, ... TONG_1, ... DONG, NAN, XI, BEI, ZHONG, FA, BAI
|
||||
// WAN_1: '<实际文件名>',
|
||||
// ...
|
||||
},
|
||||
|
||||
FEMALE: {
|
||||
// 键名与 MALE 完全相同,对应文件 ID + 100
|
||||
// CHI: '<实际文件名>',
|
||||
// WAN_1: '<实际文件名>',
|
||||
// ...
|
||||
}
|
||||
},
|
||||
|
||||
// ========================================================================
|
||||
// MUSIC - 背景音乐
|
||||
// 需同时在 game_config.soundList 中配置预加载
|
||||
// ========================================================================
|
||||
MUSIC: {
|
||||
// GAME_BGM: '<实际文件名>',
|
||||
// ROOM_BGM: '<实际文件名>',
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
/**
|
||||
* ============================================================================
|
||||
* UIBootstrap.template.js - UI 启动器规范模板
|
||||
* ============================================================================
|
||||
*
|
||||
* 使用方式:
|
||||
* 将此文件复制到游戏目录,重命名为 UIBootstrap.js。
|
||||
* 根据游戏实际使用的 UI 组件修改 _registerViews() 和 _checkDependencies()。
|
||||
*
|
||||
* 加载顺序(index.html 中必须按序):
|
||||
* 1. gameabc-framework/core/EventBus.js
|
||||
* 2. gameabc-framework/core/SpriteManager.js
|
||||
* 3. gameabc-framework/ui/BaseComponent.js
|
||||
* 4. gameabc-framework/ui/UIManager.js ← 框架层
|
||||
* 5. game/ui/UIManager.js ← 游戏层扩展(如 CreateRoomUI)
|
||||
* 6. game/ui/views/RoomView.js ← 各视图组件
|
||||
* 7. game/ui/views/GameView.js
|
||||
* 8. game/UIBootstrap.js ← 本文件(最后加载)
|
||||
*
|
||||
* 调用时机:
|
||||
* 在 Logic.AppStart() 中调用 UIBootstrap.init()
|
||||
*
|
||||
* ============================================================================
|
||||
* @guide UIBootstrap 的职责
|
||||
* ============================================================================
|
||||
*
|
||||
* UIBootstrap 是游戏专属的启动器,负责:
|
||||
* 1. 按序初始化框架系统(SpriteManager → AnimationManager → UIManager)
|
||||
* 2. 创建游戏专属视图组件
|
||||
* 3. 向 UIManager 注册组件和场景
|
||||
* 4. 提供 views 字典供全局访问
|
||||
*
|
||||
* UIBootstrap 不应该:
|
||||
* - 包含业务逻辑(发牌、胡牌判断等)
|
||||
* - 直接操作精灵(应交给各 View 组件)
|
||||
* - 被其他模块 require(单向依赖)
|
||||
*
|
||||
* ============================================================================
|
||||
* @guide 场景注册示例
|
||||
* ============================================================================
|
||||
*
|
||||
* // 在 _registerViews() 中,创建并注册完所有组件后:
|
||||
*
|
||||
* // 1. 注册到 UIManager 组件表
|
||||
* UIManager.registerComponent('RoomView', this.views.RoomView);
|
||||
* UIManager.registerComponent('GameView', this.views.GameView);
|
||||
*
|
||||
* // 2. 注册场景(组件名称必须已注册)
|
||||
* UIManager.registerScene(UIManager.SCENES.ROOM, ['RoomView']);
|
||||
* UIManager.registerScene(UIManager.SCENES.GAME, ['GameView', 'JingCardView', 'DiceView']);
|
||||
*
|
||||
* @see UIManager.js 框架层组件/场景管理(gameabc-framework/ui/)
|
||||
* @see BaseComponent.js 组件基类(gameabc-framework/ui/)
|
||||
*/
|
||||
|
||||
var UIBootstrap = UIBootstrap || {};
|
||||
|
||||
// ============================================================================
|
||||
// 状态
|
||||
// ============================================================================
|
||||
|
||||
UIBootstrap.initialized = false;
|
||||
|
||||
/** 游戏创建的所有 View 实例 */
|
||||
UIBootstrap.views = {};
|
||||
|
||||
// ============================================================================
|
||||
// 公共 API
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 初始化 UI 系统
|
||||
* 在 Logic.AppStart() 中调用一次
|
||||
* @returns {boolean}
|
||||
*/
|
||||
UIBootstrap.init = function () {
|
||||
if (this.initialized) {
|
||||
console.warn('[UIBootstrap] 已初始化,跳过');
|
||||
return true;
|
||||
}
|
||||
|
||||
console.log('[UIBootstrap] 开始初始化 UI 系统...');
|
||||
|
||||
try {
|
||||
if (!this._checkDependencies()) { return false; }
|
||||
|
||||
// 1. 初始化 SpriteManager
|
||||
SpriteManager.init();
|
||||
|
||||
// 2. 初始化 AnimationManager(如有)
|
||||
if (typeof AnimationManager !== 'undefined') {
|
||||
AnimationManager.init();
|
||||
}
|
||||
|
||||
// 3. 初始化 UIManager(框架层 + 游戏扩展)
|
||||
// 如有 Loading/Message/Confirm 全局 UI,注入各自精灵常量(框架不读子游戏全局名):
|
||||
// UIManager.init({ loadingUI: SpriteConstants.LOADING_UI, messageUI: SpriteConstants.MESSAGE_UI, confirmUI: SpriteConstants.CONFIRM_UI });
|
||||
// 无全局 UI 则直接 UIManager.init();
|
||||
UIManager.init();
|
||||
|
||||
// 4. 创建并注册所有视图
|
||||
this._registerViews();
|
||||
|
||||
this.initialized = true;
|
||||
console.log('[UIBootstrap] UI 系统初始化完成,共', Object.keys(this.views).length, '个组件');
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error('[UIBootstrap] 初始化失败:', err);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查依赖是否已加载
|
||||
* ⚠️ 按游戏实际使用的组件修改此列表
|
||||
* @private
|
||||
*/
|
||||
UIBootstrap._checkDependencies = function () {
|
||||
var required = [
|
||||
{ name: 'EventBus', ok: typeof EventBus !== 'undefined' },
|
||||
{ name: 'SpriteManager', ok: typeof SpriteManager !== 'undefined' },
|
||||
{ name: 'UIManager', ok: typeof UIManager !== 'undefined' },
|
||||
{ name: 'RoomView', ok: typeof RoomView !== 'undefined' },
|
||||
{ name: 'GameView', ok: typeof GameView !== 'undefined' }
|
||||
];
|
||||
|
||||
var optional = [
|
||||
// { name: 'JingCardView', ok: typeof JingCardView !== 'undefined' },
|
||||
// { name: 'DiceView', ok: typeof DiceView !== 'undefined' }
|
||||
];
|
||||
|
||||
var allOk = true;
|
||||
for (var i = 0; i < required.length; i++) {
|
||||
if (!required[i].ok) {
|
||||
console.error('[UIBootstrap] 缺少依赖:', required[i].name);
|
||||
allOk = false;
|
||||
}
|
||||
}
|
||||
for (var j = 0; j < optional.length; j++) {
|
||||
if (!optional[j].ok) {
|
||||
console.warn('[UIBootstrap] 可选组件未加载:', optional[j].name);
|
||||
}
|
||||
}
|
||||
return allOk;
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建视图实例并注册到 UIManager
|
||||
* ⚠️ 按游戏实际使用的组件修改此方法
|
||||
* @private
|
||||
*/
|
||||
UIBootstrap._registerViews = function () {
|
||||
// ---- 创建组件 ----
|
||||
this.views.RoomView = RoomView.create({ name: 'RoomView' });
|
||||
this.views.GameView = GameView.create({ name: 'GameView' });
|
||||
// this.views.JingCardView = JingCardView.create({ name: 'JingCardView' });
|
||||
// this.views.DiceView = DiceView.create({ name: 'DiceView' });
|
||||
|
||||
// ---- 注册到 UIManager ----
|
||||
UIManager.registerComponent('RoomView', this.views.RoomView);
|
||||
UIManager.registerComponent('GameView', this.views.GameView);
|
||||
|
||||
// ---- 注册场景 ----
|
||||
UIManager.registerScene(UIManager.SCENES.ROOM, ['RoomView']);
|
||||
UIManager.registerScene(UIManager.SCENES.GAME, ['GameView']);
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// 工具方法
|
||||
// ============================================================================
|
||||
|
||||
UIBootstrap.getView = function (viewName) {
|
||||
return this.views[viewName] || null;
|
||||
};
|
||||
|
||||
UIBootstrap.showView = function (viewName) {
|
||||
if (!this.initialized) { return; }
|
||||
UIManager.showView(viewName);
|
||||
};
|
||||
|
||||
UIBootstrap.hideView = function (viewName) {
|
||||
if (!this.initialized) { return; }
|
||||
UIManager.hideView(viewName);
|
||||
};
|
||||
|
||||
UIBootstrap.getStatus = function () {
|
||||
return {
|
||||
initialized: this.initialized,
|
||||
views: Object.keys(this.views),
|
||||
uiManagerReady: UIManager.initialized
|
||||
};
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = UIBootstrap;
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
// ============================================================================
|
||||
// 00_SubGame_Config.template.js —— 平台配置项模板(结构由平台定义,子游戏填【值】)
|
||||
// 这是配置文件(C 类,非转发壳)。复制后按本游戏界面/玩法调整各项值。
|
||||
// 严格 ES5。
|
||||
// ============================================================================
|
||||
|
||||
var Game_Config = Game_Config || {};
|
||||
|
||||
|
||||
|
||||
Game_Config.Debugger={//调试配置
|
||||
isDebugger : true,// debugger模式下会将所有收发的包输出到控制台(正式发布改为false)
|
||||
AutoLogin : true,//debugger模式下是否需要记住登录状态自动登录(正式发布改为true)
|
||||
isSubmitError : false,//是否需要服务器收集错误信息调试时可根据需要(正式发布改为true)
|
||||
visitorLogin : true,//隐藏式游客登录
|
||||
visiblePay:true,//审核通过后是否显示支付按钮
|
||||
serverType:1,//0->正式服务器 1->本地服务器 http://ylyxservice1.0791ts.cn/config/update_json.txt
|
||||
gameserver:""//子游戏填自己的更新地址
|
||||
};
|
||||
|
||||
Game_Config.Max = {
|
||||
SumOfRoomtype:3,//创建时房间类型roomtype数组长度
|
||||
ShowChat:2000,//聊天停留时间
|
||||
PlayerCnt:4,//房间最大人数(按房间最大人数设置)
|
||||
group:500,//游戏最大群组号
|
||||
showtime:10,//加载等待最少时间
|
||||
reconnecttime:30000,//唤醒游戏间隔(超过间隔断线重连)
|
||||
Mainnickname:10,//主界面玩家昵称显示长度(字符长度)
|
||||
Infonickname:16//个人信息显示长度(字符长度)
|
||||
};
|
||||
Game_Config.Combat = {
|
||||
height:80,//战绩页单行高度高度
|
||||
up_y:190,//战绩页裁剪y坐标
|
||||
bannerheight:60,//战绩横幅高度
|
||||
bannery:80,//战绩横幅Y左边(相对48精灵)
|
||||
btnbg:50
|
||||
};
|
||||
Game_Config.Info = {
|
||||
Mainnickname:8,//游戏主界面玩家信息显示最大长度(字符)
|
||||
textwidth_1:12.5,//昵称文字显示的宽度(未改动聊天显示文字大小无需改动无需修改)
|
||||
textwidth_2:12.5,//积分文字显示的宽度(未改动聊天显示文字大小无需改动无需修改)
|
||||
otherPositionDefault:true,//其他主界面玩家信息(昵称、积分)是否采用默认对齐方式对齐居中点为头像中点
|
||||
myPositionDefault:true,//其他主界面玩家信息(昵称、积分)是否采用默认对齐方式对齐居中点为头像中点
|
||||
myPosition:130,//自己信息对齐点(根据游戏界面自行修改)
|
||||
position:[],//其他主界面玩家信息(昵称、积分)居中对齐的x坐标 注意是其他玩家不包括自己从下家开始
|
||||
//TextContent:["1","2","3","4","5","6","7"],//常用语内容
|
||||
TextContent:["你好","谢谢","再来","快点","不要","加油",":)"],//常用语内容
|
||||
TextContentMp3:["","","","","","",""],//常用语对应音效
|
||||
};
|
||||
Game_Config.Share={//分享参数
|
||||
appdownload:"",//下载链接(无需配置,从服务器获取)
|
||||
title:"游戏名",//(分享标题)
|
||||
description:"",//分享描述
|
||||
gameTitle:"",//游戏中的分享标题模板工程会自动将游戏名字分享出去、不必写在这个变量里
|
||||
gameDescription:""//游戏中分享描述
|
||||
};
|
||||
Game_Config.Chat={//游戏内聊天配置信息
|
||||
LimitLength:40,//聊天最大长度(字节长度)
|
||||
textwidth:12.5,//聊天显示文字的宽度(未改动聊天显示文字大小无需改动无需修改)
|
||||
ChatDis:[30,12],//聊天气泡与内容的间隔0位置左右间隔(最好不要低于30)1位置上下间隔
|
||||
isLeft:[1,0,0,1,1],//聊天气泡是否为以左边为基准线(坐标/基准按各游戏界面调整)
|
||||
ChatLoc:[[35,517],[1100,315],[1100,105],[175,105],[175,315]]//聊天气泡的基准点位置(注意是基准点位置!)(坐标/基准按各游戏界面调整)
|
||||
|
||||
};
|
||||
Game_Config.Voice={//游戏内聊天配置信息
|
||||
VoiceTime:600,//播放语音动画的时间一般情况无需无需修改
|
||||
VoiceDis:[30,12],//语音气泡与内容的间隔0位置左右间隔(最好不要低于30)1位置上下间隔
|
||||
isLeft:[1,0,0,1,1],//气泡是否为以左边为基准线(坐标/基准按各游戏界面调整)
|
||||
VoiceLoc:[[35,517],[1100,315],[1100,105],[175,105],[175,315]]//气泡的基准点位置(注意是基准点位置!)(坐标/基准按各游戏界面调整)
|
||||
};
|
||||
Game_Config.Setting={
|
||||
Ads1:"本游戏仅供娱乐休闲使用,\n道具及虚拟货币不可兑换\n现金或实物,不代表任何\n真实财富价值。",
|
||||
//Ads2:"\n 或客服号:\n",
|
||||
board:"",//从后台获取设置无效
|
||||
//info:[" 客服信息","QQ:","",""],//客服QQ提醒
|
||||
info:[" 客服信息","QQ:","手机:","微信:"],//客服QQ提醒
|
||||
board_blength:24,//通知页面一行最大字节数(无需设置)
|
||||
charge:"充值提示",//充值提示
|
||||
};
|
||||
Game_Config.Protocol={
|
||||
x:270,//协议图片初始x坐标
|
||||
y:70,//协议图片初始y坐标
|
||||
h:560,//协议图片显示高度
|
||||
w:729//协议图片显示宽度
|
||||
};
|
||||
Game_Config.Help={//帮助
|
||||
x:300,//帮助图片初始x坐标
|
||||
y:165,//帮助图片初始y坐标
|
||||
w:729,//帮助图片显示高度
|
||||
h:450//帮助图片显示宽度
|
||||
};
|
||||
Game_Config.Notice={//滚动公告
|
||||
x1:0,//无需设置
|
||||
x2:0,//无需设置
|
||||
y:0,//无需设置
|
||||
h:0,//无需设置
|
||||
//以上参数用来截取滚动公告的显示,截取位置是与滚动公告底大小位置一致
|
||||
speed:0.1,//滚动公告的滚动速度
|
||||
width:15//滚动公告的内容字体的字节长度(汉字是两个字节)
|
||||
};
|
||||
Game_Config.Feedback = {//反馈配置
|
||||
maxLen:250 //反馈内容最大长度
|
||||
};
|
||||
Game_Config.shakeList ={//摇一摇事件的回调ID、需要添加时在此处添加回调事件写在Utl_Input.js中的Utl.shakeEvent()中
|
||||
nil:0,
|
||||
startwar:1
|
||||
};
|
||||
Game_Config.soundList ={//声音资源名
|
||||
MenuSceneMusic:"",//大厅界面背景音
|
||||
MainSceneMusic:""//游戏主界面背景音
|
||||
};
|
||||
Game_Config.ClickButton = {//需要设置点击音效的按钮(只有有弹窗的按钮设置此音效有效、按钮已经设置好、子游戏不允许修改)
|
||||
src_1:"",//点击时播放的声音资源文件( 不需要播放则不填,下同)
|
||||
src_2:""//弹窗时播放的音效
|
||||
}
|
||||
|
||||
Game_Config.loginButton = {//登录按钮信息
|
||||
x1:415,//非审核版本微信登录按钮x
|
||||
x2:113,//审核版本微信登录按钮x
|
||||
x3:488,//审核版本游客登录按钮x
|
||||
};
|
||||
Game_Config.sysConfig = {
|
||||
mainMenuButton:false,//是否进入主菜单界面隐藏四个按钮
|
||||
mainScenePlayerInfo:false,//是否隐藏主界面玩家信息
|
||||
mainSceneButton:false,//是否隐藏主界面按钮
|
||||
shareRoom:false,//接收到星星场是否屏蔽平台框架显示
|
||||
changeSeat:false,//是否屏蔽平台自动刷新换座后界面
|
||||
hideNotice:false,//隐藏公告栏
|
||||
vipInfinite:false,//是否为百人场
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
// ============================================================================
|
||||
// 01_SubGame_modify.js —— 平台交互/创建房间接口「转发壳」(框架维护,子游戏不碰)
|
||||
// 顶部为「房型/创建房间配置区」(数据,子游戏填值);其下为接口转发壳(转发到 SubGameHooks)。
|
||||
// 严格 ES5。
|
||||
// ----------------------------------------------------------------------------
|
||||
// 【平台约定精灵:25 号 = 创建房间确认按钮】(接入子游戏必看)
|
||||
// 平台框架在「创建房间」界面提供 25 号精灵作为“确认/提交”按钮;其点击交互与
|
||||
// 发送的数据包,均需【子游戏自己实现】(平台不代发),约定流程:
|
||||
// 1. 子游戏在打开创建房间界面时注册 25 号精灵的点击(经 SpriteEventController
|
||||
// 或 mouseup),点击即“确认创建房间”。
|
||||
// 2. 子游戏按界面选项拼出 roomtype(房型配置串,编码局数/人数/扣卡/规则等,
|
||||
// 由各子游戏按玩法自定义与解析),组装并发送创建房间请求:
|
||||
// Net.Send_create_room({
|
||||
// agentid : GameData.AgentId,
|
||||
// playerid: C_Player.playerid,
|
||||
// gameid : GameData.GameId,
|
||||
// roomtype: <房型配置字符串>
|
||||
// });
|
||||
//
|
||||
// 本麻将实现见 codes/game/ui/handlers/CreateRoomEventHandler(bindEvents 注册
|
||||
// 25→submit;submit 用 UIManager._buildRoomTypeString 拼 roomtype 后 Net.Send_create_room)。
|
||||
// ============================================================================
|
||||
|
||||
// ---------- 配置区(数据,子游戏按玩法填值;与 00 的 Game_Config 分工) ----------
|
||||
var Game_Modify = Game_Modify || {};
|
||||
// ---------- 平台需要的必须字段 ----------
|
||||
Game_Modify.roomDes = ""; // 房间描述,子游戏在 setRoomDes 内填
|
||||
Game_Modify.game_config = {}; // 游戏配置默认值
|
||||
Game_Modify.combat = {
|
||||
maxPlayerCount: 5,
|
||||
pageOnelimitStrLen: 8,
|
||||
pageOneDoc: false,
|
||||
pageTwolimitStrLen: 16,
|
||||
pageTwoDoc: false
|
||||
};
|
||||
Game_Modify.Type_1 = [
|
||||
{ id: 0, des: "10局(房卡X1)", roomcard: 1, type: 1 },
|
||||
{ id: 1, des: "20局(房卡X2)", roomcard: 2, type: 2 }
|
||||
];
|
||||
Game_Modify.Type_2 = [
|
||||
{ id: 0, des: "房主扣卡", type: 1 },
|
||||
{ id: 1, des: "每人扣卡", type: 2 }
|
||||
];
|
||||
Game_Modify.CreateRoomData = {
|
||||
Type_1: 0,
|
||||
Type_2: 0
|
||||
};
|
||||
|
||||
|
||||
// ---------- 接口转发壳(A 类:无 hook 即 no-op) ----------
|
||||
Game_Modify.utlmousedown = function (gameid, spid, downx, downy, no1, no2, no3, no4, no5, no6) {
|
||||
if (window.SubGameHooks && SubGameHooks.utlmousedown) return SubGameHooks.utlmousedown(gameid, spid, downx, downy, no1, no2, no3, no4, no5, no6);
|
||||
};
|
||||
Game_Modify.utlmousedown_nomove = function (gameid, spid, downx, downy, timelong, no1, no2, no3, no4, no5) {
|
||||
if (window.SubGameHooks && SubGameHooks.utlmousedown_nomove) return SubGameHooks.utlmousedown_nomove(gameid, spid, downx, downy, timelong, no1, no2, no3, no4, no5);
|
||||
};
|
||||
Game_Modify.mouseup = function (gameid, spid_down, downx, downy, spid_up, upx, upy, timelong, no1, no2) {
|
||||
if (window.SubGameHooks && SubGameHooks.mouseup) return SubGameHooks.mouseup(gameid, spid_down, downx, downy, spid_up, upx, upy, timelong, no1, no2);
|
||||
};
|
||||
Game_Modify.utlmousemove = function (gameid, spid, downx, downy, movex, movey, timelong, offmovex, offmovey, no1) {
|
||||
if (window.SubGameHooks && SubGameHooks.utlmousemove) return SubGameHooks.utlmousemove(gameid, spid, downx, downy, movex, movey, timelong, offmovex, offmovey, no1);
|
||||
};
|
||||
Game_Modify.utlgamemydrawbegin = function (gameid, spid, times, timelong, no2, no3, no4, no5, no6, no7) {
|
||||
if (window.SubGameHooks && SubGameHooks.utlgamemydrawbegin) return SubGameHooks.utlgamemydrawbegin(gameid, spid, times, timelong, no2, no3, no4, no5, no6, no7);
|
||||
};
|
||||
Game_Modify.gamemydraw = function (gameid, spid, times, timelong, no2, no3, no4, no5, no6, no7) {
|
||||
if (window.SubGameHooks && SubGameHooks.gamemydraw) return SubGameHooks.gamemydraw(gameid, spid, times, timelong, no2, no3, no4, no5, no6, no7);
|
||||
};
|
||||
Game_Modify.OpenCreateRoom = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.OpenCreateRoom) return SubGameHooks.OpenCreateRoom();
|
||||
};
|
||||
Game_Modify.CloseCreateRoom = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.CloseCreateRoom) return SubGameHooks.CloseCreateRoom();
|
||||
};
|
||||
Game_Modify.setRoomDes = function (roomcode, asetcount, roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.setRoomDes) return SubGameHooks.setRoomDes(roomcode, asetcount, roomtype);
|
||||
};
|
||||
|
||||
// ---------- gameCombat 兼容空定义 ----------
|
||||
// 平台 gamemain.js 仍直接调用 gameCombat.utl*(战绩界面回调),保留全局对象与 6 个空接口防报错。
|
||||
// 战绩功能由 RecordView 重建(见迁移子项目 2);届时这些接口可改为委托或保持空。
|
||||
var gameCombat = gameCombat || {};
|
||||
gameCombat.utlani_doend = gameCombat.utlani_doend || function () {};
|
||||
gameCombat.utlmousedown = gameCombat.utlmousedown || function () {};
|
||||
gameCombat.utlmouseup = gameCombat.utlmouseup || function () {};
|
||||
gameCombat.utlmousemove = gameCombat.utlmousemove || function () {};
|
||||
gameCombat.utlgamemydraw = gameCombat.utlgamemydraw || function () {};
|
||||
gameCombat.utlgamemydrawbegin = gameCombat.utlgamemydrawbegin || function () {};
|
||||
// 战绩接收入口(平台 09_Net 调):转发到 SubGameHooks(框架转发壳不引用 codes;子游戏在 SubGameHooks 内转 CombatService)
|
||||
gameCombat.get_player_grade1 = function (_msg) {
|
||||
if (window.SubGameHooks && SubGameHooks.get_player_grade1) return SubGameHooks.get_player_grade1(_msg);
|
||||
};
|
||||
gameCombat.get_player_grade2 = function (_msg) {
|
||||
if (window.SubGameHooks && SubGameHooks.get_player_grade2) return SubGameHooks.get_player_grade2(_msg);
|
||||
};
|
||||
|
||||
// 战绩入口:13 号精灵点击 → 发送获取战绩请求(Net.Send_get_player_grade1,平台底层发送)
|
||||
// 点击经 平台 → Game_Modify.mouseup → SubGameHooks.mouseup → SpriteEventController 链到达
|
||||
if (typeof SpriteEventController !== 'undefined' && SpriteEventController.registerMouseUp) {
|
||||
SpriteEventController.registerMouseUp(13, function () {
|
||||
if (typeof Net !== 'undefined' && Net.Send_get_player_grade1) {
|
||||
Net.Send_get_player_grade1({
|
||||
agentid: GameData.AgentId,
|
||||
playerid: C_Player.playerid,
|
||||
gameid: GameData.GameId,
|
||||
type: 0
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 平台通用精灵交互(从 SubGameHooks 移入;经 Game_Modify.mouseup/gamemydraw→SubGameHooks→SpriteEventController 分发)
|
||||
// 注:25 号(创建房间提交)已归创建房间职责,移至 codes/game/ui/handlers/CreateRoomEventHandler.bindEvents。
|
||||
if (typeof SpriteEventController !== 'undefined') {
|
||||
// 150:帮助按钮
|
||||
if (SpriteEventController.registerMouseUp) {
|
||||
SpriteEventController.registerMouseUp(150, function () {
|
||||
if (typeof GameUI !== 'undefined' && GameUI.OpenHelp) { GameUI.OpenHelp(); }
|
||||
});
|
||||
}
|
||||
// 248:协议勾选绘制(勾上时自绘钩)
|
||||
if (SpriteEventController.registerDraw) {
|
||||
SpriteEventController.registerDraw(248, function (e) {
|
||||
if (GameData.ProtocolIndex) {
|
||||
ifast_mydrawbmp(e.spriteId, 4, 5, 5, 40, 40, 0, 0, 40, 40);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
// ============================================================================
|
||||
// 02_SubGame_Input.template.js —— 平台输入/回调接口「转发壳」模板(框架维护,子游戏不碰)
|
||||
// 平台按全局名调用 gameHallImport.* / Game_Modify.*;本文件统一转发到 SubGameHooks 同名 hook。
|
||||
// 子游戏只需在 codes/ 的 SubGameHooks 里实现需要的接口(见 SubGameHooks.template.js)。
|
||||
// 严格 ES5。接口清单与默认值依据 spec §9。
|
||||
// ============================================================================
|
||||
|
||||
var gameHallImport = gameHallImport || {};
|
||||
var Game_Modify = Game_Modify || {};
|
||||
|
||||
// ============================================================================
|
||||
// gameHallImport.* — 大厅接口(9 个)
|
||||
// ============================================================================
|
||||
|
||||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||||
// 注:与 Game_Modify.appStart 同名但语义不同(大厅启动 vs 游戏启动),故 hook 名加 hall 前缀区分
|
||||
gameHallImport.appStart = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.hallAppStart) return SubGameHooks.hallAppStart();
|
||||
};
|
||||
|
||||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||||
gameHallImport.jumpMenuScene = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.jumpMenuScene) return SubGameHooks.jumpMenuScene();
|
||||
};
|
||||
|
||||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||||
gameHallImport.gameStart = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.gameStart) return SubGameHooks.gameStart();
|
||||
};
|
||||
|
||||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||||
gameHallImport.setGameList = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.setGameList) return SubGameHooks.setGameList();
|
||||
};
|
||||
|
||||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||||
gameHallImport.clearGameinfo = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.clearGameinfo) return SubGameHooks.clearGameinfo();
|
||||
};
|
||||
|
||||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||||
gameHallImport.getWebdata = function (data) {
|
||||
if (window.SubGameHooks && SubGameHooks.getWebdata) return SubGameHooks.getWebdata(data);
|
||||
};
|
||||
|
||||
// B 类:有平台默认返回值,无 hook 即返回默认
|
||||
gameHallImport.isInstalled = function (data) {
|
||||
if (window.SubGameHooks && SubGameHooks.isInstalled) return SubGameHooks.isInstalled(data);
|
||||
return 1;
|
||||
};
|
||||
|
||||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||||
gameHallImport.up_imgurl = function (recid, photo) {
|
||||
if (window.SubGameHooks && SubGameHooks.up_imgurl) return SubGameHooks.up_imgurl(recid, photo);
|
||||
};
|
||||
|
||||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||||
gameHallImport.getphoto = function (recid, photo) {
|
||||
if (window.SubGameHooks && SubGameHooks.getphoto) return SubGameHooks.getphoto(recid, photo);
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// Game_Modify.* — 生命周期/回调接口(来自 02,45 个)
|
||||
// ============================================================================
|
||||
|
||||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||||
Game_Modify.appStart = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.appStart) return SubGameHooks.appStart();
|
||||
};
|
||||
|
||||
// A 类:开战回调,无 hook 即 no-op
|
||||
Game_Modify.StartWar = function (_msg) {
|
||||
if (window.SubGameHooks && SubGameHooks.StartWar) return SubGameHooks.StartWar(_msg);
|
||||
};
|
||||
|
||||
// A 类:接收数据包,无 hook 即 no-op
|
||||
Game_Modify._ReceiveData = function (_msg) {
|
||||
if (window.SubGameHooks && SubGameHooks._ReceiveData) return SubGameHooks._ReceiveData(_msg);
|
||||
};
|
||||
|
||||
// A 类:创建房间,无 hook 即 no-op
|
||||
Game_Modify.createRoom = function (_roomtype, _infinite) {
|
||||
if (window.SubGameHooks && SubGameHooks.createRoom) return SubGameHooks.createRoom(_roomtype, _infinite);
|
||||
};
|
||||
|
||||
// A 类:自己进入房间,无 hook 即 no-op
|
||||
Game_Modify.myJoinRoom = function (_msg) {
|
||||
if (window.SubGameHooks && SubGameHooks.myJoinRoom) return SubGameHooks.myJoinRoom(_msg);
|
||||
};
|
||||
|
||||
// A 类:重连,无 hook 即 no-op
|
||||
Game_Modify.Reconnect = function (_deskinfo) {
|
||||
if (window.SubGameHooks && SubGameHooks.Reconnect) return SubGameHooks.Reconnect(_deskinfo);
|
||||
};
|
||||
|
||||
// A 类:关闭所有声音,无 hook 即 no-op
|
||||
Game_Modify.stopAllSounds = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.stopAllSounds) return SubGameHooks.stopAllSounds();
|
||||
};
|
||||
|
||||
// A 类:投票解散确认,无 hook 即 no-op
|
||||
Game_Modify.Free = function (_msg) {
|
||||
if (window.SubGameHooks && SubGameHooks.Free) return SubGameHooks.Free(_msg);
|
||||
};
|
||||
|
||||
// A 类:未开战状态加入牌桌数据,无 hook 即 no-op
|
||||
Game_Modify.DeskInfo = function (_msg) {
|
||||
if (window.SubGameHooks && SubGameHooks.DeskInfo) return SubGameHooks.DeskInfo(_msg);
|
||||
};
|
||||
|
||||
// A 类:开局后自己退出房间,无 hook 即 no-op
|
||||
Game_Modify.breakRoom = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.breakRoom) return SubGameHooks.breakRoom();
|
||||
};
|
||||
|
||||
// A 类:其他玩家加入房间,无 hook 即 no-op
|
||||
Game_Modify.playerJoinRoom = function (seat) {
|
||||
if (window.SubGameHooks && SubGameHooks.playerJoinRoom) return SubGameHooks.playerJoinRoom(seat);
|
||||
};
|
||||
|
||||
// A 类:其他玩家离开房间,无 hook 即 no-op
|
||||
Game_Modify.playerLeaveRoom = function (seat) {
|
||||
if (window.SubGameHooks && SubGameHooks.playerLeaveRoom) return SubGameHooks.playerLeaveRoom(seat);
|
||||
};
|
||||
|
||||
// A 类:更新游戏界面,无 hook 即 no-op
|
||||
Game_Modify.updateScene = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.updateScene) return SubGameHooks.updateScene();
|
||||
};
|
||||
|
||||
// A 类:关闭游戏界面,无 hook 即 no-op
|
||||
Game_Modify.closeGameScene = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.closeGameScene) return SubGameHooks.closeGameScene();
|
||||
};
|
||||
|
||||
// A 类:玩家离线,无 hook 即 no-op
|
||||
Game_Modify.playerOffline = function (seat) {
|
||||
if (window.SubGameHooks && SubGameHooks.playerOffline) return SubGameHooks.playerOffline(seat);
|
||||
};
|
||||
|
||||
// A 类:玩家上线,无 hook 即 no-op
|
||||
Game_Modify.playerOnline = function (seat) {
|
||||
if (window.SubGameHooks && SubGameHooks.playerOnline) return SubGameHooks.playerOnline(seat);
|
||||
};
|
||||
|
||||
// A 类:玩家电话状态,无 hook 即 no-op
|
||||
Game_Modify.playerphonestate = function (seat, type) {
|
||||
if (window.SubGameHooks && SubGameHooks.playerphonestate) return SubGameHooks.playerphonestate(seat, type);
|
||||
};
|
||||
|
||||
// A 类:摇一摇事件,无 hook 即 no-op
|
||||
Game_Modify.shakeEvent = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.shakeEvent) return SubGameHooks.shakeEvent();
|
||||
};
|
||||
|
||||
// A 类:计算结果,无 hook 即 no-op
|
||||
Game_Modify.calResult = function (inputArr) {
|
||||
if (window.SubGameHooks && SubGameHooks.calResult) return SubGameHooks.calResult(inputArr);
|
||||
};
|
||||
|
||||
// A 类:进入游戏主场景,无 hook 即 no-op
|
||||
Game_Modify.onEnterMainScene = function (roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.onEnterMainScene) return SubGameHooks.onEnterMainScene(roomtype);
|
||||
};
|
||||
|
||||
// A 类:退出游戏主场景,无 hook 即 no-op
|
||||
Game_Modify.onExitMainScene = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.onExitMainScene) return SubGameHooks.onExitMainScene();
|
||||
};
|
||||
|
||||
// A 类:获取游戏配置时调用,无 hook 即 no-op
|
||||
Game_Modify.onGameConfig = function (_gameConfig) {
|
||||
if (window.SubGameHooks && SubGameHooks.onGameConfig) return SubGameHooks.onGameConfig(_gameConfig);
|
||||
};
|
||||
|
||||
// A 类:进入牌局回放,无 hook 即 no-op
|
||||
Game_Modify.onEnterVideo = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.onEnterVideo) return SubGameHooks.onEnterVideo();
|
||||
};
|
||||
|
||||
// A 类:收到投降回包,无 hook 即 no-op
|
||||
Game_Modify.onSurrender = function (_msg) {
|
||||
if (window.SubGameHooks && SubGameHooks.onSurrender) return SubGameHooks.onSurrender(_msg);
|
||||
};
|
||||
|
||||
// A 类:玩家准备触发,无 hook 即 no-op
|
||||
Game_Modify.onReady = function (seat) {
|
||||
if (window.SubGameHooks && SubGameHooks.onReady) return SubGameHooks.onReady(seat);
|
||||
};
|
||||
|
||||
// B 类:获取房间描述,无 hook 返回默认文案
|
||||
Game_Modify.getRoomInfo = function (roomtype, type, tea) {
|
||||
if (window.SubGameHooks && SubGameHooks.getRoomInfo) return SubGameHooks.getRoomInfo(roomtype, type, tea);
|
||||
return "房间描述" + roomtype;
|
||||
};
|
||||
|
||||
// B 类:获取房间星星场下限,无 hook 返回默认值
|
||||
Game_Modify.getStarLimit = function (roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.getStarLimit) return SubGameHooks.getStarLimit(roomtype);
|
||||
return 2001000;
|
||||
};
|
||||
|
||||
// B 类:获取房间星星场倍数,无 hook 返回默认值
|
||||
Game_Modify.getMult = function (roomtype, type) {
|
||||
if (window.SubGameHooks && SubGameHooks.getMult) return SubGameHooks.getMult(roomtype, type);
|
||||
return 10000;
|
||||
};
|
||||
|
||||
// B 类:获取房间全部信息描述,无 hook 返回默认文案
|
||||
Game_Modify.getFullRoomInfo = function (roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.getFullRoomInfo) return SubGameHooks.getFullRoomInfo(roomtype);
|
||||
return "房间描述" + roomtype;
|
||||
};
|
||||
|
||||
// A 类:打开帮助页面,无 hook 即 no-op
|
||||
Game_Modify.onOpenHelp = function (spid) {
|
||||
if (window.SubGameHooks && SubGameHooks.onOpenHelp) return SubGameHooks.onOpenHelp(spid);
|
||||
};
|
||||
|
||||
// A 类:显示大厅界面,无 hook 即 no-op
|
||||
Game_Modify.onMainMenuScene = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.onMainMenuScene) return SubGameHooks.onMainMenuScene();
|
||||
};
|
||||
|
||||
// A 类:数字输入框确认回调,无 hook 即 no-op
|
||||
Game_Modify.onCheckInput = function (_result) {
|
||||
if (window.SubGameHooks && SubGameHooks.onCheckInput) return SubGameHooks.onCheckInput(_result);
|
||||
};
|
||||
|
||||
// A 类:创建房间成功后触发,无 hook 即 no-op
|
||||
Game_Modify.onCreateRoom = function (_data) {
|
||||
if (window.SubGameHooks && SubGameHooks.onCreateRoom) return SubGameHooks.onCreateRoom(_data);
|
||||
};
|
||||
|
||||
// B 类:获取离场限制,无 hook 返回默认值
|
||||
Game_Modify.getLeaveLimit = function (roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.getLeaveLimit) return SubGameHooks.getLeaveLimit(roomtype);
|
||||
return 10;
|
||||
};
|
||||
|
||||
// A 类:成功获取定位信息,无 hook 即 no-op
|
||||
Game_Modify.onLocationInfo = function (_locationInfo) {
|
||||
if (window.SubGameHooks && SubGameHooks.onLocationInfo) return SubGameHooks.onLocationInfo(_locationInfo);
|
||||
};
|
||||
|
||||
// A 类:进入游戏界面创建牌桌之前,无 hook 即 no-op
|
||||
Game_Modify.onCreateDesk = function (roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.onCreateDesk) return SubGameHooks.onCreateDesk(roomtype);
|
||||
};
|
||||
|
||||
// B 类:获取是否开启视频功能,无 hook 返回默认值
|
||||
Game_Modify.getVideoByRoomType = function (roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.getVideoByRoomType) return SubGameHooks.getVideoByRoomType(roomtype);
|
||||
return 1;
|
||||
};
|
||||
|
||||
// B 类:获取房间顶部描述数组,无 hook 返回默认文案数组
|
||||
Game_Modify.getRoomTopDescAry = function (roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.getRoomTopDescAry) return SubGameHooks.getRoomTopDescAry(roomtype);
|
||||
return ["" + roomtype];
|
||||
};
|
||||
|
||||
// A 类:星星场房间列表,无 hook 即 no-op
|
||||
Game_Modify.getShareRoom = function (_msg) {
|
||||
if (window.SubGameHooks && SubGameHooks.getShareRoom) return SubGameHooks.getShareRoom(_msg);
|
||||
};
|
||||
|
||||
// A 类:玩家自己退出房间,无 hook 即 no-op
|
||||
Game_Modify.myExitRoom = function (seat) {
|
||||
if (window.SubGameHooks && SubGameHooks.myExitRoom) return SubGameHooks.myExitRoom(seat);
|
||||
};
|
||||
|
||||
// A 类:接收到换座包触发,无 hook 即 no-op
|
||||
Game_Modify.changeSeat = function (seat1, seat2) {
|
||||
if (window.SubGameHooks && SubGameHooks.changeSeat) return SubGameHooks.changeSeat(seat1, seat2);
|
||||
};
|
||||
|
||||
// A 类:关闭 vip 选项时调用,无 hook 即 no-op
|
||||
Game_Modify.onCloseVip = function () {
|
||||
if (window.SubGameHooks && SubGameHooks.onCloseVip) return SubGameHooks.onCloseVip();
|
||||
};
|
||||
|
||||
// B 类:判断房间是否为金币场,无 hook 返回默认值(0=非金币场)
|
||||
Game_Modify.getRoomMode = function (roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.getRoomMode) return SubGameHooks.getRoomMode(roomtype);
|
||||
return 0;
|
||||
};
|
||||
|
||||
// B 类:获取房间最大玩家数量,无 hook 返回默认值
|
||||
Game_Modify.getMaxPlayerCount = function (roomtype) {
|
||||
if (window.SubGameHooks && SubGameHooks.getMaxPlayerCount) return SubGameHooks.getMaxPlayerCount(roomtype);
|
||||
// 默认值依赖全局 Game_Config(须在本模板之前加载);无则回退 4
|
||||
return (Game_Config.Max && Game_Config.Max.PlayerCnt) || 4;
|
||||
};
|
||||
|
||||
// B 类:更新玩家信息 UI,无 hook 返回 false(让平台默认处理)
|
||||
Game_Modify.updatePlayerInfoUI = function (targetSeat) {
|
||||
if (window.SubGameHooks && SubGameHooks.updatePlayerInfoUI) return SubGameHooks.updatePlayerInfoUI(targetSeat);
|
||||
return false;
|
||||
};
|
||||
@@ -0,0 +1,206 @@
|
||||
// ============================================================================
|
||||
// SubGameHooks.template.js —— 子游戏接入入口(复制为 codes/SubGameHooks.js 后填实现)
|
||||
// 平台契约文件(00/01/02 转发壳)会把同名平台接口转发到这里。只需实现【本游戏需要的】hook,
|
||||
// 未实现的接口由转发壳走平台默认(B)或空操作(A)。严格 ES5。
|
||||
// 接口清单与默认值见 spec §9 / 文档 06。
|
||||
// ============================================================================
|
||||
|
||||
var SubGameHooks = window.SubGameHooks || {};
|
||||
|
||||
// ===== gameHallImport.*(大厅,9) =====
|
||||
|
||||
// [A] hallAppStart():大厅应用启动(注:与 Game_Modify.appStart 同名冲突,故加 hall 前缀区分)。
|
||||
// SubGameHooks.hallAppStart = function () { /* ... */ };
|
||||
|
||||
// [A] jumpMenuScene():大厅跳转菜单场景。
|
||||
// SubGameHooks.jumpMenuScene = function () { /* ... */ };
|
||||
|
||||
// [A] gameStart():大厅游戏开始入口。
|
||||
// SubGameHooks.gameStart = function () { /* ... */ };
|
||||
|
||||
// [A] setGameList():设置游戏列表。
|
||||
// SubGameHooks.setGameList = function () { /* ... */ };
|
||||
|
||||
// [A] clearGameinfo():清除游戏信息。
|
||||
// SubGameHooks.clearGameinfo = function () { /* ... */ };
|
||||
|
||||
// [A] getWebdata(data):获取网络数据回调。
|
||||
// SubGameHooks.getWebdata = function (data) { /* ... */ };
|
||||
|
||||
// [B] isInstalled(data):检查是否已安装;无 hook 时默认:return 1。
|
||||
// SubGameHooks.isInstalled = function (data) { /* ... */ };
|
||||
|
||||
// [A] up_imgurl(recid, photo):更新图片 URL。
|
||||
// SubGameHooks.up_imgurl = function (recid, photo) { /* ... */ };
|
||||
|
||||
// [A] getphoto(recid, photo):获取玩家头像。
|
||||
// SubGameHooks.getphoto = function (recid, photo) { /* ... */ };
|
||||
|
||||
// ===== Game_Modify.*(事件/交互,来自 01,9) =====
|
||||
|
||||
// [A] utlmousedown(gameid, spid, downx, downy, no1, no2, no3, no4, no5, no6):精灵按下事件;子游戏转发到 SpriteEventController。
|
||||
// SubGameHooks.utlmousedown = function (gameid, spid, downx, downy, no1, no2, no3, no4, no5, no6) { /* ... */ };
|
||||
|
||||
// [A] utlmousedown_nomove(gameid, spid, downx, downy, timelong, no1, no2, no3, no4, no5):精灵按下(无移动)事件。
|
||||
// SubGameHooks.utlmousedown_nomove = function (gameid, spid, downx, downy, timelong, no1, no2, no3, no4, no5) { /* ... */ };
|
||||
|
||||
// [A] mouseup(gameid, spid_down, downx, downy, spid_up, upx, upy, timelong, no1, no2):精灵抬起事件。
|
||||
// SubGameHooks.mouseup = function (gameid, spid_down, downx, downy, spid_up, upx, upy, timelong, no1, no2) { /* ... */ };
|
||||
|
||||
// [A] utlmousemove(gameid, spid, downx, downy, movex, movey, timelong, offmovex, offmovey, no1):精灵移动事件。
|
||||
// SubGameHooks.utlmousemove = function (gameid, spid, downx, downy, movex, movey, timelong, offmovex, offmovey, no1) { /* ... */ };
|
||||
|
||||
// [A] utlgamemydrawbegin(gameid, spid, times, timelong, no2, no3, no4, no5, no6, no7):精灵绘制开始事件。
|
||||
// SubGameHooks.utlgamemydrawbegin = function (gameid, spid, times, timelong, no2, no3, no4, no5, no6, no7) { /* ... */ };
|
||||
|
||||
// [A] gamemydraw(gameid, spid, times, timelong, no2, no3, no4, no5, no6, no7):精灵绘制帧事件。
|
||||
// SubGameHooks.gamemydraw = function (gameid, spid, times, timelong, no2, no3, no4, no5, no6, no7) { /* ... */ };
|
||||
|
||||
// [A] OpenCreateRoom():打开创建房间界面。
|
||||
// SubGameHooks.OpenCreateRoom = function () { /* ... */ };
|
||||
|
||||
// [A] CloseCreateRoom():关闭创建房间界面。
|
||||
// SubGameHooks.CloseCreateRoom = function () { /* ... */ };
|
||||
|
||||
// [A] setRoomDes(roomcode, asetcount, roomtype):设置房间描述文案。
|
||||
// SubGameHooks.setRoomDes = function (roomcode, asetcount, roomtype) { /* ... */ };
|
||||
|
||||
// ===== Game_Modify.*(生命周期/回调,来自 02,45) =====
|
||||
|
||||
// [A] appStart():游戏应用启动(与 gameHallImport.appStart 语义不同,对应 Game_Modify 侧启动)。
|
||||
// SubGameHooks.appStart = function () { /* ... */ };
|
||||
|
||||
// [A] StartWar(_msg):开战(开局)回调,解包开局数据并初始化游戏状态。
|
||||
// SubGameHooks.StartWar = function (_msg) { /* ... */ };
|
||||
|
||||
// [A] _ReceiveData(_msg):接收服务端主动推送的数据包,派发给对应业务处理器。
|
||||
// SubGameHooks._ReceiveData = function (_msg) { /* ... */ };
|
||||
|
||||
// [A] createRoom(_roomtype, _infinite):前端发起创建房间请求。
|
||||
// SubGameHooks.createRoom = function (_roomtype, _infinite) { /* ... */ };
|
||||
|
||||
// [A] myJoinRoom(_msg):自己成功进入房间回调。
|
||||
// SubGameHooks.myJoinRoom = function (_msg) { /* ... */ };
|
||||
|
||||
// [A] Reconnect(_deskinfo):重连回调,用服务端返回的桌面信息恢复游戏界面。
|
||||
// SubGameHooks.Reconnect = function (_deskinfo) { /* ... */ };
|
||||
|
||||
// [A] stopAllSounds():停止所有声音(切换到后台时触发)。
|
||||
// SubGameHooks.stopAllSounds = function () { /* ... */ };
|
||||
|
||||
// [A] Free(_msg):投票解散确认回调。
|
||||
// SubGameHooks.Free = function (_msg) { /* ... */ };
|
||||
|
||||
// [A] DeskInfo(_msg):未开战状态下加入牌桌的数据同步。
|
||||
// SubGameHooks.DeskInfo = function (_msg) { /* ... */ };
|
||||
|
||||
// [A] breakRoom():开局后自己退出房间触发。
|
||||
// SubGameHooks.breakRoom = function () { /* ... */ };
|
||||
|
||||
// [A] playerJoinRoom(seat):其他玩家加入房间通知。
|
||||
// SubGameHooks.playerJoinRoom = function (seat) { /* ... */ };
|
||||
|
||||
// [A] playerLeaveRoom(seat):其他玩家离开房间通知。
|
||||
// SubGameHooks.playerLeaveRoom = function (seat) { /* ... */ };
|
||||
|
||||
// [A] updateScene():更新游戏界面(分辨率变化等)。
|
||||
// SubGameHooks.updateScene = function () { /* ... */ };
|
||||
|
||||
// [A] closeGameScene():关闭游戏界面。
|
||||
// SubGameHooks.closeGameScene = function () { /* ... */ };
|
||||
|
||||
// [A] playerOffline(seat):玩家掉线通知。
|
||||
// SubGameHooks.playerOffline = function (seat) { /* ... */ };
|
||||
|
||||
// [A] playerOnline(seat):玩家上线通知。
|
||||
// SubGameHooks.playerOnline = function (seat) { /* ... */ };
|
||||
|
||||
// [A] playerphonestate(seat, type):玩家电话状态变化通知。
|
||||
// SubGameHooks.playerphonestate = function (seat, type) { /* ... */ };
|
||||
|
||||
// [A] shakeEvent():设备摇一摇事件。
|
||||
// SubGameHooks.shakeEvent = function () { /* ... */ };
|
||||
|
||||
// [A] calResult(inputArr):计算结算结果。
|
||||
// SubGameHooks.calResult = function (inputArr) { /* ... */ };
|
||||
|
||||
// [A] onEnterMainScene(roomtype):进入游戏主场景。
|
||||
// SubGameHooks.onEnterMainScene = function (roomtype) { /* ... */ };
|
||||
|
||||
// [A] onExitMainScene():退出游戏主场景。
|
||||
// SubGameHooks.onExitMainScene = function () { /* ... */ };
|
||||
|
||||
// [A] onGameConfig(_gameConfig):获取游戏配置时触发。
|
||||
// SubGameHooks.onGameConfig = function (_gameConfig) { /* ... */ };
|
||||
|
||||
// [A] onEnterVideo():进入牌局回放模式。
|
||||
// SubGameHooks.onEnterVideo = function () { /* ... */ };
|
||||
|
||||
// [A] onSurrender(_msg):收到投降回包。
|
||||
// SubGameHooks.onSurrender = function (_msg) { /* ... */ };
|
||||
|
||||
// [A] onReady(seat):玩家准备触发。
|
||||
// SubGameHooks.onReady = function (seat) { /* ... */ };
|
||||
|
||||
// [B] getRoomInfo(roomtype, type, tea):获取房间描述文案;无 hook 时默认:"房间描述" + roomtype。
|
||||
// SubGameHooks.getRoomInfo = function (roomtype, type, tea) { /* ... */ };
|
||||
|
||||
// [B] getStarLimit(roomtype):获取星星场下限分数;无 hook 时默认:return 2001000。
|
||||
// SubGameHooks.getStarLimit = function (roomtype) { /* ... */ };
|
||||
|
||||
// [B] getMult(roomtype, type):获取星星场倍数;无 hook 时默认:return 10000。
|
||||
// SubGameHooks.getMult = function (roomtype, type) { /* ... */ };
|
||||
|
||||
// [B] getFullRoomInfo(roomtype):获取房间完整信息描述;无 hook 时默认:"房间描述" + roomtype。
|
||||
// SubGameHooks.getFullRoomInfo = function (roomtype) { /* ... */ };
|
||||
|
||||
// [A] onOpenHelp(spid):打开帮助页面。
|
||||
// SubGameHooks.onOpenHelp = function (spid) { /* ... */ };
|
||||
|
||||
// [A] onMainMenuScene():显示大厅主菜单界面。
|
||||
// SubGameHooks.onMainMenuScene = function () { /* ... */ };
|
||||
|
||||
// [A] onCheckInput(_result):数字输入框确认回调。
|
||||
// SubGameHooks.onCheckInput = function (_result) { /* ... */ };
|
||||
|
||||
// [A] onCreateRoom(_data):创建房间成功后触发。
|
||||
// SubGameHooks.onCreateRoom = function (_data) { /* ... */ };
|
||||
|
||||
// [B] getLeaveLimit(roomtype):获取离场限制局数;无 hook 时默认:return 10。
|
||||
// SubGameHooks.getLeaveLimit = function (roomtype) { /* ... */ };
|
||||
|
||||
// [A] onLocationInfo(_locationInfo):成功获取定位信息回调。
|
||||
// SubGameHooks.onLocationInfo = function (_locationInfo) { /* ... */ };
|
||||
|
||||
// [A] onCreateDesk(roomtype):进入游戏界面创建牌桌之前触发。
|
||||
// SubGameHooks.onCreateDesk = function (roomtype) { /* ... */ };
|
||||
|
||||
// [B] getVideoByRoomType(roomtype):获取该房型是否开启视频功能;无 hook 时默认:return 1。
|
||||
// SubGameHooks.getVideoByRoomType = function (roomtype) { /* ... */ };
|
||||
|
||||
// [B] getRoomTopDescAry(roomtype):获取房间顶部描述文案数组;无 hook 时默认:["" + roomtype]。
|
||||
// SubGameHooks.getRoomTopDescAry = function (roomtype) { /* ... */ };
|
||||
|
||||
// [A] getShareRoom(_msg):星星场房间列表数据。
|
||||
// SubGameHooks.getShareRoom = function (_msg) { /* ... */ };
|
||||
|
||||
// [A] myExitRoom(seat):玩家自己退出房间。
|
||||
// SubGameHooks.myExitRoom = function (seat) { /* ... */ };
|
||||
|
||||
// [A] changeSeat(seat1, seat2):接收到换座包触发。
|
||||
// SubGameHooks.changeSeat = function (seat1, seat2) { /* ... */ };
|
||||
|
||||
// [A] onCloseVip():关闭 VIP 选项时调用。
|
||||
// SubGameHooks.onCloseVip = function () { /* ... */ };
|
||||
|
||||
// [B] getRoomMode(roomtype):判断房间模式(0=非金币场);无 hook 时默认:return 0。
|
||||
// SubGameHooks.getRoomMode = function (roomtype) { /* ... */ };
|
||||
|
||||
// [B] getMaxPlayerCount(roomtype):获取房间最大玩家数量;无 hook 时默认:return Game_Config.Max.PlayerCnt || 4。
|
||||
// SubGameHooks.getMaxPlayerCount = function (roomtype) { /* ... */ };
|
||||
|
||||
// [B] updatePlayerInfoUI(targetSeat):更新玩家信息 UI;无 hook 时默认:return false(让平台默认处理)。
|
||||
// SubGameHooks.updatePlayerInfoUI = function (targetSeat) { /* ... */ };
|
||||
|
||||
window.SubGameHooks = SubGameHooks;
|
||||
if (typeof module !== 'undefined' && module.exports) { module.exports = SubGameHooks; }
|
||||
Reference in New Issue
Block a user