基于Egret框架的H5小游戏源码完整解析
H5小游戏是以 HTML5 技术为核心,运行在浏览器中的轻量级游戏形式,凭借其跨平台、无需下载安装、即点即玩的特性,迅速在移动端和社交平台中占据一席之地。随着移动互联网的发展,H5小游戏已成为小游戏生态中不可或缺的一部分。从应用场景来看,H5小游戏广泛应用于社交分享、广告推广、节日活动、品牌营销等多个领域。其开发周期短、部署灵活、传播便捷,使得中小团队和个人开发者也能快速进入市场。
简介:本文围绕一个已发布在4399游戏平台的H5小游戏项目,深入剖析其源码结构与开发技术栈。项目采用Egret框架和TypeScript语言开发,结合HTML5与JavaScript实现浏览器端小游戏运行。文章详细讲解了项目中的关键文件,如配置文件、资源目录、编译输出目录、主入口HTML等内容,帮助开发者理解整个H5游戏的开发、构建与发布流程。通过本源码学习,可掌握Egret框架的项目结构设计与资源管理机制,为H5小游戏开发打下坚实基础。 
1. H5小游戏开发概述
H5小游戏是以 HTML5 技术为核心,运行在浏览器中的轻量级游戏形式,凭借其跨平台、无需下载安装、即点即玩的特性,迅速在移动端和社交平台中占据一席之地。随着移动互联网的发展,H5小游戏已成为小游戏生态中不可或缺的一部分。
从应用场景来看,H5小游戏广泛应用于社交分享、广告推广、节日活动、品牌营销等多个领域。其开发周期短、部署灵活、传播便捷,使得中小团队和个人开发者也能快速进入市场。
2. Egret框架介绍与使用
Egret 是一款专为 HTML5 游戏开发设计的开源引擎,基于 TypeScript 构建,具备良好的跨平台兼容性和高效的 2D 渲染能力。其模块化架构和丰富的功能组件,使其成为开发 H5 小游戏的理想选择。本章将深入探讨 Egret 引擎的核心组件、开发环境搭建方法、小游戏示例开发流程,并分析其在不同游戏平台中的适用性与优势。
2.1 Egret 引擎的核心组件
Egret 引擎由多个核心模块组成,这些模块共同支撑了引擎的基础架构和运行机制。理解这些组件有助于开发者更好地掌握引擎的底层原理,并在实际开发中灵活运用。
2.1.1 Egret Runtime 与 egret-core
Egret Runtime 是运行时环境,负责将 Egret 应用程序运行在目标平台上。它提供了一套统一的 API 接口,屏蔽了不同平台(如浏览器、微信小游戏、OPPO 小游戏等)之间的差异,使开发者无需关注底层平台细节。
egret-core 是 Egret 引擎的核心库,包含基础类、事件系统、显示对象管理、资源加载等核心功能。其模块化设计使得开发者可以按需引入功能,从而优化项目体积和性能。
以下是一个使用 egret-core 创建基础显示对象的示例代码:
class GameApp {
public constructor() {
// 初始化舞台
egret.runEgret({ renderMode: "webgl", fpsLabel: null, showPaintRect: false });
// 添加主显示对象
this.init();
}
private init(): void {
let stage = egret.stage;
stage.scaleMode = egret.StageScaleMode.FIXED_WIDTH;
let textField = new egret.TextField();
textField.text = "Hello Egret!";
textField.size = 24;
textField.textColor = 0xFF0000;
textField.x = 100;
textField.y = 100;
stage.addChild(textField);
}
}
new GameApp();
逐行解析:
egret.runEgret({...}):启动 Egret 引擎,设置渲染模式为 WebGL,并关闭帧率显示。egret.stage:获取舞台对象,它是显示对象的根容器。stage.scaleMode = egret.StageScaleMode.FIXED_WIDTH:设置舞台的缩放模式为固定宽度。TextField:创建一个文本对象,设置其内容、字体大小、颜色和位置。stage.addChild(textField):将文本对象添加到舞台上,使其可见。
参数说明:
renderMode: 渲染模式,支持 canvas 和 webgl。fpsLabel: 是否显示帧率信息。showPaintRect: 是否显示绘制区域,用于调试。
2.1.2 Egret Display List 与渲染机制
Egret 使用 Display List(显示列表)机制管理所有可视元素。所有可视对象都必须继承自 DisplayObject ,并添加到显示列表中才能被渲染。
Egret 的显示列表结构类似于树形结构,其中 Stage 是根节点, DisplayObjectContainer 是容器节点,可以包含多个子节点。渲染过程由舞台开始,递归遍历所有子节点,进行绘制。
以下是一个展示显示列表层级结构的流程图:
graph TD
A[Stage] --> B[DisplayObjectContainer]
B --> C[Sprite]
B --> D[Bitmap]
C --> E[TextField]
D --> F[MovieClip]
逻辑分析:
Stage是整个显示列表的根节点。DisplayObjectContainer是容器类,用于组织多个显示对象。Sprite是轻量级容器,常用于组织图形元素。Bitmap表示图像资源。TextField表示文本内容。MovieClip用于播放帧动画。
渲染机制特点:
- 层级管理 :通过 addChild/removeChild 方法控制显示对象的层级。
- 坐标系统 :每个显示对象具有 x/y 坐标,相对于其父容器。
- 自动更新 :每次帧刷新时,会自动重新渲染整个显示列表。
- 性能优化 :隐藏或移除不必要的对象可提升渲染效率。
2.2 Egret 开发环境搭建
搭建一个稳定、高效的开发环境是进行 Egret 开发的第一步。Egret 提供了专用的 IDE —— Egret Wing,同时也支持命令行工具(CLI)进行项目管理。
2.2.1 安装 Egret Wing IDE
Egret Wing 是 Egret 官方提供的集成开发环境,集成了项目创建、代码编辑、调试、资源管理等功能。
安装步骤:
- 访问 Egret 官网 下载 Egret Wing。
- 解压安装包并运行安装程序。
- 安装完成后,启动 Egret Wing,登录 Egret 账号(可选)。
IDE 功能特点:
- 支持 TypeScript 语法高亮与自动补全。
- 集成资源管理器,支持拖拽导入图片、音频等资源。
- 提供项目模板,快速创建 Egret 项目。
- 内置调试器,支持断点调试、变量查看等。
2.2.2 配置项目运行与调试环境
在 Egret Wing 中创建新项目后,需要配置运行和调试环境:
运行配置:
- 在项目属性中设置启动页面为
index.html。 - 选择运行平台(如浏览器、微信小游戏等)。
- 点击“运行”按钮,Egret 会自动编译项目并在浏览器中打开。
调试配置:
- 在代码中设置断点(点击行号左侧)。
- 点击“调试”按钮启动调试模式。
- 使用控制台查看日志输出,使用“变量”窗口查看当前作用域变量。
- 支持逐步执行、跳过函数、进入函数等调试操作。
以下是一个简单的调试示例代码:
class DebugExample {
private count: number = 0;
public start(): void {
this.count = this.increment(this.count); // 设置断点于此行
console.log("Current count: " + this.count);
}
private increment(value: number): number {
return value + 1;
}
}
调试分析:
- 设置断点后,程序会在
this.increment(this.count)处暂停执行。 - 可以查看
value参数的值,并逐步执行函数内部逻辑。 - 控制台输出
Current count: 1,验证函数逻辑是否正确。
2.3 基于 Egret 的小游戏示例开发
通过一个简单的小游戏示例,可以更直观地了解如何使用 Egret 进行项目开发。
2.3.1 创建第一个 Egret 项目
使用 Egret CLI 创建项目:
egret create myGame
该命令会创建一个名为 myGame 的 Egret 项目,包含基本的目录结构和入口文件。
项目结构如下:
myGame/
├── egretProperties.json
├── tsconfig.json
├── index.html
├── src/
│ └── Main.ts
└── resource/
└── assets/
└── icon.png
关键文件说明:
egretProperties.json:Egret 项目配置文件,定义编译目标和资源路径。tsconfig.json:TypeScript 编译配置。src/Main.ts:主程序入口。resource/assets/:资源目录,存放图片、音频等。
2.3.2 添加图形元素与交互逻辑
修改 Main.ts 文件,添加一个可点击的按钮:
class Main extends egret.DisplayObjectContainer {
public constructor() {
super();
this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
}
private onAddToStage(event: egret.Event): void {
let texture = RES.getRes("icon_png");
let button = new egret.Bitmap(texture);
button.x = 100;
button.y = 100;
button.touchEnabled = true;
button.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onClick, this);
this.addChild(button);
}
private onClick(event: egret.TouchEvent): void {
console.log("Button clicked!");
}
}
逻辑分析:
- 使用
RES.getRes()加载资源,前提是资源已添加到resource.json。 - 设置
touchEnabled = true启用触摸交互。 - 添加
TOUCH_TAP事件监听器,绑定onClick回调函数。 - 点击按钮时,控制台输出日志。
参数说明:
ADDED_TO_STAGE: 当对象被添加到舞台时触发。TOUCH_TAP: 触摸点击事件。touchEnabled: 是否启用触摸交互,默认为 false。
2.4 Egret 引擎的优势与适用场景
Egret 相较于其他主流引擎(如 Unity、Cocos)在 H5 小游戏领域具有独特优势,尤其在跨平台适配方面表现优异。
2.4.1 与 Unity、Cocos 引擎的对比
| 特性 | Egret | Unity (WebGL) | Cocos Creator |
|---|---|---|---|
| 开发语言 | TypeScript | C# | JavaScript / TypeScript |
| 渲染性能 | 中等 | 高 | 高 |
| 跨平台支持 | 极佳(浏览器、微信等) | 依赖 WebGL | 支持微信、浏览器等 |
| 学习曲线 | 低 | 中 | 低 |
| 工具链集成 | 自带 Egret Wing IDE | Unity Editor | Cocos Creator IDE |
| 社区活跃度 | 中 | 高 | 高 |
结论分析:
- Egret 更适合 :需要快速上线、跨平台部署、对性能要求中等的小游戏。
- Unity 更适合 :对性能要求极高、3D 游戏、复杂物理交互。
- Cocos 更适合 :2D 游戏开发,尤其是中大型项目。
2.4.2 在小游戏平台的适配性分析
Egret 对主流小游戏平台(如微信小游戏、OPPO 小游戏、百度小游戏)有良好的适配支持。通过 Egret CLI 可一键发布到多个平台:
egret build myGame -t wechat
该命令将项目打包为微信小游戏格式,并生成相应的 game.js 和 project.config.json 文件。
适配特点:
- 微信小游戏 :支持 Canvas 和 WebGL 模式,兼容性良好。
- OPPO 小游戏 :支持本地资源加载和平台 SDK 集成。
- 百度小游戏 :支持热更新和广告接入。
表格:适配平台特性对比
| 平台 | 渲染模式支持 | 广告接入 | 热更新 | 资源加载 |
|---|---|---|---|---|
| 微信小游戏 | Canvas/WebGL | ✅ | ✅ | ✅ |
| OPPO 小游戏 | Canvas | ✅ | ✅ | ✅ |
| 百度小游戏 | Canvas | ✅ | ✅ | ✅ |
总结:
Egret 凭借其轻量级架构、跨平台能力和对 H5 小游戏生态的深度整合,成为开发者构建多端小游戏的首选引擎。下一章将深入探讨 TypeScript 在 H5 游戏开发中的应用,帮助开发者提升代码质量与维护效率。
3. TypeScript在H5游戏中的应用
TypeScript 是 H5 小游戏开发中不可或缺的语言工具,尤其在 Egret 引擎中,它不仅提供了 JavaScript 的全部功能,还引入了类型系统和面向对象编程的支持,使得代码更易于维护、扩展和调试。本章将从 TypeScript 的基础语法入手,逐步深入到其在 H5 游戏项目中的组织方式与编译配置,帮助开发者构建高质量的游戏逻辑结构。
3.1 TypeScript 基础语法与面向对象编程
TypeScript 最大的优势在于其对面向对象编程(OOP)的良好支持。通过类(class)和接口(interface)等结构,开发者可以更清晰地组织游戏逻辑,提升代码的可读性和复用性。
3.1.1 类与接口的定义
在 TypeScript 中, 类 用于定义对象的结构和行为,而 接口 则用于定义对象的契约(即形状),常用于参数类型检查和模块间通信。
示例代码:定义一个游戏角色类
// 定义角色接口
interface ICharacter {
name: string;
hp: number;
attack(): void;
}
// 实现角色类
class Player implements ICharacter {
name: string;
hp: number;
constructor(name: string, hp: number) {
this.name = name;
this.hp = hp;
}
attack(): void {
console.log(`${this.name} 发动了攻击`);
}
}
// 使用角色类
const hero = new Player("Hero", 100);
hero.attack(); // 输出:Hero 发动了攻击
代码逻辑分析:
-
interface ICharacter:定义了一个接口,要求实现它的类必须具有name、hp属性和attack()方法。 -
class Player implements ICharacter:声明一个类并实现该接口,确保其结构符合定义。 - 构造函数
constructor:用于初始化对象属性。 - 方法
attack():实现攻击行为,输出角色名称和动作。
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
name |
string |
角色的名称 |
hp |
number |
角色的生命值 |
attack() |
void |
攻击行为函数,无返回值 |
3.1.2 泛型与装饰器的使用
TypeScript 提供了泛型(Generics)和装饰器(Decorators)功能,极大地增强了代码的灵活性和可复用性。
示例代码:使用泛型定义通用数据容器
// 泛型类
class Container<T> {
private items: T[] = [];
add(item: T): void {
this.items.push(item);
}
get(index: number): T {
return this.items[index];
}
}
// 使用泛型容器
const playerContainer = new Container<Player>();
playerContainer.add(new Player("Warrior", 80));
const warrior = playerContainer.get(0);
warrior.attack(); // 输出:Warrior 发动了攻击
代码逻辑分析:
-
class Container<T>:定义一个泛型类,T表示任意类型。 -
add(item: T):添加一个元素到容器中。 -
get(index: number): T:根据索引获取元素。
示例代码:使用装饰器记录方法执行日志
function LogMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`调用方法: ${propertyKey},参数: ${JSON.stringify(args)}`);
const result = originalMethod.apply(this, args);
console.log(`方法 ${propertyKey} 执行完毕,返回值: ${result}`);
return result;
};
return descriptor;
}
class GameService {
@LogMethod
startGame(playerName: string): string {
return `${playerName} 开始了游戏`;
}
}
const service = new GameService();
service.startGame("Alice");
输出结果:
调用方法: startGame,参数: ["Alice"]
方法 startGame 执行完毕,返回值: Alice 开始了游戏
装饰器机制说明:
- 装饰器函数
LogMethod:在方法调用前后添加日志输出。 -
descriptor.value:重写原始方法,在调用前后插入日志。 -
apply方法 :确保原始方法在正确的上下文中执行。
3.2 TypeScript 与 JavaScript 的兼容性
TypeScript 是 JavaScript 的超集,这意味着所有合法的 JavaScript 代码都是合法的 TypeScript 代码。这一特性使得开发者可以逐步迁移到 TypeScript,同时保留已有 JavaScript 代码。
3.2.1 类型推断与类型注解
TypeScript 的类型系统支持 类型推断 (Type Inference)和 类型注解 (Type Annotation),帮助开发者在编写代码时避免类型错误。
示例代码:类型推断
let count = 10; // 类型推断为 number
count = "ten"; // 编译错误:不能将类型 "string" 分配给类型 "number"
示例代码:类型注解
let score: number = 90;
score = "high"; // 编译错误
类型注解的优势:
| 特性 | 说明 |
|---|---|
| 明确类型 | 使代码意图更清晰 |
| 避免错误 | 在编译时检测类型不匹配 |
| 提高可读性 | 易于他人理解和维护 |
3.2.2 模块化编程与命名空间管理
TypeScript 支持模块化编程,通过 import 和 export 来组织代码结构,避免命名冲突。
示例代码:使用模块导出和导入
// gameModule.ts
export class Game {
start() {
console.log("游戏开始");
}
}
// main.ts
import { Game } from "./gameModule";
const game = new Game();
game.start(); // 输出:游戏开始
使用命名空间防止冲突
namespace GameUtils {
export function formatTime(seconds: number): string {
return `${seconds}s`;
}
}
console.log(GameUtils.formatTime(60)); // 输出:60s
3.3 在 Egret 项目中组织 TypeScript 代码
良好的代码组织结构对于大型 H5 小游戏项目至关重要。Egret 推荐使用模块化与类结构来管理游戏逻辑。
3.3.1 使用模块组织游戏逻辑
建议将游戏逻辑划分为多个模块,例如: PlayerModule 、 SceneModule 、 UIManager 等。
示例代码:组织模块结构
src/
├── modules/
│ ├── player/
│ │ └── Player.ts
│ ├── scene/
│ │ └── SceneManager.ts
│ └── ui/
│ └── UIManager.ts
└── main.ts
模块调用示例
// main.ts
import { Player } from "./modules/player/Player";
import { SceneManager } from "./modules/scene/SceneManager";
const player = new Player("Knight", 100);
SceneManager.loadScene("mainMenu");
3.3.2 管理游戏状态与场景切换
H5 游戏通常包含多个状态(如主菜单、战斗、设置等),可以通过状态机(State Machine)来管理。
使用枚举定义游戏状态
enum GameState {
MainMenu,
Playing,
Paused,
GameOver
}
实现状态切换逻辑
class GameManager {
private currentState: GameState = GameState.MainMenu;
changeState(newState: GameState): void {
this.currentState = newState;
this.onStateChanged();
}
private onStateChanged(): void {
switch (this.currentState) {
case GameState.MainMenu:
console.log("进入主菜单");
break;
case GameState.Playing:
console.log("开始游戏");
break;
case GameState.Paused:
console.log("游戏暂停");
break;
case GameState.GameOver:
console.log("游戏结束");
break;
}
}
}
const gameManager = new GameManager();
gameManager.changeState(GameState.Playing); // 输出:开始游戏
状态机流程图(Mermaid)
stateDiagram-v2
[*] --> MainMenu
MainMenu --> Playing : 开始游戏
Playing --> Paused : 暂停
Paused --> Playing : 恢复
Playing --> GameOver : 游戏结束
GameOver --> MainMenu : 返回主菜单
3.4 TypeScript 的编译配置与调试技巧
TypeScript 通过 tsconfig.json 文件进行编译配置,同时支持源码调试功能,提升开发效率。
3.4.1 使用 tsconfig.json 配置编译选项
tsconfig.json 是 TypeScript 项目的配置文件,控制编译器的行为。
示例 tsconfig.json 文件
{
"compilerOptions": {
"target": "ES2015",
"module": "ESNext",
"lib": ["DOM", "ES2015"],
"outDir": "./bin",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outFile": "./bin/game.js"
},
"include": ["src/**/*"]
}
配置说明:
| 配置项 | 值 | 说明 |
|---|---|---|
target |
ES2015 | 编译目标为 ES2015 版本 |
module |
ESNext | 使用现代模块系统 |
lib |
DOM, ES2015 | 支持 DOM 操作和 ES2015 特性 |
outDir |
./bin | 编译输出目录 |
rootDir |
./src | 源码目录 |
strict |
true | 启用严格类型检查 |
esModuleInterop |
true | 支持 ES 模块互操作 |
skipLibCheck |
true | 忽略库类型检查 |
3.4.2 浏览器调试与断点设置
TypeScript 支持生成 source map,使得在浏览器中可以直接调试源码。
调试流程:
- 在
tsconfig.json中启用 source map:
"sourceMap": true,
"outFile": "./bin/game.js"
- 编译 TypeScript 项目:
tsc
- 在浏览器中打开
index.html,打开开发者工具(F12),在Sources面板中找到.ts源文件,设置断点。
断点调试示例:
function calculateScore(killCount: number): number {
let score = 0;
for (let i = 0; i < killCount; i++) {
score += 10; // 设置断点在此行
}
return score;
}
console.log(calculateScore(5)); // 应输出 50
小结(非总结性语句)
通过本章内容可以看出,TypeScript 为 H5 小游戏开发提供了强大的语言支持与开发工具链。从基础语法到高级特性,再到项目结构组织与调试配置,开发者可以借助 TypeScript 构建出结构清晰、维护性强、性能优越的游戏项目。下一章将深入解析 H5 小游戏中的核心配置文件,进一步提升项目管理能力。
4. H5小游戏核心配置文件解析
在H5小游戏开发中,合理配置和管理项目文件结构是确保项目可维护性、构建效率和运行性能的关键。Egret引擎通过多个核心配置文件对项目的结构、资源加载、编译流程和开发工具进行控制。深入理解这些配置文件,有助于开发者优化项目组织方式、提升调试效率,并在多平台部署中保持良好的兼容性。
本章将从四个核心配置文件入手: egretProperties.json 、 tsconfig.json 、 wingProperties.json 和 README.md 。我们将逐个解析其结构与作用,展示实际配置示例,并结合代码片段与流程图说明其对项目构建和运行的影响。
4.1 egretProperties.json 配置详解
egretProperties.json 是 Egret 项目的核心配置文件之一,它定义了项目的编译目标、资源路径、运行时类型等关键参数。
4.1.1 runtimeType 与编译目标设定
runtimeType 指定了项目运行的目标环境。例如,设置为 "web" 表示游戏将运行在浏览器中,而设置为 "native" 则用于 Egret Native 打包的原生应用。
{
"runtimeType": "web"
}
- 参数说明 :
"web":适用于浏览器环境,适用于H5小游戏。"native":适用于使用 Egret Native 构建的原生应用。"miniGame":用于微信小游戏等平台。
该配置影响后续构建命令的执行逻辑。例如,在构建微信小游戏时,Egret CLI 会根据此参数选择不同的打包流程。
4.1.2 资源路径与加载策略配置
资源路径通过 resourcePath 指定,Egret 默认使用 resource 文件夹作为资源目录。你也可以自定义路径,如:
{
"resourcePath": "assets"
}
此外,资源加载策略通过 resourceLoadType 设置,支持以下几种模式:
| 加载策略 | 说明 |
|---|---|
"merge" |
合并所有资源为一个文件,适合资源较少的小游戏 |
"version" |
使用版本号控制资源缓存,适合资源更新频繁的项目 |
"default" |
默认策略,资源按需加载 |
{
"resourceLoadType": "version"
}
配置流程图
graph TD
A[egretProperties.json] --> B{runtimeType}
B -->|web| C[编译为H5项目]
B -->|native| D[构建为原生应用]
B -->|miniGame| E[适配微信小游戏平台]
A --> F{resourceLoadType}
F -->|merge| G[资源合并加载]
F -->|version| H[带版本号缓存策略]
F -->|default| I[按需加载资源]
4.2 tsconfig.json 编译配置说明
tsconfig.json 是 TypeScript 项目的标准配置文件,用于控制 TypeScript 编译器的行为。Egret 引擎默认使用该文件进行代码编译。
4.2.1 target、module 与 lib 的设置
这三个字段决定了编译后的 JavaScript 版本和模块格式。
{
"compilerOptions": {
"target": "ES5",
"module": "ESNext",
"lib": ["ES2017", "DOM"]
}
}
- target :指定编译目标版本。
ES5保证兼容性较好,适合广泛浏览器支持。 - module :指定模块打包方式。
ESNext支持现代模块加载方式。 - lib :定义 TypeScript 编译时引入的库类型。
DOM支持浏览器API。
4.2.2 outDir 与 rootDir 的作用
outDir:指定编译输出目录,默认为bin-debug。rootDir:指定 TypeScript 源代码目录,默认为src。
示例配置:
{
"compilerOptions": {
"outDir": "./bin-debug",
"rootDir": "./src"
}
}
这两个配置直接影响编译后的目录结构和资源组织方式。如果项目结构复杂,建议明确指定路径,避免编译混乱。
代码示例解析
// src/Main.ts
class Main extends egret.DisplayObjectContainer {
public constructor() {
super();
this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
}
private onAddToStage(event: egret.Event): void {
let label = new egret.TextField();
label.text = "Hello, Egret!";
label.x = 100;
label.y = 100;
this.addChild(label);
}
}
该代码定义了一个基础的 Egret 场景,编译时将被转换为 JS 文件,并输出到 bin-debug 目录中。
4.3 wingProperties.json 与开发工具配置
wingProperties.json 是 Egret Wing IDE 的配置文件,用于控制开发工具的行为,如默认启动页面、插件配置等。
4.3.1 默认启动页面与调试设置
{
"startPage": "index.html",
"debugger": {
"enabled": true,
"port": 9999
}
}
- startPage :指定默认启动的 HTML 页面,通常是
index.html。 - debugger :启用调试模式,并设置调试端口。
该配置影响开发者在 IDE 中运行项目时的加载流程和调试方式。
4.3.2 项目构建参数与插件配置
Egret 插件如资源管理器、代码模板等可以通过 plugins 字段进行配置:
{
"plugins": {
"resourcemanager": {
"enabled": true
},
"template": {
"type": "game"
}
}
}
- resourcemanager.enabled :是否启用资源管理插件。
- template.type :项目模板类型,
game表示小游戏项目。
插件配置流程图
graph TD
A[wingProperties.json] --> B[启动页面配置]
B --> C[startPage=index.html]
A --> D[调试器配置]
D --> E[启用调试端口9999]
A --> F[插件配置]
F --> G[resourcemanager: 启用]
F --> H[template: game]
4.4 README.md 项目说明文档规范
README.md 是项目根目录下的说明文档,用于描述项目结构、安装步骤、开发规范等内容,尤其在团队协作中至关重要。
4.4.1 项目结构说明与依赖安装指南
一个典型的 README 内容如下:
# My Egret Game
## 项目结构
- `src/`:TypeScript 源代码
- `resource/`:游戏资源文件
- `bin-debug/`:编译输出目录
- `index.html`:游戏入口页面
## 安装依赖
1. 安装 Egret CLI:`npm install -g egret`
2. 初始化项目:`egret init`
3. 安装资源插件:`egret install resourcemanager`
4.4.2 开发与部署流程文档编写规范
建议在 README 中加入开发流程说明:
## 开发流程
1. 编写 TypeScript 代码至 `src/`
2. 添加资源文件至 `resource/`
3. 使用 `egret run` 启动本地服务器调试
4. 使用 `egret build` 构建发布版本
## 部署流程
1. 发布到微信小游戏:
- 安装微信开发者工具
- 导出为小程序格式
- 提交审核
2. 发布到 H5 平台:
- 使用 `egret publish` 生成优化版本
- 上传至游戏平台
总结
本章深入解析了 Egret 项目中四个关键配置文件的作用与配置方式:
- egretProperties.json 控制项目运行环境和资源加载策略;
- tsconfig.json 决定 TypeScript 编译行为;
- wingProperties.json 管理 IDE 行为与插件;
- README.md 提供项目结构说明与开发部署流程。
通过合理配置这些文件,开发者可以优化项目结构、提升构建效率,并在多平台部署中保持一致性。下一章我们将继续探讨 H5 小游戏的目录结构与资源管理机制,进一步提升项目组织能力。
5. H5小游戏目录结构与资源管理
良好的项目结构是 H5 小游戏长期维护与扩展的基础,同时资源管理机制直接影响游戏性能和加载效率。本章将围绕 H5 小游戏的典型目录结构展开,深入解析 src 、 resource 、 bin-debug 和 index.html 等关键目录和文件的作用与配置方式,帮助开发者构建清晰、高效的项目结构。
5.1 src 目录结构与核心逻辑分析
src 是 H5 小游戏的核心代码目录,包含所有 TypeScript 编写的逻辑代码。其结构设计直接影响项目的可维护性、可扩展性以及团队协作效率。
5.1.1 核心类结构设计与模块划分
在 Egret 项目中, src 目录通常包含如下结构:
src/
├── Main.ts
├── modules/
│ ├── game/
│ │ ├── GameScene.ts
│ │ └── Player.ts
│ ├── ui/
│ │ ├── UIManager.ts
│ │ └── MenuView.ts
│ └── utils/
│ └── TimerUtils.ts
└── config/
└── GameConfig.ts
- Main.ts :程序入口文件,负责初始化游戏主舞台、加载资源并启动主场景。
- modules/ :按功能模块划分的游戏逻辑,例如
game模块负责核心游戏逻辑,ui模块处理界面交互,utils存放通用工具类。 - config/ :游戏配置文件,如分辨率适配、关卡数据、资源路径等。
代码示例:GameScene.ts
class GameScene extends egret.DisplayObjectContainer {
private player: Player;
constructor() {
super();
this.init();
}
private init(): void {
this.player = new Player();
this.addChild(this.player);
}
}
逐行解读:
1. class GameScene extends egret.DisplayObjectContainer :定义游戏主场景类,继承自 Egret 的容器类。
2. private player: Player; :声明一个 Player 类型的私有变量。
3. constructor() :构造函数,执行初始化逻辑。
4. init() :初始化方法,创建玩家对象并添加到场景中。
5.1.2 主程序入口与游戏初始化流程
主程序入口通常为 Main.ts 文件,负责启动整个游戏流程。
代码示例:Main.ts
class Main extends egret.DisplayObjectContainer {
public constructor() {
super();
this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
}
private onAddToStage(event: egret.Event): void {
this.removeEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);
// 设置舞台尺寸
this.stage.scaleMode = egret.StageScaleMode.FIXED_WIDTH;
// 加载资源配置文件
RES.addEventListener(RES.ResourceEvent.CONFIG_COMPLETE, this.onConfigComplete, this);
RES.loadConfig("resource/default.res.json", "resource/");
}
private onConfigComplete(event: RES.ResourceEvent): void {
RES.removeEventListener(RES.ResourceEvent.CONFIG_COMPLETE, this.onConfigComplete, this);
// 加载资源组
RES.addEventListener(RES.ResourceEvent.GROUP_COMPLETE, this.onGroupComplete, this);
RES.loadGroup("preload");
}
private onGroupComplete(event: RES.ResourceEvent): void {
if (event.groupName === "preload") {
RES.removeEventListener(RES.ResourceEvent.GROUP_COMPLETE, this.onGroupComplete, this);
// 启动主场景
const gameScene = new GameScene();
this.addChild(gameScene);
}
}
}
逻辑分析:
- onAddToStage :监听舞台加载完成事件,设置舞台缩放模式并加载资源配置。
- onConfigComplete :资源配置加载完成后,开始加载资源组。
- onGroupComplete :资源组加载完成后,创建并添加主场景。
5.2 resource 资源目录管理机制
资源目录 resource 是 H5 小游戏中存储所有静态资源的地方,包括图片、音频、字体、纹理集等。合理的资源管理能够提升加载效率,降低内存占用。
5.2.1 图片、音频与纹理集配置
资源目录结构通常如下:
resource/
├── assets/
│ ├── images/
│ ├── audios/
│ └── fonts/
├── config/
│ └── default.res.json
└── texture/
└── atlas/
└── main_atlas.json
- assets/ :存放原始资源文件,如 PNG 图片、MP3 音频、TTF 字体等。
- config/ :资源配置文件,定义资源组与加载策略。
- texture/ :纹理集资源,用于优化图片加载与渲染性能。
图片资源加载示例:
let texture: egret.Texture = RES.getRes("bg_jpg");
let bitmap: egret.Bitmap = new egret.Bitmap(texture);
this.addChild(bitmap);
参数说明:
- "bg_jpg" :为资源配置中定义的资源 ID,通常在 default.res.json 中配置。
5.2.2 resource.json 资源加载清单解析
default.res.json 是资源配置的核心文件,用于定义资源组、路径与类型。
示例配置:
{
"groups": [
{
"keys": "bg_jpg,btn_play_png,btn_exit_png",
"name": "preload"
}
],
"resources": [
{
"type": "image",
"url": "assets/images/bg.jpg",
"name": "bg_jpg"
},
{
"type": "image",
"url": "assets/images/btn_play.png",
"name": "btn_play_png"
},
{
"type": "image",
"url": "assets/images/btn_exit.png",
"name": "btn_exit_png"
}
]
}
参数说明:
- "groups" :资源组定义, preload 表示预加载资源组。
- "resources" :资源项列表,每个资源包含类型、URL 和唯一标识名。
流程图:
graph TD
A[开始加载资源配置] --> B[读取 default.res.json]
B --> C[解析资源组 preload]
C --> D[加载资源组中的资源]
D --> E[资源加载完成事件触发]
E --> F[进入主游戏场景]
5.3 bin-debug 目录作用与编译流程
bin-debug 是 Egret 编译后的输出目录,主要用于调试和本地测试。该目录包含完整的 HTML5 项目结构,适合在浏览器中直接运行。
5.3.1 编译输出目录结构说明
编译后 bin-debug 目录结构如下:
bin-debug/
├── index.html
├── resource/
│ └── ...(资源文件)
├── egret/
│ └── egret.js
├── main.js
└── assets/
└── ...(编译后的资源)
- main.js :编译后的 JavaScript 入口文件。
- egret/ :Egret 引擎的核心 JS 文件。
- resource/ :资源文件复制目录,与
src中的resource对应。
5.3.2 Debug 模式下的资源加载与性能分析
Debug 模式下,资源加载路径为原始资源,便于调试和查看资源加载过程。开发者可使用浏览器开发者工具(如 Chrome DevTools)分析加载性能。
浏览器调试技巧:
- 打开 DevTools → Network 面板,查看资源加载耗时。
- 使用 Performance 面板记录并分析帧率、CPU 占用情况。
5.4 index.html 主入口文件解析
index.html 是 H5 小游戏的主入口文件,负责初始化 HTML 页面并加载 Egret 引擎与游戏逻辑。
5.4.1 Canvas 与 DOM 元素初始化
标准 index.html 示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Egret Game</title>
<style>
html, body { margin: 0; padding: 0; overflow: hidden; }
canvas { display: block; }
</style>
</head>
<body>
<script src="egret/egret.js"></script>
<script src="egret/egret-game.js"></script>
<script src="main.js"></script>
</body>
</html>
分析:
- <canvas> :Egret 渲染的目标容器。
- <script src="egret/egret.js"> :引入 Egret 引擎核心库。
- <script src="egret/egret-game.js"> :引入 Egret 游戏框架。
- <script src="main.js"> :游戏逻辑主入口。
5.4.2 加载进度条与错误提示处理
为了提升用户体验, index.html 可集成加载进度条与错误提示功能。
实现方式:
<div id="loading" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #000; color: #fff; text-align: center; padding-top: 200px;">
Loading... <span id="progress">0%</span>
</div>
JavaScript 控制加载进度:
RES.addEventListener(RES.ResourceEvent.ITEM_LOAD_ERROR, () => {
document.getElementById("loading").style.display = "none";
alert("资源加载失败,请刷新重试!");
});
RES.addEventListener(RES.ResourceEvent.GROUP_PROGRESS, (e: RES.ResourceEvent) => {
const percent = Math.floor(e.itemsLoaded / e.itemsTotal * 100);
document.getElementById("progress").innerText = percent + "%";
});
表格:加载状态与处理方式
| 加载状态 | 事件类型 | 处理方式 |
|---|---|---|
| 资源加载失败 | ITEM_LOAD_ERROR | 显示错误提示 |
| 资源组加载进度 | GROUP_PROGRESS | 更新进度条 |
| 资源组加载完成 | GROUP_COMPLETE | 隐藏加载界面并启动游戏 |
通过本章内容的学习,读者应能掌握 H5 小游戏的目录结构设计、资源管理机制以及入口文件配置,从而为开发高性能、易维护的游戏项目打下坚实基础。
6. H5小游戏项目构建与发布实践
完成开发与调试后,构建和发布是将 H5 小游戏推向用户的关键步骤。本章将详细介绍从项目打包到多平台发布、性能优化的全流程,帮助开发者顺利完成上线部署。
6.1 项目打包流程详解
在完成 Egret 项目开发后,使用 Egret CLI 工具可以将项目打包为适用于不同平台的可发布版本。打包流程主要包含资源合并、代码压缩和平台适配等步骤。
6.1.1 使用 Egret CLI 进行项目构建
Egret 提供了命令行工具 egret build 来构建项目。以下是构建命令示例:
egret build myGameProject --runtime html5
myGameProject:项目目录名。--runtime html5:指定目标平台为 HTML5。
执行该命令后,Egret 会将 TypeScript 编译为 JavaScript,并将资源文件打包至 bin-release 目录下。
构建完成后,目录结构如下:
| 文件/目录 | 说明 |
|---|---|
| index.html | 游戏主入口页面 |
| egret.js | 引擎核心库 |
| main.js | 编译后的游戏主程序 |
| resource/ | 所有资源文件(图片、音频等) |
6.1.2 多平台资源适配与优化
不同平台对资源格式、分辨率和加载方式有不同要求。例如,微信小游戏支持 canvas 和 WebGL 渲染模式,而 OPPO 小游戏则要求特定的 SDK 集成。
优化策略包括:
- 使用纹理集(Texture Atlas)减少加载请求;
- 图片使用 webp 格式以减小体积;
- 音频文件进行压缩(如使用 ogg 格式);
- 设置资源加载优先级(resource.json 中配置);
6.2 发布到微信小游戏平台
微信小游戏是 H5 小游戏的重要发布渠道之一。开发者需要使用微信开发者工具进行打包与调试。
6.2.1 微信小游戏开发工具配置
- 打开 微信开发者工具 ;
- 创建新项目,选择“小游戏”模板;
- 将 Egret 构建后的
bin-release文件夹内容复制到微信项目根目录; - 修改
game.js入口文件,确保引擎正确加载; - 启动调试,查看控制台日志。
微信小游戏支持如下关键配置项:
| 配置项 | 值 | 说明 |
|---|---|---|
platform |
wechatgame | 指定平台 |
customUpdate |
true | 自定义资源加载逻辑 |
showFPS |
false | 隐藏帧率显示 |
6.2.2 小程序包结构与审核注意事项
微信小游戏的包结构需符合以下规范:
game.js:游戏主程序;engine/:引擎库文件;res/:资源文件;project.config.json:项目配置文件;
审核注意事项:
- 不得使用网络请求加载外部脚本;
- 图片、音频等资源需上传至平台审核;
- 不能包含敏感词汇或非法内容;
- 游戏启动后需在30秒内加载完成;
6.3 发布到其他 H5 游戏平台
除了微信平台,OPPO、百度等平台也提供了丰富的小游戏分发渠道。
6.3.1 OPPO、百度小游戏平台接入
OPPO 和百度小游戏平台通常基于 HTML5 技术,接入流程如下:
- 在平台开发者后台创建应用;
- 上传构建后的
bin-release文件夹; - 配置启动页面为
index.html; - 集成平台 SDK 实现登录、支付、广告等功能;
- 测试并提交审核。
不同平台的接入文档如下:
| 平台 | 接入文档链接 |
|---|---|
| OPPO小游戏 | OPPO小游戏开发者文档 |
| 百度小游戏 | 百度小游戏开发文档 |
6.3.2 平台 SDK 集成与广告接入
以百度小游戏为例,集成广告的代码如下:
if (window['swan']) {
const bannerAd = swan.createBannerAd({
adUnitId: '你的广告位ID',
style: {
top: 10,
left: 0,
width: 300
}
});
bannerAd.show();
}
该代码检测是否在百度小游戏运行环境,若存在则创建并展示广告条。
6.4 H5 小游戏上线后的性能监控与优化
上线后,开发者应持续监控游戏性能,及时发现并解决卡顿、加载慢等问题。
6.4.1 使用 Chrome DevTools 分析性能瓶颈
Chrome DevTools 提供了丰富的性能分析功能。使用步骤如下:
- 打开游戏页面;
- 按
F12打开开发者工具; - 切换到 Performance 标签;
- 点击 “Record” 开始录制,操作游戏后停止;
- 查看火焰图,分析主线程耗时函数。
关键性能指标包括:
- FPS:帧率应保持在 30 以上;
- Main Thread Time:主线程耗时不宜过高;
- Paint Flashing:减少不必要的重绘区域;
6.4.2 网络请求与资源加载优化策略
优化资源加载是提升用户体验的关键。以下是常用策略:
- 合并资源 :使用 Texture Atlas 减少 HTTP 请求;
- 预加载资源 :在游戏启动前加载关键资源;
- 使用 CDN :将资源部署到 CDN 加速加载;
- 延迟加载 :非核心资源在游戏运行时按需加载;
- 缓存策略 :设置合适的缓存头,减少重复下载;
示例:使用 Egret 的资源加载器进行预加载:
RES.addEventListener(RES.ResourceEvent.CONFIG_COMPLETE, () => {
RES.loadGroup("preload");
}, this);
RES.addEventListener(RES.ResourceEvent.GROUP_COMPLETE, (e) => {
if (e.groupName === "preload") {
console.log("预加载完成");
}
}, this);
RES.loadConfig("resource/resource.json", "resource/");
该代码在配置加载完成后,自动加载名为 preload 的资源组,确保关键资源在游戏开始前已就绪。
简介:本文围绕一个已发布在4399游戏平台的H5小游戏项目,深入剖析其源码结构与开发技术栈。项目采用Egret框架和TypeScript语言开发,结合HTML5与JavaScript实现浏览器端小游戏运行。文章详细讲解了项目中的关键文件,如配置文件、资源目录、编译输出目录、主入口HTML等内容,帮助开发者理解整个H5游戏的开发、构建与发布流程。通过本源码学习,可掌握Egret框架的项目结构设计与资源管理机制,为H5小游戏开发打下坚实基础。
更多推荐




所有评论(0)