Files
oops-plugin-framework/assets/libs/ecs/ECSSystem.ts
dgflash 5937f2faf5 1、优化语法
2、修复更新后的API注释
2024-09-04 21:23:53 +08:00

221 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ecs } from "./ECS";
import { ECSEntity } from "./ECSEntity";
import { ECSGroup } from "./ECSGroup";
import { ECSModel } from "./ECSModel";
/** 继承此类实现具体业务逻辑的系统 */
export abstract class ECSComblockSystem<E extends ECSEntity = ECSEntity> {
static s: boolean = true;
protected group: ECSGroup<E>;
protected dt: number = 0;
private enteredEntities: Map<number, E> = null!;
private removedEntities: Map<number, E> = null!;
private hasEntityEnter: boolean = false;
private hasEntityRemove: boolean = false;
private hasUpdate: boolean = false;
private tmpExecute: ((dt: number) => void) | null = null;
private execute!: (dt: number) => void;
/** 构造函数 */
constructor() {
let hasOwnProperty = Object.hasOwnProperty;
let prototype = Object.getPrototypeOf(this);
let hasEntityEnter = hasOwnProperty.call(prototype, 'entityEnter');
let hasEntityRemove = hasOwnProperty.call(prototype, 'entityRemove');
let hasFirstUpdate = hasOwnProperty.call(prototype, 'firstUpdate');
let hasUpdate = hasOwnProperty.call(prototype, 'update');
this.hasEntityEnter = hasEntityEnter;
this.hasEntityRemove = hasEntityRemove;
this.hasUpdate = hasUpdate;
if (hasEntityEnter || hasEntityRemove) {
this.enteredEntities = new Map<number, E>();
this.removedEntities = new Map<number, E>();
this.execute = this.execute1;
this.group = ECSModel.createGroup(this.filter());
this.group.watchEntityEnterAndRemove(this.enteredEntities, this.removedEntities);
}
else {
this.execute = this.execute0;
this.group = ECSModel.createGroup(this.filter());
}
if (hasFirstUpdate) {
this.tmpExecute = this.execute;
this.execute = this.updateOnce;
}
}
/** 系统实始化 */
init(): void {
}
/** 系统释放事件 */
onDestroy(): void {
}
/** 是否存在实体 */
hasEntity(): boolean {
return this.group.count > 0;
}
/**
* 先执行entityEnter最后执行firstUpdate
* @param dt
* @returns
*/
private updateOnce(dt: number) {
if (this.group.count === 0) {
return;
}
this.dt = dt;
// 处理刚进来的实体
if (this.enteredEntities.size > 0) {
var entities = this.enteredEntities.values();
for (let entity of entities) {
(this as unknown as ecs.IEntityEnterSystem).entityEnter(entity);
}
this.enteredEntities.clear();
}
// 只执行firstUpdate
for (let entity of this.group.matchEntities) {
(this as unknown as ecs.ISystemFirstUpdate).firstUpdate(entity);
}
this.execute = this.tmpExecute!;
this.execute(dt);
this.tmpExecute = null;
}
/**
* 只执行update
* @param dt
* @returns
*/
private execute0(dt: number): void {
if (this.group.count === 0) return;
this.dt = dt;
// 执行update
if (this.hasUpdate) {
for (let entity of this.group.matchEntities) {
(this as unknown as ecs.ISystemUpdate).update(entity);
}
}
}
/**
* 先执行entityRemove再执行entityEnter最后执行update
* @param dt
* @returns
*/
private execute1(dt: number): void {
let entities;
if (this.removedEntities.size > 0) {
if (this.hasEntityRemove) {
entities = this.removedEntities.values();
for (let entity of entities) {
(this as unknown as ecs.IEntityRemoveSystem).entityRemove(entity);
}
}
this.removedEntities.clear();
}
if (this.group.count === 0) return;
this.dt = dt;
// 处理刚进来的实体
if (this.enteredEntities!.size > 0) {
if (this.hasEntityEnter) {
entities = this.enteredEntities!.values();
for (let entity of entities) {
(this as unknown as ecs.IEntityEnterSystem).entityEnter(entity);
}
}
this.enteredEntities!.clear();
}
// 执行update
if (this.hasUpdate) {
for (let entity of this.group.matchEntities) {
(this as unknown as ecs.ISystemUpdate).update(entity);
}
}
}
/**
* 实体过滤规则
*
* 根据提供的组件过滤实体。
*/
abstract filter(): ecs.IMatcher;
}
/** 根System对游戏中的System遍历从这里开始一个System组合中只能有一个RootSystem可以有多个并行的RootSystem */
export class ECSRootSystem {
private executeSystemFlows: ECSComblockSystem[] = [];
private systemCnt: number = 0;
add(system: ECSSystem | ECSComblockSystem) {
if (system instanceof ECSSystem) {
// 将嵌套的System都“摊平”放在根System中进行遍历减少execute的频繁进入退出。
Array.prototype.push.apply(this.executeSystemFlows, system.comblockSystems);
}
else {
this.executeSystemFlows.push(system as ECSComblockSystem);
}
this.systemCnt = this.executeSystemFlows.length;
return this;
}
init() {
// 自动注册系统组件
ECSModel.systems.forEach(sys => this.add(sys));
// 初始化组件
this.executeSystemFlows.forEach(sys => sys.init());
}
execute(dt: number) {
for (let i = 0; i < this.systemCnt; i++) {
// @ts-ignore
this.executeSystemFlows[i].execute(dt);
}
}
clear() {
this.executeSystemFlows.forEach(sys => sys.onDestroy());
}
}
/** 系统组合器,用于将多个相同功能模块的系统逻辑上放在一起,系统也可以嵌套系统 */
export class ECSSystem {
private _comblockSystems: ECSComblockSystem[] = [];
get comblockSystems() {
return this._comblockSystems;
}
add(system: ECSSystem | ECSComblockSystem) {
if (system instanceof ECSSystem) {
Array.prototype.push.apply(this._comblockSystems, system._comblockSystems);
system._comblockSystems.length = 0;
}
else {
this._comblockSystems.push(system as ECSComblockSystem);
}
return this;
}
}