更新文档
This commit is contained in:
80
README.md
80
README.md
@@ -49,7 +49,7 @@ npm install @esengine/ecs-framework
|
|||||||
### 1. 基础使用
|
### 1. 基础使用
|
||||||
|
|
||||||
```typescript
|
```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 });
|
const core = Core.create({ debug: true });
|
||||||
@@ -58,14 +58,26 @@ Core.scene = scene;
|
|||||||
|
|
||||||
// 定义组件
|
// 定义组件
|
||||||
class PositionComponent extends Component {
|
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();
|
super();
|
||||||
|
const [x = 0, y = 0] = args as [number?, number?];
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VelocityComponent extends Component {
|
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();
|
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 {
|
class MovementSystem extends EntitySystem {
|
||||||
public process(entities: Entity[]) {
|
constructor() {
|
||||||
for (const entity of entities) {
|
super(Matcher.all(PositionComponent, VelocityComponent));
|
||||||
const position = entity.getComponent(PositionComponent);
|
}
|
||||||
const velocity = entity.getComponent(VelocityComponent);
|
|
||||||
|
|
||||||
if (position && velocity) {
|
protected override process(entities: Entity[]) {
|
||||||
position.x += velocity.dx;
|
for (const entity of entities) {
|
||||||
position.y += velocity.dy;
|
const position = entity.getComponent(PositionComponent)!;
|
||||||
}
|
const velocity = entity.getComponent(VelocityComponent)!;
|
||||||
|
|
||||||
|
position.x += velocity.x * Time.deltaTime;
|
||||||
|
position.y += velocity.y * Time.deltaTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,16 +114,26 @@ Core.update(deltaTime);
|
|||||||
### 查询系统
|
### 查询系统
|
||||||
|
|
||||||
```typescript
|
```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));
|
||||||
|
}
|
||||||
|
|
||||||
// 流式查询 API
|
protected override process(entities: Entity[]) {
|
||||||
const results = entityManager
|
// 处理匹配的实体
|
||||||
.query()
|
console.log(`Found ${entities.length} entities`);
|
||||||
.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 {
|
class GameSystem {
|
||||||
@EventHandler(ECSEventType.ENTITY_DESTROYED)
|
@EventHandler(ECSEventType.ENTITY_DESTROYED)
|
||||||
onEntityDestroyed(data: EntityDestroyedEventData) {
|
onEntityDestroyed(data: any) {
|
||||||
console.log('实体销毁:', data.entityName);
|
console.log('实体销毁:', data.entityName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,12 +222,16 @@ function gameLoop(currentTime: number) {
|
|||||||
### 查询 API
|
### 查询 API
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
entityManager.query()
|
// Matcher API - 用于EntitySystem
|
||||||
.withAll(...components) // 包含所有组件
|
Matcher.all(...components) // 包含所有组件
|
||||||
.withAny(...components) // 包含任意组件
|
Matcher.any(...components) // 包含任意组件
|
||||||
.withNone(...components) // 不包含组件
|
Matcher.none(...components) // 不包含组件
|
||||||
.withTag(tag) // 包含标签
|
|
||||||
.execute() // 执行查询
|
// 手动查询 - 用于场景实体过滤
|
||||||
|
scene.entities.buffer.filter(entity =>
|
||||||
|
entity.hasComponent(ComponentA) &&
|
||||||
|
entity.tag === someTag
|
||||||
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
## 文档
|
## 文档
|
||||||
|
|||||||
@@ -221,31 +221,18 @@ class LayaECSGame extends LayaScene {
|
|||||||
// Laya渲染系统
|
// Laya渲染系统
|
||||||
class LayaRenderSystem extends EntitySystem {
|
class LayaRenderSystem extends EntitySystem {
|
||||||
private layaScene: LayaScene;
|
private layaScene: LayaScene;
|
||||||
private renderMatcher: Matcher;
|
|
||||||
|
|
||||||
constructor(layaScene: LayaScene) {
|
constructor(layaScene: LayaScene) {
|
||||||
super();
|
super(Matcher.all(PositionComponent, SpriteComponent));
|
||||||
this.layaScene = layaScene;
|
this.layaScene = layaScene;
|
||||||
}
|
}
|
||||||
|
|
||||||
public initialize(): void {
|
protected override process(entities: Entity[]): void {
|
||||||
super.initialize();
|
entities.forEach(entity => {
|
||||||
// 创建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 => {
|
|
||||||
const pos = entity.getComponent(PositionComponent)!;
|
const pos = entity.getComponent(PositionComponent)!;
|
||||||
const sprite = entity.getComponent(SpriteComponent)!;
|
const sprite = entity.getComponent(SpriteComponent)!;
|
||||||
|
|
||||||
if (pos && sprite && sprite.layaSprite) {
|
if (sprite.layaSprite) {
|
||||||
sprite.layaSprite.x = pos.x;
|
sprite.layaSprite.x = pos.x;
|
||||||
sprite.layaSprite.y = pos.y;
|
sprite.layaSprite.y = pos.y;
|
||||||
}
|
}
|
||||||
@@ -260,7 +247,7 @@ Laya.Scene.open("GameScene.scene", false, null, null, LayaECSGame);
|
|||||||
### Cocos Creator
|
### Cocos Creator
|
||||||
|
|
||||||
```typescript
|
```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';
|
import { Core, Scene as ECSScene, EntityManager, EntitySystem } from '@esengine/ecs-framework';
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
@@ -307,25 +294,14 @@ export class ECSGameManager extends CocosComponent {
|
|||||||
// Cocos渲染系统
|
// Cocos渲染系统
|
||||||
class CocosRenderSystem extends EntitySystem {
|
class CocosRenderSystem extends EntitySystem {
|
||||||
private rootNode: Node;
|
private rootNode: Node;
|
||||||
private renderMatcher: Matcher;
|
|
||||||
|
|
||||||
constructor(rootNode: Node) {
|
constructor(rootNode: Node) {
|
||||||
super();
|
super(Matcher.all(PositionComponent, SpriteComponent));
|
||||||
this.rootNode = rootNode;
|
this.rootNode = rootNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public initialize(): void {
|
protected override process(entities: Entity[]): void {
|
||||||
super.initialize();
|
entities.forEach(entity => {
|
||||||
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 => {
|
|
||||||
const pos = entity.getComponent(PositionComponent)!;
|
const pos = entity.getComponent(PositionComponent)!;
|
||||||
const sprite = entity.getComponent(SpriteComponent)!;
|
const sprite = entity.getComponent(SpriteComponent)!;
|
||||||
|
|
||||||
@@ -507,8 +483,9 @@ class PositionComponent extends Component {
|
|||||||
public x: number = 0;
|
public x: number = 0;
|
||||||
public y: number = 0;
|
public y: number = 0;
|
||||||
|
|
||||||
constructor(x: number = 0, y: number = 0) {
|
constructor(...args: unknown[]) {
|
||||||
super();
|
super();
|
||||||
|
const [x = 0, y = 0] = args as [number?, number?];
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
@@ -524,8 +501,9 @@ class VelocityComponent extends Component {
|
|||||||
public x: number = 0;
|
public x: number = 0;
|
||||||
public y: number = 0;
|
public y: number = 0;
|
||||||
|
|
||||||
constructor(x: number = 0, y: number = 0) {
|
constructor(...args: unknown[]) {
|
||||||
super();
|
super();
|
||||||
|
const [x = 0, y = 0] = args as [number?, number?];
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
@@ -541,8 +519,9 @@ class HealthComponent extends Component {
|
|||||||
public maxHealth: number = 100;
|
public maxHealth: number = 100;
|
||||||
public currentHealth: number = 100;
|
public currentHealth: number = 100;
|
||||||
|
|
||||||
constructor(maxHealth: number = 100) {
|
constructor(...args: unknown[]) {
|
||||||
super();
|
super();
|
||||||
|
const [maxHealth = 100] = args as [number?];
|
||||||
this.maxHealth = maxHealth;
|
this.maxHealth = maxHealth;
|
||||||
this.currentHealth = maxHealth;
|
this.currentHealth = maxHealth;
|
||||||
}
|
}
|
||||||
@@ -576,44 +555,26 @@ class MovementSystem extends EntitySystem {
|
|||||||
super(Matcher.all(PositionComponent, VelocityComponent));
|
super(Matcher.all(PositionComponent, VelocityComponent));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected process(entities: Entity[]): void {
|
protected override process(entities: Entity[]): void {
|
||||||
const movingEntities = entities;
|
entities.forEach(entity => {
|
||||||
|
const position = entity.getComponent(PositionComponent)!;
|
||||||
|
const velocity = entity.getComponent(VelocityComponent)!;
|
||||||
|
|
||||||
movingEntities.forEach(entity => {
|
position.x += velocity.x * Time.deltaTime;
|
||||||
const position = entity.getComponent(PositionComponent);
|
position.y += velocity.y * Time.deltaTime;
|
||||||
const velocity = entity.getComponent(VelocityComponent);
|
|
||||||
|
|
||||||
if (position && velocity) {
|
|
||||||
position.x += velocity.x * Time.deltaTime;
|
|
||||||
position.y += velocity.y * Time.deltaTime;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HealthSystem extends EntitySystem {
|
class HealthSystem extends EntitySystem {
|
||||||
private healthMatcher: Matcher;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super(Matcher.all(HealthComponent));
|
||||||
}
|
}
|
||||||
|
|
||||||
public initialize(): void {
|
protected override process(entities: Entity[]): void {
|
||||||
super.initialize();
|
entities.forEach(entity => {
|
||||||
if (this.scene) {
|
const health = entity.getComponent(HealthComponent)!;
|
||||||
this.healthMatcher = Matcher.create(this.scene.querySystem)
|
if (health.currentHealth <= 0) {
|
||||||
.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) {
|
|
||||||
entity.destroy();
|
entity.destroy();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user