From d539bb3dd9e1db79e84783de59f8ed1bca7e45c6 Mon Sep 17 00:00:00 2001 From: YHH <359807859@qq.com> Date: Mon, 11 Aug 2025 08:18:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 78 ++++++++++++++++++++++++------------ docs/getting-started.md | 89 ++++++++++++----------------------------- 2 files changed, 78 insertions(+), 89 deletions(-) diff --git a/README.md b/README.md index 4e127e7e..a67a035c 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ npm install @esengine/ecs-framework ### 1. 基础使用 ```typescript -import { Core, Scene, Entity, Component, EntitySystem } from '@esengine/ecs-framework'; +import { Core, Scene, Entity, Component, EntitySystem, Matcher, Time } from '@esengine/ecs-framework'; // 创建核心实例 const core = Core.create({ debug: true }); @@ -58,14 +58,26 @@ Core.scene = scene; // 定义组件 class PositionComponent extends Component { - constructor(public x: number = 0, public y: number = 0) { + public x: number = 0; + public y: number = 0; + + constructor(...args: unknown[]) { super(); + const [x = 0, y = 0] = args as [number?, number?]; + this.x = x; + this.y = y; } } class VelocityComponent extends Component { - constructor(public dx: number = 0, public dy: number = 0) { + public x: number = 0; + public y: number = 0; + + constructor(...args: unknown[]) { super(); + const [x = 0, y = 0] = args as [number?, number?]; + this.x = x; + this.y = y; } } @@ -76,15 +88,17 @@ entity.addComponent(new VelocityComponent(5, 0)); // 创建系统 class MovementSystem extends EntitySystem { - public process(entities: Entity[]) { + constructor() { + super(Matcher.all(PositionComponent, VelocityComponent)); + } + + protected override process(entities: Entity[]) { for (const entity of entities) { - const position = entity.getComponent(PositionComponent); - const velocity = entity.getComponent(VelocityComponent); + const position = entity.getComponent(PositionComponent)!; + const velocity = entity.getComponent(VelocityComponent)!; - if (position && velocity) { - position.x += velocity.dx; - position.y += velocity.dy; - } + position.x += velocity.x * Time.deltaTime; + position.y += velocity.y * Time.deltaTime; } } } @@ -100,16 +114,26 @@ Core.update(deltaTime); ### 查询系统 ```typescript -import { EntityManager } from '@esengine/ecs-framework'; +import { Matcher } from '@esengine/ecs-framework'; -const entityManager = new EntityManager(); +// 方式1:使用Matcher和EntitySystem +class QuerySystem extends EntitySystem { + constructor() { + super(Matcher.all(PositionComponent, VelocityComponent).none(HealthComponent)); + } + + protected override process(entities: Entity[]) { + // 处理匹配的实体 + console.log(`Found ${entities.length} entities`); + } +} -// 流式查询 API -const results = entityManager - .query() - .withAll(PositionComponent, VelocityComponent) - .withNone(HealthComponent) - .execute(); +// 方式2:手动过滤场景中的实体 +const results = scene.entities.buffer.filter(entity => + entity.hasComponent(PositionComponent) && + entity.hasComponent(VelocityComponent) && + !entity.hasComponent(HealthComponent) +); ``` ### 事件系统 @@ -119,7 +143,7 @@ import { EventHandler, ECSEventType } from '@esengine/ecs-framework'; class GameSystem { @EventHandler(ECSEventType.ENTITY_DESTROYED) - onEntityDestroyed(data: EntityDestroyedEventData) { + onEntityDestroyed(data: any) { console.log('实体销毁:', data.entityName); } } @@ -198,12 +222,16 @@ function gameLoop(currentTime: number) { ### 查询 API ```typescript -entityManager.query() - .withAll(...components) // 包含所有组件 - .withAny(...components) // 包含任意组件 - .withNone(...components) // 不包含组件 - .withTag(tag) // 包含标签 - .execute() // 执行查询 +// Matcher API - 用于EntitySystem +Matcher.all(...components) // 包含所有组件 +Matcher.any(...components) // 包含任意组件 +Matcher.none(...components) // 不包含组件 + +// 手动查询 - 用于场景实体过滤 +scene.entities.buffer.filter(entity => + entity.hasComponent(ComponentA) && + entity.tag === someTag +); ``` ## 文档 diff --git a/docs/getting-started.md b/docs/getting-started.md index 381d873a..d5ab8b3b 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -221,31 +221,18 @@ class LayaECSGame extends LayaScene { // Laya渲染系统 class LayaRenderSystem extends EntitySystem { private layaScene: LayaScene; - private renderMatcher: Matcher; constructor(layaScene: LayaScene) { - super(); + super(Matcher.all(PositionComponent, SpriteComponent)); this.layaScene = layaScene; } - public initialize(): void { - super.initialize(); - // 创建Matcher来查询需要渲染的实体 - if (this.scene) { - this.renderMatcher = Matcher.create(this.scene.querySystem) - .all(PositionComponent, SpriteComponent); - } - } - - protected process(entities: Entity[]): void { - // 获取需要渲染的实体 - const renderableEntities = this.renderMatcher.query(); - - renderableEntities.forEach(entity => { + protected override process(entities: Entity[]): void { + entities.forEach(entity => { const pos = entity.getComponent(PositionComponent)!; const sprite = entity.getComponent(SpriteComponent)!; - if (pos && sprite && sprite.layaSprite) { + if (sprite.layaSprite) { sprite.layaSprite.x = pos.x; sprite.layaSprite.y = pos.y; } @@ -260,7 +247,7 @@ Laya.Scene.open("GameScene.scene", false, null, null, LayaECSGame); ### Cocos Creator ```typescript -import { Component as CocosComponent, _decorator } from 'cc'; +import { Component as CocosComponent, _decorator, Node } from 'cc'; import { Core, Scene as ECSScene, EntityManager, EntitySystem } from '@esengine/ecs-framework'; const { ccclass, property } = _decorator; @@ -307,25 +294,14 @@ export class ECSGameManager extends CocosComponent { // Cocos渲染系统 class CocosRenderSystem extends EntitySystem { private rootNode: Node; - private renderMatcher: Matcher; constructor(rootNode: Node) { - super(); + super(Matcher.all(PositionComponent, SpriteComponent)); this.rootNode = rootNode; } - public initialize(): void { - super.initialize(); - if (this.scene) { - this.renderMatcher = Matcher.create(this.scene.querySystem) - .all(PositionComponent, SpriteComponent); - } - } - - protected process(entities: Entity[]): void { - const renderableEntities = this.renderMatcher.query(); - - renderableEntities.forEach(entity => { + protected override process(entities: Entity[]): void { + entities.forEach(entity => { const pos = entity.getComponent(PositionComponent)!; const sprite = entity.getComponent(SpriteComponent)!; @@ -507,8 +483,9 @@ class PositionComponent extends Component { public x: number = 0; public y: number = 0; - constructor(x: number = 0, y: number = 0) { + constructor(...args: unknown[]) { super(); + const [x = 0, y = 0] = args as [number?, number?]; this.x = x; this.y = y; } @@ -524,8 +501,9 @@ class VelocityComponent extends Component { public x: number = 0; public y: number = 0; - constructor(x: number = 0, y: number = 0) { + constructor(...args: unknown[]) { super(); + const [x = 0, y = 0] = args as [number?, number?]; this.x = x; this.y = y; } @@ -541,8 +519,9 @@ class HealthComponent extends Component { public maxHealth: number = 100; public currentHealth: number = 100; - constructor(maxHealth: number = 100) { + constructor(...args: unknown[]) { super(); + const [maxHealth = 100] = args as [number?]; this.maxHealth = maxHealth; this.currentHealth = maxHealth; } @@ -576,44 +555,26 @@ class MovementSystem extends EntitySystem { super(Matcher.all(PositionComponent, VelocityComponent)); } - protected process(entities: Entity[]): void { - const movingEntities = entities; - - movingEntities.forEach(entity => { - const position = entity.getComponent(PositionComponent); - const velocity = entity.getComponent(VelocityComponent); + protected override process(entities: Entity[]): void { + entities.forEach(entity => { + const position = entity.getComponent(PositionComponent)!; + const velocity = entity.getComponent(VelocityComponent)!; - if (position && velocity) { - position.x += velocity.x * Time.deltaTime; - position.y += velocity.y * Time.deltaTime; - } + position.x += velocity.x * Time.deltaTime; + position.y += velocity.y * Time.deltaTime; }); } } class HealthSystem extends EntitySystem { - private healthMatcher: Matcher; - constructor() { - super(); + super(Matcher.all(HealthComponent)); } - public initialize(): void { - super.initialize(); - if (this.scene) { - this.healthMatcher = Matcher.create(this.scene.querySystem) - .all(HealthComponent); - } - } - - protected process(entities: Entity[]): void { - if (!this.healthMatcher) return; - - const healthEntities = this.healthMatcher.query(); - - healthEntities.forEach(entity => { - const health = entity.getComponent(HealthComponent); - if (health && health.currentHealth <= 0) { + protected override process(entities: Entity[]): void { + entities.forEach(entity => { + const health = entity.getComponent(HealthComponent)!; + if (health.currentHealth <= 0) { entity.destroy(); } });