目录结构调整
This commit is contained in:
606
codes/games/server/docs/guides/framework/00-框架基础概述.md
Normal file
606
codes/games/server/docs/guides/framework/00-框架基础概述.md
Normal file
@@ -0,0 +1,606 @@
|
||||
# 友乐游戏框架基础概述
|
||||
|
||||
> **文档目标**:帮助开发者理解友乐游戏平台的整体架构、前后端分离机制、模块化设计和基础开发规范。
|
||||
|
||||
## 📚 目录
|
||||
|
||||
1. [友乐游戏平台架构](#1-友乐游戏平台架构)
|
||||
2. [前后端分离部署](#2-前后端分离部署)
|
||||
3. [三文件架构规范](#3-三文件架构规范)
|
||||
4. [模块加载机制](#4-模块加载机制)
|
||||
5. [数据包协议基础](#5-数据包协议基础)
|
||||
6. [开发环境与兼容性](#6-开发环境与兼容性)
|
||||
|
||||
---
|
||||
|
||||
## 1. 友乐游戏平台架构
|
||||
|
||||
### 1.1 整体架构
|
||||
|
||||
友乐游戏平台采用**模块化、可扩展**的架构设计,支持多个子游戏的独立开发和部署。
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ 友乐游戏平台(Node.js) │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ 应用层(youle_app) │
|
||||
│ ├─ 房间管理(youle_room) │
|
||||
│ ├─ 玩家管理(youle_player) │
|
||||
│ ├─ 通信服务(youle_socket) │
|
||||
│ └─ 数据存储(youle_database) │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ 游戏模块层(mod_*) │
|
||||
│ ├─ mod_jinxianmahjong(进贤麻将) │
|
||||
│ ├─ mod_other_game1(其他游戏1) │
|
||||
│ └─ mod_other_game2(其他游戏2) │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ 网络层(packet.js) │
|
||||
│ ├─ WebSocket通信 │
|
||||
│ ├─ HTTP通信 │
|
||||
│ └─ RPC路由分发 │
|
||||
└─────────────────────────────────────────────────┘
|
||||
↕ WebSocket/HTTP
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ 客户端(浏览器环境) │
|
||||
│ ├─ 游戏界面渲染 │
|
||||
│ ├─ 用户交互处理 │
|
||||
│ ├─ 本地状态管理 │
|
||||
│ └─ 网络通信封装 │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.2 核心组件
|
||||
|
||||
| 组件名称 | 职责说明 | 部署位置 |
|
||||
|---------|---------|---------|
|
||||
| **youle_app** | 应用级服务提供者,管理所有游戏模块 | 服务端 |
|
||||
| **youle_room** | 房间管理服务,处理房间创建、加入、解散 | 服务端 |
|
||||
| **packet.js** | 数据包路由分发器,实现RPC调用 | 服务端 |
|
||||
| **mod_*(游戏模块)** | 子游戏具体实现,独立封装游戏逻辑 | 服务端 |
|
||||
| **客户端界面** | 游戏前端界面和交互逻辑 | 浏览器 |
|
||||
|
||||
### 1.3 关键设计理念
|
||||
|
||||
1. **模块独立性**:每个游戏模块独立开发、测试、部署
|
||||
2. **接口标准化**:所有游戏模块遵循统一的接口规范
|
||||
3. **双向解耦**:框架和游戏通过export/import接口解耦
|
||||
4. **状态同步**:服务端为权威状态源,客户端被动接收
|
||||
|
||||
---
|
||||
|
||||
## 2. 前后端分离部署
|
||||
|
||||
### 2.1 部署架构
|
||||
|
||||
> ⚠️ **重要**:友乐游戏采用**真正的前后端物理分离**,而非同进程模块调用。
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 用户浏览器(客户端) │
|
||||
│ 环境:Chrome/Firefox/Safari等浏览器 │
|
||||
│ 语言:JavaScript ES5(不使用Node.js) │
|
||||
│ 部署:静态HTML/JS/CSS文件 │
|
||||
│ 运行:浏览器JavaScript引擎 │
|
||||
└──────────────────────────────────────────────┘
|
||||
↕
|
||||
WebSocket/HTTP协议通信
|
||||
↕
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ 游戏服务器(服务端) │
|
||||
│ 环境:Node.js运行时 │
|
||||
│ 语言:JavaScript ES5 │
|
||||
│ 部署:服务器进程(pm2/systemd等) │
|
||||
│ 运行:Node.js引擎 │
|
||||
└──────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.2 前后端通信特点
|
||||
|
||||
#### 客户端特点(浏览器环境)
|
||||
- **运行环境**:运行在用户浏览器中(Chrome、Firefox、Safari等)
|
||||
- **语言规范**:使用原生JavaScript ES5标准,不使用Node.js特性
|
||||
- **部署方式**:作为静态资源部署(HTML、JS、CSS文件)
|
||||
- **模块系统**:不使用npm包管理,不使用require/import
|
||||
- **依赖管理**:通过`<script>`标签按顺序加载
|
||||
|
||||
#### 服务端特点(Node.js环境)
|
||||
- **运行环境**:运行在服务器Node.js进程中
|
||||
- **语言规范**:使用JavaScript ES5,遵循Node.js模块规范
|
||||
- **部署方式**:作为Node.js应用部署
|
||||
- **模块系统**:使用Node.js的`require()`进行模块加载
|
||||
- **依赖管理**:使用npm管理依赖包
|
||||
|
||||
#### 通信机制
|
||||
|
||||
| 特性 | 说明 | 影响 |
|
||||
|-----|------|------|
|
||||
| **物理分离** | 客户端和服务端是完全独立的进程 | 不能直接调用函数,必须通过网络通信 |
|
||||
| **网络通信** | 使用WebSocket/HTTP协议 | 存在网络延迟,需要异步处理 |
|
||||
| **数据序列化** | 所有数据必须JSON序列化 | 不能传递函数、对象引用等 |
|
||||
| **异步交互** | 所有请求都是异步的 | 需要回调或事件机制处理响应 |
|
||||
| **状态同步** | 服务端主动推送状态变化 | 客户端需要维护本地状态副本 |
|
||||
|
||||
### 2.3 代码共享机制
|
||||
|
||||
由于前后端部署环境不同,代码共享通过**文件复制**方式实现:
|
||||
|
||||
```
|
||||
server/games2/jinxianmahjong/shared/
|
||||
├── core/ # 核心算法(前后端共享)
|
||||
│ ├── JingAlgorithm.js # 精牌算法
|
||||
│ ├── HandEvaluator.js # 牌型评估
|
||||
│ └── ScoringEngine.js # 计分引擎
|
||||
├── constants/ # 常量定义(前后端共享)
|
||||
├── dataStructures/ # 数据结构(前后端共享)
|
||||
└── utils/ # 工具函数(前后端共享)
|
||||
|
||||
↓ 文件复制(构建时)↓
|
||||
|
||||
client/js/shared/ # 复制到客户端目录
|
||||
├── core/
|
||||
├── constants/
|
||||
├── dataStructures/
|
||||
└── utils/
|
||||
```
|
||||
|
||||
**共享代码编写要求**:
|
||||
1. **ES5语法**:不使用任何ES6+特性(箭头函数、class、let/const等)
|
||||
2. **无副作用**:纯函数设计,不依赖全局状态
|
||||
3. **环境兼容**:同时兼容浏览器和Node.js环境
|
||||
4. **无依赖**:不依赖Node.js特定API或浏览器特定API
|
||||
|
||||
---
|
||||
|
||||
## 3. 三文件架构规范
|
||||
|
||||
每个子游戏必须遵循**三文件架构规范**:
|
||||
|
||||
### 3.1 架构概览
|
||||
|
||||
```
|
||||
server/games2/jinxianmahjong/
|
||||
├── mod.js # 【1】模块主入口
|
||||
├── export.js # 【2】输出接口(框架→子游戏)
|
||||
└── import.js # 【3】输入接口(子游戏→框架)
|
||||
```
|
||||
|
||||
### 3.2 三个核心文件
|
||||
|
||||
#### 1️⃣ mod.js - 模块主入口
|
||||
|
||||
**职责**:
|
||||
- 创建游戏模块实例
|
||||
- 按顺序加载依赖文件
|
||||
- 初始化模块状态
|
||||
- 定义RPC方法
|
||||
|
||||
**关键代码**:
|
||||
```javascript
|
||||
// 创建模块实例
|
||||
var mod_jinxianmahjong = cls_mod.new(
|
||||
"mod_jinxianmahjong", // 模块名称
|
||||
"jinxianmahjong", // 游戏ID
|
||||
youle_app // 父级应用
|
||||
);
|
||||
|
||||
// 加载依赖(按顺序)
|
||||
require('./export.js'); // 输出接口
|
||||
require('./import.js'); // 输入接口
|
||||
require('./rpc/RpcHandler.js'); // RPC处理器
|
||||
// ... 其他依赖
|
||||
|
||||
// 定义RPC方法
|
||||
mod_jinxianmahjong.player_draw = function(pack) {
|
||||
// 处理玩家摸牌请求
|
||||
};
|
||||
```
|
||||
|
||||
#### 2️⃣ export.js - 输出接口
|
||||
|
||||
**职责**:框架调用子游戏的标准接口
|
||||
|
||||
**必需的8个接口**:
|
||||
1. `get_needroomcard` - 创建房间所需房卡
|
||||
2. `get_asetcount` - 游戏局数
|
||||
3. `get_needroomcard_joinroom` - 加入房间所需房卡
|
||||
4. `makewar` - 开战(游戏开始)
|
||||
5. `get_deskinfo` - 获取牌桌信息(断线重连)
|
||||
6. `get_disbandRoom` - 解散房间
|
||||
7. `player_enter` - 玩家进入
|
||||
8. `player_leave` - 玩家离开
|
||||
|
||||
**实现模式**:
|
||||
```javascript
|
||||
var cls_jinxianmahjong_export = {
|
||||
new: function() {
|
||||
var exp = {};
|
||||
|
||||
exp.get_needroomcard = function(roomtype, o_game_config) {
|
||||
// 根据roomtype返回所需房卡数
|
||||
return 1; // 示例
|
||||
};
|
||||
|
||||
exp.makewar = function(o_room, o_game_config) {
|
||||
// 创建游戏桌对象
|
||||
var o_desk = createDesk(o_room);
|
||||
o_room.o_desk = o_desk;
|
||||
o_desk.o_room = o_room;
|
||||
|
||||
// 返回开战数据包
|
||||
return {
|
||||
app: "youle",
|
||||
route: "jinxianmahjong",
|
||||
rpc: "makewar",
|
||||
data: { /* 开战数据 */ }
|
||||
};
|
||||
};
|
||||
|
||||
// ... 其他6个接口
|
||||
|
||||
return exp;
|
||||
}
|
||||
};
|
||||
|
||||
// 挂载到模块
|
||||
mod_jinxianmahjong.export = cls_jinxianmahjong_export.new();
|
||||
```
|
||||
|
||||
#### 3️⃣ import.js - 输入接口
|
||||
|
||||
**职责**:子游戏调用框架服务
|
||||
|
||||
**核心的4个接口**:
|
||||
1. `check_player` - 验证玩家身份和位置
|
||||
2. `deduct_roomcard` - 扣除房卡
|
||||
3. `save_grade` - 保存游戏成绩
|
||||
4. `finish_gametask` - 完成游戏任务
|
||||
|
||||
**实现模式**:
|
||||
```javascript
|
||||
var cls_jinxianmahjong_import = {
|
||||
new: function() {
|
||||
var imp = {};
|
||||
|
||||
imp.check_player = function(agentid, gameid, roomcode, seat, playerid, conmode, fromid) {
|
||||
// 调用框架验证服务
|
||||
return mod_jinxianmahjong.app.youle_room.export.check_player(
|
||||
agentid, gameid, roomcode, seat, playerid, conmode, fromid
|
||||
);
|
||||
};
|
||||
|
||||
imp.deduct_roomcard = function(o_room) {
|
||||
// ⚠️ 必须在第一小局结算时调用
|
||||
return mod_jinxianmahjong.app.youle_room.export.deduct_roomcard(o_room);
|
||||
};
|
||||
|
||||
imp.save_grade = function(o_room, o_gameinfo1, o_gameinfo2, freeroomflag) {
|
||||
// ⚠️ 必须在大局结束时调用
|
||||
mod_jinxianmahjong.app.youle_room.export.save_grade(
|
||||
o_room, o_gameinfo1, o_gameinfo2, freeroomflag
|
||||
);
|
||||
};
|
||||
|
||||
// ... 其他接口
|
||||
|
||||
return imp;
|
||||
}
|
||||
};
|
||||
|
||||
// 挂载到模块
|
||||
mod_jinxianmahjong.import = cls_jinxianmahjong_import.new();
|
||||
```
|
||||
|
||||
### 3.3 文件加载顺序
|
||||
|
||||
**严格的加载顺序**(不可变更):
|
||||
|
||||
```
|
||||
1. mod.js # 首先加载,创建模块实例
|
||||
↓
|
||||
2. export.js # 加载输出接口
|
||||
↓
|
||||
3. import.js # 加载输入接口
|
||||
↓
|
||||
4. RpcHandler.js # 加载RPC处理器
|
||||
↓
|
||||
5. 其他业务文件 # 加载游戏逻辑
|
||||
```
|
||||
|
||||
**为什么顺序重要**:
|
||||
- `export.js`和`import.js`在模块初始化时就需要
|
||||
- 后续文件可能依赖这两个接口
|
||||
- 错误的顺序会导致`undefined`错误
|
||||
|
||||
---
|
||||
|
||||
## 4. 模块加载机制
|
||||
|
||||
### 4.1 双环境加载支持
|
||||
|
||||
友乐游戏框架支持两种运行环境:
|
||||
|
||||
#### Node.js环境(服务器/测试)
|
||||
```javascript
|
||||
if (typeof require !== 'undefined' && typeof module !== 'undefined') {
|
||||
// Node.js环境:使用require同步加载
|
||||
require('./export.js');
|
||||
require('./import.js');
|
||||
require('./rpc/RpcHandler.js');
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 友乐平台环境(生产服务器)
|
||||
```javascript
|
||||
else if (typeof min_loadJsFile !== 'undefined') {
|
||||
// 友乐平台:使用min_loadJsFile异步加载
|
||||
min_loadJsFile("games2/jinxianmahjong/export.js", function() {
|
||||
min_loadJsFile("games2/jinxianmahjong/import.js", function() {
|
||||
min_loadJsFile("games2/jinxianmahjong/rpc/RpcHandler.js", function() {
|
||||
// 嵌套回调加载
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 模块初始化
|
||||
|
||||
```javascript
|
||||
function initializeModule() {
|
||||
console.log("[mod_jinxianmahjong] 模块初始化开始");
|
||||
|
||||
// 1. 验证必需接口
|
||||
if (!mod_jinxianmahjong.export) {
|
||||
throw new Error("export接口未加载");
|
||||
}
|
||||
if (!mod_jinxianmahjong.import) {
|
||||
throw new Error("import接口未加载");
|
||||
}
|
||||
|
||||
// 2. 设置就绪状态
|
||||
mod_jinxianmahjong.isReady = true;
|
||||
mod_jinxianmahjong.loadTime = new Date();
|
||||
|
||||
console.log("[mod_jinxianmahjong] ✅ 模块加载完成");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 数据包协议基础
|
||||
|
||||
### 5.1 统一包结构
|
||||
|
||||
所有数据包必须遵循以下结构:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"app": "youle", // 应用标识(固定为"youle")
|
||||
"route": "jinxianmahjong", // 路由模块名(游戏ID)
|
||||
"rpc": "player_draw", // RPC方法名
|
||||
"data": { // 业务数据
|
||||
"agentid": "agent001",
|
||||
"playerid": 12345,
|
||||
"gameid": "jinxianmahjong",
|
||||
"roomcode": 100001,
|
||||
"seat": 0,
|
||||
// ... 其他业务参数
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 三层路由机制
|
||||
|
||||
```
|
||||
客户端发送数据包
|
||||
↓
|
||||
【1】packet.js(网络层)
|
||||
↓ 根据app字段路由
|
||||
【2】youle_app(应用层)
|
||||
↓ 根据route字段路由
|
||||
【3】mod_jinxianmahjong(模块层)
|
||||
↓ 根据rpc字段调用
|
||||
【4】mod_jinxianmahjong.player_draw(pack)
|
||||
↓
|
||||
执行游戏逻辑
|
||||
```
|
||||
|
||||
**路由过程**:
|
||||
1. **packet.js**:接收网络数据包,解析app字段
|
||||
2. **youle_app**:根据route字段找到对应游戏模块
|
||||
3. **mod_jinxianmahjong**:根据rpc字段调用对应方法
|
||||
4. **RPC方法**:执行具体游戏逻辑
|
||||
|
||||
### 5.3 RPC方法标准模板
|
||||
|
||||
```javascript
|
||||
mod_jinxianmahjong.player_draw = function(pack) {
|
||||
// 1. 提取参数
|
||||
var agentid = pack.data.agentid;
|
||||
var playerid = parseInt(pack.data.playerid);
|
||||
var gameid = pack.data.gameid;
|
||||
var roomcode = parseInt(pack.data.roomcode);
|
||||
var seat = parseInt(pack.data.seat);
|
||||
|
||||
// 2. 验证玩家(必须)
|
||||
var o_room = mod_jinxianmahjong.import.check_player(
|
||||
agentid, gameid, roomcode, seat, playerid,
|
||||
pack.conmode, pack.fromid
|
||||
);
|
||||
if (!o_room) {
|
||||
return; // 验证失败
|
||||
}
|
||||
|
||||
// 3. 获取游戏桌对象
|
||||
var o_desk = o_room.o_desk;
|
||||
|
||||
// 4. 执行业务逻辑
|
||||
var result = o_desk.gameService.playerDraw(seat);
|
||||
|
||||
// 5. 构造响应包
|
||||
var msg = {
|
||||
app: "youle",
|
||||
route: "jinxianmahjong",
|
||||
rpc: "player_draw_result",
|
||||
data: {
|
||||
seat: seat,
|
||||
card: result.card,
|
||||
// ...
|
||||
}
|
||||
};
|
||||
|
||||
// 6. 发送响应
|
||||
o_room.method.sendpack_toall(msg);
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 开发环境与兼容性
|
||||
|
||||
### 6.1 ES5语法规范
|
||||
|
||||
**必须遵循ES5语法**,不使用任何ES6+特性:
|
||||
|
||||
✅ **允许使用**:
|
||||
```javascript
|
||||
// 函数声明
|
||||
function myFunction() { }
|
||||
|
||||
// 变量声明
|
||||
var myVar = 123;
|
||||
|
||||
// 对象字面量
|
||||
var obj = {
|
||||
key: 'value',
|
||||
method: function() { }
|
||||
};
|
||||
|
||||
// 数组操作
|
||||
var arr = [1, 2, 3];
|
||||
arr.push(4);
|
||||
arr.forEach(function(item) { });
|
||||
|
||||
// 原型继承
|
||||
function MyClass() { }
|
||||
MyClass.prototype.method = function() { };
|
||||
```
|
||||
|
||||
❌ **禁止使用**:
|
||||
```javascript
|
||||
// 箭头函数(ES6)
|
||||
const func = () => { };
|
||||
|
||||
// let/const(ES6)
|
||||
let myVar = 123;
|
||||
const MY_CONST = 456;
|
||||
|
||||
// 类语法(ES6)
|
||||
class MyClass { }
|
||||
|
||||
// 模板字符串(ES6)
|
||||
var str = `Hello ${name}`;
|
||||
|
||||
// 解构赋值(ES6)
|
||||
var {x, y} = point;
|
||||
|
||||
// async/await(ES7)
|
||||
async function func() { }
|
||||
```
|
||||
|
||||
### 6.2 环境检测
|
||||
|
||||
```javascript
|
||||
// 检测Node.js环境
|
||||
if (typeof require !== 'undefined' && typeof module !== 'undefined') {
|
||||
// Node.js环境
|
||||
}
|
||||
|
||||
// 检测浏览器环境
|
||||
if (typeof window !== 'undefined') {
|
||||
// 浏览器环境
|
||||
}
|
||||
|
||||
// 检测友乐平台环境
|
||||
if (typeof min_loadJsFile !== 'undefined') {
|
||||
// 友乐平台环境
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 兼容性要求
|
||||
|
||||
| 特性 | Node.js环境 | 浏览器环境 | 要求 |
|
||||
|-----|------------|-----------|------|
|
||||
| **语法** | ES5 | ES5 | 不使用ES6+特性 |
|
||||
| **模块系统** | require() | `<script>`标签 | 双环境兼容 |
|
||||
| **全局对象** | global | window | 使用条件判断 |
|
||||
| **文件系统** | fs模块 | ❌ 不可用 | 共享代码不能依赖 |
|
||||
| **DOM API** | ❌ 不可用 | document等 | 共享代码不能依赖 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 关键概念总结
|
||||
|
||||
### 7.1 核心术语
|
||||
|
||||
| 术语 | 含义 | 重要性 |
|
||||
|-----|------|-------|
|
||||
| **mod** | 游戏模块实例(如mod_jinxianmahjong) | ⭐⭐⭐⭐⭐ |
|
||||
| **export** | 框架调用子游戏的接口集合 | ⭐⭐⭐⭐⭐ |
|
||||
| **import** | 子游戏调用框架的接口集合 | ⭐⭐⭐⭐⭐ |
|
||||
| **RPC** | 远程过程调用,客户端调用服务端方法 | ⭐⭐⭐⭐⭐ |
|
||||
| **o_room** | 房间对象,管理房间状态和玩家 | ⭐⭐⭐⭐ |
|
||||
| **o_desk** | 游戏桌对象,管理具体游戏状态 | ⭐⭐⭐⭐ |
|
||||
| **roomtype** | 房间类型配置数组(局数、玩法等) | ⭐⭐⭐ |
|
||||
| **pack** | 数据包对象,包含app、route、rpc、data | ⭐⭐⭐⭐⭐ |
|
||||
|
||||
### 7.2 开发要点
|
||||
|
||||
1. **严格遵循三文件架构**:mod.js、export.js、import.js
|
||||
2. **加载顺序不可变更**:export → import → 其他文件
|
||||
3. **使用ES5语法**:确保浏览器和Node.js双环境兼容
|
||||
4. **理解前后端分离**:通过网络通信,不是函数调用
|
||||
5. **掌握RPC机制**:packet.js → app → mod → RPC方法
|
||||
6. **注意调用时机**:deduct_roomcard(第一局结算)、save_grade(大局结束)
|
||||
|
||||
---
|
||||
|
||||
## 8. 相关文档
|
||||
|
||||
- [01-Export接口说明](./01-Export接口说明.md) - 详细的8个必需接口说明
|
||||
- [02-Import接口说明](./02-Import接口说明.md) - 详细的4个框架服务接口
|
||||
- [03-RPC处理机制](./03-RPC处理机制.md) - RPC路由和处理流程
|
||||
- [08-游戏流程概述](../architecture/08-游戏流程概述.md) - 完整游戏流程说明
|
||||
|
||||
---
|
||||
|
||||
## 9. 快速上手
|
||||
|
||||
### 9.1 创建新游戏模块的步骤
|
||||
|
||||
1. **创建游戏目录**:`server/games2/yourgame/`
|
||||
2. **创建mod.js**:定义模块实例和RPC方法
|
||||
3. **创建export.js**:实现8个必需接口
|
||||
4. **创建import.js**:封装4个框架接口
|
||||
5. **创建RPC处理器**:处理客户端请求
|
||||
6. **创建游戏逻辑**:实现具体游戏功能
|
||||
7. **测试验证**:确保接口正确调用
|
||||
|
||||
### 9.2 常见问题
|
||||
|
||||
**Q: export和import的区别?**
|
||||
A: export是框架调用子游戏(框架→游戏),import是子游戏调用框架(游戏→框架)。
|
||||
|
||||
**Q: 为什么必须使用ES5语法?**
|
||||
A: 客户端部署在浏览器中,需要兼容老版本浏览器。ES5语法兼容性最好。
|
||||
|
||||
**Q: 什么时候调用deduct_roomcard?**
|
||||
A: 必须在第一小局结算时调用,不是开战时。
|
||||
|
||||
**Q: o_room和o_desk的关系?**
|
||||
A: o_room是房间对象(框架管理),o_desk是游戏桌对象(子游戏管理),通过`o_room.o_desk`关联。
|
||||
|
||||
---
|
||||
|
||||
**下一步**:阅读[01-Export接口说明](./01-Export接口说明.md)了解8个必需接口的详细实现。
|
||||
Reference in New Issue
Block a user