更新快速入门指南
This commit is contained in:
@@ -312,7 +312,7 @@ ecs-framework/
|
|||||||
|
|
||||||
### 🎯 新手入门
|
### 🎯 新手入门
|
||||||
- **[📖 新手教程完整指南](docs/beginner-tutorials.md)** - 完整学习路径,从零开始 ⭐ **强烈推荐**
|
- **[📖 新手教程完整指南](docs/beginner-tutorials.md)** - 完整学习路径,从零开始 ⭐ **强烈推荐**
|
||||||
- [🚀 快速入门](docs/getting-started.md) - 详细的入门教程
|
- **[🚀 快速入门](docs/getting-started.md)** - 详细的入门教程,包含Laya/Cocos/Node.js集成指南 ⭐ **平台集成必读**
|
||||||
- [🧠 技术概念详解](docs/concepts-explained.md) - 通俗易懂的技术概念解释 ⭐ **推荐新手阅读**
|
- [🧠 技术概念详解](docs/concepts-explained.md) - 通俗易懂的技术概念解释 ⭐ **推荐新手阅读**
|
||||||
- [🎯 位掩码使用指南](docs/bitmask-guide.md) - 位掩码概念、原理和高级使用技巧
|
- [🎯 位掩码使用指南](docs/bitmask-guide.md) - 位掩码概念、原理和高级使用技巧
|
||||||
- [💡 使用场景示例](docs/use-cases.md) - 不同类型游戏的具体应用案例
|
- [💡 使用场景示例](docs/use-cases.md) - 不同类型游戏的具体应用案例
|
||||||
|
|||||||
@@ -2,138 +2,299 @@
|
|||||||
|
|
||||||
本指南将帮助您快速上手 ECS Framework,这是一个专业级的实体组件系统框架,采用现代化架构设计,专为高性能游戏开发打造。
|
本指南将帮助您快速上手 ECS Framework,这是一个专业级的实体组件系统框架,采用现代化架构设计,专为高性能游戏开发打造。
|
||||||
|
|
||||||
## 项目结构
|
## 安装
|
||||||
|
|
||||||
```
|
|
||||||
ecs-framework/
|
|
||||||
├── src/ # 源代码
|
|
||||||
│ ├── ECS/ # ECS核心系统
|
|
||||||
│ │ ├── Core/ # 核心管理器
|
|
||||||
│ │ ├── Systems/ # 系统类型
|
|
||||||
│ │ ├── Utils/ # ECS工具类
|
|
||||||
│ │ └── Components/# 组件类型
|
|
||||||
│ ├── Types/ # TypeScript接口定义(精简版)
|
|
||||||
│ └── Utils/ # 通用工具类
|
|
||||||
├── docs/ # 文档
|
|
||||||
├── scripts/ # 构建脚本
|
|
||||||
├── bin/ # 编译输出
|
|
||||||
└── dist/ # 发布版本
|
|
||||||
```
|
|
||||||
|
|
||||||
## 安装和使用
|
|
||||||
|
|
||||||
### NPM 安装
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install @esengine/ecs-framework
|
npm install @esengine/ecs-framework
|
||||||
```
|
```
|
||||||
|
|
||||||
### 从源码构建
|
## 平台集成
|
||||||
|
|
||||||
```bash
|
### Laya引擎
|
||||||
# 克隆项目
|
|
||||||
git clone https://github.com/esengine/ecs-framework.git
|
|
||||||
|
|
||||||
# 进入项目目录
|
|
||||||
cd ecs-framework
|
|
||||||
|
|
||||||
# 安装依赖
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# 编译TypeScript
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# 或者使用监听模式开发
|
|
||||||
npm run build:watch
|
|
||||||
```
|
|
||||||
|
|
||||||
## 基础设置
|
|
||||||
|
|
||||||
### 1. 导入框架
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// 导入核心类
|
import { Scene as LayaScene } from "laya/display/Scene";
|
||||||
import {
|
import { Core, Scene as ECSScene, EntityManager, EntitySystem } from '@esengine/ecs-framework';
|
||||||
Core,
|
|
||||||
Entity,
|
|
||||||
Component,
|
|
||||||
Scene,
|
|
||||||
EntitySystem,
|
|
||||||
EntityManager,
|
|
||||||
ComponentIndexManager,
|
|
||||||
ArchetypeSystem,
|
|
||||||
DirtyTrackingSystem
|
|
||||||
} from '@esengine/ecs-framework';
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 创建基础管理器
|
class LayaECSGame extends LayaScene {
|
||||||
|
private ecsScene: ECSScene;
|
||||||
```typescript
|
|
||||||
class GameManager {
|
|
||||||
private core: Core;
|
|
||||||
private scene: Scene;
|
|
||||||
private entityManager: EntityManager;
|
private entityManager: EntityManager;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// 创建核心实例
|
super();
|
||||||
this.core = Core.create(true);
|
|
||||||
|
|
||||||
// 创建场景
|
// 初始化ECS框架
|
||||||
this.scene = new Scene();
|
Core.create(true);
|
||||||
this.scene.name = "GameScene";
|
this.ecsScene = new ECSScene();
|
||||||
|
this.ecsScene.name = "LayaGameScene";
|
||||||
|
Core.scene = this.ecsScene;
|
||||||
|
|
||||||
// 设置当前场景
|
|
||||||
Core.scene = this.scene;
|
|
||||||
|
|
||||||
// 初始化实体管理器
|
|
||||||
this.entityManager = new EntityManager();
|
this.entityManager = new EntityManager();
|
||||||
|
this.setupSystems();
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(deltaTime: number): void {
|
onAwake(): void {
|
||||||
// 更新场景
|
super.onAwake();
|
||||||
this.scene.update();
|
// 使用Laya的帧循环更新ECS
|
||||||
|
Laya.timer.frameLoop(1, this, this.updateECS);
|
||||||
// 处理系统逻辑
|
|
||||||
this.updateSystems(deltaTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateSystems(deltaTime: number): void {
|
onDestroy(): void {
|
||||||
// 在这里添加您的系统更新逻辑
|
Laya.timer.clear(this, this.updateECS);
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateECS(): void {
|
||||||
|
this.ecsScene.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupSystems(): void {
|
||||||
|
this.ecsScene.addEntityProcessor(new LayaRenderSystem(this));
|
||||||
|
this.ecsScene.addEntityProcessor(new MovementSystem());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Laya渲染系统
|
||||||
|
class LayaRenderSystem extends EntitySystem {
|
||||||
|
private layaScene: LayaScene;
|
||||||
|
|
||||||
|
constructor(layaScene: LayaScene) {
|
||||||
|
super(Matcher.empty().all(PositionComponent, SpriteComponent));
|
||||||
|
this.layaScene = layaScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected process(entities: Entity[]): void {
|
||||||
|
entities.forEach(entity => {
|
||||||
|
const pos = entity.getComponent(PositionComponent);
|
||||||
|
const sprite = entity.getComponent(SpriteComponent);
|
||||||
|
|
||||||
|
if (pos && sprite && sprite.layaSprite) {
|
||||||
|
sprite.layaSprite.x = pos.x;
|
||||||
|
sprite.layaSprite.y = pos.y;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用方法
|
||||||
|
Laya.Scene.open("GameScene.scene", false, null, null, LayaECSGame);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cocos Creator
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Component as CocosComponent, _decorator } from 'cc';
|
||||||
|
import { Core, Scene as ECSScene, EntityManager, EntitySystem } from '@esengine/ecs-framework';
|
||||||
|
|
||||||
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
|
@ccclass('ECSGameManager')
|
||||||
|
export class ECSGameManager extends CocosComponent {
|
||||||
|
private ecsScene: ECSScene;
|
||||||
|
private entityManager: EntityManager;
|
||||||
|
|
||||||
|
start() {
|
||||||
|
// 初始化ECS框架
|
||||||
|
Core.create(true);
|
||||||
|
this.ecsScene = new ECSScene();
|
||||||
|
this.ecsScene.name = "CocosGameScene";
|
||||||
|
Core.scene = this.ecsScene;
|
||||||
|
|
||||||
|
this.entityManager = new EntityManager();
|
||||||
|
this.setupSystems();
|
||||||
|
}
|
||||||
|
|
||||||
|
update(deltaTime: number) {
|
||||||
|
// 在Cocos的update中更新ECS
|
||||||
|
this.ecsScene.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
onDestroy() {
|
||||||
|
if (this.ecsScene) {
|
||||||
|
this.ecsScene.onDestroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupSystems(): void {
|
||||||
|
this.ecsScene.addEntityProcessor(new CocosRenderSystem(this.node));
|
||||||
|
this.ecsScene.addEntityProcessor(new MovementSystem());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提供实体管理器访问
|
|
||||||
public getEntityManager(): EntityManager {
|
public getEntityManager(): EntityManager {
|
||||||
return this.entityManager;
|
return this.entityManager;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 游戏循环
|
// Cocos渲染系统
|
||||||
|
class CocosRenderSystem extends EntitySystem {
|
||||||
|
private rootNode: Node;
|
||||||
|
|
||||||
```typescript
|
constructor(rootNode: Node) {
|
||||||
const gameManager = new GameManager();
|
super(Matcher.empty().all(PositionComponent, SpriteComponent));
|
||||||
let lastTime = performance.now();
|
this.rootNode = rootNode;
|
||||||
|
|
||||||
function gameLoop() {
|
|
||||||
const currentTime = performance.now();
|
|
||||||
const deltaTime = (currentTime - lastTime) / 1000; // 转换为秒
|
|
||||||
lastTime = currentTime;
|
|
||||||
|
|
||||||
gameManager.update(deltaTime);
|
|
||||||
|
|
||||||
requestAnimationFrame(gameLoop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动游戏循环
|
protected process(entities: Entity[]): void {
|
||||||
gameLoop();
|
entities.forEach(entity => {
|
||||||
|
const pos = entity.getComponent(PositionComponent);
|
||||||
|
const sprite = entity.getComponent(SpriteComponent);
|
||||||
|
|
||||||
|
if (pos && sprite && sprite.cocosNode) {
|
||||||
|
sprite.cocosNode.setPosition(pos.x, pos.y);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将ECSGameManager脚本挂载到场景根节点
|
||||||
```
|
```
|
||||||
|
|
||||||
## 创建实体和组件
|
### Node.js后端
|
||||||
|
|
||||||
### 1. 定义组件
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Component, ComponentPoolManager } from '@esengine/ecs-framework';
|
import { Core, Scene, EntityManager, EntitySystem, Time } from '@esengine/ecs-framework';
|
||||||
|
|
||||||
|
class ServerGameManager {
|
||||||
|
private scene: Scene;
|
||||||
|
private entityManager: EntityManager;
|
||||||
|
private isRunning: boolean = false;
|
||||||
|
private tickRate: number = 60; // 60 TPS
|
||||||
|
private lastUpdate: number = Date.now();
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
Core.create(true);
|
||||||
|
this.scene = new Scene();
|
||||||
|
this.scene.name = "ServerScene";
|
||||||
|
Core.scene = this.scene;
|
||||||
|
|
||||||
|
this.entityManager = new EntityManager();
|
||||||
|
this.setupSystems();
|
||||||
|
}
|
||||||
|
|
||||||
|
public start(): void {
|
||||||
|
this.isRunning = true;
|
||||||
|
console.log(`游戏服务器启动,TPS: ${this.tickRate}`);
|
||||||
|
this.gameLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public stop(): void {
|
||||||
|
this.isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private gameLoop(): void {
|
||||||
|
if (!this.isRunning) return;
|
||||||
|
|
||||||
|
const now = Date.now();
|
||||||
|
const deltaTime = (now - this.lastUpdate) / 1000;
|
||||||
|
this.lastUpdate = now;
|
||||||
|
|
||||||
|
Time.update(deltaTime);
|
||||||
|
this.scene.update();
|
||||||
|
|
||||||
|
const frameTime = 1000 / this.tickRate;
|
||||||
|
const processingTime = Date.now() - now;
|
||||||
|
const delay = Math.max(0, frameTime - processingTime);
|
||||||
|
|
||||||
|
setTimeout(() => this.gameLoop(), delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupSystems(): void {
|
||||||
|
this.scene.addEntityProcessor(new ServerMovementSystem());
|
||||||
|
this.scene.addEntityProcessor(new NetworkSyncSystem());
|
||||||
|
this.scene.addEntityProcessor(new AISystem());
|
||||||
|
}
|
||||||
|
|
||||||
|
public handlePlayerInput(playerId: string, input: any): void {
|
||||||
|
const playerEntity = this.findPlayerEntity(playerId);
|
||||||
|
if (playerEntity) {
|
||||||
|
const inputComp = playerEntity.getComponent(InputComponent);
|
||||||
|
if (inputComp) {
|
||||||
|
inputComp.updateInput(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getWorldState(): any {
|
||||||
|
const entities = this.entityManager
|
||||||
|
.query()
|
||||||
|
.withAll(PositionComponent, NetworkComponent)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
return entities.map(entity => ({
|
||||||
|
id: entity.id,
|
||||||
|
position: entity.getComponent(PositionComponent),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private findPlayerEntity(playerId: string): Entity | null {
|
||||||
|
const players = this.entityManager
|
||||||
|
.query()
|
||||||
|
.withAll(PlayerComponent)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
return players.find(player =>
|
||||||
|
player.getComponent(PlayerComponent).playerId === playerId
|
||||||
|
) || null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动服务器
|
||||||
|
const server = new ServerGameManager();
|
||||||
|
server.start();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 原生浏览器
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Core, Scene, EntityManager, EntitySystem } from '@esengine/ecs-framework';
|
||||||
|
|
||||||
|
class BrowserGame {
|
||||||
|
private scene: Scene;
|
||||||
|
private entityManager: EntityManager;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
Core.create(true);
|
||||||
|
this.scene = new Scene();
|
||||||
|
this.scene.name = "BrowserScene";
|
||||||
|
Core.scene = this.scene;
|
||||||
|
|
||||||
|
this.entityManager = new EntityManager();
|
||||||
|
this.setupSystems();
|
||||||
|
}
|
||||||
|
|
||||||
|
public start(): void {
|
||||||
|
this.createEntities();
|
||||||
|
this.gameLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private gameLoop(): void {
|
||||||
|
const update = () => {
|
||||||
|
this.scene.update();
|
||||||
|
requestAnimationFrame(update);
|
||||||
|
};
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupSystems(): void {
|
||||||
|
this.scene.addEntityProcessor(new MovementSystem());
|
||||||
|
this.scene.addEntityProcessor(new RenderSystem());
|
||||||
|
}
|
||||||
|
|
||||||
|
private createEntities(): void {
|
||||||
|
const player = this.entityManager.createEntity("Player");
|
||||||
|
player.addComponent(new PositionComponent(400, 300));
|
||||||
|
player.addComponent(new VelocityComponent(0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const game = new BrowserGame();
|
||||||
|
game.start();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 基础组件定义
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Component } from '@esengine/ecs-framework';
|
||||||
|
|
||||||
// 位置组件
|
// 位置组件
|
||||||
class PositionComponent extends Component {
|
class PositionComponent extends Component {
|
||||||
@@ -146,7 +307,6 @@ class PositionComponent extends Component {
|
|||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 对象池重置方法
|
|
||||||
public reset() {
|
public reset() {
|
||||||
this.x = 0;
|
this.x = 0;
|
||||||
this.y = 0;
|
this.y = 0;
|
||||||
@@ -198,89 +358,12 @@ class HealthComponent extends Component {
|
|||||||
return this.currentHealth <= 0;
|
return this.currentHealth <= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 简单的组件定义
|
|
||||||
// 注:框架会自动优化组件的存储和查询
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 使用 EntityManager
|
## 基础系统创建
|
||||||
|
|
||||||
EntityManager 是框架的核心功能,提供统一的实体管理和高性能查询接口。
|
|
||||||
|
|
||||||
### 基础实体操作
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// 获取EntityManager实例(在GameManager中已创建)
|
import { EntitySystem, Entity, Matcher, Time } from '@esengine/ecs-framework';
|
||||||
const entityManager = gameManager.getEntityManager();
|
|
||||||
|
|
||||||
// 创建单个实体
|
|
||||||
const player = entityManager.createEntity("Player");
|
|
||||||
|
|
||||||
// 批量创建实体(使用Scene方法)
|
|
||||||
const enemies = scene.createEntities(50, "Enemy");
|
|
||||||
|
|
||||||
// 查询操作
|
|
||||||
const movingEntities = entityManager
|
|
||||||
.query()
|
|
||||||
.withAll(PositionComponent, VelocityComponent)
|
|
||||||
.withNone(HealthComponent)
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
// 组件查询
|
|
||||||
const healthEntities = entityManager.getEntitiesWithComponent(HealthComponent);
|
|
||||||
|
|
||||||
// 标签查询
|
|
||||||
const allEnemies = entityManager.getEntitiesByTag(2);
|
|
||||||
|
|
||||||
// 名称查询
|
|
||||||
const specificEnemy = entityManager.getEntityByName("BossEnemy");
|
|
||||||
|
|
||||||
// 复合查询
|
|
||||||
const livingEnemies = entityManager
|
|
||||||
.query()
|
|
||||||
.withAll(HealthComponent)
|
|
||||||
.withTag(2)
|
|
||||||
.execute();
|
|
||||||
```
|
|
||||||
|
|
||||||
### 实体遍历
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// 遍历所有实体
|
|
||||||
const allEntities = entityManager.getAllEntities();
|
|
||||||
allEntities.forEach(entity => {
|
|
||||||
console.log(`实体: ${entity.name}, ID: ${entity.id}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 遍历特定组件的实体
|
|
||||||
const healthEntities = entityManager.getEntitiesWithComponent(HealthComponent);
|
|
||||||
healthEntities.forEach(entity => {
|
|
||||||
const health = entity.getComponent(HealthComponent);
|
|
||||||
console.log(`${entity.name} 生命值: ${health.currentHealth}/${health.maxHealth}`);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 性能监控
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// 获取场景统计
|
|
||||||
const sceneStats = scene.getStats();
|
|
||||||
console.log('实体数量:', sceneStats.entityCount);
|
|
||||||
console.log('系统数量:', sceneStats.processorCount);
|
|
||||||
|
|
||||||
// 获取查询系统统计
|
|
||||||
const queryStats = scene.querySystem.getStats();
|
|
||||||
console.log('查询统计:', queryStats);
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## 创建系统
|
|
||||||
|
|
||||||
系统处理具有特定组件的实体集合,实现游戏逻辑。
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { EntitySystem, Entity, Matcher, EntityManager } from '@esengine/ecs-framework';
|
|
||||||
|
|
||||||
class MovementSystem extends EntitySystem {
|
class MovementSystem extends EntitySystem {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -288,7 +371,6 @@ class MovementSystem extends EntitySystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected process(entities: Entity[]): void {
|
protected process(entities: Entity[]): void {
|
||||||
// 使用Scene的查询系统进行高效查询
|
|
||||||
const movingEntities = this.scene.querySystem.queryAll(PositionComponent, VelocityComponent);
|
const movingEntities = this.scene.querySystem.queryAll(PositionComponent, VelocityComponent);
|
||||||
|
|
||||||
movingEntities.entities.forEach(entity => {
|
movingEntities.entities.forEach(entity => {
|
||||||
@@ -296,8 +378,8 @@ class MovementSystem extends EntitySystem {
|
|||||||
const velocity = entity.getComponent(VelocityComponent);
|
const velocity = entity.getComponent(VelocityComponent);
|
||||||
|
|
||||||
if (position && velocity) {
|
if (position && velocity) {
|
||||||
position.x += velocity.dx * Time.deltaTime;
|
position.x += velocity.x * Time.deltaTime;
|
||||||
position.y += velocity.dy * Time.deltaTime;
|
position.y += velocity.y * Time.deltaTime;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -319,15 +401,35 @@ class HealthSystem extends EntitySystem {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加系统到场景
|
|
||||||
gameManager.scene.addEntityProcessor(new MovementSystem());
|
|
||||||
gameManager.scene.addEntityProcessor(new HealthSystem());
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 高级功能
|
## 实体管理
|
||||||
|
|
||||||
### 事件系统
|
```typescript
|
||||||
|
// 创建实体
|
||||||
|
const player = entityManager.createEntity("Player");
|
||||||
|
player.addComponent(new PositionComponent(100, 100));
|
||||||
|
player.addComponent(new VelocityComponent(5, 0));
|
||||||
|
player.addComponent(new HealthComponent(100));
|
||||||
|
|
||||||
|
// 批量创建实体
|
||||||
|
const enemies = scene.createEntities(50, "Enemy");
|
||||||
|
enemies.forEach(enemy => {
|
||||||
|
enemy.addComponent(new PositionComponent(Math.random() * 800, Math.random() * 600));
|
||||||
|
enemy.addComponent(new HealthComponent(50));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 查询实体
|
||||||
|
const movingEntities = entityManager
|
||||||
|
.query()
|
||||||
|
.withAll(PositionComponent, VelocityComponent)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
const healthEntities = entityManager.getEntitiesWithComponent(HealthComponent);
|
||||||
|
const enemiesByTag = entityManager.getEntitiesByTag(2);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 事件系统
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Core, CoreEvents } from '@esengine/ecs-framework';
|
import { Core, CoreEvents } from '@esengine/ecs-framework';
|
||||||
@@ -342,160 +444,22 @@ Core.emitter.emit("playerDied", { player: entity, score: 1000 });
|
|||||||
Core.emitter.removeObserver(CoreEvents.frameUpdated, this.onFrameUpdate);
|
Core.emitter.removeObserver(CoreEvents.frameUpdated, this.onFrameUpdate);
|
||||||
```
|
```
|
||||||
|
|
||||||
### 性能监控
|
## 性能监控
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// 获取场景性能统计
|
// 获取场景统计
|
||||||
const sceneStats = scene.getStats();
|
const sceneStats = scene.getStats();
|
||||||
console.log(`总实体数: ${sceneStats.entityCount}`);
|
console.log('实体数量:', sceneStats.entityCount);
|
||||||
console.log(`系统数量: ${sceneStats.processorCount}`);
|
console.log('系统数量:', sceneStats.processorCount);
|
||||||
|
|
||||||
// 获取查询系统统计
|
// 获取查询统计
|
||||||
const queryStats = scene.querySystem.getStats();
|
const queryStats = scene.querySystem.getStats();
|
||||||
console.log('查询统计:', queryStats);
|
console.log('查询统计:', queryStats);
|
||||||
```
|
```
|
||||||
|
|
||||||
## 简单示例
|
|
||||||
|
|
||||||
以下是一个完整的示例,展示了框架的主要功能:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import {
|
|
||||||
Core,
|
|
||||||
Entity,
|
|
||||||
Component,
|
|
||||||
Scene,
|
|
||||||
EntitySystem,
|
|
||||||
EntityManager
|
|
||||||
} from '@esengine/ecs-framework';
|
|
||||||
|
|
||||||
// 游戏管理器
|
|
||||||
class SimpleGame {
|
|
||||||
private core: Core;
|
|
||||||
private scene: Scene;
|
|
||||||
private entityManager: EntityManager;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.core = Core.create(true);
|
|
||||||
this.scene = new Scene();
|
|
||||||
this.scene.name = "GameScene";
|
|
||||||
Core.scene = this.scene;
|
|
||||||
|
|
||||||
this.entityManager = new EntityManager();
|
|
||||||
this.setupSystems();
|
|
||||||
}
|
|
||||||
|
|
||||||
private setupSystems(): void {
|
|
||||||
this.scene.addEntityProcessor(new MovementSystem());
|
|
||||||
this.scene.addEntityProcessor(new HealthSystem());
|
|
||||||
}
|
|
||||||
|
|
||||||
public start(): void {
|
|
||||||
// 创建游戏实体
|
|
||||||
this.createPlayer();
|
|
||||||
this.createEnemies(50);
|
|
||||||
|
|
||||||
// 启动游戏循环
|
|
||||||
this.gameLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private createPlayer(): Entity {
|
|
||||||
const player = this.entityManager.createEntity("Player");
|
|
||||||
player.addComponent(new PositionComponent(400, 300));
|
|
||||||
player.addComponent(new VelocityComponent(0, 0));
|
|
||||||
player.addComponent(new HealthComponent(100));
|
|
||||||
player.tag = "player";
|
|
||||||
return player;
|
|
||||||
}
|
|
||||||
|
|
||||||
private createEnemies(count: number): Entity[] {
|
|
||||||
const enemies = this.scene.createEntities(count, "Enemy");
|
|
||||||
|
|
||||||
enemies.forEach((enemy, index) => {
|
|
||||||
enemy.addComponent(new PositionComponent(
|
|
||||||
Math.random() * 800,
|
|
||||||
Math.random() * 600
|
|
||||||
));
|
|
||||||
enemy.addComponent(new VelocityComponent(
|
|
||||||
(Math.random() - 0.5) * 100,
|
|
||||||
(Math.random() - 0.5) * 100
|
|
||||||
));
|
|
||||||
enemy.addComponent(new HealthComponent(50));
|
|
||||||
enemy.tag = "enemy";
|
|
||||||
});
|
|
||||||
|
|
||||||
return enemies;
|
|
||||||
}
|
|
||||||
|
|
||||||
private gameLoop(): void {
|
|
||||||
const update = () => {
|
|
||||||
// 更新场景
|
|
||||||
this.scene.update();
|
|
||||||
requestAnimationFrame(update);
|
|
||||||
};
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 启动游戏
|
|
||||||
const game = new SimpleGame();
|
|
||||||
game.start();
|
|
||||||
```
|
|
||||||
|
|
||||||
## 性能优化建议
|
|
||||||
|
|
||||||
### 1. 大规模实体处理
|
|
||||||
- 使用 `scene.createEntities()` 批量创建实体
|
|
||||||
- 利用组件索引系统进行高效查询
|
|
||||||
- 启用Archetype系统减少查询遍历
|
|
||||||
|
|
||||||
### 2. 查询优化
|
|
||||||
- 使用 `EntityManager.query()` 流式API构建复杂查询
|
|
||||||
- 缓存频繁查询的结果
|
|
||||||
- 利用脏标记系统避免不必要的更新
|
|
||||||
|
|
||||||
### 3. 性能监控
|
|
||||||
- 定期检查 `scene.getStats()` 获取性能数据
|
|
||||||
- 监控组件索引命中率
|
|
||||||
- 使用框架提供的性能统计功能
|
|
||||||
|
|
||||||
## 下一步
|
## 下一步
|
||||||
|
|
||||||
现在您已经掌握了 ECS Framework 的基础用法,可以继续学习:
|
|
||||||
|
|
||||||
- [EntityManager 使用指南](entity-manager-example.md) - 详细了解实体管理器的高级功能
|
- [EntityManager 使用指南](entity-manager-example.md) - 详细了解实体管理器的高级功能
|
||||||
- [性能优化指南](performance-optimization.md) - 深入了解三大性能优化系统
|
- [性能优化指南](performance-optimization.md) - 深入了解三大性能优化系统
|
||||||
- [核心概念](core-concepts.md) - 深入了解 ECS 架构和设计原理
|
- [核心概念](core-concepts.md) - 深入了解 ECS 架构和设计原理
|
||||||
- [查询系统使用指南](query-system-usage.md) - 学习高性能查询系统的详细用法
|
- [查询系统使用指南](query-system-usage.md) - 学习高性能查询系统的详细用法
|
||||||
|
|
||||||
## 常见问题
|
|
||||||
|
|
||||||
### Q: 如何在不同游戏引擎中集成?
|
|
||||||
|
|
||||||
A: ECS Framework 是引擎无关的,您只需要:
|
|
||||||
1. 通过npm安装框架 `npm install @esengine/ecs-framework`
|
|
||||||
2. 在游戏引擎的主循环中调用 `scene.update()`
|
|
||||||
3. 根据需要集成渲染、输入等引擎特定功能
|
|
||||||
|
|
||||||
### Q: 如何处理输入?
|
|
||||||
|
|
||||||
A: 框架本身不提供输入处理,建议:
|
|
||||||
1. 创建一个输入组件来存储输入状态
|
|
||||||
2. 在游戏引擎的输入回调中更新输入组件
|
|
||||||
3. 创建输入处理系统来响应输入状态
|
|
||||||
|
|
||||||
### Q: 如何优化大规模实体性能?
|
|
||||||
|
|
||||||
A: 关键优化策略:
|
|
||||||
1. 使用 `EntityManager` 的高级查询功能
|
|
||||||
2. 启用组件索引系统进行快速查询
|
|
||||||
3. 利用Archetype系统减少查询遍历
|
|
||||||
4. 使用脏标记系统避免不必要的更新
|
|
||||||
|
|
||||||
### Q: EntityManager 有什么优势?
|
|
||||||
|
|
||||||
A: EntityManager 提供了:
|
|
||||||
- O(1) 复杂度的组件查询(使用索引)
|
|
||||||
- 流式API的复杂查询构建
|
|
||||||
- 自动的性能优化系统集成
|
|
||||||
- 统一的实体管理接口
|
|
||||||
Reference in New Issue
Block a user