mirror of
https://gitee.com/dgflash/oops-plugin-framework.git
synced 2026-05-19 14:36:49 +08:00
ECS代码优化
This commit is contained in:
@@ -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<T> = CompCtor<T> | number;
|
||||
|
||||
//#region 接口
|
||||
/** 实体构造器接口 */
|
||||
export interface EntityCtor<T> {
|
||||
new(): T;
|
||||
}
|
||||
|
||||
/** 组件接口 */
|
||||
export interface IComp {
|
||||
@@ -46,15 +38,6 @@ export module ecs {
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
/** 组件构造器接口 */
|
||||
export interface CompCtor<T> {
|
||||
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<E extends ECSEntity = ECSEntity>(matcher: ecs.IMatcher): ECSGroup<E> {
|
||||
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<E>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态查询实体
|
||||
* @param matcher 匹配器
|
||||
@@ -215,7 +181,7 @@ export module ecs {
|
||||
export function query<E extends Entity = Entity>(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[];
|
||||
|
||||
@@ -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<T extends ecs.IComp>(ctor: ecs.CompCtor<T>): T {
|
||||
function createComp<T extends ecs.IComp>(ctor: CompCtor<T>): 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<T>);
|
||||
let component = comps.pop() || new (cct as CompCtor<T>);
|
||||
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<number, ecs.CompType<ecs.IComp>> = new Map();
|
||||
private compTid2Ctor: Map<number, CompType<ecs.IComp>> = new Map();
|
||||
/** 配合 entity.remove(Comp, false), 记录组件实例上的缓存数据,在添加时恢复原数据 */
|
||||
private compTid2Obj: Map<number, ecs.IComp> = new Map();
|
||||
|
||||
@@ -117,9 +118,9 @@ export class ECSEntity {
|
||||
*/
|
||||
add<T extends ecs.IComp>(obj: T): ECSEntity;
|
||||
add(ctor: number, isReAdd?: boolean): ECSEntity;
|
||||
add<T extends ecs.IComp>(ctor: ecs.CompCtor<T>, isReAdd?: boolean): T;
|
||||
add<T extends ecs.IComp>(ctor: ecs.CompType<T>, isReAdd?: boolean): T;
|
||||
add<T extends ecs.IComp>(ctor: ecs.CompType<T> | T, isReAdd: boolean = false): T | ECSEntity {
|
||||
add<T extends ecs.IComp>(ctor: CompCtor<T>, isReAdd?: boolean): T;
|
||||
add<T extends ecs.IComp>(ctor: CompType<T>, isReAdd?: boolean): T;
|
||||
add<T extends ecs.IComp>(ctor: CompType<T> | 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<T>);
|
||||
let tmpCtor = (ctor.constructor as CompCtor<T>);
|
||||
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<T extends ecs.IComp>(...ctors: ecs.CompType<T>[]) {
|
||||
addComponents<T extends ecs.IComp>(...ctors: CompType<T>[]) {
|
||||
for (let ctor of ctors) {
|
||||
this.add(ctor);
|
||||
}
|
||||
@@ -200,8 +201,8 @@ export class ECSEntity {
|
||||
* @param ctor 组件类
|
||||
*/
|
||||
get(ctor: number): number;
|
||||
get<T extends ecs.IComp>(ctor: ecs.CompCtor<T>): T;
|
||||
get<T extends ecs.IComp>(ctor: ecs.CompCtor<T> | number): T {
|
||||
get<T extends ecs.IComp>(ctor: CompCtor<T>): T;
|
||||
get<T extends ecs.IComp>(ctor: CompCtor<T> | number): T {
|
||||
// @ts-ignore
|
||||
return this[ctor.compName];
|
||||
}
|
||||
@@ -210,7 +211,7 @@ export class ECSEntity {
|
||||
* 组件是否在实体存在内
|
||||
* @param ctor 组件类
|
||||
*/
|
||||
has(ctor: ecs.CompType<ecs.IComp>): boolean {
|
||||
has(ctor: CompType<ecs.IComp>): boolean {
|
||||
if (typeof ctor == "number") {
|
||||
return this.mask.has(ctor);
|
||||
}
|
||||
@@ -226,7 +227,7 @@ export class ECSEntity {
|
||||
* 设置该参数为false,这样该组件对象会缓存在实体身上,下次重新添加组件时会将该组件对象添加回来,不会重新从组件缓存
|
||||
* 池中拿一个组件来用。
|
||||
*/
|
||||
remove(ctor: ecs.CompType<ecs.IComp>, isRecycle: boolean = true) {
|
||||
remove(ctor: CompType<ecs.IComp>, isRecycle: boolean = true) {
|
||||
let hasComp = false;
|
||||
//@ts-ignore
|
||||
let componentTypeId = ctor.tid;
|
||||
@@ -258,7 +259,7 @@ export class ECSEntity {
|
||||
}
|
||||
}
|
||||
|
||||
private _remove(comp: ecs.CompType<ecs.IComp>) {
|
||||
private _remove(comp: CompType<ecs.IComp>) {
|
||||
this.remove(comp, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ecs.IComp>[]): ECSMatcher {
|
||||
anyOf(...args: CompType<ecs.IComp>[]): 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<ecs.IComp>[]): ECSMatcher {
|
||||
allOf(...args: CompType<ecs.IComp>[]): 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<ecs.IComp>[]): ECSMatcher {
|
||||
onlyOf(...args: CompType<ecs.IComp>[]): ECSMatcher {
|
||||
this.rules.push(new AllOf(...args));
|
||||
let otherTids: ecs.CompType<ecs.IComp>[] = [];
|
||||
let otherTids: CompType<ecs.IComp>[] = [];
|
||||
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<ecs.IComp>[]) {
|
||||
excludeOf(...args: CompType<ecs.IComp>[]) {
|
||||
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<ecs.IComp>[]) {
|
||||
constructor(...args: CompType<ecs.IComp>[]) {
|
||||
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<ecs.IComp>).tid;
|
||||
componentTypeId = (args[i] as CompCtor<ecs.IComp>).tid;
|
||||
}
|
||||
if (componentTypeId == -1) {
|
||||
throw Error('存在没有注册的组件!');
|
||||
|
||||
@@ -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<T> = CompCtor<T> | number;
|
||||
|
||||
/** 实体构造器接口 */
|
||||
export interface EntityCtor<T> {
|
||||
new(): T;
|
||||
}
|
||||
|
||||
/** 组件构造器接口 */
|
||||
export interface CompCtor<T> {
|
||||
new(): T;
|
||||
/** 组件编号 */
|
||||
tid: number;
|
||||
/** 组件名 */
|
||||
compName: string;
|
||||
}
|
||||
|
||||
/** ECS框架内部数据 */
|
||||
export class ECSModel {
|
||||
/** 实体自增id */
|
||||
static eid = 1;
|
||||
/** 实体造函数 */
|
||||
static entityCtors: Map<ecs.EntityCtor<any>, string> = new Map();
|
||||
static entityCtors: Map<EntityCtor<any>, string> = new Map();
|
||||
/** 实体对象缓存池 */
|
||||
static entityPool: Map<string, ECSEntity[]> = new Map();
|
||||
/** 通过实体id查找实体对象 */
|
||||
@@ -26,7 +43,7 @@ export class ECSModel {
|
||||
/** 组件缓存池 */
|
||||
static compPools: Map<number, ecs.IComp[]> = new Map();
|
||||
/** 组件构造函数 */
|
||||
static compCtors: (ecs.CompCtor<any> | number)[] = [];
|
||||
static compCtors: (CompCtor<any> | number)[] = [];
|
||||
/**
|
||||
* 每个组件的添加和删除的动作都要派送到“关心”它们的group上。goup对当前拥有或者之前(删除前)拥有该组件的实体进行组件规则判断。判断该实体是否满足group
|
||||
* 所期望的组件组合。
|
||||
@@ -42,4 +59,21 @@ export class ECSModel {
|
||||
* key是组件的筛选规则,一个筛选规则对应一个group
|
||||
*/
|
||||
static groups: Map<number, ECSGroup> = new Map();
|
||||
|
||||
/**
|
||||
* 创建group,每个group只关心对应组件的添加和删除
|
||||
* @param matcher 实体筛选器
|
||||
*/
|
||||
static createGroup<E extends ECSEntity = ECSEntity>(matcher: ecs.IMatcher): ECSGroup<E> {
|
||||
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<E>;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ecs } from "./ECS";
|
||||
import { ECSEntity } from "./ECSEntity";
|
||||
import { ECSGroup } from "./ECSGroup";
|
||||
import { ECSModel } from "./ECSModel";
|
||||
|
||||
/** 继承此类实现具体业务逻辑的系统 */
|
||||
export abstract class ECSComblockSystem<E extends ECSEntity = ECSEntity> {
|
||||
@@ -35,12 +36,12 @@ export abstract class ECSComblockSystem<E extends ECSEntity = ECSEntity> {
|
||||
this.removedEntities = new Map<number, E>();
|
||||
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user