From 17550343c7a5d8fca2ab63de9fd54e60365e3dd8 Mon Sep 17 00:00:00 2001 From: dgflash Date: Mon, 5 Sep 2022 16:41:24 +0800 Subject: [PATCH] =?UTF-8?q?ECS=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/libs/ecs/ECS.ts | 38 ++------------------------------- assets/libs/ecs/ECSEntity.ts | 29 +++++++++++++------------ assets/libs/ecs/ECSMatcher.ts | 16 +++++++------- assets/libs/ecs/ECSModel.ts | 40 ++++++++++++++++++++++++++++++++--- assets/libs/ecs/ECSSystem.ts | 5 +++-- 5 files changed, 65 insertions(+), 63 deletions(-) diff --git a/assets/libs/ecs/ECS.ts b/assets/libs/ecs/ECS.ts index 595c8c2..48d6586 100644 --- a/assets/libs/ecs/ECS.ts +++ b/assets/libs/ecs/ECS.ts @@ -1,8 +1,7 @@ import { ECSComp } from "./ECSComp"; import { ECSEntity } from "./ECSEntity"; -import { ECSGroup } from "./ECSGroup"; import { ECSMatcher } from "./ECSMatcher"; -import { ECSModel } from "./ECSModel"; +import { CompCtor, CompType, ECSModel, EntityCtor } from "./ECSModel"; import { ECSComblockSystem, ECSRootSystem, ECSSystem } from "./ECSSystem"; /** Entity-Component-System(实体-组件-系统)框架 */ @@ -29,14 +28,7 @@ export module ecs { /** 处理游戏逻辑系统对象 - 继承此对象实现自定义业务逻辑 */ export const ComblockSystem = ECSComblockSystem; - /** 组件类型 */ - export type CompType = CompCtor | number; - //#region 接口 - /** 实体构造器接口 */ - export interface EntityCtor { - new(): T; - } /** 组件接口 */ export interface IComp { @@ -46,15 +38,6 @@ export module ecs { reset(): void; } - /** 组件构造器接口 */ - export interface CompCtor { - new(): T; - /** 组件编号 */ - tid: number; - /** 组件名 */ - compName: string; - } - /** 实体匹配器接口 */ export interface IMatcher { mid: number; @@ -189,23 +172,6 @@ export module ecs { return entity as T; } - /** - * 创建group,每个group只关心对应组件的添加和删除 - * @param matcher 实体筛选器 - */ - export function createGroup(matcher: ecs.IMatcher): ECSGroup { - let group = ECSModel.groups.get(matcher.mid); - if (!group) { - group = new ECSGroup(matcher); - ECSModel.groups.set(matcher.mid, group); - let careComponentTypeIds = matcher.indices; - for (let i = 0; i < careComponentTypeIds.length; i++) { - ECSModel.compAddOrRemove.get(careComponentTypeIds[i])!.push(group.onComponentAddOrRemove.bind(group)); - } - } - return group as unknown as ECSGroup; - } - /** * 动态查询实体 * @param matcher 匹配器 @@ -215,7 +181,7 @@ export module ecs { export function query(matcher: IMatcher): E[] { let group = ECSModel.groups.get(matcher.mid); if (!group) { - group = createGroup(matcher); + group = ECSModel.createGroup(matcher); ECSModel.eid2Entity.forEach(group.onComponentAddOrRemove, group); } return group.matchEntities as E[]; diff --git a/assets/libs/ecs/ECSEntity.ts b/assets/libs/ecs/ECSEntity.ts index ba5336a..e2b68df 100644 --- a/assets/libs/ecs/ECSEntity.ts +++ b/assets/libs/ecs/ECSEntity.ts @@ -1,6 +1,6 @@ import { ecs } from "./ECS"; import { ECSMask } from "./ECSMask"; -import { ECSModel } from "./ECSModel"; +import { CompCtor, CompType, ECSModel } from "./ECSModel"; //#region 辅助方法 @@ -24,13 +24,13 @@ function broadcastCompAddOrRemove(entity: ECSEntity, componentTypeId: number) { * 创建组件对象 * @param ctor */ -function createComp(ctor: ecs.CompCtor): T { +function createComp(ctor: CompCtor): T { var cct = ECSModel.compCtors[ctor.tid]; if (!cct) { throw Error(`没有找到该组件的构造函数,检查${ctor.compName}是否为不可构造的组件`); } let comps = ECSModel.compPools.get(ctor.tid)!; - let component = comps.pop() || new (cct as ecs.CompCtor); + let component = comps.pop() || new (cct as CompCtor); return component as T; } @@ -57,6 +57,7 @@ function destroyEntity(entity: ECSEntity) { //#endregion +/** ECS实体对象 */ export class ECSEntity { /** 实体唯一标识,不要手动修改 */ eid: number = -1; @@ -65,7 +66,7 @@ export class ECSEntity { /** 组件过滤数据 */ private mask = new ECSMask(); /** 当前实体身上附加的组件构造函数 */ - private compTid2Ctor: Map> = new Map(); + private compTid2Ctor: Map> = new Map(); /** 配合 entity.remove(Comp, false), 记录组件实例上的缓存数据,在添加时恢复原数据 */ private compTid2Obj: Map = new Map(); @@ -117,9 +118,9 @@ export class ECSEntity { */ add(obj: T): ECSEntity; add(ctor: number, isReAdd?: boolean): ECSEntity; - add(ctor: ecs.CompCtor, isReAdd?: boolean): T; - add(ctor: ecs.CompType, isReAdd?: boolean): T; - add(ctor: ecs.CompType | T, isReAdd: boolean = false): T | ECSEntity { + add(ctor: CompCtor, isReAdd?: boolean): T; + add(ctor: CompType, isReAdd?: boolean): T; + add(ctor: CompType | T, isReAdd: boolean = false): T | ECSEntity { if (typeof ctor === 'function') { let compTid = ctor.tid; if (ctor.tid === -1) { @@ -158,7 +159,7 @@ export class ECSEntity { return comp; } else { - let tmpCtor = (ctor.constructor as ecs.CompCtor); + let tmpCtor = (ctor.constructor as CompCtor); let compTid = tmpCtor.tid; // console.assert(compTid !== -1 || !compTid, '组件未注册!'); // console.assert(this.compTid2Ctor.has(compTid), '已存在该组件!'); @@ -188,7 +189,7 @@ export class ECSEntity { * @param ctors 组件类 * @returns */ - addComponents(...ctors: ecs.CompType[]) { + addComponents(...ctors: CompType[]) { for (let ctor of ctors) { this.add(ctor); } @@ -200,8 +201,8 @@ export class ECSEntity { * @param ctor 组件类 */ get(ctor: number): number; - get(ctor: ecs.CompCtor): T; - get(ctor: ecs.CompCtor | number): T { + get(ctor: CompCtor): T; + get(ctor: CompCtor | number): T { // @ts-ignore return this[ctor.compName]; } @@ -210,7 +211,7 @@ export class ECSEntity { * 组件是否在实体存在内 * @param ctor 组件类 */ - has(ctor: ecs.CompType): boolean { + has(ctor: CompType): boolean { if (typeof ctor == "number") { return this.mask.has(ctor); } @@ -226,7 +227,7 @@ export class ECSEntity { * 设置该参数为false,这样该组件对象会缓存在实体身上,下次重新添加组件时会将该组件对象添加回来,不会重新从组件缓存 * 池中拿一个组件来用。 */ - remove(ctor: ecs.CompType, isRecycle: boolean = true) { + remove(ctor: CompType, isRecycle: boolean = true) { let hasComp = false; //@ts-ignore let componentTypeId = ctor.tid; @@ -258,7 +259,7 @@ export class ECSEntity { } } - private _remove(comp: ecs.CompType) { + private _remove(comp: CompType) { this.remove(comp, false); } diff --git a/assets/libs/ecs/ECSMatcher.ts b/assets/libs/ecs/ECSMatcher.ts index 82969e0..fb87062 100644 --- a/assets/libs/ecs/ECSMatcher.ts +++ b/assets/libs/ecs/ECSMatcher.ts @@ -1,7 +1,7 @@ import { ecs } from "./ECS"; import { ECSEntity } from "./ECSEntity"; import { ECSMask } from "./ECSMask"; -import { ECSModel } from "./ECSModel"; +import { CompCtor, CompType, ECSModel } from "./ECSModel"; let macherId: number = 1; @@ -51,7 +51,7 @@ export class ECSMatcher implements ecs.IMatcher { * 组件间是或的关系,表示关注拥有任意一个这些组件的实体。 * @param args 组件索引 */ - anyOf(...args: ecs.CompType[]): ECSMatcher { + anyOf(...args: CompType[]): ECSMatcher { this.rules.push(new AnyOf(...args)); this.bindMatchMethod(); return this; @@ -61,7 +61,7 @@ export class ECSMatcher implements ecs.IMatcher { * 组件间是与的关系,表示关注拥有所有这些组件的实体。 * @param args 组件索引 */ - allOf(...args: ecs.CompType[]): ECSMatcher { + allOf(...args: CompType[]): ECSMatcher { this.rules.push(new AllOf(...args)); this.bindMatchMethod(); return this; @@ -74,9 +74,9 @@ export class ECSMatcher implements ecs.IMatcher { * 不是特殊情况不建议使用onlyOf。因为onlyOf会监听所有组件的添加和删除事件。 * @param args 组件索引 */ - onlyOf(...args: ecs.CompType[]): ECSMatcher { + onlyOf(...args: CompType[]): ECSMatcher { this.rules.push(new AllOf(...args)); - let otherTids: ecs.CompType[] = []; + let otherTids: CompType[] = []; for (let ctor of ECSModel.compCtors) { if (args.indexOf(ctor) < 0) { otherTids.push(ctor); @@ -91,7 +91,7 @@ export class ECSMatcher implements ecs.IMatcher { * 不包含指定的任意一个组件 * @param args */ - excludeOf(...args: ecs.CompType[]) { + excludeOf(...args: CompType[]) { this.rules.push(new ExcludeOf(...args)); this.bindMatchMethod(); return this; @@ -139,7 +139,7 @@ abstract class BaseOf { protected mask = new ECSMask(); - constructor(...args: ecs.CompType[]) { + constructor(...args: CompType[]) { let componentTypeId = -1; let len = args.length; for (let i = 0; i < len; i++) { @@ -147,7 +147,7 @@ abstract class BaseOf { componentTypeId = args[i] as number; } else { - componentTypeId = (args[i] as ecs.CompCtor).tid; + componentTypeId = (args[i] as CompCtor).tid; } if (componentTypeId == -1) { throw Error('存在没有注册的组件!'); diff --git a/assets/libs/ecs/ECSModel.ts b/assets/libs/ecs/ECSModel.ts index a612bbc..12afa5e 100644 --- a/assets/libs/ecs/ECSModel.ts +++ b/assets/libs/ecs/ECSModel.ts @@ -2,7 +2,7 @@ * @Author: dgflash * @Date: 2022-05-12 14:18:44 * @LastEditors: dgflash - * @LastEditTime: 2022-09-05 14:16:15 + * @LastEditTime: 2022-09-05 16:37:10 */ import { ecs } from "./ECS"; import { ECSEntity } from "./ECSEntity"; @@ -10,12 +10,29 @@ import { ECSGroup } from "./ECSGroup"; type CompAddOrRemove = (entity: ecs.Entity) => void; +/** 组件类型 */ +export type CompType = CompCtor | number; + +/** 实体构造器接口 */ +export interface EntityCtor { + new(): T; +} + +/** 组件构造器接口 */ +export interface CompCtor { + new(): T; + /** 组件编号 */ + tid: number; + /** 组件名 */ + compName: string; +} + /** ECS框架内部数据 */ export class ECSModel { /** 实体自增id */ static eid = 1; /** 实体造函数 */ - static entityCtors: Map, string> = new Map(); + static entityCtors: Map, string> = new Map(); /** 实体对象缓存池 */ static entityPool: Map = new Map(); /** 通过实体id查找实体对象 */ @@ -26,7 +43,7 @@ export class ECSModel { /** 组件缓存池 */ static compPools: Map = new Map(); /** 组件构造函数 */ - static compCtors: (ecs.CompCtor | number)[] = []; + static compCtors: (CompCtor | number)[] = []; /** * 每个组件的添加和删除的动作都要派送到“关心”它们的group上。goup对当前拥有或者之前(删除前)拥有该组件的实体进行组件规则判断。判断该实体是否满足group * 所期望的组件组合。 @@ -42,4 +59,21 @@ export class ECSModel { * key是组件的筛选规则,一个筛选规则对应一个group */ static groups: Map = new Map(); + + /** + * 创建group,每个group只关心对应组件的添加和删除 + * @param matcher 实体筛选器 + */ + static createGroup(matcher: ecs.IMatcher): ECSGroup { + let group = ECSModel.groups.get(matcher.mid); + if (!group) { + group = new ECSGroup(matcher); + ECSModel.groups.set(matcher.mid, group); + let careComponentTypeIds = matcher.indices; + for (let i = 0; i < careComponentTypeIds.length; i++) { + ECSModel.compAddOrRemove.get(careComponentTypeIds[i])!.push(group.onComponentAddOrRemove.bind(group)); + } + } + return group as unknown as ECSGroup; + } } \ No newline at end of file diff --git a/assets/libs/ecs/ECSSystem.ts b/assets/libs/ecs/ECSSystem.ts index f667a0c..67c4a56 100644 --- a/assets/libs/ecs/ECSSystem.ts +++ b/assets/libs/ecs/ECSSystem.ts @@ -1,6 +1,7 @@ import { ecs } from "./ECS"; import { ECSEntity } from "./ECSEntity"; import { ECSGroup } from "./ECSGroup"; +import { ECSModel } from "./ECSModel"; /** 继承此类实现具体业务逻辑的系统 */ export abstract class ECSComblockSystem { @@ -35,12 +36,12 @@ export abstract class ECSComblockSystem { this.removedEntities = new Map(); this.execute = this.execute1; - this.group = ecs.createGroup(this.filter()); + this.group = ECSModel.createGroup(this.filter()); this.group.watchEntityEnterAndRemove(this.enteredEntities, this.removedEntities); } else { this.execute = this.execute0; - this.group = ecs.createGroup(this.filter()); + this.group = ECSModel.createGroup(this.filter()); } if (hasFirstUpdate) {