重构项目结构:整理gitignore,移动source目录到根目录,统一依赖管理

This commit is contained in:
YHH
2025-06-09 14:51:26 +08:00
parent ec5f70ecfc
commit f2d3880a06
89 changed files with 3912 additions and 6820 deletions

337
src/Core.ts Normal file
View File

@@ -0,0 +1,337 @@
import { Emitter } from './Utils/Emitter';
import { CoreEvents } from './ECS/CoreEvents';
import { GlobalManager } from './Utils/GlobalManager';
import { TimerManager } from './Utils/Timers/TimerManager';
import { ITimer } from './Utils/Timers/ITimer';
import { Time } from './Utils/Time';
import { PerformanceMonitor } from './Utils/PerformanceMonitor';
import { PoolManager } from './Utils/Pool';
import { ECSFluentAPI, createECSAPI } from './ECS/Core/FluentAPI';
import { Scene } from './ECS/Scene';
/**
* 游戏引擎核心类
*
* 负责管理游戏的生命周期、场景切换、全局管理器和定时器系统。
* 提供统一的游戏循环和事件分发机制。
*
* @example
* ```typescript
* // 创建核心实例
* const core = Core.create(true);
*
* // 设置场景
* Core.scene = new MyScene();
*
* // 调度定时器
* Core.schedule(1.0, false, null, (timer) => {
* console.log("1秒后执行");
* });
* ```
*/
export class Core {
/**
* 核心事件发射器
*
* 用于发布和订阅核心级别的事件,如帧更新、场景切换等。
*/
public static emitter: Emitter<CoreEvents>;
/**
* 游戏暂停状态
*
* 当设置为true时游戏循环将暂停执行。
*/
public static paused = false;
/**
* 全局核心实例
*/
private static _instance: Core;
/**
* 实体系统启用状态
*
* 控制是否启用ECS实体系统功能。
*/
public static entitySystemsEnabled: boolean;
/**
* 调试模式标志
*
* 在调试模式下会启用额外的性能监控和错误检查。
*/
public readonly debug: boolean;
/**
* 待切换的场景
*
* 存储下一帧要切换到的场景实例。
*/
public _nextScene: Scene | null = null;
/**
* 全局管理器集合
*
* 存储所有注册的全局管理器实例。
*/
public _globalManagers: GlobalManager[] = [];
/**
* 定时器管理器
*
* 负责管理所有的游戏定时器。
*/
public _timerManager: TimerManager;
/**
* 性能监控器
*
* 监控游戏性能并提供优化建议。
*/
public _performanceMonitor: PerformanceMonitor;
/**
* 对象池管理器
*
* 管理所有对象池的生命周期。
*/
public _poolManager: PoolManager;
/**
* ECS流式API
*
* 提供便捷的ECS操作接口。
*/
public _ecsAPI?: ECSFluentAPI;
/**
* 当前活动场景
*/
public _scene?: Scene;
/**
* 创建核心实例
*
* @param debug - 是否启用调试模式默认为true
* @param enableEntitySystems - 是否启用实体系统默认为true
*/
private constructor(debug: boolean = true, enableEntitySystems: boolean = true) {
Core._instance = this;
Core.emitter = new Emitter<CoreEvents>();
Core.emitter.addObserver(CoreEvents.frameUpdated, this.update, this);
// 初始化管理器
this._timerManager = new TimerManager();
Core.registerGlobalManager(this._timerManager);
// 初始化性能监控器
this._performanceMonitor = PerformanceMonitor.instance;
// 初始化对象池管理器
this._poolManager = PoolManager.getInstance();
Core.entitySystemsEnabled = enableEntitySystems;
this.debug = debug;
this.initialize();
}
/**
* 获取核心实例
*
* @returns 全局核心实例
*/
public static get Instance() {
return this._instance;
}
/**
* 获取当前活动的场景
*
* @returns 当前场景实例如果没有则返回null
*/
public static get scene(): Scene | null {
if (!this._instance)
return null;
return this._instance._scene || null;
}
/**
* 设置当前活动的场景
*
* 如果当前没有场景,会立即切换;否则会在下一帧切换。
*
* @param value - 要设置的场景实例
* @throws {Error} 当场景为空时抛出错误
*/
public static set scene(value: Scene | null) {
if (!value) return;
if (!value) {
throw new Error("场景不能为空");
}
if (this._instance._scene == null) {
this._instance._scene = value;
this._instance.onSceneChanged();
this._instance._scene.begin();
} else {
this._instance._nextScene = value;
}
}
/**
* 创建Core实例
*
* 如果实例已存在,则返回现有实例。
*
* @param debug - 是否为调试模式默认为true
* @returns Core实例
*/
public static create(debug: boolean = true): Core {
if (this._instance == null) {
this._instance = new Core(debug);
}
return this._instance;
}
/**
* 注册全局管理器
*
* 将管理器添加到全局管理器列表中,并启用它。
*
* @param manager - 要注册的全局管理器
*/
public static registerGlobalManager(manager: GlobalManager) {
this._instance._globalManagers.push(manager);
manager.enabled = true;
}
/**
* 注销全局管理器
*
* 从全局管理器列表中移除管理器,并禁用它。
*
* @param manager - 要注销的全局管理器
*/
public static unregisterGlobalManager(manager: GlobalManager) {
this._instance._globalManagers.splice(this._instance._globalManagers.indexOf(manager), 1);
manager.enabled = false;
}
/**
* 获取指定类型的全局管理器
*
* @param type - 管理器类型构造函数
* @returns 管理器实例如果未找到则返回null
*/
public static getGlobalManager<T extends GlobalManager>(type: new (...args: any[]) => T): T | null {
for (const manager of this._instance._globalManagers) {
if (manager instanceof type)
return manager as T;
}
return null;
}
/**
* 调度定时器
*
* 创建一个定时器,在指定时间后执行回调函数。
*
* @param timeInSeconds - 延迟时间(秒)
* @param repeats - 是否重复执行默认为false
* @param context - 回调函数的上下文默认为null
* @param onTime - 定时器触发时的回调函数
* @returns 创建的定时器实例
*/
public static schedule(timeInSeconds: number, repeats: boolean = false, context: any = null, onTime: (timer: ITimer) => void) {
return this._instance._timerManager.schedule(timeInSeconds, repeats, context, onTime);
}
/**
* 获取ECS流式API
*
* @returns ECS API实例如果未初始化则返回null
*/
public static get ecsAPI(): ECSFluentAPI | null {
return this._instance?._ecsAPI || null;
}
/**
* 场景切换回调
*
* 在场景切换时调用,用于重置时间系统等。
*/
public onSceneChanged() {
Time.sceneChanged();
// 初始化ECS API如果场景支持
if (this._scene && typeof (this._scene as any).querySystem !== 'undefined') {
const scene = this._scene as any;
this._ecsAPI = createECSAPI(scene, scene.querySystem, scene.eventSystem);
}
}
/**
* 初始化核心系统
*
* 执行核心系统的初始化逻辑。
*/
protected initialize() {
// 核心系统初始化
}
/**
* 游戏主循环更新
*
* 每帧调用,负责更新时间系统、全局管理器和当前场景。
*
* @param currentTime - 当前时间戳,默认为-1使用系统时间
*/
protected update(currentTime: number = -1): void {
if (Core.paused) return;
// 开始性能监控
const frameStartTime = this._performanceMonitor.startMonitoring('Core.update');
Time.update(currentTime);
// 更新FPS监控如果性能监控器支持
if (typeof (this._performanceMonitor as any).updateFPS === 'function') {
(this._performanceMonitor as any).updateFPS(Time.deltaTime);
}
// 更新全局管理器
const managersStartTime = this._performanceMonitor.startMonitoring('GlobalManagers.update');
for (const globalManager of this._globalManagers) {
if (globalManager.enabled)
globalManager.update();
}
this._performanceMonitor.endMonitoring('GlobalManagers.update', managersStartTime, this._globalManagers.length);
// 更新对象池管理器
this._poolManager.update();
// 处理场景切换
if (this._nextScene != null) {
if (this._scene != null)
this._scene.end();
this._scene = this._nextScene;
this._nextScene = null;
this.onSceneChanged();
this._scene.begin();
}
// 更新当前场景
if (this._scene != null && this._scene.update) {
const sceneStartTime = this._performanceMonitor.startMonitoring('Scene.update');
this._scene.update();
const entityCount = (this._scene as any).entities?.count || 0;
this._performanceMonitor.endMonitoring('Scene.update', sceneStartTime, entityCount);
}
// 结束性能监控
this._performanceMonitor.endMonitoring('Core.update', frameStartTime);
}
}

158
src/ECS/Component.ts Normal file
View File

@@ -0,0 +1,158 @@
import type { IComponent } from '../Types';
/**
* 游戏组件基类
*
* ECS架构中的组件Component用于实现具体的游戏功能。
* 组件包含数据和行为,可以被添加到实体上以扩展实体的功能。
*
* @example
* ```typescript
* class HealthComponent extends Component {
* public health: number = 100;
*
* public takeDamage(damage: number): void {
* this.health -= damage;
* if (this.health <= 0) {
* this.entity.destroy();
* }
* }
* }
* ```
*/
export abstract class Component implements IComponent {
/**
* 组件ID生成器
*
* 用于为每个组件分配唯一的ID。
*/
public static _idGenerator: number = 0;
/**
* 组件唯一标识符
*
* 在整个游戏生命周期中唯一的数字ID。
*/
public readonly id: number;
/**
* 组件所属的实体
*
* 指向拥有此组件的实体实例。
*/
public entity!: Entity;
/**
* 组件启用状态
*
* 控制组件是否参与更新循环。
*/
private _enabled: boolean = true;
/**
* 更新顺序
*
* 决定组件在更新循环中的执行顺序。
*/
private _updateOrder: number = 0;
/**
* 创建组件实例
*
* 自动分配唯一ID给组件。
*/
constructor() {
this.id = Component._idGenerator++;
}
/**
* 获取组件启用状态
*
* 组件的实际启用状态取决于自身状态和所属实体的状态。
*
* @returns 如果组件和所属实体都启用则返回true
*/
public get enabled(): boolean {
return this.entity ? this.entity.enabled && this._enabled : this._enabled;
}
/**
* 设置组件启用状态
*
* 当状态改变时会触发相应的生命周期回调。
*
* @param value - 新的启用状态
*/
public set enabled(value: boolean) {
if (this._enabled !== value) {
this._enabled = value;
if (this._enabled) {
this.onEnabled();
} else {
this.onDisabled();
}
}
}
/**
* 获取更新顺序
*
* @returns 组件的更新顺序值
*/
public get updateOrder(): number {
return this._updateOrder;
}
/**
* 设置更新顺序
*
* @param value - 新的更新顺序值
*/
public set updateOrder(value: number) {
this._updateOrder = value;
}
/**
* 组件添加到实体时的回调
*
* 当组件被添加到实体时调用,可以在此方法中进行初始化操作。
*/
public onAddedToEntity(): void {
}
/**
* 组件从实体移除时的回调
*
* 当组件从实体中移除时调用,可以在此方法中进行清理操作。
*/
public onRemovedFromEntity(): void {
}
/**
* 组件启用时的回调
*
* 当组件被启用时调用。
*/
public onEnabled(): void {
}
/**
* 组件禁用时的回调
*
* 当组件被禁用时调用。
*/
public onDisabled(): void {
}
/**
* 更新组件
*
* 每帧调用,用于更新组件的逻辑。
* 子类应该重写此方法来实现具体的更新逻辑。
*/
public update(): void {
}
}
// 避免循环引用在文件末尾导入Entity
import type { Entity } from './Entity';

View File

@@ -0,0 +1,27 @@
/**
* 可更新接口
* 当添加到组件时只要组件和实体被启用就会在每帧调用update方法
*/
export interface IUpdatable {
enabled: boolean;
updateOrder: number;
update(): void;
}
/**
* 用于比较组件更新排序的比较器
*/
export class IUpdatableComparer {
public compare(a: IUpdatable, b: IUpdatable): number {
return a.updateOrder - b.updateOrder;
}
}
/**
* 检查对象是否实现了IUpdatable接口
* @param props 要检查的对象
* @returns 如果实现了IUpdatable接口返回true否则返回false
*/
export function isIUpdatable(props: any): props is IUpdatable {
return typeof (props as IUpdatable)['update'] !== 'undefined';
}

View File

@@ -0,0 +1,64 @@
import type { Scene } from '../Scene';
/**
* 场景组件基类
* 附加到场景的组件,用于实现场景级别的功能
*/
export class SceneComponent {
/** 组件所属的场景 */
public scene!: Scene;
/** 更新顺序 */
public updateOrder: number = 0;
/** 是否启用 */
private _enabled: boolean = true;
/** 获取是否启用 */
public get enabled(): boolean {
return this._enabled;
}
/** 设置是否启用 */
public set enabled(value: boolean) {
if (this._enabled !== value) {
this._enabled = value;
if (this._enabled) {
this.onEnabled();
} else {
this.onDisabled();
}
}
}
/**
* 当组件启用时调用
*/
public onEnabled(): void {
}
/**
* 当组件禁用时调用
*/
public onDisabled(): void {
}
/**
* 当组件从场景中移除时调用
*/
public onRemovedFromScene(): void {
}
/**
* 每帧更新
*/
public update(): void {
}
/**
* 比较组件的更新顺序
* @param other 其他组件
* @returns 比较结果
*/
public compare(other: SceneComponent): number {
return this.updateOrder - other.updateOrder;
}
}

View File

@@ -0,0 +1,261 @@
import { Entity } from '../Entity';
import { ComponentType } from './ComponentStorage';
/**
* 原型标识符
*/
export type ArchetypeId = string;
/**
* 原型数据结构
*/
export interface Archetype {
/** 原型唯一标识符 */
id: ArchetypeId;
/** 包含的组件类型 */
componentTypes: ComponentType[];
/** 属于该原型的实体列表 */
entities: Entity[];
/** 原型创建时间 */
createdAt: number;
/** 最后更新时间 */
updatedAt: number;
}
/**
* 原型查询结果
*/
export interface ArchetypeQueryResult {
/** 匹配的原型列表 */
archetypes: Archetype[];
/** 所有匹配实体的总数 */
totalEntities: number;
/** 查询执行时间(毫秒) */
executionTime: number;
/** 是否使用了缓存 */
fromCache: boolean;
}
/**
* Archetype系统
*
* 根据实体的组件组合将实体分组到不同的原型中,提供高效的查询性能。
*/
export class ArchetypeSystem {
/** 所有原型的映射表 */
private _archetypes = new Map<ArchetypeId, Archetype>();
/** 实体到原型的映射 */
private _entityToArchetype = new Map<Entity, Archetype>();
/** 组件类型到原型的映射 */
private _componentToArchetypes = new Map<ComponentType, Set<Archetype>>();
/** 查询缓存 */
private _queryCache = new Map<string, {
result: ArchetypeQueryResult;
timestamp: number;
}>();
private _cacheTimeout = 5000;
private _maxCacheSize = 100;
/**
* 添加实体到原型系统
*/
public addEntity(entity: Entity): void {
const componentTypes = this.getEntityComponentTypes(entity);
const archetypeId = this.generateArchetypeId(componentTypes);
let archetype = this._archetypes.get(archetypeId);
if (!archetype) {
archetype = this.createArchetype(componentTypes);
}
archetype.entities.push(entity);
archetype.updatedAt = Date.now();
this._entityToArchetype.set(entity, archetype);
this.updateComponentIndexes(archetype, componentTypes, true);
this.invalidateQueryCache();
}
/**
* 从原型系统中移除实体
*/
public removeEntity(entity: Entity): void {
const archetype = this._entityToArchetype.get(entity);
if (!archetype) return;
const index = archetype.entities.indexOf(entity);
if (index !== -1) {
archetype.entities.splice(index, 1);
archetype.updatedAt = Date.now();
}
this._entityToArchetype.delete(entity);
this.invalidateQueryCache();
}
/**
* 查询包含指定组件组合的原型
*/
public queryArchetypes(componentTypes: ComponentType[], operation: 'AND' | 'OR' = 'AND'): ArchetypeQueryResult {
const startTime = performance.now();
const cacheKey = `${operation}:${componentTypes.map(t => t.name).sort().join(',')}`;
// 检查缓存
const cached = this._queryCache.get(cacheKey);
if (cached && (Date.now() - cached.timestamp < this._cacheTimeout)) {
return {
...cached.result,
executionTime: performance.now() - startTime,
fromCache: true
};
}
const matchingArchetypes: Archetype[] = [];
let totalEntities = 0;
if (operation === 'AND') {
for (const archetype of this._archetypes.values()) {
if (this.archetypeContainsAllComponents(archetype, componentTypes)) {
matchingArchetypes.push(archetype);
totalEntities += archetype.entities.length;
}
}
} else {
const foundArchetypes = new Set<Archetype>();
for (const componentType of componentTypes) {
const archetypes = this._componentToArchetypes.get(componentType);
if (archetypes) {
for (const archetype of archetypes) {
foundArchetypes.add(archetype);
}
}
}
for (const archetype of foundArchetypes) {
matchingArchetypes.push(archetype);
totalEntities += archetype.entities.length;
}
}
const result: ArchetypeQueryResult = {
archetypes: matchingArchetypes,
totalEntities,
executionTime: performance.now() - startTime,
fromCache: false
};
// 缓存结果
this._queryCache.set(cacheKey, {
result,
timestamp: Date.now()
});
return result;
}
/**
* 获取实体所属的原型
*/
public getEntityArchetype(entity: Entity): Archetype | undefined {
return this._entityToArchetype.get(entity);
}
/**
* 获取所有原型
*/
public getAllArchetypes(): Archetype[] {
return Array.from(this._archetypes.values());
}
/**
* 清空所有数据
*/
public clear(): void {
this._archetypes.clear();
this._entityToArchetype.clear();
this._componentToArchetypes.clear();
this._queryCache.clear();
}
/**
* 获取实体的组件类型列表
*/
private getEntityComponentTypes(entity: Entity): ComponentType[] {
return entity.components.map(component => component.constructor as ComponentType);
}
/**
* 生成原型ID
*/
private generateArchetypeId(componentTypes: ComponentType[]): ArchetypeId {
return componentTypes
.map(type => type.name)
.sort()
.join('|');
}
/**
* 创建新原型
*/
private createArchetype(componentTypes: ComponentType[]): Archetype {
const id = this.generateArchetypeId(componentTypes);
const archetype: Archetype = {
id,
componentTypes: [...componentTypes],
entities: [],
createdAt: Date.now(),
updatedAt: Date.now()
};
this._archetypes.set(id, archetype);
return archetype;
}
/**
* 检查原型是否包含所有指定组件
*/
private archetypeContainsAllComponents(archetype: Archetype, componentTypes: ComponentType[]): boolean {
for (const componentType of componentTypes) {
if (!archetype.componentTypes.includes(componentType)) {
return false;
}
}
return true;
}
/**
* 更新组件索引
*/
private updateComponentIndexes(archetype: Archetype, componentTypes: ComponentType[], add: boolean): void {
for (const componentType of componentTypes) {
let archetypes = this._componentToArchetypes.get(componentType);
if (!archetypes) {
archetypes = new Set();
this._componentToArchetypes.set(componentType, archetypes);
}
if (add) {
archetypes.add(archetype);
} else {
archetypes.delete(archetype);
if (archetypes.size === 0) {
this._componentToArchetypes.delete(componentType);
}
}
}
}
/**
* 使查询缓存失效
*/
private invalidateQueryCache(): void {
this._queryCache.clear();
}
}

View File

@@ -0,0 +1,187 @@
/**
* 位掩码优化器,用于预计算和缓存常用的组件掩码
*/
export class BitMaskOptimizer {
private static instance: BitMaskOptimizer;
private maskCache = new Map<string, bigint>();
private componentTypeMap = new Map<string, number>();
private nextComponentId = 0;
private constructor() {}
static getInstance(): BitMaskOptimizer {
if (!BitMaskOptimizer.instance) {
BitMaskOptimizer.instance = new BitMaskOptimizer();
}
return BitMaskOptimizer.instance;
}
/**
* 注册组件类型
*/
registerComponentType(componentName: string): number {
if (!this.componentTypeMap.has(componentName)) {
this.componentTypeMap.set(componentName, this.nextComponentId++);
}
return this.componentTypeMap.get(componentName)!;
}
/**
* 获取组件类型ID
*/
getComponentTypeId(componentName: string): number | undefined {
return this.componentTypeMap.get(componentName);
}
/**
* 创建单个组件的掩码
*/
createSingleComponentMask(componentName: string): bigint {
const cacheKey = `single:${componentName}`;
if (this.maskCache.has(cacheKey)) {
return this.maskCache.get(cacheKey)!;
}
const componentId = this.getComponentTypeId(componentName);
if (componentId === undefined) {
throw new Error(`Component type not registered: ${componentName}`);
}
const mask = 1n << BigInt(componentId);
this.maskCache.set(cacheKey, mask);
return mask;
}
/**
* 创建多个组件的组合掩码
*/
createCombinedMask(componentNames: string[]): bigint {
const sortedNames = [...componentNames].sort();
const cacheKey = `combined:${sortedNames.join(',')}`;
if (this.maskCache.has(cacheKey)) {
return this.maskCache.get(cacheKey)!;
}
let mask = 0n;
for (const componentName of componentNames) {
const componentId = this.getComponentTypeId(componentName);
if (componentId === undefined) {
throw new Error(`Component type not registered: ${componentName}`);
}
mask |= 1n << BigInt(componentId);
}
this.maskCache.set(cacheKey, mask);
return mask;
}
/**
* 检查掩码是否包含指定组件
*/
maskContainsComponent(mask: bigint, componentName: string): boolean {
const componentMask = this.createSingleComponentMask(componentName);
return (mask & componentMask) !== 0n;
}
/**
* 检查掩码是否包含所有指定组件
*/
maskContainsAllComponents(mask: bigint, componentNames: string[]): boolean {
const requiredMask = this.createCombinedMask(componentNames);
return (mask & requiredMask) === requiredMask;
}
/**
* 检查掩码是否包含任一指定组件
*/
maskContainsAnyComponent(mask: bigint, componentNames: string[]): boolean {
const anyMask = this.createCombinedMask(componentNames);
return (mask & anyMask) !== 0n;
}
/**
* 添加组件到掩码
*/
addComponentToMask(mask: bigint, componentName: string): bigint {
const componentMask = this.createSingleComponentMask(componentName);
return mask | componentMask;
}
/**
* 从掩码中移除组件
*/
removeComponentFromMask(mask: bigint, componentName: string): bigint {
const componentMask = this.createSingleComponentMask(componentName);
return mask & ~componentMask;
}
/**
* 预计算常用掩码组合
*/
precomputeCommonMasks(commonCombinations: string[][]): void {
for (const combination of commonCombinations) {
this.createCombinedMask(combination);
}
}
/**
* 获取掩码缓存统计信息
*/
getCacheStats(): { size: number; componentTypes: number } {
return {
size: this.maskCache.size,
componentTypes: this.componentTypeMap.size
};
}
/**
* 清空缓存
*/
clearCache(): void {
this.maskCache.clear();
}
/**
* 重置优化器
*/
reset(): void {
this.maskCache.clear();
this.componentTypeMap.clear();
this.nextComponentId = 0;
}
/**
* 将掩码转换为组件名称数组
*/
maskToComponentNames(mask: bigint): string[] {
const componentNames: string[] = [];
for (const [componentName, componentId] of this.componentTypeMap) {
const componentMask = 1n << BigInt(componentId);
if ((mask & componentMask) !== 0n) {
componentNames.push(componentName);
}
}
return componentNames;
}
/**
* 获取掩码中组件的数量
*/
getComponentCount(mask: bigint): number {
let count = 0;
let tempMask = mask;
while (tempMask !== 0n) {
if ((tempMask & 1n) !== 0n) {
count++;
}
tempMask >>= 1n;
}
return count;
}
}

View File

@@ -0,0 +1,488 @@
import { Entity } from '../Entity';
import { Component } from '../Component';
import { ComponentType } from './ComponentStorage';
/**
* 组件索引类型
*/
export enum IndexType {
/** 哈希索引 - 最快查找 */
HASH = 'hash',
/** 位图索引 - 内存高效 */
BITMAP = 'bitmap',
/** 排序索引 - 支持范围查询 */
SORTED = 'sorted'
}
/**
* 索引统计信息
*/
export interface IndexStats {
/** 索引类型 */
type: IndexType;
/** 索引大小 */
size: number;
/** 内存使用量(字节) */
memoryUsage: number;
/** 查询次数 */
queryCount: number;
/** 平均查询时间(毫秒) */
avgQueryTime: number;
/** 最后更新时间 */
lastUpdated: number;
}
/**
* 组件索引接口
*/
export interface IComponentIndex {
/** 索引类型 */
readonly type: IndexType;
/** 添加实体到索引 */
addEntity(entity: Entity): void;
/** 从索引中移除实体 */
removeEntity(entity: Entity): void;
/** 查询包含指定组件的实体 */
query(componentType: ComponentType): Set<Entity>;
/** 批量查询多个组件 */
queryMultiple(componentTypes: ComponentType[], operation: 'AND' | 'OR'): Set<Entity>;
/** 清空索引 */
clear(): void;
/** 获取索引统计信息 */
getStats(): IndexStats;
}
/**
* 哈希索引实现
*
* 使用Map数据结构提供O(1)的查找性能。
* 适合大多数查询场景。
*/
export class HashComponentIndex implements IComponentIndex {
public readonly type = IndexType.HASH;
private _componentToEntities = new Map<ComponentType, Set<Entity>>();
private _entityToComponents = new Map<Entity, Set<ComponentType>>();
private _queryCount = 0;
private _totalQueryTime = 0;
private _lastUpdated = Date.now();
public addEntity(entity: Entity): void {
const components = entity.components;
const componentTypes = new Set<ComponentType>();
for (const component of components) {
const componentType = component.constructor as ComponentType;
componentTypes.add(componentType);
let entities = this._componentToEntities.get(componentType);
if (!entities) {
entities = new Set();
this._componentToEntities.set(componentType, entities);
}
entities.add(entity);
}
this._entityToComponents.set(entity, componentTypes);
this._lastUpdated = Date.now();
}
public removeEntity(entity: Entity): void {
const componentTypes = this._entityToComponents.get(entity);
if (!componentTypes) return;
for (const componentType of componentTypes) {
const entities = this._componentToEntities.get(componentType);
if (entities) {
entities.delete(entity);
if (entities.size === 0) {
this._componentToEntities.delete(componentType);
}
}
}
this._entityToComponents.delete(entity);
this._lastUpdated = Date.now();
}
public query(componentType: ComponentType): Set<Entity> {
const startTime = performance.now();
const result = new Set(this._componentToEntities.get(componentType) || []);
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return result;
}
public queryMultiple(componentTypes: ComponentType[], operation: 'AND' | 'OR'): Set<Entity> {
const startTime = performance.now();
if (componentTypes.length === 0) {
return new Set();
}
if (componentTypes.length === 1) {
return this.query(componentTypes[0]);
}
let result: Set<Entity>;
if (operation === 'AND') {
let smallestSet: Set<Entity> | undefined;
let smallestSize = Infinity;
for (const componentType of componentTypes) {
const entities = this._componentToEntities.get(componentType);
if (!entities || entities.size === 0) {
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return new Set();
}
if (entities.size < smallestSize) {
smallestSize = entities.size;
smallestSet = entities;
}
}
result = new Set();
if (smallestSet) {
for (const entity of smallestSet) {
let hasAll = true;
for (const componentType of componentTypes) {
const entities = this._componentToEntities.get(componentType);
if (!entities || !entities.has(entity)) {
hasAll = false;
break;
}
}
if (hasAll) {
result.add(entity);
}
}
}
} else {
result = new Set();
for (const componentType of componentTypes) {
const entities = this._componentToEntities.get(componentType);
if (entities) {
for (const entity of entities) {
result.add(entity);
}
}
}
}
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return result;
}
public clear(): void {
this._componentToEntities.clear();
this._entityToComponents.clear();
this._lastUpdated = Date.now();
}
public getStats(): IndexStats {
let memoryUsage = 0;
memoryUsage += this._componentToEntities.size * 64;
memoryUsage += this._entityToComponents.size * 64;
for (const entities of this._componentToEntities.values()) {
memoryUsage += entities.size * 8;
}
for (const components of this._entityToComponents.values()) {
memoryUsage += components.size * 8;
}
return {
type: this.type,
size: this._componentToEntities.size,
memoryUsage,
queryCount: this._queryCount,
avgQueryTime: this._queryCount > 0 ? this._totalQueryTime / this._queryCount : 0,
lastUpdated: this._lastUpdated
};
}
}
/**
* 位图索引实现
*
* 使用位操作进行快速集合运算,内存效率高。
* 适合有限组件类型和大量实体的场景。
*/
export class BitmapComponentIndex implements IComponentIndex {
public readonly type = IndexType.BITMAP;
private _componentTypeToBit = new Map<ComponentType, number>();
private _entityToBitmap = new Map<Entity, number>();
private _bitToEntities = new Map<number, Set<Entity>>();
private _nextBit = 0;
private _queryCount = 0;
private _totalQueryTime = 0;
private _lastUpdated = Date.now();
public addEntity(entity: Entity): void {
let bitmap = 0;
for (const component of entity.components) {
const componentType = component.constructor as ComponentType;
let bit = this._componentTypeToBit.get(componentType);
if (bit === undefined) {
bit = this._nextBit++;
this._componentTypeToBit.set(componentType, bit);
}
bitmap |= (1 << bit);
let entities = this._bitToEntities.get(1 << bit);
if (!entities) {
entities = new Set();
this._bitToEntities.set(1 << bit, entities);
}
entities.add(entity);
}
this._entityToBitmap.set(entity, bitmap);
this._lastUpdated = Date.now();
}
public removeEntity(entity: Entity): void {
const bitmap = this._entityToBitmap.get(entity);
if (bitmap === undefined) return;
// 从所有相关的位集合中移除实体
for (const [bitMask, entities] of this._bitToEntities) {
if ((bitmap & bitMask) !== 0) {
entities.delete(entity);
if (entities.size === 0) {
this._bitToEntities.delete(bitMask);
}
}
}
this._entityToBitmap.delete(entity);
this._lastUpdated = Date.now();
}
public query(componentType: ComponentType): Set<Entity> {
const startTime = performance.now();
const bit = this._componentTypeToBit.get(componentType);
if (bit === undefined) {
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return new Set();
}
const result = new Set(this._bitToEntities.get(1 << bit) || []);
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return result;
}
public queryMultiple(componentTypes: ComponentType[], operation: 'AND' | 'OR'): Set<Entity> {
const startTime = performance.now();
if (componentTypes.length === 0) {
return new Set();
}
let targetBitmap = 0;
const validBits: number[] = [];
for (const componentType of componentTypes) {
const bit = this._componentTypeToBit.get(componentType);
if (bit !== undefined) {
targetBitmap |= (1 << bit);
validBits.push(1 << bit);
}
}
const result = new Set<Entity>();
if (operation === 'AND') {
for (const [entity, entityBitmap] of this._entityToBitmap) {
if ((entityBitmap & targetBitmap) === targetBitmap) {
result.add(entity);
}
}
} else {
for (const bitMask of validBits) {
const entities = this._bitToEntities.get(bitMask);
if (entities) {
for (const entity of entities) {
result.add(entity);
}
}
}
}
this._queryCount++;
this._totalQueryTime += performance.now() - startTime;
return result;
}
public clear(): void {
this._componentTypeToBit.clear();
this._entityToBitmap.clear();
this._bitToEntities.clear();
this._nextBit = 0;
this._lastUpdated = Date.now();
}
public getStats(): IndexStats {
let memoryUsage = 0;
memoryUsage += this._componentTypeToBit.size * 12;
memoryUsage += this._entityToBitmap.size * 12;
memoryUsage += this._bitToEntities.size * 64;
for (const entities of this._bitToEntities.values()) {
memoryUsage += entities.size * 8;
}
return {
type: this.type,
size: this._componentTypeToBit.size,
memoryUsage,
queryCount: this._queryCount,
avgQueryTime: this._queryCount > 0 ? this._totalQueryTime / this._queryCount : 0,
lastUpdated: this._lastUpdated
};
}
}
/**
* 智能组件索引管理器
*
* 根据使用模式自动选择最优的索引策略。
* 支持动态切换索引类型以获得最佳性能。
*/
export class ComponentIndexManager {
private _activeIndex: IComponentIndex;
private _indexHistory: Map<IndexType, IndexStats> = new Map();
private _autoOptimize = true;
private _optimizationThreshold = 1000;
constructor(initialType: IndexType = IndexType.HASH) {
this._activeIndex = this.createIndex(initialType);
}
/**
* 添加实体到索引
*/
public addEntity(entity: Entity): void {
this._activeIndex.addEntity(entity);
this.checkOptimization();
}
/**
* 从索引中移除实体
*/
public removeEntity(entity: Entity): void {
this._activeIndex.removeEntity(entity);
}
/**
* 查询包含指定组件的实体
*/
public query(componentType: ComponentType): Set<Entity> {
return this._activeIndex.query(componentType);
}
/**
* 批量查询多个组件
*/
public queryMultiple(componentTypes: ComponentType[], operation: 'AND' | 'OR'): Set<Entity> {
return this._activeIndex.queryMultiple(componentTypes, operation);
}
/**
* 手动切换索引类型
*/
public switchIndexType(type: IndexType): void {
if (type === this._activeIndex.type) return;
this._indexHistory.set(this._activeIndex.type, this._activeIndex.getStats());
const oldIndex = this._activeIndex;
this._activeIndex = this.createIndex(type);
oldIndex.clear();
}
/**
* 启用/禁用自动优化
*/
public setAutoOptimize(enabled: boolean): void {
this._autoOptimize = enabled;
}
/**
* 获取当前索引统计信息
*/
public getStats(): IndexStats {
return this._activeIndex.getStats();
}
/**
* 获取所有索引类型的历史统计信息
*/
public getAllStats(): Map<IndexType, IndexStats> {
const current = this._activeIndex.getStats();
return new Map([
...this._indexHistory,
[current.type, current]
]);
}
/**
* 清空索引
*/
public clear(): void {
this._activeIndex.clear();
}
/**
* 创建指定类型的索引
*/
private createIndex(type: IndexType): IComponentIndex {
switch (type) {
case IndexType.HASH:
return new HashComponentIndex();
case IndexType.BITMAP:
return new BitmapComponentIndex();
case IndexType.SORTED:
return new HashComponentIndex();
default:
return new HashComponentIndex();
}
}
/**
* 检查是否需要优化索引
*/
private checkOptimization(): void {
if (!this._autoOptimize) return;
const stats = this._activeIndex.getStats();
if (stats.queryCount < this._optimizationThreshold) return;
if (stats.avgQueryTime > 1.0 && stats.type !== IndexType.HASH) {
this.switchIndexType(IndexType.HASH);
} else if (stats.memoryUsage > 10 * 1024 * 1024 && stats.type !== IndexType.BITMAP) {
this.switchIndexType(IndexType.BITMAP);
}
}
}

View File

@@ -0,0 +1,152 @@
import { Component } from '../Component';
/**
* 组件对象池,用于复用组件实例以减少内存分配
*/
export class ComponentPool<T extends Component> {
private pool: T[] = [];
private createFn: () => T;
private resetFn?: (component: T) => void;
private maxSize: number;
constructor(
createFn: () => T,
resetFn?: (component: T) => void,
maxSize: number = 1000
) {
this.createFn = createFn;
this.resetFn = resetFn;
this.maxSize = maxSize;
}
/**
* 获取一个组件实例
*/
acquire(): T {
if (this.pool.length > 0) {
return this.pool.pop()!;
}
return this.createFn();
}
/**
* 释放一个组件实例回池中
*/
release(component: T): void {
if (this.pool.length < this.maxSize) {
if (this.resetFn) {
this.resetFn(component);
}
this.pool.push(component);
}
}
/**
* 预填充对象池
*/
prewarm(count: number): void {
for (let i = 0; i < count && this.pool.length < this.maxSize; i++) {
this.pool.push(this.createFn());
}
}
/**
* 清空对象池
*/
clear(): void {
this.pool.length = 0;
}
/**
* 获取池中可用对象数量
*/
getAvailableCount(): number {
return this.pool.length;
}
/**
* 获取池的最大容量
*/
getMaxSize(): number {
return this.maxSize;
}
}
/**
* 全局组件池管理器
*/
export class ComponentPoolManager {
private static instance: ComponentPoolManager;
private pools = new Map<string, ComponentPool<any>>();
private constructor() {}
static getInstance(): ComponentPoolManager {
if (!ComponentPoolManager.instance) {
ComponentPoolManager.instance = new ComponentPoolManager();
}
return ComponentPoolManager.instance;
}
/**
* 注册组件池
*/
registerPool<T extends Component>(
componentName: string,
createFn: () => T,
resetFn?: (component: T) => void,
maxSize?: number
): void {
this.pools.set(componentName, new ComponentPool(createFn, resetFn, maxSize));
}
/**
* 获取组件实例
*/
acquireComponent<T extends Component>(componentName: string): T | null {
const pool = this.pools.get(componentName);
return pool ? pool.acquire() : null;
}
/**
* 释放组件实例
*/
releaseComponent<T extends Component>(componentName: string, component: T): void {
const pool = this.pools.get(componentName);
if (pool) {
pool.release(component);
}
}
/**
* 预热所有池
*/
prewarmAll(count: number = 100): void {
for (const pool of this.pools.values()) {
pool.prewarm(count);
}
}
/**
* 清空所有池
*/
clearAll(): void {
for (const pool of this.pools.values()) {
pool.clear();
}
}
/**
* 获取池统计信息
*/
getPoolStats(): Map<string, { available: number; maxSize: number }> {
const stats = new Map();
for (const [name, pool] of this.pools) {
stats.set(name, {
available: pool.getAvailableCount(),
maxSize: pool.getMaxSize()
});
}
return stats;
}
}

View File

@@ -0,0 +1,404 @@
import { Component } from '../Component';
/**
* 组件类型定义
*/
export type ComponentType<T extends Component = Component> = new (...args: any[]) => T;
/**
* 组件注册表
* 管理组件类型的位掩码分配
*/
export class ComponentRegistry {
private static componentTypes = new Map<Function, number>();
private static nextBitIndex = 0;
private static maxComponents = 64; // 支持最多64种组件类型
/**
* 注册组件类型并分配位掩码
* @param componentType 组件类型
* @returns 分配的位索引
*/
public static register<T extends Component>(componentType: ComponentType<T>): number {
if (this.componentTypes.has(componentType)) {
return this.componentTypes.get(componentType)!;
}
if (this.nextBitIndex >= this.maxComponents) {
throw new Error(`Maximum number of component types (${this.maxComponents}) exceeded`);
}
const bitIndex = this.nextBitIndex++;
this.componentTypes.set(componentType, bitIndex);
return bitIndex;
}
/**
* 获取组件类型的位掩码
* @param componentType 组件类型
* @returns 位掩码
*/
public static getBitMask<T extends Component>(componentType: ComponentType<T>): bigint {
const bitIndex = this.componentTypes.get(componentType);
if (bitIndex === undefined) {
throw new Error(`Component type ${componentType.name} is not registered`);
}
return BigInt(1) << BigInt(bitIndex);
}
/**
* 获取组件类型的位索引
* @param componentType 组件类型
* @returns 位索引
*/
public static getBitIndex<T extends Component>(componentType: ComponentType<T>): number {
const bitIndex = this.componentTypes.get(componentType);
if (bitIndex === undefined) {
throw new Error(`Component type ${componentType.name} is not registered`);
}
return bitIndex;
}
/**
* 检查组件类型是否已注册
* @param componentType 组件类型
* @returns 是否已注册
*/
public static isRegistered<T extends Component>(componentType: ComponentType<T>): boolean {
return this.componentTypes.has(componentType);
}
/**
* 获取所有已注册的组件类型
* @returns 组件类型映射
*/
public static getAllRegisteredTypes(): Map<Function, number> {
return new Map(this.componentTypes);
}
}
/**
* 高性能组件存储器
* 使用SoAStructure of Arrays模式存储组件
*/
export class ComponentStorage<T extends Component> {
private components: (T | null)[] = [];
private entityToIndex = new Map<number, number>();
private indexToEntity: number[] = [];
private freeIndices: number[] = [];
private componentType: ComponentType<T>;
private _size = 0;
constructor(componentType: ComponentType<T>) {
this.componentType = componentType;
// 确保组件类型已注册
if (!ComponentRegistry.isRegistered(componentType)) {
ComponentRegistry.register(componentType);
}
}
/**
* 添加组件
* @param entityId 实体ID
* @param component 组件实例
*/
public addComponent(entityId: number, component: T): void {
// 检查实体是否已有此组件
if (this.entityToIndex.has(entityId)) {
throw new Error(`Entity ${entityId} already has component ${this.componentType.name}`);
}
let index: number;
if (this.freeIndices.length > 0) {
// 重用空闲索引
index = this.freeIndices.pop()!;
this.components[index] = component;
this.indexToEntity[index] = entityId;
} else {
// 添加到末尾
index = this.components.length;
this.components.push(component);
this.indexToEntity.push(entityId);
}
this.entityToIndex.set(entityId, index);
this._size++;
}
/**
* 获取组件
* @param entityId 实体ID
* @returns 组件实例或null
*/
public getComponent(entityId: number): T | null {
const index = this.entityToIndex.get(entityId);
return index !== undefined ? this.components[index] : null;
}
/**
* 检查实体是否有此组件
* @param entityId 实体ID
* @returns 是否有组件
*/
public hasComponent(entityId: number): boolean {
return this.entityToIndex.has(entityId);
}
/**
* 移除组件
* @param entityId 实体ID
* @returns 被移除的组件或null
*/
public removeComponent(entityId: number): T | null {
const index = this.entityToIndex.get(entityId);
if (index === undefined) {
return null;
}
const component = this.components[index];
this.entityToIndex.delete(entityId);
this.components[index] = null;
this.freeIndices.push(index);
this._size--;
return component;
}
/**
* 高效遍历所有组件
* @param callback 回调函数
*/
public forEach(callback: (component: T, entityId: number, index: number) => void): void {
for (let i = 0; i < this.components.length; i++) {
const component = this.components[i];
if (component) {
callback(component, this.indexToEntity[i], i);
}
}
}
/**
* 获取所有组件(密集数组)
* @returns 组件数组
*/
public getDenseArray(): { components: T[]; entityIds: number[] } {
const components: T[] = [];
const entityIds: number[] = [];
for (let i = 0; i < this.components.length; i++) {
const component = this.components[i];
if (component) {
components.push(component);
entityIds.push(this.indexToEntity[i]);
}
}
return { components, entityIds };
}
/**
* 清空所有组件
*/
public clear(): void {
this.components.length = 0;
this.entityToIndex.clear();
this.indexToEntity.length = 0;
this.freeIndices.length = 0;
this._size = 0;
}
/**
* 获取组件数量
*/
public get size(): number {
return this._size;
}
/**
* 获取组件类型
*/
public get type(): ComponentType<T> {
return this.componentType;
}
/**
* 压缩存储(移除空洞)
*/
public compact(): void {
if (this.freeIndices.length === 0) {
return; // 没有空洞,无需压缩
}
const newComponents: T[] = [];
const newIndexToEntity: number[] = [];
const newEntityToIndex = new Map<number, number>();
let newIndex = 0;
for (let i = 0; i < this.components.length; i++) {
const component = this.components[i];
if (component) {
newComponents[newIndex] = component;
newIndexToEntity[newIndex] = this.indexToEntity[i];
newEntityToIndex.set(this.indexToEntity[i], newIndex);
newIndex++;
}
}
this.components = newComponents;
this.indexToEntity = newIndexToEntity;
this.entityToIndex = newEntityToIndex;
this.freeIndices.length = 0;
}
/**
* 获取存储统计信息
*/
public getStats(): {
totalSlots: number;
usedSlots: number;
freeSlots: number;
fragmentation: number;
} {
const totalSlots = this.components.length;
const usedSlots = this._size;
const freeSlots = this.freeIndices.length;
const fragmentation = totalSlots > 0 ? freeSlots / totalSlots : 0;
return {
totalSlots,
usedSlots,
freeSlots,
fragmentation
};
}
}
/**
* 组件存储管理器
* 管理所有组件类型的存储器
*/
export class ComponentStorageManager {
private storages = new Map<Function, ComponentStorage<any>>();
/**
* 获取或创建组件存储器
* @param componentType 组件类型
* @returns 组件存储器
*/
public getStorage<T extends Component>(componentType: ComponentType<T>): ComponentStorage<T> {
let storage = this.storages.get(componentType);
if (!storage) {
storage = new ComponentStorage(componentType);
this.storages.set(componentType, storage);
}
return storage;
}
/**
* 添加组件
* @param entityId 实体ID
* @param component 组件实例
*/
public addComponent<T extends Component>(entityId: number, component: T): void {
const componentType = component.constructor as ComponentType<T>;
const storage = this.getStorage(componentType);
storage.addComponent(entityId, component);
}
/**
* 获取组件
* @param entityId 实体ID
* @param componentType 组件类型
* @returns 组件实例或null
*/
public getComponent<T extends Component>(entityId: number, componentType: ComponentType<T>): T | null {
const storage = this.storages.get(componentType);
return storage ? storage.getComponent(entityId) : null;
}
/**
* 检查实体是否有组件
* @param entityId 实体ID
* @param componentType 组件类型
* @returns 是否有组件
*/
public hasComponent<T extends Component>(entityId: number, componentType: ComponentType<T>): boolean {
const storage = this.storages.get(componentType);
return storage ? storage.hasComponent(entityId) : false;
}
/**
* 移除组件
* @param entityId 实体ID
* @param componentType 组件类型
* @returns 被移除的组件或null
*/
public removeComponent<T extends Component>(entityId: number, componentType: ComponentType<T>): T | null {
const storage = this.storages.get(componentType);
return storage ? storage.removeComponent(entityId) : null;
}
/**
* 移除实体的所有组件
* @param entityId 实体ID
*/
public removeAllComponents(entityId: number): void {
for (const storage of this.storages.values()) {
storage.removeComponent(entityId);
}
}
/**
* 获取实体的组件位掩码
* @param entityId 实体ID
* @returns 组件位掩码
*/
public getComponentMask(entityId: number): bigint {
let mask = BigInt(0);
for (const [componentType, storage] of this.storages.entries()) {
if (storage.hasComponent(entityId)) {
mask |= ComponentRegistry.getBitMask(componentType as ComponentType);
}
}
return mask;
}
/**
* 压缩所有存储器
*/
public compactAll(): void {
for (const storage of this.storages.values()) {
storage.compact();
}
}
/**
* 获取所有存储器的统计信息
*/
public getAllStats(): Map<string, any> {
const stats = new Map<string, any>();
for (const [componentType, storage] of this.storages.entries()) {
const typeName = (componentType as any).name || 'Unknown';
stats.set(typeName, storage.getStats());
}
return stats;
}
/**
* 清空所有存储器
*/
public clear(): void {
for (const storage of this.storages.values()) {
storage.clear();
}
this.storages.clear();
}
}

View File

@@ -0,0 +1,375 @@
import { Entity } from '../Entity';
import { Component } from '../Component';
import { ComponentType } from './ComponentStorage';
/**
* 脏标记类型
*/
export enum DirtyFlag {
/** 组件数据已修改 */
COMPONENT_MODIFIED = 1 << 0,
/** 组件已添加 */
COMPONENT_ADDED = 1 << 1,
/** 组件已移除 */
COMPONENT_REMOVED = 1 << 2,
/** 实体位置已改变 */
TRANSFORM_CHANGED = 1 << 3,
/** 实体状态已改变 */
STATE_CHANGED = 1 << 4,
/** 自定义标记1 */
CUSTOM_1 = 1 << 8,
/** 自定义标记2 */
CUSTOM_2 = 1 << 9,
/** 自定义标记3 */
CUSTOM_3 = 1 << 10,
/** 所有标记 */
ALL = 0xFFFFFFFF
}
/**
* 脏标记数据
*/
export interface DirtyData {
/** 实体引用 */
entity: Entity;
/** 脏标记位 */
flags: number;
/** 修改的组件类型列表 */
modifiedComponents: Set<ComponentType>;
/** 标记时间戳 */
timestamp: number;
/** 帧编号 */
frameNumber: number;
}
/**
* 脏标记监听器
*/
export interface DirtyListener {
/** 感兴趣的标记类型 */
flags: number;
/** 回调函数 */
callback: (dirtyData: DirtyData) => void;
/** 监听器优先级(数字越小优先级越高) */
priority?: number;
}
/**
* 脏标记统计信息
*/
export interface DirtyStats {
/** 当前脏实体数量 */
dirtyEntityCount: number;
/** 总标记次数 */
totalMarkings: number;
/** 总清理次数 */
totalCleanups: number;
/** 监听器数量 */
listenerCount: number;
/** 平均每帧脏实体数量 */
avgDirtyPerFrame: number;
/** 内存使用量估算 */
estimatedMemoryUsage: number;
}
/**
* 脏标记追踪系统
*
* 提供高效的组件和实体变更追踪,避免不必要的计算和更新。
* 支持细粒度的脏标记和批量处理机制。
*
* @example
* ```typescript
* const dirtySystem = new DirtyTrackingSystem();
*
* // 标记实体的位置组件已修改
* dirtySystem.markDirty(entity, DirtyFlag.TRANSFORM_CHANGED, [PositionComponent]);
*
* // 监听位置变化
* dirtySystem.addListener({
* flags: DirtyFlag.TRANSFORM_CHANGED,
* callback: (data) => {
* console.log('Entity position changed:', data.entity.name);
* }
* });
*
* // 处理所有脏标记
* dirtySystem.processDirtyEntities();
* ```
*/
export class DirtyTrackingSystem {
/** 脏实体映射表 */
private _dirtyEntities = new Map<Entity, DirtyData>();
/** 脏标记监听器 */
private _listeners: DirtyListener[] = [];
/** 性能统计 */
private _stats = {
totalMarkings: 0,
totalCleanups: 0,
frameCount: 0,
totalDirtyPerFrame: 0
};
/** 当前帧编号 */
private _currentFrame = 0;
private _batchSize = 100;
private _maxProcessingTime = 16;
/** 延迟处理队列 */
private _processingQueue: DirtyData[] = [];
private _isProcessing = false;
/**
* 标记实体为脏状态
*
* @param entity 要标记的实体
* @param flags 脏标记位
* @param modifiedComponents 修改的组件类型列表
*/
public markDirty(entity: Entity, flags: DirtyFlag, modifiedComponents: ComponentType[] = []): void {
this._stats.totalMarkings++;
let dirtyData = this._dirtyEntities.get(entity);
if (!dirtyData) {
dirtyData = {
entity,
flags: 0,
modifiedComponents: new Set(),
timestamp: performance.now(),
frameNumber: this._currentFrame
};
this._dirtyEntities.set(entity, dirtyData);
}
dirtyData.flags |= flags;
dirtyData.timestamp = performance.now();
dirtyData.frameNumber = this._currentFrame;
for (const componentType of modifiedComponents) {
dirtyData.modifiedComponents.add(componentType);
}
this.notifyListeners(dirtyData, flags);
}
/**
* 检查实体是否有指定的脏标记
*
* @param entity 要检查的实体
* @param flags 要检查的标记位
* @returns 是否有指定的脏标记
*/
public isDirty(entity: Entity, flags: DirtyFlag = DirtyFlag.ALL): boolean {
const dirtyData = this._dirtyEntities.get(entity);
return dirtyData ? (dirtyData.flags & flags) !== 0 : false;
}
/**
* 清除实体的脏标记
*
* @param entity 要清除的实体
* @param flags 要清除的标记位,默认清除所有
*/
public clearDirty(entity: Entity, flags: DirtyFlag = DirtyFlag.ALL): void {
const dirtyData = this._dirtyEntities.get(entity);
if (!dirtyData) return;
if (flags === DirtyFlag.ALL) {
this._dirtyEntities.delete(entity);
} else {
dirtyData.flags &= ~flags;
if (dirtyData.flags === 0) {
this._dirtyEntities.delete(entity);
}
}
this._stats.totalCleanups++;
}
/**
* 获取所有脏实体
*
* @param flags 过滤标记位,只返回包含指定标记的实体
* @returns 脏实体数据数组
*/
public getDirtyEntities(flags: DirtyFlag = DirtyFlag.ALL): DirtyData[] {
const result: DirtyData[] = [];
for (const dirtyData of this._dirtyEntities.values()) {
if ((dirtyData.flags & flags) !== 0) {
result.push(dirtyData);
}
}
return result;
}
/**
* 批量处理脏实体
*
* 使用时间分片的方式处理脏实体,避免单帧卡顿
*/
public processDirtyEntities(): void {
if (this._isProcessing) return;
this._isProcessing = true;
const startTime = performance.now();
if (this._processingQueue.length === 0) {
this._processingQueue.push(...this._dirtyEntities.values());
}
let processed = 0;
while (this._processingQueue.length > 0 && processed < this._batchSize) {
const elapsed = performance.now() - startTime;
if (elapsed > this._maxProcessingTime) {
break;
}
const dirtyData = this._processingQueue.shift()!;
this.processEntity(dirtyData);
processed++;
}
if (this._processingQueue.length === 0) {
this._isProcessing = false;
this.onFrameEnd();
}
}
/**
* 添加脏标记监听器
*
* @param listener 监听器配置
*/
public addListener(listener: DirtyListener): void {
this._listeners.push(listener);
this._listeners.sort((a, b) => (a.priority || 100) - (b.priority || 100));
}
/**
* 移除脏标记监听器
*
* @param callback 要移除的回调函数
*/
public removeListener(callback: (dirtyData: DirtyData) => void): void {
const index = this._listeners.findIndex(l => l.callback === callback);
if (index !== -1) {
this._listeners.splice(index, 1);
}
}
/**
* 开始新的帧
*/
public beginFrame(): void {
this._currentFrame++;
}
/**
* 结束当前帧
*/
public endFrame(): void {
if (!this._isProcessing) {
this.processDirtyEntities();
}
}
/**
* 获取统计信息
*/
public getStats(): DirtyStats {
return {
dirtyEntityCount: this._dirtyEntities.size,
totalMarkings: this._stats.totalMarkings,
totalCleanups: this._stats.totalCleanups,
listenerCount: this._listeners.length,
avgDirtyPerFrame: this._stats.frameCount > 0 ?
this._stats.totalDirtyPerFrame / this._stats.frameCount : 0,
estimatedMemoryUsage: this.estimateMemoryUsage()
};
}
/**
* 清空所有脏标记和统计信息
*/
public clear(): void {
this._dirtyEntities.clear();
this._processingQueue.length = 0;
this._isProcessing = false;
this._stats = {
totalMarkings: 0,
totalCleanups: 0,
frameCount: 0,
totalDirtyPerFrame: 0
};
}
/**
* 配置批量处理参数
*
* @param batchSize 每次处理的最大实体数量
* @param maxProcessingTime 每帧最大处理时间(毫秒)
*/
public configureBatchProcessing(batchSize: number, maxProcessingTime: number): void {
this._batchSize = batchSize;
this._maxProcessingTime = maxProcessingTime;
}
/**
* 处理单个脏实体
*/
private processEntity(dirtyData: DirtyData): void {
for (const listener of this._listeners) {
if ((dirtyData.flags & listener.flags) !== 0) {
try {
listener.callback(dirtyData);
} catch (error) {
console.error('Dirty listener error:', error);
}
}
}
this.clearDirty(dirtyData.entity);
}
/**
* 通知监听器
*/
private notifyListeners(dirtyData: DirtyData, newFlags: DirtyFlag): void {
for (const listener of this._listeners) {
if ((newFlags & listener.flags) !== 0) {
try {
listener.callback(dirtyData);
} catch (error) {
console.error('Dirty listener notification error:', error);
}
}
}
}
/**
* 帧结束时的统计更新
*/
private onFrameEnd(): void {
this._stats.frameCount++;
this._stats.totalDirtyPerFrame += this._dirtyEntities.size;
}
/**
* 估算内存使用量
*/
private estimateMemoryUsage(): number {
let usage = 0;
usage += this._dirtyEntities.size * 100;
usage += this._listeners.length * 50;
usage += this._processingQueue.length * 8;
return usage;
}
}

View File

@@ -0,0 +1,674 @@
import { Entity } from '../Entity';
import { Component } from '../Component';
import { ComponentType } from './ComponentStorage';
import { IdentifierPool } from '../Utils/IdentifierPool';
import { ComponentIndexManager, IndexType } from './ComponentIndex';
import { ArchetypeSystem } from './ArchetypeSystem';
import { DirtyTrackingSystem, DirtyFlag } from './DirtyTrackingSystem';
import { EventBus } from './EventBus';
import { ECSEventType } from '../CoreEvents';
import { IEntityEventData, IComponentEventData } from '../../Types';
/**
* 实体查询构建器
*
* 提供流式API来构建复杂的实体查询条件。支持组件过滤、标签过滤、状态过滤和自定义条件。
*
* @example
* ```typescript
* const results = entityManager.query()
* .withAll(PositionComponent, HealthComponent)
* .without(VelocityComponent)
* .withTag(1)
* .active()
* .where(entity => entity.name.startsWith("Player"))
* .execute();
* ```
*/
export class EntityQueryBuilder {
/** 必须包含的组件类型 */
private _allComponents: ComponentType[] = [];
/** 至少包含一个的组件类型 */
private _anyComponents: ComponentType[] = [];
/** 不能包含的组件类型 */
private _withoutComponents: ComponentType[] = [];
/** 必须包含的标签 */
private _withTags: number[] = [];
/** 不能包含的标签 */
private _withoutTags: number[] = [];
/** 是否只查询激活状态的实体 */
private _activeOnly: boolean = false;
/** 是否只查询启用状态的实体 */
private _enabledOnly: boolean = false;
/** 自定义过滤条件 */
private _customPredicates: Array<(entity: Entity) => boolean> = [];
/**
* 创建查询构建器实例
* @param entityManager 实体管理器实例
*/
constructor(private entityManager: EntityManager) {}
/**
* 添加必须包含的组件条件
*
* 返回的实体必须包含所有指定的组件类型。
*
* @param componentTypes 组件类型列表
* @returns 查询构建器实例,支持链式调用
*/
public withAll(...componentTypes: ComponentType[]): EntityQueryBuilder {
this._allComponents.push(...componentTypes);
return this;
}
/**
* 添加至少包含一个的组件条件
*
* 返回的实体必须至少包含其中一个指定的组件类型。
*
* @param componentTypes 组件类型列表
* @returns 查询构建器实例,支持链式调用
*/
public withAny(...componentTypes: ComponentType[]): EntityQueryBuilder {
this._anyComponents.push(...componentTypes);
return this;
}
/**
* 添加不能包含的组件条件
*
* 返回的实体不能包含任何指定的组件类型。
*
* @param componentTypes 组件类型列表
* @returns 查询构建器实例,支持链式调用
*/
public without(...componentTypes: ComponentType[]): EntityQueryBuilder {
this._withoutComponents.push(...componentTypes);
return this;
}
/**
* 添加必须包含的标签条件
*
* 返回的实体必须具有指定的标签。
*
* @param tag 标签值
* @returns 查询构建器实例,支持链式调用
*/
public withTag(tag: number): EntityQueryBuilder {
this._withTags.push(tag);
return this;
}
/**
* 添加不能包含的标签条件
*
* 返回的实体不能具有指定的标签。
*
* @param tag 标签值
* @returns 查询构建器实例,支持链式调用
*/
public withoutTag(tag: number): EntityQueryBuilder {
this._withoutTags.push(tag);
return this;
}
/**
* 添加激活状态过滤条件
*
* 返回的实体必须处于激活状态active = true
*
* @returns 查询构建器实例,支持链式调用
*/
public active(): EntityQueryBuilder {
this._activeOnly = true;
return this;
}
/**
* 添加启用状态过滤条件
*
* 返回的实体必须处于启用状态enabled = true
*
* @returns 查询构建器实例,支持链式调用
*/
public enabled(): EntityQueryBuilder {
this._enabledOnly = true;
return this;
}
/**
* 添加自定义过滤条件
*
* 允许用户定义复杂的过滤逻辑。
*
* @param predicate 自定义过滤函数,接收实体作为参数,返回布尔值
* @returns 查询构建器实例,支持链式调用
*
* @example
* ```typescript
* .where(entity => entity.name.startsWith("Player"))
* .where(entity => entity.components.length > 5)
* ```
*/
public where(predicate: (entity: Entity) => boolean): EntityQueryBuilder {
this._customPredicates.push(predicate);
return this;
}
/**
* 执行查询并返回所有匹配的实体
*
* @returns 符合所有查询条件的实体数组
*/
public execute(): Entity[] {
let candidates: Entity[] = [];
if (this._allComponents.length > 0) {
const indexResult = this.entityManager.queryWithComponentIndex(this._allComponents, 'AND');
candidates = Array.from(indexResult);
} else if (this._anyComponents.length > 0) {
const indexResult = this.entityManager.queryWithComponentIndex(this._anyComponents, 'OR');
candidates = Array.from(indexResult);
} else {
candidates = this.entityManager.getAllEntities();
}
return candidates.filter(entity => this.matchesEntity(entity));
}
/**
* 执行查询并返回第一个匹配的实体
*
* @returns 第一个符合查询条件的实体如果没有找到则返回null
*/
public first(): Entity | null {
const entities = this.entityManager.getAllEntities();
return entities.find(entity => this.matchesEntity(entity)) || null;
}
/**
* 执行查询并返回匹配实体的数量
*
* @returns 符合查询条件的实体数量
*/
public count(): number {
const entities = this.entityManager.getAllEntities();
return entities.filter(entity => this.matchesEntity(entity)).length;
}
/**
* 对所有匹配的实体执行指定操作
*
* @param action 要执行的操作函数,接收匹配的实体作为参数
*/
public forEach(action: (entity: Entity) => void): void {
const entities = this.entityManager.getAllEntities();
entities.forEach(entity => {
if (this.matchesEntity(entity)) {
action(entity);
}
});
}
/**
* 检查实体是否匹配所有查询条件
*
* 按优先级顺序检查各种过滤条件一旦发现不匹配立即返回false。
*
* @param entity 要检查的实体
* @returns 实体是否匹配所有查询条件
*/
private matchesEntity(entity: Entity): boolean {
// 检查激活状态
if (this._activeOnly && !entity.active) {
return false;
}
// 检查启用状态
if (this._enabledOnly && !entity.enabled) {
return false;
}
// 检查必须包含的组件
if (this._allComponents.length > 0) {
for (const componentType of this._allComponents) {
if (!entity.hasComponent(componentType)) {
return false;
}
}
}
// 检查至少包含一个的组件
if (this._anyComponents.length > 0) {
let hasAny = false;
for (const componentType of this._anyComponents) {
if (entity.hasComponent(componentType)) {
hasAny = true;
break;
}
}
if (!hasAny) {
return false;
}
}
// 检查不能包含的组件
if (this._withoutComponents.length > 0) {
for (const componentType of this._withoutComponents) {
if (entity.hasComponent(componentType)) {
return false;
}
}
}
// 检查必须包含的标签
if (this._withTags.length > 0) {
if (!this._withTags.includes(entity.tag)) {
return false;
}
}
// 检查不能包含的标签
if (this._withoutTags.length > 0) {
if (this._withoutTags.includes(entity.tag)) {
return false;
}
}
// 检查自定义条件
if (this._customPredicates.length > 0) {
for (const predicate of this._customPredicates) {
if (!predicate(entity)) {
return false;
}
}
}
return true;
}
}
/**
* 实体管理器
*
* 提供统一的实体管理和查询机制,支持高效的实体操作。
* 包括实体的创建、销毁、查询和索引管理功能。
*
* @example
* ```typescript
* const entityManager = new EntityManager();
*
* // 创建实体
* const player = entityManager.createEntity("Player");
*
* // 查询实体
* const playerEntity = entityManager.getEntityByName("Player");
*
* // 复杂查询
* const results = entityManager.query()
* .withAll(HealthComponent, PositionComponent)
* .active()
* .execute();
* ```
*/
export class EntityManager {
/** 主要实体存储使用ID作为键 */
private _entities: Map<number, Entity> = new Map();
/** 按名称索引的实体映射 */
private _entitiesByName: Map<string, Entity[]> = new Map();
/** 按标签索引的实体映射 */
private _entitiesByTag: Map<number, Entity[]> = new Map();
/** 实体ID分配器 */
private _identifierPool: IdentifierPool;
/** 已销毁实体的ID集合 */
private _destroyedEntities: Set<number> = new Set();
/** 性能优化系统 */
private _componentIndexManager: ComponentIndexManager;
private _archetypeSystem: ArchetypeSystem;
private _dirtyTrackingSystem: DirtyTrackingSystem;
/** 事件总线 */
private _eventBus: EventBus;
/**
* 创建实体管理器实例
*
* 初始化内部数据结构和ID分配器。
*/
constructor() {
this._identifierPool = new IdentifierPool();
// 初始化性能优化系统
this._componentIndexManager = new ComponentIndexManager(IndexType.HASH);
this._archetypeSystem = new ArchetypeSystem();
this._dirtyTrackingSystem = new DirtyTrackingSystem();
this._eventBus = new EventBus(false);
// 设置Entity的静态事件总线引用
Entity.eventBus = this._eventBus;
}
/**
* 获取实体总数
*
* @returns 当前管理的实体总数量
*/
public get entityCount(): number {
return this._entities.size;
}
/**
* 获取激活状态的实体数量
*
* 只计算同时满足激活状态且未被销毁的实体。
*
* @returns 激活状态的实体数量
*/
public get activeEntityCount(): number {
let count = 0;
for (const entity of this._entities.values()) {
if (entity.active && !entity.isDestroyed) {
count++;
}
}
return count;
}
/**
* 创建新实体
*
* 分配唯一ID并将实体添加到管理系统中同时更新相关索引。
*
* @param name 实体名称,如果未指定则使用时间戳生成默认名称
* @returns 创建的实体实例
*
* @example
* ```typescript
* const player = entityManager.createEntity("Player");
* const enemy = entityManager.createEntity(); // 使用默认名称
* ```
*/
public createEntity(name: string = `Entity_${Date.now()}`): Entity {
const id = this._identifierPool.checkOut();
const entity = new Entity(name, id);
this._entities.set(id, entity);
this.updateNameIndex(entity, true);
this.updateTagIndex(entity, true);
this._componentIndexManager.addEntity(entity);
this._archetypeSystem.addEntity(entity);
this._dirtyTrackingSystem.markDirty(entity, DirtyFlag.COMPONENT_ADDED);
// 发射实体创建事件
this._eventBus.emitEntityCreated({
timestamp: Date.now(),
source: 'EntityManager',
entityId: entity.id,
entityName: entity.name,
entityTag: entity.tag?.toString()
});
return entity;
}
/**
* 销毁实体
*
* 支持通过实体对象、名称或ID来销毁实体。
* 会清理所有相关索引并回收ID。
*
* @param entityOrId 要销毁的实体可以是实体对象、名称字符串或ID数字
* @returns 是否成功销毁实体
*
* @example
* ```typescript
* // 通过实体对象销毁
* entityManager.destroyEntity(player);
*
* // 通过名称销毁
* entityManager.destroyEntity("Enemy_1");
*
* // 通过ID销毁
* entityManager.destroyEntity(123);
* ```
*/
public destroyEntity(entityOrId: Entity | string | number): boolean {
let entity: Entity | null = null;
if (typeof entityOrId === 'string') {
entity = this.getEntityByName(entityOrId);
} else if (typeof entityOrId === 'number') {
entity = this._entities.get(entityOrId) || null;
} else {
entity = this._entities.get(entityOrId.id) || null;
}
if (!entity) {
return false;
}
this._destroyedEntities.add(entity.id);
this.updateNameIndex(entity, false);
this.updateTagIndex(entity, false);
this._componentIndexManager.removeEntity(entity);
this._archetypeSystem.removeEntity(entity);
this._dirtyTrackingSystem.markDirty(entity, DirtyFlag.COMPONENT_REMOVED);
// 发射实体销毁事件
this._eventBus.emitEntityDestroyed({
timestamp: Date.now(),
source: 'EntityManager',
entityId: entity.id,
entityName: entity.name,
entityTag: entity.tag?.toString()
});
entity.destroy();
this._entities.delete(entity.id);
this._identifierPool.checkIn(entity.id);
return true;
}
/**
* 获取所有实体
*
* 返回当前管理的所有实体的副本数组。
*
* @returns 所有实体的数组
*/
public getAllEntities(): Entity[] {
return Array.from(this._entities.values());
}
/**
* 根据ID获取实体
*
* 支持字符串和数字类型的ID。
*
* @param id 实体ID可以是字符串或数字
* @returns 对应的实体如果不存在则返回null
*/
public getEntity(id: string | number): Entity | null {
const numId = typeof id === 'string' ? parseInt(id) : id;
return this._entities.get(numId) || null;
}
/**
* 根据名称获取实体
*
* 如果存在多个同名实体,返回第一个找到的实体。
*
* @param name 实体名称
* @returns 匹配的实体如果不存在则返回null
*/
public getEntityByName(name: string): Entity | null {
const entities = this._entitiesByName.get(name);
return entities && entities.length > 0 ? entities[0] : null;
}
/**
* 根据标签获取实体列表
*
* 返回所有具有指定标签的实体。
*
* @param tag 标签值
* @returns 具有指定标签的实体数组
*/
public getEntitiesByTag(tag: number): Entity[] {
return [...(this._entitiesByTag.get(tag) || [])];
}
/**
* 获取包含指定组件的所有实体
*
* 遍历所有实体,查找包含指定组件类型的实体。
*
* @param componentType 组件类型
* @returns 包含指定组件的实体数组
*
* @example
* ```typescript
* const entitiesWithHealth = entityManager.getEntitiesWithComponent(HealthComponent);
* ```
*/
public getEntitiesWithComponent<T extends Component>(componentType: ComponentType<T>): Entity[] {
const indexResult = this._componentIndexManager.query(componentType);
return Array.from(indexResult);
}
/**
* 创建查询构建器
*
* 返回一个新的查询构建器实例,用于构建复杂的实体查询。
*
* @returns 新的查询构建器实例
*
* @example
* ```typescript
* const results = entityManager.query()
* .withAll(PositionComponent, HealthComponent)
* .without(VelocityComponent)
* .active()
* .execute();
* ```
*/
public query(): EntityQueryBuilder {
return new EntityQueryBuilder(this);
}
/**
* 使用组件索引进行多组件查询
*
* @param componentTypes 组件类型数组
* @param operation 查询操作:'AND' 或 'OR'
* @returns 匹配的实体集合
*/
public queryWithComponentIndex(componentTypes: ComponentType[], operation: 'AND' | 'OR'): Set<Entity> {
return this._componentIndexManager.queryMultiple(componentTypes, operation);
}
/**
* 标记实体组件已修改
*
* @param entity 修改的实体
* @param componentTypes 修改的组件类型
*/
public markEntityDirty(entity: Entity, componentTypes: ComponentType[]): void {
this._dirtyTrackingSystem.markDirty(entity, DirtyFlag.COMPONENT_MODIFIED, componentTypes);
}
/**
* 获取性能优化统计信息
*/
public getOptimizationStats(): any {
return {
componentIndex: this._componentIndexManager.getStats(),
archetypeSystem: this._archetypeSystem.getAllArchetypes().map(a => ({
id: a.id,
componentTypes: a.componentTypes.map(t => t.name),
entityCount: a.entities.length
})),
dirtyTracking: this._dirtyTrackingSystem.getStats()
};
}
/**
* 获取事件总线实例
*
* 允许外部代码监听和发射ECS相关事件。
*
* @returns 事件总线实例
*/
public get eventBus(): EventBus {
return this._eventBus;
}
/**
* 更新名称索引
*
* 维护按名称查找实体的索引结构。支持添加和移除操作。
*
* @param entity 要更新索引的实体
* @param isAdd true表示添加到索引false表示从索引中移除
*/
private updateNameIndex(entity: Entity, isAdd: boolean): void {
if (!entity.name) {
return;
}
if (isAdd) {
let entities = this._entitiesByName.get(entity.name);
if (!entities) {
entities = [];
this._entitiesByName.set(entity.name, entities);
}
entities.push(entity);
} else {
const entities = this._entitiesByName.get(entity.name);
if (entities) {
const index = entities.indexOf(entity);
if (index !== -1) {
entities.splice(index, 1);
if (entities.length === 0) {
this._entitiesByName.delete(entity.name);
}
}
}
}
}
/**
* 更新标签索引
*
* 维护按标签查找实体的索引结构。支持添加和移除操作。
*
* @param entity 要更新索引的实体
* @param isAdd true表示添加到索引false表示从索引中移除
*/
private updateTagIndex(entity: Entity, isAdd: boolean): void {
if (isAdd) {
let entities = this._entitiesByTag.get(entity.tag);
if (!entities) {
entities = [];
this._entitiesByTag.set(entity.tag, entities);
}
entities.push(entity);
} else {
const entities = this._entitiesByTag.get(entity.tag);
if (entities) {
const index = entities.indexOf(entity);
if (index !== -1) {
entities.splice(index, 1);
if (entities.length === 0) {
this._entitiesByTag.delete(entity.tag);
}
}
}
}
}
}

497
src/ECS/Core/EventBus.ts Normal file
View File

@@ -0,0 +1,497 @@
import {
IEventBus,
IEventListenerConfig,
IEventStats,
IEventData,
IEntityEventData,
IComponentEventData,
ISystemEventData,
ISceneEventData,
IPerformanceEventData
} from '../../Types';
import {
TypeSafeEventSystem,
EventListenerConfig,
EventStats
} from './EventSystem';
import {
ECSEventType,
EventPriority,
EVENT_TYPES,
EventTypeValidator
} from '../CoreEvents';
/**
* 增强的事件总线实现
* 基于TypeSafeEventSystem提供类型安全的事件发布订阅机制
*/
export class EventBus implements IEventBus {
private eventSystem: TypeSafeEventSystem;
private eventIdCounter = 0;
private isDebugMode = false;
constructor(debugMode: boolean = false) {
this.eventSystem = new TypeSafeEventSystem();
this.isDebugMode = debugMode;
}
/**
* 发射事件
* @param eventType 事件类型
* @param data 事件数据
*/
public emit<T>(eventType: string, data: T): void {
this.validateEventType(eventType);
// 增强事件数据
const enhancedData = this.enhanceEventData(eventType, data);
if (this.isDebugMode) {
console.log(`[EventBus] Emitting event: ${eventType}`, enhancedData);
}
this.eventSystem.emitSync(eventType, enhancedData);
}
/**
* 异步发射事件
* @param eventType 事件类型
* @param data 事件数据
*/
public async emitAsync<T>(eventType: string, data: T): Promise<void> {
this.validateEventType(eventType);
// 增强事件数据
const enhancedData = this.enhanceEventData(eventType, data);
if (this.isDebugMode) {
console.log(`[EventBus] Emitting async event: ${eventType}`, enhancedData);
}
await this.eventSystem.emit(eventType, enhancedData);
}
/**
* 监听事件
* @param eventType 事件类型
* @param handler 事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
public on<T>(
eventType: string,
handler: (data: T) => void,
config: IEventListenerConfig = {}
): string {
this.validateEventType(eventType);
const eventConfig: EventListenerConfig = {
once: config.once || false,
priority: config.priority || EventPriority.NORMAL,
async: config.async || false,
context: config.context
};
if (this.isDebugMode) {
console.log(`[EventBus] Adding listener for: ${eventType}`, eventConfig);
}
return this.eventSystem.on(eventType, handler, eventConfig);
}
/**
* 监听事件(一次性)
* @param eventType 事件类型
* @param handler 事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
public once<T>(
eventType: string,
handler: (data: T) => void,
config: IEventListenerConfig = {}
): string {
return this.on(eventType, handler, { ...config, once: true });
}
/**
* 异步监听事件
* @param eventType 事件类型
* @param handler 异步事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
public onAsync<T>(
eventType: string,
handler: (data: T) => Promise<void>,
config: IEventListenerConfig = {}
): string {
return this.on(eventType, handler as any, { ...config, async: true });
}
/**
* 移除事件监听器
* @param eventType 事件类型
* @param listenerId 监听器ID
*/
public off(eventType: string, listenerId: string): boolean {
if (this.isDebugMode) {
console.log(`[EventBus] Removing listener: ${listenerId} for event: ${eventType}`);
}
return this.eventSystem.off(eventType, listenerId);
}
/**
* 移除指定事件类型的所有监听器
* @param eventType 事件类型
*/
public offAll(eventType: string): void {
if (this.isDebugMode) {
console.log(`[EventBus] Removing all listeners for event: ${eventType}`);
}
this.eventSystem.offAll(eventType);
}
/**
* 检查是否有指定事件的监听器
* @param eventType 事件类型
*/
public hasListeners(eventType: string): boolean {
return this.eventSystem.hasListeners(eventType);
}
/**
* 获取事件统计信息
* @param eventType 事件类型(可选)
*/
public getStats(eventType?: string): IEventStats | Map<string, IEventStats> {
const stats = this.eventSystem.getStats(eventType);
if (stats instanceof Map) {
// 转换Map中的每个EventStats为IEventStats
const result = new Map<string, IEventStats>();
stats.forEach((stat, key) => {
result.set(key, this.convertEventStats(stat));
});
return result;
} else {
return this.convertEventStats(stats);
}
}
/**
* 清空所有监听器
*/
public clear(): void {
if (this.isDebugMode) {
console.log('[EventBus] Clearing all listeners');
}
this.eventSystem.clear();
}
/**
* 启用或禁用事件系统
* @param enabled 是否启用
*/
public setEnabled(enabled: boolean): void {
this.eventSystem.setEnabled(enabled);
}
/**
* 设置调试模式
* @param debug 是否启用调试
*/
public setDebugMode(debug: boolean): void {
this.isDebugMode = debug;
}
/**
* 设置最大监听器数量
* @param max 最大数量
*/
public setMaxListeners(max: number): void {
this.eventSystem.setMaxListeners(max);
}
/**
* 获取监听器数量
* @param eventType 事件类型
*/
public getListenerCount(eventType: string): number {
return this.eventSystem.getListenerCount(eventType);
}
/**
* 设置事件批处理配置
* @param eventType 事件类型
* @param batchSize 批处理大小
* @param delay 延迟时间(毫秒)
*/
public setBatchConfig(eventType: string, batchSize: number, delay: number): void {
this.eventSystem.setBatchConfig(eventType, {
batchSize,
delay,
enabled: true
});
}
/**
* 刷新指定事件的批处理队列
* @param eventType 事件类型
*/
public flushBatch(eventType: string): void {
this.eventSystem.flushBatch(eventType);
}
/**
* 重置事件统计
* @param eventType 事件类型(可选)
*/
public resetStats(eventType?: string): void {
this.eventSystem.resetStats(eventType);
}
// 便捷方法发射预定义的ECS事件
/**
* 发射实体创建事件
* @param entityData 实体事件数据
*/
public emitEntityCreated(entityData: IEntityEventData): void {
this.emit(ECSEventType.ENTITY_CREATED, entityData);
}
/**
* 发射实体销毁事件
* @param entityData 实体事件数据
*/
public emitEntityDestroyed(entityData: IEntityEventData): void {
this.emit(ECSEventType.ENTITY_DESTROYED, entityData);
}
/**
* 发射组件添加事件
* @param componentData 组件事件数据
*/
public emitComponentAdded(componentData: IComponentEventData): void {
this.emit(ECSEventType.COMPONENT_ADDED, componentData);
}
/**
* 发射组件移除事件
* @param componentData 组件事件数据
*/
public emitComponentRemoved(componentData: IComponentEventData): void {
this.emit(ECSEventType.COMPONENT_REMOVED, componentData);
}
/**
* 发射系统添加事件
* @param systemData 系统事件数据
*/
public emitSystemAdded(systemData: ISystemEventData): void {
this.emit(ECSEventType.SYSTEM_ADDED, systemData);
}
/**
* 发射系统移除事件
* @param systemData 系统事件数据
*/
public emitSystemRemoved(systemData: ISystemEventData): void {
this.emit(ECSEventType.SYSTEM_REMOVED, systemData);
}
/**
* 发射场景变化事件
* @param sceneData 场景事件数据
*/
public emitSceneChanged(sceneData: ISceneEventData): void {
this.emit(EVENT_TYPES.CORE.SCENE_CHANGED, sceneData);
}
/**
* 发射性能警告事件
* @param performanceData 性能事件数据
*/
public emitPerformanceWarning(performanceData: IPerformanceEventData): void {
this.emit(ECSEventType.PERFORMANCE_WARNING, performanceData);
}
// 便捷方法监听预定义的ECS事件
/**
* 监听实体创建事件
* @param handler 事件处理器
* @param config 监听器配置
*/
public onEntityCreated(
handler: (data: IEntityEventData) => void,
config?: IEventListenerConfig
): string {
return this.on(ECSEventType.ENTITY_CREATED, handler, config);
}
/**
* 监听组件添加事件
* @param handler 事件处理器
* @param config 监听器配置
*/
public onComponentAdded(
handler: (data: IComponentEventData) => void,
config?: IEventListenerConfig
): string {
return this.on(ECSEventType.COMPONENT_ADDED, handler, config);
}
/**
* 监听系统错误事件
* @param handler 事件处理器
* @param config 监听器配置
*/
public onSystemError(
handler: (data: ISystemEventData) => void,
config?: IEventListenerConfig
): string {
return this.on(ECSEventType.SYSTEM_ERROR, handler, config);
}
/**
* 监听性能警告事件
* @param handler 事件处理器
* @param config 监听器配置
*/
public onPerformanceWarning(
handler: (data: IPerformanceEventData) => void,
config?: IEventListenerConfig
): string {
return this.on(ECSEventType.PERFORMANCE_WARNING, handler, config);
}
// 私有方法
/**
* 验证事件类型
* @param eventType 事件类型
*/
private validateEventType(eventType: string): void {
if (!EventTypeValidator.isValid(eventType)) {
if (this.isDebugMode) {
console.warn(`[EventBus] Unknown event type: ${eventType}`);
}
// 在调试模式下添加自定义事件类型
if (this.isDebugMode) {
EventTypeValidator.addCustomType(eventType);
}
}
}
/**
* 增强事件数据
* @param eventType 事件类型
* @param data 原始数据
*/
private enhanceEventData<T>(eventType: string, data: T): T & IEventData {
const enhanced = data as T & IEventData;
// 如果数据还没有基础事件属性,添加它们
if (!enhanced.timestamp) {
enhanced.timestamp = Date.now();
}
if (!enhanced.eventId) {
enhanced.eventId = `${eventType}_${++this.eventIdCounter}`;
}
if (!enhanced.source) {
enhanced.source = 'EventBus';
}
return enhanced;
}
/**
* 转换EventStats为IEventStats
* @param stats EventStats实例
*/
private convertEventStats(stats: EventStats): IEventStats {
return {
eventType: stats.eventType,
listenerCount: stats.listenerCount,
triggerCount: stats.triggerCount,
totalExecutionTime: stats.totalExecutionTime,
averageExecutionTime: stats.averageExecutionTime,
lastTriggerTime: stats.lastTriggerTime
};
}
}
/**
* 全局事件总线实例
* 提供全局访问的事件总线
*/
export class GlobalEventBus {
private static instance: EventBus;
/**
* 获取全局事件总线实例
* @param debugMode 是否启用调试模式
*/
public static getInstance(debugMode: boolean = false): EventBus {
if (!this.instance) {
this.instance = new EventBus(debugMode);
}
return this.instance;
}
/**
* 重置全局事件总线实例
* @param debugMode 是否启用调试模式
*/
public static reset(debugMode: boolean = false): EventBus {
if (this.instance) {
this.instance.clear();
}
this.instance = new EventBus(debugMode);
return this.instance;
}
}
/**
* 事件装饰器工厂
* 用于自动注册事件监听器
*/
export function EventHandler(eventType: string, config: IEventListenerConfig = {}) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
// 在类实例化时自动注册监听器
const initMethod = target.constructor.prototype.initEventListeners || function() {};
target.constructor.prototype.initEventListeners = function() {
initMethod.call(this);
const eventBus = GlobalEventBus.getInstance();
eventBus.on(eventType, originalMethod.bind(this), config);
};
return descriptor;
};
}
/**
* 异步事件装饰器工厂
* 用于自动注册异步事件监听器
*/
export function AsyncEventHandler(eventType: string, config: IEventListenerConfig = {}) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const initMethod = target.constructor.prototype.initEventListeners || function() {};
target.constructor.prototype.initEventListeners = function() {
initMethod.call(this);
const eventBus = GlobalEventBus.getInstance();
eventBus.onAsync(eventType, originalMethod.bind(this), config);
};
return descriptor;
};
}

611
src/ECS/Core/EventSystem.ts Normal file
View File

@@ -0,0 +1,611 @@
/**
* 事件处理器函数类型
*/
export type EventHandler<T = any> = (event: T) => void;
/**
* 异步事件处理器函数类型
*/
export type AsyncEventHandler<T = any> = (event: T) => Promise<void>;
/**
* 事件监听器配置
*/
export interface EventListenerConfig {
/** 是否只执行一次 */
once?: boolean;
/** 优先级(数字越大优先级越高) */
priority?: number;
/** 是否异步执行 */
async?: boolean;
/** 执行上下文 */
context?: any;
}
/**
* 内部事件监听器
*/
interface InternalEventListener<T = any> {
handler: EventHandler<T> | AsyncEventHandler<T>;
config: EventListenerConfig;
id: string;
}
/**
* 事件统计信息
*/
export interface EventStats {
/** 事件类型 */
eventType: string;
/** 监听器数量 */
listenerCount: number;
/** 触发次数 */
triggerCount: number;
/** 总执行时间(毫秒) */
totalExecutionTime: number;
/** 平均执行时间(毫秒) */
averageExecutionTime: number;
/** 最后触发时间 */
lastTriggerTime: number;
}
/**
* 事件批处理配置
*/
export interface EventBatchConfig {
/** 批处理大小 */
batchSize: number;
/** 批处理延迟(毫秒) */
delay: number;
/** 是否启用批处理 */
enabled: boolean;
}
/**
* 类型安全的高性能事件系统
* 支持同步/异步事件、优先级、批处理等功能
*/
export class TypeSafeEventSystem {
private listeners = new Map<string, InternalEventListener[]>();
private stats = new Map<string, EventStats>();
private batchQueue = new Map<string, any[]>();
private batchTimers = new Map<string, number>();
private batchConfigs = new Map<string, EventBatchConfig>();
private nextListenerId = 0;
private isEnabled = true;
private maxListeners = 100; // 每个事件类型的最大监听器数量
/**
* 添加事件监听器
* @param eventType 事件类型
* @param handler 事件处理器
* @param config 监听器配置
* @returns 监听器ID用于移除
*/
public on<T>(
eventType: string,
handler: EventHandler<T>,
config: EventListenerConfig = {}
): string {
return this.addListener(eventType, handler, config);
}
/**
* 添加一次性事件监听器
* @param eventType 事件类型
* @param handler 事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
public once<T>(
eventType: string,
handler: EventHandler<T>,
config: EventListenerConfig = {}
): string {
return this.addListener(eventType, handler, { ...config, once: true });
}
/**
* 添加异步事件监听器
* @param eventType 事件类型
* @param handler 异步事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
public onAsync<T>(
eventType: string,
handler: AsyncEventHandler<T>,
config: EventListenerConfig = {}
): string {
return this.addListener(eventType, handler, { ...config, async: true });
}
/**
* 移除事件监听器
* @param eventType 事件类型
* @param listenerId 监听器ID
* @returns 是否成功移除
*/
public off(eventType: string, listenerId: string): boolean {
const listeners = this.listeners.get(eventType);
if (!listeners) return false;
const index = listeners.findIndex(l => l.id === listenerId);
if (index === -1) return false;
listeners.splice(index, 1);
// 如果没有监听器了,清理相关数据
if (listeners.length === 0) {
this.listeners.delete(eventType);
this.stats.delete(eventType);
}
return true;
}
/**
* 移除指定事件类型的所有监听器
* @param eventType 事件类型
*/
public offAll(eventType: string): void {
this.listeners.delete(eventType);
this.stats.delete(eventType);
this.clearBatch(eventType);
}
/**
* 触发事件
* @param eventType 事件类型
* @param event 事件数据
* @returns Promise如果有异步监听器
*/
public async emit<T>(eventType: string, event: T): Promise<void> {
if (!this.isEnabled) return;
// 检查是否启用了批处理
const batchConfig = this.batchConfigs.get(eventType);
if (batchConfig?.enabled) {
this.addToBatch(eventType, event);
return;
}
await this.executeEvent(eventType, event);
}
/**
* 同步触发事件(忽略异步监听器)
* @param eventType 事件类型
* @param event 事件数据
*/
public emitSync<T>(eventType: string, event: T): void {
if (!this.isEnabled) return;
const listeners = this.listeners.get(eventType);
if (!listeners || listeners.length === 0) return;
const startTime = performance.now();
const toRemove: string[] = [];
// 按优先级排序
const sortedListeners = this.sortListenersByPriority(listeners);
for (const listener of sortedListeners) {
if (listener.config.async) continue; // 跳过异步监听器
try {
if (listener.config.context) {
(listener.handler as EventHandler<T>).call(listener.config.context, event);
} else {
(listener.handler as EventHandler<T>)(event);
}
if (listener.config.once) {
toRemove.push(listener.id);
}
} catch (error) {
console.error(`Error in event handler for ${eventType}:`, error);
}
}
// 移除一次性监听器
this.removeListeners(eventType, toRemove);
// 更新统计信息
this.updateStats(eventType, performance.now() - startTime);
}
/**
* 设置事件批处理配置
* @param eventType 事件类型
* @param config 批处理配置
*/
public setBatchConfig(eventType: string, config: EventBatchConfig): void {
this.batchConfigs.set(eventType, config);
}
/**
* 立即处理指定事件类型的批处理队列
* @param eventType 事件类型
*/
public flushBatch(eventType: string): void {
const batch = this.batchQueue.get(eventType);
if (!batch || batch.length === 0) return;
// 清除定时器
const timer = this.batchTimers.get(eventType);
if (timer) {
clearTimeout(timer);
this.batchTimers.delete(eventType);
}
// 处理批处理事件
this.processBatch(eventType, batch);
// 清空队列
this.batchQueue.delete(eventType);
}
/**
* 获取事件统计信息
* @param eventType 事件类型(可选)
* @returns 统计信息
*/
public getStats(eventType?: string): EventStats | Map<string, EventStats> {
if (eventType) {
return this.stats.get(eventType) || this.createEmptyStats(eventType);
}
return new Map(this.stats);
}
/**
* 重置统计信息
* @param eventType 事件类型(可选,不指定则重置所有)
*/
public resetStats(eventType?: string): void {
if (eventType) {
this.stats.delete(eventType);
} else {
this.stats.clear();
}
}
/**
* 启用/禁用事件系统
* @param enabled 是否启用
*/
public setEnabled(enabled: boolean): void {
this.isEnabled = enabled;
}
/**
* 检查是否有指定事件类型的监听器
* @param eventType 事件类型
* @returns 是否有监听器
*/
public hasListeners(eventType: string): boolean {
const listeners = this.listeners.get(eventType);
return listeners ? listeners.length > 0 : false;
}
/**
* 获取指定事件类型的监听器数量
* @param eventType 事件类型
* @returns 监听器数量
*/
public getListenerCount(eventType: string): number {
const listeners = this.listeners.get(eventType);
return listeners ? listeners.length : 0;
}
/**
* 清空所有事件监听器和数据
*/
public clear(): void {
this.listeners.clear();
this.stats.clear();
this.clearAllBatches();
}
/**
* 设置每个事件类型的最大监听器数量
* @param max 最大数量
*/
public setMaxListeners(max: number): void {
this.maxListeners = max;
}
/**
* 添加监听器的内部实现
* @param eventType 事件类型
* @param handler 事件处理器
* @param config 配置
* @returns 监听器ID
*/
private addListener<T>(
eventType: string,
handler: EventHandler<T> | AsyncEventHandler<T>,
config: EventListenerConfig
): string {
let listeners = this.listeners.get(eventType);
if (!listeners) {
listeners = [];
this.listeners.set(eventType, listeners);
}
// 检查监听器数量限制
if (listeners.length >= this.maxListeners) {
console.warn(`Maximum listeners (${this.maxListeners}) exceeded for event type: ${eventType}`);
return '';
}
const listenerId = `listener_${this.nextListenerId++}`;
const listener: InternalEventListener<T> = {
handler,
config: {
priority: 0,
...config
},
id: listenerId
};
listeners.push(listener);
// 初始化统计信息
if (!this.stats.has(eventType)) {
this.stats.set(eventType, this.createEmptyStats(eventType));
}
return listenerId;
}
/**
* 执行事件的内部实现
* @param eventType 事件类型
* @param event 事件数据
*/
private async executeEvent<T>(eventType: string, event: T): Promise<void> {
const listeners = this.listeners.get(eventType);
if (!listeners || listeners.length === 0) return;
const startTime = performance.now();
const toRemove: string[] = [];
// 按优先级排序
const sortedListeners = this.sortListenersByPriority(listeners);
// 分离同步和异步监听器
const syncListeners = sortedListeners.filter(l => !l.config.async);
const asyncListeners = sortedListeners.filter(l => l.config.async);
// 执行同步监听器
for (const listener of syncListeners) {
try {
if (listener.config.context) {
(listener.handler as EventHandler<T>).call(listener.config.context, event);
} else {
(listener.handler as EventHandler<T>)(event);
}
if (listener.config.once) {
toRemove.push(listener.id);
}
} catch (error) {
console.error(`Error in sync event handler for ${eventType}:`, error);
}
}
// 执行异步监听器
const asyncPromises = asyncListeners.map(async (listener) => {
try {
if (listener.config.context) {
await (listener.handler as AsyncEventHandler<T>).call(listener.config.context, event);
} else {
await (listener.handler as AsyncEventHandler<T>)(event);
}
if (listener.config.once) {
toRemove.push(listener.id);
}
} catch (error) {
console.error(`Error in async event handler for ${eventType}:`, error);
}
});
// 等待所有异步监听器完成
await Promise.all(asyncPromises);
// 移除一次性监听器
this.removeListeners(eventType, toRemove);
// 更新统计信息
this.updateStats(eventType, performance.now() - startTime);
}
/**
* 按优先级排序监听器
* @param listeners 监听器数组
* @returns 排序后的监听器数组
*/
private sortListenersByPriority<T>(listeners: InternalEventListener<T>[]): InternalEventListener<T>[] {
return listeners.slice().sort((a, b) => (b.config.priority || 0) - (a.config.priority || 0));
}
/**
* 移除指定的监听器
* @param eventType 事件类型
* @param listenerIds 要移除的监听器ID数组
*/
private removeListeners(eventType: string, listenerIds: string[]): void {
if (listenerIds.length === 0) return;
const listeners = this.listeners.get(eventType);
if (!listeners) return;
for (const id of listenerIds) {
const index = listeners.findIndex(l => l.id === id);
if (index !== -1) {
listeners.splice(index, 1);
}
}
// 如果没有监听器了,清理相关数据
if (listeners.length === 0) {
this.listeners.delete(eventType);
this.stats.delete(eventType);
}
}
/**
* 添加事件到批处理队列
* @param eventType 事件类型
* @param event 事件数据
*/
private addToBatch<T>(eventType: string, event: T): void {
let batch = this.batchQueue.get(eventType);
if (!batch) {
batch = [];
this.batchQueue.set(eventType, batch);
}
batch.push(event);
const config = this.batchConfigs.get(eventType)!;
// 如果达到批处理大小,立即处理
if (batch.length >= config.batchSize) {
this.flushBatch(eventType);
return;
}
// 设置延迟处理定时器
if (!this.batchTimers.has(eventType)) {
const timer = setTimeout(() => {
this.flushBatch(eventType);
}, config.delay);
this.batchTimers.set(eventType, timer as any);
}
}
/**
* 处理批处理事件
* @param eventType 事件类型
* @param batch 批处理事件数组
*/
private async processBatch<T>(eventType: string, batch: T[]): Promise<void> {
// 创建批处理事件对象
const batchEvent = {
type: eventType,
events: batch,
count: batch.length,
timestamp: Date.now()
};
// 触发批处理事件
await this.executeEvent(`${eventType}:batch`, batchEvent);
}
/**
* 清除指定事件类型的批处理
* @param eventType 事件类型
*/
private clearBatch(eventType: string): void {
this.batchQueue.delete(eventType);
const timer = this.batchTimers.get(eventType);
if (timer) {
clearTimeout(timer);
this.batchTimers.delete(eventType);
}
}
/**
* 清除所有批处理
*/
private clearAllBatches(): void {
this.batchQueue.clear();
for (const timer of this.batchTimers.values()) {
clearTimeout(timer);
}
this.batchTimers.clear();
this.batchConfigs.clear();
}
/**
* 更新事件统计信息
* @param eventType 事件类型
* @param executionTime 执行时间
*/
private updateStats(eventType: string, executionTime: number): void {
let stats = this.stats.get(eventType);
if (!stats) {
stats = this.createEmptyStats(eventType);
this.stats.set(eventType, stats);
}
stats.triggerCount++;
stats.totalExecutionTime += executionTime;
stats.averageExecutionTime = stats.totalExecutionTime / stats.triggerCount;
stats.lastTriggerTime = Date.now();
stats.listenerCount = this.getListenerCount(eventType);
}
/**
* 创建空的统计信息
* @param eventType 事件类型
* @returns 空的统计信息
*/
private createEmptyStats(eventType: string): EventStats {
return {
eventType,
listenerCount: 0,
triggerCount: 0,
totalExecutionTime: 0,
averageExecutionTime: 0,
lastTriggerTime: 0
};
}
}
/**
* 全局事件系统实例
*/
export const GlobalEventSystem = new TypeSafeEventSystem();
/**
* 事件装饰器 - 用于自动注册事件监听器
* @param eventType 事件类型
* @param config 监听器配置
*/
export function EventListener(eventType: string, config: EventListenerConfig = {}) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
// 在类实例化时自动注册监听器
const initMethod = target.constructor.prototype.initEventListeners || function() {};
target.constructor.prototype.initEventListeners = function() {
initMethod.call(this);
GlobalEventSystem.on(eventType, originalMethod.bind(this), config);
};
};
}
/**
* 异步事件装饰器
* @param eventType 事件类型
* @param config 监听器配置
*/
export function AsyncEventListener(eventType: string, config: EventListenerConfig = {}) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const initMethod = target.constructor.prototype.initEventListeners || function() {};
target.constructor.prototype.initEventListeners = function() {
initMethod.call(this);
GlobalEventSystem.onAsync(eventType, originalMethod.bind(this), config);
};
};
}

View File

@@ -0,0 +1,2 @@
export { EventBus, GlobalEventBus, EventHandler, AsyncEventHandler } from '../EventBus';
export { TypeSafeEventSystem, EventListenerConfig, EventStats } from '../EventSystem';

637
src/ECS/Core/FluentAPI.ts Normal file
View File

@@ -0,0 +1,637 @@
import { Entity } from '../Entity';
import { Component } from '../Component';
import { Scene } from '../Scene';
import { ComponentType, ComponentStorageManager } from './ComponentStorage';
import { QuerySystem, QueryBuilder } from './QuerySystem';
import { TypeSafeEventSystem } from './EventSystem';
/**
* 实体构建器 - 提供流式API创建和配置实体
*/
export class EntityBuilder {
private entity: Entity;
private scene: Scene;
private storageManager: ComponentStorageManager;
constructor(scene: Scene, storageManager: ComponentStorageManager) {
this.scene = scene;
this.storageManager = storageManager;
this.entity = new Entity("", scene.identifierPool.checkOut());
}
/**
* 设置实体名称
* @param name 实体名称
* @returns 实体构建器
*/
public named(name: string): EntityBuilder {
this.entity.name = name;
return this;
}
/**
* 设置实体标签
* @param tag 标签
* @returns 实体构建器
*/
public tagged(tag: number): EntityBuilder {
this.entity.tag = tag;
return this;
}
/**
* 添加组件
* @param component 组件实例
* @returns 实体构建器
*/
public with<T extends Component>(component: T): EntityBuilder {
this.entity.addComponent(component);
return this;
}
/**
* 添加多个组件
* @param components 组件数组
* @returns 实体构建器
*/
public withComponents(...components: Component[]): EntityBuilder {
for (const component of components) {
this.entity.addComponent(component);
}
return this;
}
/**
* 条件性添加组件
* @param condition 条件
* @param component 组件实例
* @returns 实体构建器
*/
public withIf<T extends Component>(condition: boolean, component: T): EntityBuilder {
if (condition) {
this.entity.addComponent(component);
}
return this;
}
/**
* 使用工厂函数创建并添加组件
* @param factory 组件工厂函数
* @returns 实体构建器
*/
public withFactory<T extends Component>(factory: () => T): EntityBuilder {
const component = factory();
this.entity.addComponent(component);
return this;
}
/**
* 配置组件属性
* @param componentType 组件类型
* @param configurator 配置函数
* @returns 实体构建器
*/
public configure<T extends Component>(
componentType: ComponentType<T>,
configurator: (component: T) => void
): EntityBuilder {
const component = this.entity.getComponent(componentType);
if (component) {
configurator(component);
}
return this;
}
/**
* 设置实体为启用状态
* @param enabled 是否启用
* @returns 实体构建器
*/
public enabled(enabled: boolean = true): EntityBuilder {
this.entity.enabled = enabled;
return this;
}
/**
* 设置实体为活跃状态
* @param active 是否活跃
* @returns 实体构建器
*/
public active(active: boolean = true): EntityBuilder {
this.entity.active = active;
return this;
}
/**
* 添加子实体
* @param childBuilder 子实体构建器
* @returns 实体构建器
*/
public withChild(childBuilder: EntityBuilder): EntityBuilder {
const child = childBuilder.build();
this.entity.addChild(child);
return this;
}
/**
* 批量添加子实体
* @param childBuilders 子实体构建器数组
* @returns 实体构建器
*/
public withChildren(...childBuilders: EntityBuilder[]): EntityBuilder {
for (const childBuilder of childBuilders) {
const child = childBuilder.build();
this.entity.addChild(child);
}
return this;
}
/**
* 使用工厂函数创建子实体
* @param childFactory 子实体工厂函数
* @returns 实体构建器
*/
public withChildFactory(childFactory: (parent: Entity) => EntityBuilder): EntityBuilder {
const childBuilder = childFactory(this.entity);
const child = childBuilder.build();
this.entity.addChild(child);
return this;
}
/**
* 条件性添加子实体
* @param condition 条件
* @param childBuilder 子实体构建器
* @returns 实体构建器
*/
public withChildIf(condition: boolean, childBuilder: EntityBuilder): EntityBuilder {
if (condition) {
const child = childBuilder.build();
this.entity.addChild(child);
}
return this;
}
/**
* 构建并返回实体
* @returns 构建的实体
*/
public build(): Entity {
return this.entity;
}
/**
* 构建实体并添加到场景
* @returns 构建的实体
*/
public spawn(): Entity {
this.scene.addEntity(this.entity);
return this.entity;
}
/**
* 克隆当前构建器
* @returns 新的实体构建器
*/
public clone(): EntityBuilder {
const newBuilder = new EntityBuilder(this.scene, this.storageManager);
// 这里需要深度克隆实体,简化实现
newBuilder.entity = this.entity; // 实际应该是深度克隆
return newBuilder;
}
}
/**
* 场景构建器 - 提供流式API创建和配置场景
*/
export class SceneBuilder {
private scene: Scene;
constructor() {
this.scene = new Scene();
}
/**
* 设置场景名称
* @param name 场景名称
* @returns 场景构建器
*/
public named(name: string): SceneBuilder {
this.scene.name = name;
return this;
}
/**
* 添加实体
* @param entity 实体
* @returns 场景构建器
*/
public withEntity(entity: Entity): SceneBuilder {
this.scene.addEntity(entity);
return this;
}
/**
* 使用实体构建器添加实体
* @param builderFn 实体构建器函数
* @returns 场景构建器
*/
public withEntityBuilder(builderFn: (builder: EntityBuilder) => EntityBuilder): SceneBuilder {
const builder = new EntityBuilder(this.scene, this.scene.componentStorageManager);
const configuredBuilder = builderFn(builder);
const entity = configuredBuilder.build();
this.scene.addEntity(entity);
return this;
}
/**
* 批量添加实体
* @param entities 实体数组
* @returns 场景构建器
*/
public withEntities(...entities: Entity[]): SceneBuilder {
for (const entity of entities) {
this.scene.addEntity(entity);
}
return this;
}
/**
* 添加系统
* @param system 系统实例
* @returns 场景构建器
*/
public withSystem(system: any): SceneBuilder {
this.scene.addSystem(system);
return this;
}
/**
* 批量添加系统
* @param systems 系统数组
* @returns 场景构建器
*/
public withSystems(...systems: any[]): SceneBuilder {
for (const system of systems) {
this.scene.addSystem(system);
}
return this;
}
/**
* 构建并返回场景
* @returns 构建的场景
*/
public build(): Scene {
return this.scene;
}
}
/**
* 组件构建器 - 提供流式API创建组件
*/
export class ComponentBuilder<T extends Component> {
private component: T;
constructor(componentClass: new (...args: any[]) => T, ...args: any[]) {
this.component = new componentClass(...args);
}
/**
* 设置组件属性
* @param property 属性名
* @param value 属性值
* @returns 组件构建器
*/
public set<K extends keyof T>(property: K, value: T[K]): ComponentBuilder<T> {
this.component[property] = value;
return this;
}
/**
* 使用配置函数设置组件
* @param configurator 配置函数
* @returns 组件构建器
*/
public configure(configurator: (component: T) => void): ComponentBuilder<T> {
configurator(this.component);
return this;
}
/**
* 条件性设置属性
* @param condition 条件
* @param property 属性名
* @param value 属性值
* @returns 组件构建器
*/
public setIf<K extends keyof T>(condition: boolean, property: K, value: T[K]): ComponentBuilder<T> {
if (condition) {
this.component[property] = value;
}
return this;
}
/**
* 构建并返回组件
* @returns 构建的组件
*/
public build(): T {
return this.component;
}
}
/**
* ECS流式API主入口
* 提供统一的流式接口
*/
export class ECSFluentAPI {
private scene: Scene;
private querySystem: QuerySystem;
private eventSystem: TypeSafeEventSystem;
constructor(scene: Scene, querySystem: QuerySystem, eventSystem: TypeSafeEventSystem) {
this.scene = scene;
this.querySystem = querySystem;
this.eventSystem = eventSystem;
}
/**
* 创建实体构建器
* @returns 实体构建器
*/
public createEntity(): EntityBuilder {
return new EntityBuilder(this.scene, this.scene.componentStorageManager);
}
/**
* 创建场景构建器
* @returns 场景构建器
*/
public createScene(): SceneBuilder {
return new SceneBuilder();
}
/**
* 创建组件构建器
* @param componentClass 组件类
* @param args 构造参数
* @returns 组件构建器
*/
public createComponent<T extends Component>(
componentClass: new (...args: any[]) => T,
...args: any[]
): ComponentBuilder<T> {
return new ComponentBuilder(componentClass, ...args);
}
/**
* 创建查询构建器
* @returns 查询构建器
*/
public query(): QueryBuilder {
return new QueryBuilder(this.querySystem);
}
/**
* 查找实体(简化版)
* @param componentTypes 组件类型
* @returns 实体数组
*/
public find(...componentTypes: ComponentType[]): Entity[] {
return this.querySystem.queryAll(...componentTypes).entities;
}
/**
* 查找第一个匹配的实体
* @param componentTypes 组件类型
* @returns 实体或null
*/
public findFirst(...componentTypes: ComponentType[]): Entity | null {
const result = this.querySystem.queryAll(...componentTypes);
return result.entities.length > 0 ? result.entities[0] : null;
}
/**
* 按名称查找实体
* @param name 实体名称
* @returns 实体或null
*/
public findByName(name: string): Entity | null {
return this.scene.getEntityByName(name);
}
/**
* 按标签查找实体
* @param tag 标签
* @returns 实体数组
*/
public findByTag(tag: number): Entity[] {
return this.scene.getEntitiesByTag(tag);
}
/**
* 触发事件
* @param eventType 事件类型
* @param event 事件数据
*/
public emit<T>(eventType: string, event: T): void {
this.eventSystem.emitSync(eventType, event);
}
/**
* 异步触发事件
* @param eventType 事件类型
* @param event 事件数据
*/
public async emitAsync<T>(eventType: string, event: T): Promise<void> {
await this.eventSystem.emit(eventType, event);
}
/**
* 监听事件
* @param eventType 事件类型
* @param handler 事件处理器
* @returns 监听器ID
*/
public on<T>(eventType: string, handler: (event: T) => void): string {
return this.eventSystem.on(eventType, handler);
}
/**
* 一次性监听事件
* @param eventType 事件类型
* @param handler 事件处理器
* @returns 监听器ID
*/
public once<T>(eventType: string, handler: (event: T) => void): string {
return this.eventSystem.once(eventType, handler);
}
/**
* 移除事件监听器
* @param eventType 事件类型
* @param listenerId 监听器ID
*/
public off(eventType: string, listenerId: string): void {
this.eventSystem.off(eventType, listenerId);
}
/**
* 批量操作实体
* @param entities 实体数组
* @returns 批量操作器
*/
public batch(entities: Entity[]): EntityBatchOperator {
return new EntityBatchOperator(entities);
}
/**
* 获取场景统计信息
* @returns 统计信息
*/
public getStats(): {
entityCount: number;
systemCount: number;
componentStats: Map<string, any>;
queryStats: any;
eventStats: Map<string, any>;
} {
return {
entityCount: this.scene.entities.count,
systemCount: this.scene.systems.length,
componentStats: this.scene.componentStorageManager.getAllStats(),
queryStats: this.querySystem.getStats(),
eventStats: this.eventSystem.getStats() as Map<string, any>
};
}
}
/**
* 实体批量操作器
* 提供对多个实体的批量操作
*/
export class EntityBatchOperator {
private entities: Entity[];
constructor(entities: Entity[]) {
this.entities = entities;
}
/**
* 批量添加组件
* @param component 组件实例
* @returns 批量操作器
*/
public addComponent<T extends Component>(component: T): EntityBatchOperator {
for (const entity of this.entities) {
entity.addComponent(component);
}
return this;
}
/**
* 批量移除组件
* @param componentType 组件类型
* @returns 批量操作器
*/
public removeComponent<T extends Component>(componentType: ComponentType<T>): EntityBatchOperator {
for (const entity of this.entities) {
entity.removeComponentByType(componentType);
}
return this;
}
/**
* 批量设置活跃状态
* @param active 是否活跃
* @returns 批量操作器
*/
public setActive(active: boolean): EntityBatchOperator {
for (const entity of this.entities) {
entity.active = active;
}
return this;
}
/**
* 批量设置标签
* @param tag 标签
* @returns 批量操作器
*/
public setTag(tag: number): EntityBatchOperator {
for (const entity of this.entities) {
entity.tag = tag;
}
return this;
}
/**
* 批量执行操作
* @param operation 操作函数
* @returns 批量操作器
*/
public forEach(operation: (entity: Entity, index: number) => void): EntityBatchOperator {
this.entities.forEach(operation);
return this;
}
/**
* 过滤实体
* @param predicate 过滤条件
* @returns 新的批量操作器
*/
public filter(predicate: (entity: Entity) => boolean): EntityBatchOperator {
return new EntityBatchOperator(this.entities.filter(predicate));
}
/**
* 获取实体数组
* @returns 实体数组
*/
public toArray(): Entity[] {
return this.entities.slice();
}
/**
* 获取实体数量
* @returns 实体数量
*/
public count(): number {
return this.entities.length;
}
}
/**
* 创建ECS流式API实例
* @param scene 场景
* @param querySystem 查询系统
* @param eventSystem 事件系统
* @returns ECS流式API实例
*/
export function createECSAPI(
scene: Scene,
querySystem: QuerySystem,
eventSystem: TypeSafeEventSystem
): ECSFluentAPI {
return new ECSFluentAPI(scene, querySystem, eventSystem);
}
/**
* 全局ECS流式API实例需要在使用前初始化
*/
export let ECS: ECSFluentAPI;
/**
* 初始化全局ECS API
* @param scene 场景
* @param querySystem 查询系统
* @param eventSystem 事件系统
*/
export function initializeECS(
scene: Scene,
querySystem: QuerySystem,
eventSystem: TypeSafeEventSystem
): void {
ECS = createECSAPI(scene, querySystem, eventSystem);
}

View File

@@ -0,0 +1,256 @@
import { Entity } from '../Entity';
/**
* 索引更新操作类型
*/
export enum IndexUpdateType {
ADD_ENTITY = 'add_entity',
REMOVE_ENTITY = 'remove_entity',
UPDATE_ENTITY = 'update_entity'
}
/**
* 索引更新操作
*/
export interface IndexUpdateOperation {
type: IndexUpdateType;
entity: Entity;
oldMask?: bigint;
newMask?: bigint;
}
/**
* 延迟索引更新器,用于批量更新查询索引以提高性能
*/
export class IndexUpdateBatcher {
private pendingOperations: IndexUpdateOperation[] = [];
private isProcessing = false;
private batchSize = 1000;
private flushTimeout: NodeJS.Timeout | null = null;
private flushDelay = 16; // 16ms约60fps
/**
* 添加索引更新操作
*/
addOperation(operation: IndexUpdateOperation): void {
this.pendingOperations.push(operation);
// 如果达到批量大小,立即处理
if (this.pendingOperations.length >= this.batchSize) {
this.flush();
} else {
// 否则延迟处理
this.scheduleFlush();
}
}
/**
* 批量添加实体
*/
addEntities(entities: Entity[]): void {
for (const entity of entities) {
this.pendingOperations.push({
type: IndexUpdateType.ADD_ENTITY,
entity
});
}
if (this.pendingOperations.length >= this.batchSize) {
this.flush();
} else {
this.scheduleFlush();
}
}
/**
* 批量移除实体
*/
removeEntities(entities: Entity[]): void {
for (const entity of entities) {
this.pendingOperations.push({
type: IndexUpdateType.REMOVE_ENTITY,
entity
});
}
if (this.pendingOperations.length >= this.batchSize) {
this.flush();
} else {
this.scheduleFlush();
}
}
/**
* 批量更新实体
*/
updateEntities(updates: Array<{ entity: Entity; oldMask: bigint; newMask: bigint }>): void {
for (const update of updates) {
this.pendingOperations.push({
type: IndexUpdateType.UPDATE_ENTITY,
entity: update.entity,
oldMask: update.oldMask,
newMask: update.newMask
});
}
if (this.pendingOperations.length >= this.batchSize) {
this.flush();
} else {
this.scheduleFlush();
}
}
/**
* 安排延迟刷新
*/
private scheduleFlush(): void {
if (this.flushTimeout) {
return;
}
this.flushTimeout = setTimeout(() => {
this.flush();
}, this.flushDelay);
}
/**
* 立即处理所有待处理的操作
*/
flush(): void {
if (this.isProcessing || this.pendingOperations.length === 0) {
return;
}
this.isProcessing = true;
if (this.flushTimeout) {
clearTimeout(this.flushTimeout);
this.flushTimeout = null;
}
try {
this.processBatch();
} finally {
this.isProcessing = false;
}
}
/**
* 处理批量操作
*/
private processBatch(): void {
const operations = this.pendingOperations;
this.pendingOperations = [];
// 按操作类型分组以优化处理
const addOperations: Entity[] = [];
const removeOperations: Entity[] = [];
const updateOperations: Array<{ entity: Entity; oldMask: bigint; newMask: bigint }> = [];
for (const operation of operations) {
switch (operation.type) {
case IndexUpdateType.ADD_ENTITY:
addOperations.push(operation.entity);
break;
case IndexUpdateType.REMOVE_ENTITY:
removeOperations.push(operation.entity);
break;
case IndexUpdateType.UPDATE_ENTITY:
if (operation.oldMask !== undefined && operation.newMask !== undefined) {
updateOperations.push({
entity: operation.entity,
oldMask: operation.oldMask,
newMask: operation.newMask
});
}
break;
}
}
// 批量处理每种类型的操作
if (addOperations.length > 0) {
this.processBatchAdd(addOperations);
}
if (removeOperations.length > 0) {
this.processBatchRemove(removeOperations);
}
if (updateOperations.length > 0) {
this.processBatchUpdate(updateOperations);
}
}
/**
* 批量处理添加操作
*/
private processBatchAdd(entities: Entity[]): void {
// 这里应该调用QuerySystem的批量添加方法
// 由于需要访问QuerySystem这个方法应该由外部注入处理函数
if (this.onBatchAdd) {
this.onBatchAdd(entities);
}
}
/**
* 批量处理移除操作
*/
private processBatchRemove(entities: Entity[]): void {
if (this.onBatchRemove) {
this.onBatchRemove(entities);
}
}
/**
* 批量处理更新操作
*/
private processBatchUpdate(updates: Array<{ entity: Entity; oldMask: bigint; newMask: bigint }>): void {
if (this.onBatchUpdate) {
this.onBatchUpdate(updates);
}
}
/**
* 设置批量大小
*/
setBatchSize(size: number): void {
this.batchSize = Math.max(1, size);
}
/**
* 设置刷新延迟
*/
setFlushDelay(delay: number): void {
this.flushDelay = Math.max(0, delay);
}
/**
* 获取待处理操作数量
*/
getPendingCount(): number {
return this.pendingOperations.length;
}
/**
* 清空所有待处理操作
*/
clear(): void {
this.pendingOperations.length = 0;
if (this.flushTimeout) {
clearTimeout(this.flushTimeout);
this.flushTimeout = null;
}
}
/**
* 检查是否有待处理操作
*/
hasPendingOperations(): boolean {
return this.pendingOperations.length > 0;
}
// 回调函数,由外部设置
public onBatchAdd?: (entities: Entity[]) => void;
public onBatchRemove?: (entities: Entity[]) => void;
public onBatchUpdate?: (updates: Array<{ entity: Entity; oldMask: bigint; newMask: bigint }>) => void;
}

View File

@@ -0,0 +1,22 @@
export {
ComponentIndexManager,
HashComponentIndex,
BitmapComponentIndex,
IndexType
} from '../ComponentIndex';
export {
ArchetypeSystem,
Archetype,
ArchetypeQueryResult
} from '../ArchetypeSystem';
export {
DirtyTrackingSystem,
DirtyFlag,
DirtyData,
DirtyListener
} from '../DirtyTrackingSystem';
export { IndexUpdateBatcher } from '../IndexUpdateBatcher';
export { BitMaskOptimizer } from '../BitMaskOptimizer';

View File

@@ -0,0 +1,3 @@
export { QuerySystem } from '../QuerySystem';
export { ECSFluentAPI, createECSAPI } from '../FluentAPI';
export { EntityManager, EntityQueryBuilder } from '../EntityManager';

1227
src/ECS/Core/QuerySystem.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
export { ComponentPool } from '../ComponentPool';
export { ComponentStorage } from '../ComponentStorage';

209
src/ECS/CoreEvents.ts Normal file
View File

@@ -0,0 +1,209 @@
/**
* 核心事件枚举
* 定义框架中的核心事件类型
*/
export enum CoreEvents {
/**
* 当场景发生变化时触发
*/
sceneChanged,
/**
* 每帧更新事件
*/
frameUpdated,
/**
* 当渲染发生时触发
*/
renderChanged,
}
/**
* ECS事件类型枚举
* 定义实体组件系统中的所有事件类型
*/
export enum ECSEventType {
// 实体相关事件
ENTITY_CREATED = 'entity:created',
ENTITY_DESTROYED = 'entity:destroyed',
ENTITY_ENABLED = 'entity:enabled',
ENTITY_DISABLED = 'entity:disabled',
ENTITY_TAG_ADDED = 'entity:tag:added',
ENTITY_TAG_REMOVED = 'entity:tag:removed',
ENTITY_NAME_CHANGED = 'entity:name:changed',
// 组件相关事件
COMPONENT_ADDED = 'component:added',
COMPONENT_REMOVED = 'component:removed',
COMPONENT_MODIFIED = 'component:modified',
COMPONENT_ENABLED = 'component:enabled',
COMPONENT_DISABLED = 'component:disabled',
// 系统相关事件
SYSTEM_ADDED = 'system:added',
SYSTEM_REMOVED = 'system:removed',
SYSTEM_ENABLED = 'system:enabled',
SYSTEM_DISABLED = 'system:disabled',
SYSTEM_PROCESSING_START = 'system:processing:start',
SYSTEM_PROCESSING_END = 'system:processing:end',
SYSTEM_ERROR = 'system:error',
// 场景相关事件
SCENE_CREATED = 'scene:created',
SCENE_DESTROYED = 'scene:destroyed',
SCENE_ACTIVATED = 'scene:activated',
SCENE_DEACTIVATED = 'scene:deactivated',
SCENE_PAUSED = 'scene:paused',
SCENE_RESUMED = 'scene:resumed',
// 查询相关事件
QUERY_EXECUTED = 'query:executed',
QUERY_CACHE_HIT = 'query:cache:hit',
QUERY_CACHE_MISS = 'query:cache:miss',
QUERY_OPTIMIZED = 'query:optimized',
// 性能相关事件
PERFORMANCE_WARNING = 'performance:warning',
PERFORMANCE_CRITICAL = 'performance:critical',
MEMORY_USAGE_HIGH = 'memory:usage:high',
FRAME_RATE_DROP = 'frame:rate:drop',
// 索引相关事件
INDEX_CREATED = 'index:created',
INDEX_UPDATED = 'index:updated',
INDEX_OPTIMIZED = 'index:optimized',
// Archetype相关事件
ARCHETYPE_CREATED = 'archetype:created',
ARCHETYPE_ENTITY_ADDED = 'archetype:entity:added',
ARCHETYPE_ENTITY_REMOVED = 'archetype:entity:removed',
// 脏标记相关事件
DIRTY_MARK_ADDED = 'dirty:mark:added',
DIRTY_BATCH_PROCESSED = 'dirty:batch:processed',
// 错误和警告事件
ERROR_OCCURRED = 'error:occurred',
WARNING_ISSUED = 'warning:issued',
// 生命周期事件
FRAMEWORK_INITIALIZED = 'framework:initialized',
FRAMEWORK_SHUTDOWN = 'framework:shutdown',
// 调试相关事件
DEBUG_INFO = 'debug:info',
DEBUG_STATS_UPDATED = 'debug:stats:updated'
}
/**
* 事件优先级枚举
* 定义事件处理的优先级级别
*/
export enum EventPriority {
LOWEST = 0,
LOW = 25,
NORMAL = 50,
HIGH = 75,
HIGHEST = 100,
CRITICAL = 200
}
/**
* 预定义的事件类型常量
* 提供类型安全的事件类型字符串
*/
export const EVENT_TYPES = {
// 核心事件
CORE: {
SCENE_CHANGED: 'core:scene:changed',
FRAME_UPDATED: 'core:frame:updated',
RENDER_CHANGED: 'core:render:changed'
},
// 实体事件
ENTITY: {
CREATED: ECSEventType.ENTITY_CREATED,
DESTROYED: ECSEventType.ENTITY_DESTROYED,
ENABLED: ECSEventType.ENTITY_ENABLED,
DISABLED: ECSEventType.ENTITY_DISABLED,
TAG_ADDED: ECSEventType.ENTITY_TAG_ADDED,
TAG_REMOVED: ECSEventType.ENTITY_TAG_REMOVED,
NAME_CHANGED: ECSEventType.ENTITY_NAME_CHANGED
},
// 组件事件
COMPONENT: {
ADDED: ECSEventType.COMPONENT_ADDED,
REMOVED: ECSEventType.COMPONENT_REMOVED,
MODIFIED: ECSEventType.COMPONENT_MODIFIED,
ENABLED: ECSEventType.COMPONENT_ENABLED,
DISABLED: ECSEventType.COMPONENT_DISABLED
},
// 系统事件
SYSTEM: {
ADDED: ECSEventType.SYSTEM_ADDED,
REMOVED: ECSEventType.SYSTEM_REMOVED,
ENABLED: ECSEventType.SYSTEM_ENABLED,
DISABLED: ECSEventType.SYSTEM_DISABLED,
PROCESSING_START: ECSEventType.SYSTEM_PROCESSING_START,
PROCESSING_END: ECSEventType.SYSTEM_PROCESSING_END,
ERROR: ECSEventType.SYSTEM_ERROR
},
// 性能事件
PERFORMANCE: {
WARNING: ECSEventType.PERFORMANCE_WARNING,
CRITICAL: ECSEventType.PERFORMANCE_CRITICAL,
MEMORY_HIGH: ECSEventType.MEMORY_USAGE_HIGH,
FRAME_DROP: ECSEventType.FRAME_RATE_DROP
}
} as const;
/**
* 事件类型验证器
* 验证事件类型是否有效
*/
export class EventTypeValidator {
private static validTypes = new Set([
...Object.values(CoreEvents).map(e => e.toString()),
...Object.values(ECSEventType),
...Object.values(EVENT_TYPES.CORE),
...Object.values(EVENT_TYPES.ENTITY),
...Object.values(EVENT_TYPES.COMPONENT),
...Object.values(EVENT_TYPES.SYSTEM),
...Object.values(EVENT_TYPES.PERFORMANCE)
]);
/**
* 验证事件类型是否有效
* @param eventType 事件类型
* @returns 是否有效
*/
public static isValid(eventType: string): boolean {
return this.validTypes.has(eventType);
}
/**
* 获取所有有效的事件类型
* @returns 事件类型数组
*/
public static getAllValidTypes(): string[] {
return Array.from(this.validTypes);
}
/**
* 添加自定义事件类型
* @param eventType 事件类型
*/
public static addCustomType(eventType: string): void {
this.validTypes.add(eventType);
}
/**
* 移除自定义事件类型
* @param eventType 事件类型
*/
public static removeCustomType(eventType: string): void {
this.validTypes.delete(eventType);
}
}

1329
src/ECS/Entity.ts Normal file

File diff suppressed because it is too large Load Diff

420
src/ECS/Scene.ts Normal file
View File

@@ -0,0 +1,420 @@
import { Entity } from './Entity';
import { EntityList } from './Utils/EntityList';
import { EntityProcessorList } from './Utils/EntityProcessorList';
import { IdentifierPool } from './Utils/IdentifierPool';
import { EntitySystem } from './Systems/EntitySystem';
import { ComponentStorageManager } from './Core/ComponentStorage';
import { QuerySystem } from './Core/QuerySystem';
import { TypeSafeEventSystem, GlobalEventSystem } from './Core/EventSystem';
import type { IScene } from '../Types';
/**
* 游戏场景类
*
* 管理游戏场景中的所有实体和系统,提供场景生命周期管理。
* 场景是游戏世界的容器,负责协调实体和系统的运行。
*
* @example
* ```typescript
* class GameScene extends Scene {
* public initialize(): void {
* // 创建游戏实体
* const player = this.createEntity("Player");
*
* // 添加系统
* this.addEntityProcessor(new MovementSystem());
* }
* }
* ```
*/
export class Scene {
/**
* 场景名称
*
* 用于标识和调试的友好名称。
*/
public name: string = "";
/**
* 场景中的实体集合
*
* 管理场景内所有实体的生命周期。
*/
public readonly entities: EntityList;
/**
* 实体系统处理器集合
*
* 管理场景内所有实体系统的执行。
*/
public readonly entityProcessors: EntityProcessorList;
/**
* 实体ID池
*
* 用于分配和回收实体的唯一标识符。
*/
public readonly identifierPool: IdentifierPool;
/**
* 组件存储管理器
*
* 高性能的组件存储和查询系统。
*/
public readonly componentStorageManager: ComponentStorageManager;
/**
* 查询系统
*
* 基于位掩码的高性能实体查询系统。
*/
public readonly querySystem: QuerySystem;
/**
* 事件系统
*
* 类型安全的事件系统。
*/
public readonly eventSystem: TypeSafeEventSystem;
/**
* 场景是否已开始运行
*/
private _didSceneBegin: boolean = false;
/**
* 获取系统列表(兼容性属性)
*/
public get systems(): EntitySystem[] {
return this.entityProcessors.processors;
}
/**
* 创建场景实例
* @param enableWasmAcceleration 是否启用WebAssembly加速默认为true
*/
constructor(enableWasmAcceleration: boolean = true) {
this.entities = new EntityList(this);
this.entityProcessors = new EntityProcessorList();
this.identifierPool = new IdentifierPool();
this.componentStorageManager = new ComponentStorageManager();
this.querySystem = new QuerySystem();
this.eventSystem = new TypeSafeEventSystem();
this.initialize();
}
/**
* 初始化场景
*
* 在场景创建时调用,子类可以重写此方法来设置初始实体和组件。
*/
public initialize(): void {
}
/**
* 场景开始运行时的回调
*
* 在场景开始运行时调用,可以在此方法中执行场景启动逻辑。
*/
public onStart(): void {
}
/**
* 场景卸载时的回调
*
* 在场景被销毁时调用,可以在此方法中执行清理工作。
*/
public unload(): void {
}
/**
* 开始场景,启动实体处理器等
*
* 这个方法会启动场景。它将启动实体处理器等并调用onStart方法。
*/
public begin() {
// 启动实体处理器
if (this.entityProcessors != null)
this.entityProcessors.begin();
// 标记场景已开始运行并调用onStart方法
this._didSceneBegin = true;
this.onStart();
}
/**
* 结束场景,清除实体、实体处理器等
*
* 这个方法会结束场景。它将移除所有实体结束实体处理器等并调用unload方法。
*/
public end() {
// 标记场景已结束运行
this._didSceneBegin = false;
// 移除所有实体
this.entities.removeAllEntities();
// 清空组件存储
this.componentStorageManager.clear();
// 结束实体处理器
if (this.entityProcessors)
this.entityProcessors.end();
// 调用卸载方法
this.unload();
}
/**
* 更新场景,更新实体组件、实体处理器等
*/
public update() {
// 更新实体列表
this.entities.updateLists();
// 更新实体处理器
if (this.entityProcessors != null)
this.entityProcessors.update();
// 更新实体组
this.entities.update();
// 更新实体处理器的后处理方法
if (this.entityProcessors != null)
this.entityProcessors.lateUpdate();
}
/**
* 将实体添加到此场景,并返回它
* @param name 实体名称
*/
public createEntity(name: string) {
let entity = new Entity(name, this.identifierPool.checkOut());
return this.addEntity(entity);
}
/**
* 在场景的实体列表中添加一个实体
* @param entity 要添加的实体
* @param deferCacheClear 是否延迟缓存清理(用于批量操作)
*/
public addEntity(entity: Entity, deferCacheClear: boolean = false) {
this.entities.add(entity);
entity.scene = this;
// 将实体添加到查询系统(可延迟缓存清理)
this.querySystem.addEntity(entity, deferCacheClear);
// 触发实体添加事件
this.eventSystem.emitSync('entity:added', { entity, scene: this });
return entity;
}
/**
* 批量创建实体(高性能版本)
* @param count 要创建的实体数量
* @param namePrefix 实体名称前缀
* @returns 创建的实体列表
*/
public createEntities(count: number, namePrefix: string = "Entity"): Entity[] {
const entities: Entity[] = [];
// 批量创建实体对象,不立即添加到系统
for (let i = 0; i < count; i++) {
const entity = new Entity(`${namePrefix}_${i}`, this.identifierPool.checkOut());
entity.scene = this;
entities.push(entity);
}
// 批量添加到实体列表
for (const entity of entities) {
this.entities.add(entity);
}
// 批量添加到查询系统(无重复检查,性能最优)
this.querySystem.addEntitiesUnchecked(entities);
// 批量触发事件(可选,减少事件开销)
this.eventSystem.emitSync('entities:batch_added', { entities, scene: this, count });
return entities;
}
/**
* 批量创建实体
* @param count 要创建的实体数量
* @param namePrefix 实体名称前缀
* @returns 创建的实体列表
*/
public createEntitiesOld(count: number, namePrefix: string = "Entity"): Entity[] {
const entities: Entity[] = [];
// 批量创建实体,延迟缓存清理
for (let i = 0; i < count; i++) {
const entity = new Entity(`${namePrefix}_${i}`, this.identifierPool.checkOut());
entities.push(entity);
this.addEntity(entity, true); // 延迟缓存清理
}
// 最后统一清理缓存
this.querySystem.clearCache();
return entities;
}
/**
* 从场景中删除所有实体
*/
public destroyAllEntities() {
for (let i = 0; i < this.entities.count; i++) {
this.entities.buffer[i].destroy();
}
}
/**
* 搜索并返回第一个具有名称的实体
* @param name 实体名称
*/
public findEntity(name: string): Entity | null {
return this.entities.findEntity(name);
}
/**
* 根据ID查找实体
* @param id 实体ID
*/
public findEntityById(id: number): Entity | null {
return this.entities.findEntityById(id);
}
/**
* 根据标签查找实体
* @param tag 实体标签
*/
public findEntitiesByTag(tag: number): Entity[] {
const result: Entity[] = [];
for (const entity of this.entities.buffer) {
if (entity.tag === tag) {
result.push(entity);
}
}
return result;
}
/**
* 根据名称查找实体(别名方法)
* @param name 实体名称
*/
public getEntityByName(name: string): Entity | null {
return this.findEntity(name);
}
/**
* 根据标签查找实体(别名方法)
* @param tag 实体标签
*/
public getEntitiesByTag(tag: number): Entity[] {
return this.findEntitiesByTag(tag);
}
/**
* 在场景中添加一个EntitySystem处理器
* @param processor 处理器
*/
public addEntityProcessor(processor: EntitySystem) {
processor.scene = this;
this.entityProcessors.add(processor);
processor.setUpdateOrder(this.entityProcessors.count - 1);
return processor;
}
/**
* 添加系统到场景addEntityProcessor的别名
* @param system 系统
*/
public addSystem(system: EntitySystem) {
return this.addEntityProcessor(system);
}
/**
* 从场景中删除EntitySystem处理器
* @param processor 要删除的处理器
*/
public removeEntityProcessor(processor: EntitySystem) {
this.entityProcessors.remove(processor);
}
/**
* 获取指定类型的EntitySystem处理器
* @param type 处理器类型
*/
public getEntityProcessor<T extends EntitySystem>(type: new (...args: any[]) => T): T | null {
return this.entityProcessors.getProcessor(type);
}
/**
* 获取场景统计信息
*/
public getStats(): {
entityCount: number;
processorCount: number;
componentStorageStats: Map<string, any>;
} {
return {
entityCount: this.entities.count,
processorCount: this.entityProcessors.count,
componentStorageStats: this.componentStorageManager.getAllStats()
};
}
/**
* 压缩组件存储(清理碎片)
*/
public compactComponentStorage(): void {
this.componentStorageManager.compactAll();
}
/**
* 获取场景的调试信息
*/
public getDebugInfo(): {
name: string;
entityCount: number;
processorCount: number;
isRunning: boolean;
entities: Array<{
name: string;
id: number;
componentCount: number;
componentTypes: string[];
}>;
processors: Array<{
name: string;
updateOrder: number;
entityCount: number;
}>;
componentStats: Map<string, any>;
} {
return {
name: this.constructor.name,
entityCount: this.entities.count,
processorCount: this.entityProcessors.count,
isRunning: this._didSceneBegin,
entities: this.entities.buffer.map(entity => ({
name: entity.name,
id: entity.id,
componentCount: entity.components.length,
componentTypes: entity.components.map(c => c.constructor.name)
})),
processors: this.entityProcessors.processors.map(processor => ({
name: processor.constructor.name,
updateOrder: processor.updateOrder,
entityCount: (processor as any)._entities?.length || 0
})),
componentStats: this.componentStorageManager.getAllStats()
};
}
}

View File

@@ -0,0 +1,319 @@
import { Entity } from '../Entity';
import { Core } from '../../Core';
import { Matcher } from '../Utils/Matcher';
import { PerformanceMonitor } from '../../Utils/PerformanceMonitor';
import type { Scene } from '../Scene';
import type { ISystemBase } from '../../Types';
/**
* 实体系统的基类
*
* 用于处理一组符合特定条件的实体。系统是ECS架构中的逻辑处理单元
* 负责对拥有特定组件组合的实体执行业务逻辑。
*
* @example
* ```typescript
* class MovementSystem extends EntitySystem {
* constructor() {
* super(Matcher.empty().all(Transform, Velocity));
* }
*
* protected process(entities: Entity[]): void {
* for (const entity of entities) {
* const transform = entity.getComponent(Transform);
* const velocity = entity.getComponent(Velocity);
* transform.position.add(velocity.value);
* }
* }
* }
* ```
*/
export abstract class EntitySystem implements ISystemBase {
private _entities: Entity[] = [];
private _updateOrder: number = 0;
private _enabled: boolean = true;
private _performanceMonitor = PerformanceMonitor.instance;
private _systemName: string;
/**
* 获取系统处理的实体列表
*/
public get entities(): readonly Entity[] {
return this._entities;
}
/**
* 获取系统的更新时序
*/
public get updateOrder(): number {
return this._updateOrder;
}
public set updateOrder(value: number) {
this.setUpdateOrder(value);
}
/**
* 获取系统的启用状态
*/
public get enabled(): boolean {
return this._enabled;
}
/**
* 设置系统的启用状态
*/
public set enabled(value: boolean) {
this._enabled = value;
}
/**
* 获取系统名称
*/
public get systemName(): string {
return this._systemName;
}
constructor(matcher?: Matcher) {
this._matcher = matcher ? matcher : Matcher.empty();
this._systemName = this.constructor.name;
this.initialize();
}
private _scene!: Scene;
/**
* 这个系统所属的场景
*/
public get scene(): Scene {
return this._scene;
}
public set scene(value: Scene) {
this._scene = value;
this._entities = [];
}
private _matcher: Matcher;
/**
* 获取实体匹配器
*/
public get matcher(): Matcher {
return this._matcher;
}
/**
* 设置更新时序
* @param order 更新时序
*/
public setUpdateOrder(order: number): void {
this._updateOrder = order;
this.scene.entityProcessors.setDirty();
}
/**
* 系统初始化
*
* 在系统创建时调用,子类可以重写此方法进行初始化操作。
*/
public initialize(): void {
// 子类可以重写此方法
}
/**
* 当实体的组件发生变化时调用
*
* 检查实体是否仍然符合系统的匹配条件,并相应地添加或移除实体。
*
* @param entity 发生变化的实体
*/
public onChanged(entity: Entity): void {
const contains = this._entities.includes(entity);
const interest = this._matcher.isInterestedEntity(entity);
if (interest && !contains) {
this.add(entity);
} else if (!interest && contains) {
this.remove(entity);
}
}
/**
* 添加实体到系统
*
* @param entity 要添加的实体
*/
public add(entity: Entity): void {
if (!this._entities.includes(entity)) {
this._entities.push(entity);
this.onAdded(entity);
}
}
/**
* 当实体被添加到系统时调用
*
* 子类可以重写此方法来处理实体添加事件。
*
* @param entity 被添加的实体
*/
protected onAdded(entity: Entity): void {
// 子类可以重写此方法
}
/**
* 从系统中移除实体
*
* @param entity 要移除的实体
*/
public remove(entity: Entity): void {
const index = this._entities.indexOf(entity);
if (index !== -1) {
this._entities.splice(index, 1);
this.onRemoved(entity);
}
}
/**
* 当实体从系统中移除时调用
*
* 子类可以重写此方法来处理实体移除事件。
*
* @param entity 被移除的实体
*/
protected onRemoved(entity: Entity): void {
// 子类可以重写此方法
}
/**
* 更新系统
*
* 在每帧调用,处理系统的主要逻辑。
*/
public update(): void {
if (!this._enabled || !this.checkProcessing()) {
return;
}
const startTime = this._performanceMonitor.startMonitoring(this._systemName);
try {
this.begin();
this.process(this._entities);
} finally {
this._performanceMonitor.endMonitoring(this._systemName, startTime, this._entities.length);
}
}
/**
* 后期更新系统
*
* 在所有系统的update方法执行完毕后调用。
*/
public lateUpdate(): void {
if (!this._enabled || !this.checkProcessing()) {
return;
}
const startTime = this._performanceMonitor.startMonitoring(`${this._systemName}_Late`);
try {
this.lateProcess(this._entities);
this.end();
} finally {
this._performanceMonitor.endMonitoring(`${this._systemName}_Late`, startTime, this._entities.length);
}
}
/**
* 在系统处理开始前调用
*
* 子类可以重写此方法进行预处理操作。
*/
protected begin(): void {
// 子类可以重写此方法
}
/**
* 处理实体列表
*
* 系统的核心逻辑,子类必须实现此方法来定义具体的处理逻辑。
*
* @param entities 要处理的实体列表
*/
protected process(entities: Entity[]): void {
// 子类必须实现此方法
}
/**
* 后期处理实体列表
*
* 在主要处理逻辑之后执行,子类可以重写此方法。
*
* @param entities 要处理的实体列表
*/
protected lateProcess(entities: Entity[]): void {
// 子类可以重写此方法
}
/**
* 系统处理完毕后调用
*
* 子类可以重写此方法进行后处理操作。
*/
protected end(): void {
// 子类可以重写此方法
}
/**
* 检查系统是否需要处理
*
* 在启用系统时有用,但仅偶尔需要处理。
* 这只影响处理,不影响事件或订阅列表。
*
* @returns 如果系统应该处理则为true如果不处理则为false
*/
protected checkProcessing(): boolean {
return true;
}
/**
* 获取系统的性能数据
*
* @returns 性能数据或undefined
*/
public getPerformanceData() {
return this._performanceMonitor.getSystemData(this._systemName);
}
/**
* 获取系统的性能统计
*
* @returns 性能统计或undefined
*/
public getPerformanceStats() {
return this._performanceMonitor.getSystemStats(this._systemName);
}
/**
* 重置系统的性能数据
*/
public resetPerformanceData(): void {
this._performanceMonitor.resetSystem(this._systemName);
}
/**
* 获取系统信息的字符串表示
*
* @returns 系统信息字符串
*/
public toString(): string {
const entityCount = this._entities.length;
const perfData = this.getPerformanceData();
const perfInfo = perfData ? ` (${perfData.executionTime.toFixed(2)}ms)` : '';
return `${this._systemName}[${entityCount} entities]${perfInfo}`;
}
}

View File

@@ -0,0 +1,58 @@
import { EntitySystem } from './EntitySystem';
import { Matcher } from '../Utils/Matcher';
import { Time } from '../../Utils/Time';
/**
* 间隔系统抽象类
* 定义一个按时间间隔处理的抽象类继承自EntitySystem类
* 子类需要实现process方法用于实现具体的处理逻辑
*/
export abstract class IntervalSystem extends EntitySystem {
/** 累积增量以跟踪间隔 */
private acc: number = 0;
/** 更新之间需要等待多长时间 */
private readonly interval: number;
/** 时间间隔的余数,用于计算下一次需要等待的时间 */
private intervalRemainder: number = 0;
/**
* 构造函数,初始化时间间隔
* @param matcher 实体匹配器
* @param interval 时间间隔
*/
constructor(matcher: Matcher, interval: number) {
super(matcher);
this.interval = interval;
}
/**
* 判断是否需要进行处理
* 如果需要进行处理则更新累积增量和时间间隔余数返回true
* 否则返回false
*/
protected override checkProcessing(): boolean {
// 更新累积增量
this.acc += Time.deltaTime;
// 如果累积增量超过时间间隔,则进行处理
if (this.acc >= this.interval) {
// 更新时间间隔余数
this.intervalRemainder = this.acc - this.interval;
// 重置累积增量
this.acc = 0;
// 返回true表示需要进行处理
return true;
}
// 返回false表示不需要进行处理
return false;
}
/**
* 获取本系统上次处理后的实际delta值
* 实际delta值等于时间间隔加上时间间隔余数
*/
protected getIntervalDelta(): number {
return this.interval + this.intervalRemainder;
}
}

View File

@@ -0,0 +1,23 @@
import { EntitySystem } from './EntitySystem';
import { Entity } from '../Entity';
/**
* 被动实体系统
* 定义一个被动的实体系统继承自EntitySystem类
* 被动的实体系统不会对实体进行任何修改,只会被动地接收实体的变化事件
*/
export abstract class PassiveSystem extends EntitySystem {
/**
* 当实体发生变化时,不进行任何操作
* @param entity 发生变化的实体
*/
public override onChanged(entity: Entity): void { }
/**
* 不进行任何处理
* @param entities 实体数组,未被使用
*/
protected override process(entities: Entity[]): void {
// 被动系统不进行任何处理
}
}

View File

@@ -0,0 +1,29 @@
import { EntitySystem } from './EntitySystem';
import { Entity } from '../Entity';
/**
* 处理系统抽象类
* 定义一个处理实体的抽象类继承自EntitySystem类
* 子类需要实现processSystem方法用于实现具体的处理逻辑
*/
export abstract class ProcessingSystem extends EntitySystem {
/**
* 当实体发生变化时,不进行任何操作
* @param entity 发生变化的实体
*/
public override onChanged(entity: Entity): void { }
/**
* 处理实体每帧调用processSystem方法进行处理
* @param entities 实体数组,未被使用
*/
protected override process(entities: Entity[]): void {
// 调用子类实现的processSystem方法进行实体处理
this.processSystem();
}
/**
* 处理实体的具体方法,由子类实现
*/
public abstract processSystem(): void;
}

5
src/ECS/Systems/index.ts Normal file
View File

@@ -0,0 +1,5 @@
// ECS系统导出
export { EntitySystem } from './EntitySystem';
export { ProcessingSystem } from './ProcessingSystem';
export { PassiveSystem } from './PassiveSystem';
export { IntervalSystem } from './IntervalSystem';

164
src/ECS/Utils/Bits.ts Normal file
View File

@@ -0,0 +1,164 @@
/**
* 高性能位操作类
* 用于快速操作位数组,支持组件匹配等场景
*/
export class Bits {
private _words: number[] = [];
private static readonly WORD_SIZE = 32;
constructor() {
this._words = [];
}
/**
* 设置指定位置的位为1
* @param index 位置索引
*/
public set(index: number): void {
const wordIndex = Math.floor(index / Bits.WORD_SIZE);
const bitIndex = index % Bits.WORD_SIZE;
// 确保数组足够大
while (this._words.length <= wordIndex) {
this._words.push(0);
}
this._words[wordIndex] |= (1 << bitIndex);
}
/**
* 清除指定位置的位设为0
* @param index 位置索引
*/
public clear(index: number): void {
const wordIndex = Math.floor(index / Bits.WORD_SIZE);
const bitIndex = index % Bits.WORD_SIZE;
if (wordIndex < this._words.length) {
this._words[wordIndex] &= ~(1 << bitIndex);
}
}
/**
* 获取指定位置的位值
* @param index 位置索引
* @returns 位值true或false
*/
public get(index: number): boolean {
const wordIndex = Math.floor(index / Bits.WORD_SIZE);
const bitIndex = index % Bits.WORD_SIZE;
if (wordIndex >= this._words.length) {
return false;
}
return (this._words[wordIndex] & (1 << bitIndex)) !== 0;
}
/**
* 检查是否包含所有指定的位
* @param other 另一个Bits对象
* @returns 如果包含所有位则返回true
*/
public containsAll(other: Bits): boolean {
const maxLength = Math.max(this._words.length, other._words.length);
for (let i = 0; i < maxLength; i++) {
const thisWord = i < this._words.length ? this._words[i] : 0;
const otherWord = i < other._words.length ? other._words[i] : 0;
if ((thisWord & otherWord) !== otherWord) {
return false;
}
}
return true;
}
/**
* 检查是否包含任意一个指定的位
* @param other 另一个Bits对象
* @returns 如果包含任意位则返回true
*/
public intersects(other: Bits): boolean {
const minLength = Math.min(this._words.length, other._words.length);
for (let i = 0; i < minLength; i++) {
if ((this._words[i] & other._words[i]) !== 0) {
return true;
}
}
return false;
}
/**
* 检查是否不包含任何指定的位
* @param other 另一个Bits对象
* @returns 如果不包含任何位则返回true
*/
public excludes(other: Bits): boolean {
return !this.intersects(other);
}
/**
* 清空所有位
*/
public clearAll(): void {
this._words.length = 0;
}
/**
* 检查是否为空(没有设置任何位)
* @returns 如果为空则返回true
*/
public isEmpty(): boolean {
for (const word of this._words) {
if (word !== 0) {
return false;
}
}
return true;
}
/**
* 获取设置的位数量
* @returns 设置的位数量
*/
public cardinality(): number {
let count = 0;
for (const word of this._words) {
count += this.popCount(word);
}
return count;
}
/**
* 计算一个32位整数中设置的位数量
* @param n 32位整数
* @returns 设置的位数量
*/
private popCount(n: number): number {
n = n - ((n >>> 1) & 0x55555555);
n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);
return (((n + (n >>> 4)) & 0xF0F0F0F) * 0x1010101) >>> 24;
}
/**
* 复制另一个Bits对象
* @param other 要复制的Bits对象
*/
public copyFrom(other: Bits): void {
this._words = [...other._words];
}
/**
* 创建当前Bits的副本
* @returns 新的Bits对象
*/
public clone(): Bits {
const newBits = new Bits();
newBits.copyFrom(this);
return newBits;
}
}

View File

@@ -0,0 +1,99 @@
import { Component } from '../Component';
import { Bits } from './Bits';
/**
* 组件类型管理器
* 负责管理组件类型的注册和ID分配
*/
export class ComponentTypeManager {
private static _instance: ComponentTypeManager;
private _componentTypes = new Map<Function, number>();
private _typeNames = new Map<number, string>();
private _nextTypeId = 0;
/**
* 获取单例实例
*/
public static get instance(): ComponentTypeManager {
if (!ComponentTypeManager._instance) {
ComponentTypeManager._instance = new ComponentTypeManager();
}
return ComponentTypeManager._instance;
}
private constructor() {}
/**
* 获取组件类型的ID
* @param componentType 组件类型构造函数
* @returns 组件类型ID
*/
public getTypeId<T extends Component>(componentType: new (...args: any[]) => T): number {
let typeId = this._componentTypes.get(componentType);
if (typeId === undefined) {
typeId = this._nextTypeId++;
this._componentTypes.set(componentType, typeId);
this._typeNames.set(typeId, componentType.name);
}
return typeId;
}
/**
* 获取组件类型名称
* @param typeId 组件类型ID
* @returns 组件类型名称
*/
public getTypeName(typeId: number): string {
return this._typeNames.get(typeId) || 'Unknown';
}
/**
* 创建包含指定组件类型的Bits对象
* @param componentTypes 组件类型构造函数数组
* @returns Bits对象
*/
public createBits(...componentTypes: (new (...args: any[]) => Component)[]): Bits {
const bits = new Bits();
for (const componentType of componentTypes) {
const typeId = this.getTypeId(componentType);
bits.set(typeId);
}
return bits;
}
/**
* 获取实体的组件位掩码
* @param components 组件数组
* @returns Bits对象
*/
public getEntityBits(components: Component[]): Bits {
const bits = new Bits();
for (const component of components) {
const typeId = this.getTypeId(component.constructor as new (...args: any[]) => Component);
bits.set(typeId);
}
return bits;
}
/**
* 重置管理器(主要用于测试)
*/
public reset(): void {
this._componentTypes.clear();
this._typeNames.clear();
this._nextTypeId = 0;
}
/**
* 获取已注册的组件类型数量
*/
public get registeredTypeCount(): number {
return this._componentTypes.size;
}
}

288
src/ECS/Utils/EntityList.ts Normal file
View File

@@ -0,0 +1,288 @@
import { Entity } from '../Entity';
import { Component } from '../Component';
/**
* 高性能实体列表管理器
* 管理场景中的所有实体,支持快速查找和批量操作
*/
export class EntityList {
public buffer: Entity[] = [];
private _scene: any; // 临时使用any避免循环依赖
// 索引映射,提升查找性能
private _idToEntity = new Map<number, Entity>();
private _nameToEntities = new Map<string, Entity[]>();
// 延迟操作队列
private _entitiesToAdd: Entity[] = [];
private _entitiesToRemove: Entity[] = [];
private _isUpdating = false;
public get count(): number {
return this.buffer.length;
}
constructor(scene: any) {
this._scene = scene;
}
/**
* 添加实体(立即添加或延迟添加)
* @param entity 要添加的实体
*/
public add(entity: Entity): void {
if (this._isUpdating) {
// 如果正在更新中,延迟添加
this._entitiesToAdd.push(entity);
} else {
this.addImmediate(entity);
}
}
/**
* 立即添加实体
* @param entity 要添加的实体
*/
private addImmediate(entity: Entity): void {
// 检查是否已存在
if (this._idToEntity.has(entity.id)) {
return;
}
this.buffer.push(entity);
this._idToEntity.set(entity.id, entity);
// 更新名称索引
this.updateNameIndex(entity, true);
}
/**
* 移除实体(立即移除或延迟移除)
* @param entity 要移除的实体
*/
public remove(entity: Entity): void {
if (this._isUpdating) {
// 如果正在更新中,延迟移除
this._entitiesToRemove.push(entity);
} else {
this.removeImmediate(entity);
}
}
/**
* 立即移除实体
* @param entity 要移除的实体
*/
private removeImmediate(entity: Entity): void {
const index = this.buffer.indexOf(entity);
if (index !== -1) {
this.buffer.splice(index, 1);
this._idToEntity.delete(entity.id);
// 更新名称索引
this.updateNameIndex(entity, false);
}
}
/**
* 移除所有实体
*/
public removeAllEntities(): void {
for (let i = this.buffer.length - 1; i >= 0; i--) {
this.buffer[i].destroy();
}
this.buffer.length = 0;
this._idToEntity.clear();
this._nameToEntities.clear();
this._entitiesToAdd.length = 0;
this._entitiesToRemove.length = 0;
}
/**
* 更新实体列表,处理延迟操作
*/
public updateLists(): void {
// 处理延迟添加的实体
if (this._entitiesToAdd.length > 0) {
for (const entity of this._entitiesToAdd) {
this.addImmediate(entity);
}
this._entitiesToAdd.length = 0;
}
// 处理延迟移除的实体
if (this._entitiesToRemove.length > 0) {
for (const entity of this._entitiesToRemove) {
this.removeImmediate(entity);
}
this._entitiesToRemove.length = 0;
}
}
/**
* 更新所有实体
*/
public update(): void {
this._isUpdating = true;
try {
for (let i = 0; i < this.buffer.length; i++) {
const entity = this.buffer[i];
if (entity.enabled && !entity.isDestroyed) {
entity.update();
}
}
} finally {
this._isUpdating = false;
}
// 处理延迟操作
this.updateLists();
}
/**
* 根据名称查找实体使用索引O(1)复杂度)
* @param name 实体名称
* @returns 找到的第一个实体或null
*/
public findEntity(name: string): Entity | null {
const entities = this._nameToEntities.get(name);
return entities && entities.length > 0 ? entities[0] : null;
}
/**
* 根据名称查找所有实体
* @param name 实体名称
* @returns 找到的所有实体数组
*/
public findEntitiesByName(name: string): Entity[] {
return this._nameToEntities.get(name) || [];
}
/**
* 根据ID查找实体使用索引O(1)复杂度)
* @param id 实体ID
* @returns 找到的实体或null
*/
public findEntityById(id: number): Entity | null {
return this._idToEntity.get(id) || null;
}
/**
* 根据标签查找实体
* @param tag 标签
* @returns 找到的所有实体数组
*/
public findEntitiesByTag(tag: number): Entity[] {
const result: Entity[] = [];
for (const entity of this.buffer) {
if (entity.tag === tag) {
result.push(entity);
}
}
return result;
}
/**
* 根据组件类型查找实体
* @param componentType 组件类型
* @returns 找到的所有实体数组
*/
public findEntitiesWithComponent<T extends Component>(componentType: new (...args: any[]) => T): Entity[] {
const result: Entity[] = [];
for (const entity of this.buffer) {
if (entity.hasComponent(componentType)) {
result.push(entity);
}
}
return result;
}
/**
* 批量操作:对所有实体执行指定操作
* @param action 要执行的操作
*/
public forEach(action: (entity: Entity) => void): void {
for (const entity of this.buffer) {
action(entity);
}
}
/**
* 批量操作:对符合条件的实体执行指定操作
* @param predicate 筛选条件
* @param action 要执行的操作
*/
public forEachWhere(predicate: (entity: Entity) => boolean, action: (entity: Entity) => void): void {
for (const entity of this.buffer) {
if (predicate(entity)) {
action(entity);
}
}
}
/**
* 更新名称索引
* @param entity 实体
* @param isAdd 是否为添加操作
*/
private updateNameIndex(entity: Entity, isAdd: boolean): void {
if (!entity.name) {
return;
}
if (isAdd) {
let entities = this._nameToEntities.get(entity.name);
if (!entities) {
entities = [];
this._nameToEntities.set(entity.name, entities);
}
entities.push(entity);
} else {
const entities = this._nameToEntities.get(entity.name);
if (entities) {
const index = entities.indexOf(entity);
if (index !== -1) {
entities.splice(index, 1);
// 如果数组为空,删除映射
if (entities.length === 0) {
this._nameToEntities.delete(entity.name);
}
}
}
}
}
/**
* 获取实体列表的统计信息
* @returns 统计信息
*/
public getStats(): {
totalEntities: number;
activeEntities: number;
pendingAdd: number;
pendingRemove: number;
nameIndexSize: number;
} {
let activeCount = 0;
for (const entity of this.buffer) {
if (entity.enabled && !entity.isDestroyed) {
activeCount++;
}
}
return {
totalEntities: this.buffer.length,
activeEntities: activeCount,
pendingAdd: this._entitiesToAdd.length,
pendingRemove: this._entitiesToRemove.length,
nameIndexSize: this._nameToEntities.size
};
}
}

View File

@@ -0,0 +1,108 @@
import { EntitySystem } from '../Systems/EntitySystem';
/**
* 实体处理器列表管理器
* 管理场景中的所有实体系统
*/
export class EntityProcessorList {
private _processors: EntitySystem[] = [];
private _isDirty = false;
/**
* 设置为脏状态,需要重新排序
*/
public setDirty(): void {
this._isDirty = true;
}
/**
* 添加实体处理器
* @param processor 要添加的处理器
*/
public add(processor: EntitySystem): void {
this._processors.push(processor);
this.setDirty();
}
/**
* 移除实体处理器
* @param processor 要移除的处理器
*/
public remove(processor: EntitySystem): void {
const index = this._processors.indexOf(processor);
if (index !== -1) {
this._processors.splice(index, 1);
}
}
/**
* 获取指定类型的处理器
* @param type 处理器类型
*/
public getProcessor<T extends EntitySystem>(type: new (...args: any[]) => T): T | null {
for (const processor of this._processors) {
if (processor instanceof type) {
return processor as T;
}
}
return null;
}
/**
* 开始处理
*/
public begin(): void {
this.sortProcessors();
for (const processor of this._processors) {
processor.initialize();
}
}
/**
* 结束处理
*/
public end(): void {
// 清理处理器
}
/**
* 更新所有处理器
*/
public update(): void {
this.sortProcessors();
for (const processor of this._processors) {
processor.update();
}
}
/**
* 后期更新所有处理器
*/
public lateUpdate(): void {
for (const processor of this._processors) {
processor.lateUpdate();
}
}
/**
* 排序处理器
*/
private sortProcessors(): void {
if (this._isDirty) {
this._processors.sort((a, b) => a.updateOrder - b.updateOrder);
this._isDirty = false;
}
}
/** 获取处理器列表 */
public get processors() {
return this._processors;
}
/** 获取处理器数量 */
public get count() {
return this._processors.length;
}
}

View File

@@ -0,0 +1,26 @@
/**
* ID池管理器
* 用于管理实体ID的分配和回收
*/
export class IdentifierPool {
private _nextAvailableId = 0;
private _ids: number[] = [];
/**
* 获取一个可用的ID
*/
public checkOut(): number {
if (this._ids.length > 0) {
return this._ids.pop()!;
}
return this._nextAvailableId++;
}
/**
* 回收一个ID
* @param id 要回收的ID
*/
public checkIn(id: number): void {
this._ids.push(id);
}
}

168
src/ECS/Utils/Matcher.ts Normal file
View File

@@ -0,0 +1,168 @@
import { Entity } from '../Entity';
import { Component } from '../Component';
import { Bits } from './Bits';
import { ComponentTypeManager } from './ComponentTypeManager';
/**
* 高性能实体匹配器
* 用于快速匹配符合条件的实体
*/
export class Matcher {
protected allSet: (new (...args: any[]) => Component)[] = [];
protected exclusionSet: (new (...args: any[]) => Component)[] = [];
protected oneSet: (new (...args: any[]) => Component)[] = [];
// 缓存的位掩码,避免重复计算
private _allBits?: Bits;
private _exclusionBits?: Bits;
private _oneBits?: Bits;
private _isDirty = true;
public static empty(): Matcher {
return new Matcher();
}
public getAllSet(): (new (...args: any[]) => Component)[] {
return this.allSet;
}
public getExclusionSet(): (new (...args: any[]) => Component)[] {
return this.exclusionSet;
}
public getOneSet(): (new (...args: any[]) => Component)[] {
return this.oneSet;
}
/**
* 检查实体是否匹配条件
* @param entity 要检查的实体
* @returns 是否匹配
*/
public isInterestedEntity(entity: Entity): boolean {
const entityBits = this.getEntityBits(entity);
return this.isInterested(entityBits);
}
/**
* 检查组件位掩码是否匹配条件
* @param componentBits 组件位掩码
* @returns 是否匹配
*/
public isInterested(componentBits: Bits): boolean {
this.updateBitsIfDirty();
// 检查必须包含的组件
if (this._allBits && !componentBits.containsAll(this._allBits)) {
return false;
}
// 检查排除的组件
if (this._exclusionBits && componentBits.intersects(this._exclusionBits)) {
return false;
}
// 检查至少包含其中之一的组件
if (this._oneBits && !componentBits.intersects(this._oneBits)) {
return false;
}
return true;
}
/**
* 添加所有包含的组件类型
* @param types 所有包含的组件类型列表
*/
public all(...types: (new (...args: any[]) => Component)[]): Matcher {
this.allSet.push(...types);
this._isDirty = true;
return this;
}
/**
* 添加排除包含的组件类型
* @param types 排除包含的组件类型列表
*/
public exclude(...types: (new (...args: any[]) => Component)[]): Matcher {
this.exclusionSet.push(...types);
this._isDirty = true;
return this;
}
/**
* 添加至少包含其中之一的组件类型
* @param types 至少包含其中之一的组件类型列表
*/
public one(...types: (new (...args: any[]) => Component)[]): Matcher {
this.oneSet.push(...types);
this._isDirty = true;
return this;
}
/**
* 获取实体的组件位掩码
* @param entity 实体
* @returns 组件位掩码
*/
private getEntityBits(entity: Entity): Bits {
const components = entity.components;
return ComponentTypeManager.instance.getEntityBits(components);
}
/**
* 如果位掩码已过期,则更新它们
*/
private updateBitsIfDirty(): void {
if (!this._isDirty) {
return;
}
const typeManager = ComponentTypeManager.instance;
// 更新必须包含的组件位掩码
if (this.allSet.length > 0) {
this._allBits = typeManager.createBits(...this.allSet);
} else {
this._allBits = undefined;
}
// 更新排除的组件位掩码
if (this.exclusionSet.length > 0) {
this._exclusionBits = typeManager.createBits(...this.exclusionSet);
} else {
this._exclusionBits = undefined;
}
// 更新至少包含其中之一的组件位掩码
if (this.oneSet.length > 0) {
this._oneBits = typeManager.createBits(...this.oneSet);
} else {
this._oneBits = undefined;
}
this._isDirty = false;
}
/**
* 创建匹配器的字符串表示(用于调试)
* @returns 字符串表示
*/
public toString(): string {
const parts: string[] = [];
if (this.allSet.length > 0) {
parts.push(`all: [${this.allSet.map(t => t.name).join(', ')}]`);
}
if (this.exclusionSet.length > 0) {
parts.push(`exclude: [${this.exclusionSet.map(t => t.name).join(', ')}]`);
}
if (this.oneSet.length > 0) {
parts.push(`one: [${this.oneSet.map(t => t.name).join(', ')}]`);
}
return `Matcher(${parts.join(', ')})`;
}
}

7
src/ECS/Utils/index.ts Normal file
View File

@@ -0,0 +1,7 @@
// ECS工具类导出
export { EntityList } from './EntityList';
export { EntityProcessorList } from './EntityProcessorList';
export { IdentifierPool } from './IdentifierPool';
export { Matcher } from './Matcher';
export { Bits } from './Bits';
export { ComponentTypeManager } from './ComponentTypeManager';

11
src/ECS/index.ts Normal file
View File

@@ -0,0 +1,11 @@
export { Entity } from './Entity';
export { Component } from './Component';
export { CoreEvents, ECSEventType, EventPriority, EVENT_TYPES, EventTypeValidator } from './CoreEvents';
export * from './Systems';
export * from './Utils';
export { Scene } from './Scene';
export { EntityManager, EntityQueryBuilder } from './Core/EntityManager';
export * from './Core/Events';
export * from './Core/Query';
export * from './Core/Performance';
export * from './Core/Storage';

View File

@@ -0,0 +1,768 @@
/**
* ECS框架性能基准测试
* 测试框架在不同场景下的性能表现
*/
import { Scene } from '../../ECS/Scene';
import { Entity } from '../../ECS/Entity';
import { Component } from '../../ECS/Component';
console.log('🚀 ECS框架性能基准测试');
console.log('============================================================');
console.log('测试目标: 评估ECS框架在不同场景下的性能表现');
console.log('============================================================');
/**
* 位置组件
*/
class PositionComponent extends Component {
public x: number = 0;
public y: number = 0;
constructor(x: number = 0, y: number = 0) {
super();
this.x = x;
this.y = y;
}
}
/**
* 速度组件
*/
class VelocityComponent extends Component {
public vx: number = 0;
public vy: number = 0;
constructor(vx: number = 0, vy: number = 0) {
super();
this.vx = vx;
this.vy = vy;
}
}
/**
* 生命值组件
*/
class HealthComponent extends Component {
public health: number = 100;
public maxHealth: number = 100;
constructor(health: number = 100) {
super();
this.health = health;
this.maxHealth = health;
}
}
/**
* 渲染组件
*/
class RenderComponent extends Component {
public sprite: string = '';
public visible: boolean = true;
constructor(sprite: string = '') {
super();
this.sprite = sprite;
}
}
/**
* AI组件
*/
class AIComponent extends Component {
public state: string = 'idle';
public target: Entity | null = null;
constructor(state: string = 'idle') {
super();
this.state = state;
}
}
/**
* 测试配置接口
*/
interface TestConfig {
entityCounts: number[];
queryIterations: number;
updateIterations: number;
}
/**
* 测试配置
*/
const TEST_CONFIG: TestConfig = {
entityCounts: [1000, 5000, 10000, 25000, 50000, 100000, 200000, 500000],
queryIterations: 1000,
updateIterations: 100
};
/**
* 性能测试结果
*/
interface PerformanceResult {
entityCount: number;
singleQuery: number;
multiQuery: number;
complexQuery: number;
tagQuery: number;
singleTagQuery: number;
entityUpdate: number;
memoryUsage: number;
}
/**
* 测试创建实体的性能
*/
function testEntityCreation(scene: Scene, count: number): {
totalTime: number;
averageTime: number;
entitiesPerSecond: number;
breakdown: {
entityCreation: number;
componentAddition: number;
tagAssignment: number;
};
} {
const startTime = performance.now();
let entityCreationTime = 0;
let componentAdditionTime = 0;
let tagAssignmentTime = 0;
// 批量创建实体(不添加组件)
const entityStart = performance.now();
const entities = scene.createEntities(count, "Entity");
entityCreationTime = performance.now() - entityStart;
// 批量添加组件
const componentStart = performance.now();
for (let i = 0; i < entities.length; i++) {
const entity = entities[i];
// 所有实体都有位置组件
entity.addComponent(new PositionComponent(
Math.random() * 1000,
Math.random() * 1000
));
// 70%的实体有速度组件
if (Math.random() < 0.7) {
entity.addComponent(new VelocityComponent(
(Math.random() - 0.5) * 10,
(Math.random() - 0.5) * 10
));
}
// 50%的实体有生命值组件
if (Math.random() < 0.5) {
entity.addComponent(new HealthComponent(
Math.floor(Math.random() * 100) + 50
));
}
// 30%的实体有渲染组件
if (Math.random() < 0.3) {
entity.addComponent(new RenderComponent(`sprite_${i % 10}`));
}
// 20%的实体有AI组件
if (Math.random() < 0.2) {
entity.addComponent(new AIComponent(['idle', 'patrol', 'chase'][Math.floor(Math.random() * 3)]));
}
}
componentAdditionTime = performance.now() - componentStart;
// 批量设置标签
const tagStart = performance.now();
for (const entity of entities) {
entity.tag = Math.floor(Math.random() * 10);
}
tagAssignmentTime = performance.now() - tagStart;
const totalTime = performance.now() - startTime;
return {
totalTime,
averageTime: totalTime / count,
entitiesPerSecond: count / (totalTime / 1000),
breakdown: {
entityCreation: entityCreationTime,
componentAddition: componentAdditionTime,
tagAssignment: tagAssignmentTime
}
};
}
/**
* 创建测试实体
*/
function createTestEntities(scene: Scene, count: number): Entity[] {
const entities: Entity[] = [];
for (let i = 0; i < count; i++) {
const entity = scene.createEntity(`Entity_${i}`);
// 所有实体都有位置组件
entity.addComponent(new PositionComponent(
Math.random() * 1000,
Math.random() * 1000
));
// 70%的实体有速度组件
if (Math.random() < 0.7) {
entity.addComponent(new VelocityComponent(
(Math.random() - 0.5) * 10,
(Math.random() - 0.5) * 10
));
}
// 50%的实体有生命值组件
if (Math.random() < 0.5) {
entity.addComponent(new HealthComponent(
Math.floor(Math.random() * 100) + 50
));
}
// 30%的实体有渲染组件
if (Math.random() < 0.3) {
entity.addComponent(new RenderComponent(`sprite_${i % 10}`));
}
// 20%的实体有AI组件
if (Math.random() < 0.2) {
entity.addComponent(new AIComponent(['idle', 'patrol', 'chase'][Math.floor(Math.random() * 3)]));
}
// 设置随机标签
entity.tag = Math.floor(Math.random() * 10);
entities.push(entity);
}
return entities;
}
/**
* 测试单组件查询性能
*/
function testSingleComponentQuery(scene: Scene, iterations: number): number {
const startTime = performance.now();
for (let i = 0; i < iterations; i++) {
scene.querySystem.queryAll(PositionComponent);
}
return performance.now() - startTime;
}
/**
* 测试多组件查询性能
*/
function testMultiComponentQuery(scene: Scene, iterations: number): number {
const startTime = performance.now();
for (let i = 0; i < iterations; i++) {
scene.querySystem.queryAll(PositionComponent, VelocityComponent);
}
return performance.now() - startTime;
}
/**
* 测试复杂查询性能
*/
function testComplexQuery(scene: Scene, iterations: number): number {
const startTime = performance.now();
for (let i = 0; i < iterations; i++) {
scene.querySystem.queryAll(PositionComponent, VelocityComponent, HealthComponent);
}
return performance.now() - startTime;
}
/**
* 测试标签查询性能
*/
function testTagQuery(scene: Scene, iterations: number): number {
const startTime = performance.now();
// 优化:预先获取所有标签查询结果,然后重复使用
// 这更符合实际游戏中的使用模式
const tags = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (let i = 0; i < iterations; i++) {
// 批量查询所有标签
for (const tag of tags) {
scene.querySystem.queryByTag(tag);
}
}
return performance.now() - startTime;
}
/**
* 测试单个标签查询性能
*/
function testSingleTagQuery(scene: Scene, iterations: number): number {
const startTime = performance.now();
// 只查询标签0测试单个标签的查询性能和缓存效果
for (let i = 0; i < iterations; i++) {
scene.querySystem.queryByTag(0);
}
return performance.now() - startTime;
}
/**
* 测试实体更新性能
*/
function testEntityUpdate(scene: Scene, iterations: number): number {
const entities = scene.querySystem.queryAll(PositionComponent, VelocityComponent).entities;
const startTime = performance.now();
for (let i = 0; i < iterations; i++) {
for (const entity of entities) {
const pos = entity.getComponent(PositionComponent);
const vel = entity.getComponent(VelocityComponent);
if (pos && vel) {
pos.x += vel.vx;
pos.y += vel.vy;
}
}
}
return performance.now() - startTime;
}
/**
* 获取内存使用情况
*/
function getMemoryUsage(): number {
if (typeof process !== 'undefined' && process.memoryUsage) {
return process.memoryUsage().heapUsed / 1024 / 1024; // MB
}
return 0;
}
/**
* 运行性能测试
*/
function runPerformanceTest(scene: Scene, entityCount: number, config: TestConfig): PerformanceResult {
console.log(`\n📊 测试 ${entityCount.toLocaleString()} 个实体...`);
// 测试实体创建性能
const startMemory = getMemoryUsage();
console.log(` 🔧 测试实体创建性能...`);
const creationStats = testEntityCreation(scene, entityCount);
const endMemory = getMemoryUsage();
console.log(` 📈 实体创建性能分析:`);
console.log(` 总时间: ${creationStats.totalTime.toFixed(2)}ms`);
console.log(` 平均时间: ${creationStats.averageTime.toFixed(4)}ms/实体`);
console.log(` 创建速度: ${creationStats.entitiesPerSecond.toFixed(0)} 实体/秒`);
console.log(` 时间分解:`);
console.log(` - 实体创建: ${creationStats.breakdown.entityCreation.toFixed(2)}ms (${(creationStats.breakdown.entityCreation / creationStats.totalTime * 100).toFixed(1)}%)`);
console.log(` - 组件添加: ${creationStats.breakdown.componentAddition.toFixed(2)}ms (${(creationStats.breakdown.componentAddition / creationStats.totalTime * 100).toFixed(1)}%)`);
console.log(` - 标签分配: ${creationStats.breakdown.tagAssignment.toFixed(2)}ms (${(creationStats.breakdown.tagAssignment / creationStats.totalTime * 100).toFixed(1)}%)`);
console.log(` 内存使用: ${(endMemory - startMemory).toFixed(1)}MB`);
// 运行测试
console.log(` 🔍 执行查询测试...`);
const singleQuery = testSingleComponentQuery(scene, config.queryIterations);
const multiQuery = testMultiComponentQuery(scene, config.queryIterations);
const complexQuery = testComplexQuery(scene, config.queryIterations);
const tagQuery = testTagQuery(scene, config.queryIterations);
const singleTagQuery = testSingleTagQuery(scene, config.queryIterations);
console.log(` ⚡ 执行更新测试...`);
const entityUpdate = testEntityUpdate(scene, config.updateIterations);
console.log(` ✅ 测试完成`);
return {
entityCount,
singleQuery,
multiQuery,
complexQuery,
tagQuery,
singleTagQuery,
entityUpdate,
memoryUsage: endMemory - startMemory
};
}
/**
* 显示系统信息
*/
function displaySystemInfo(scene: Scene): void {
const status = scene.querySystem.getAccelerationStatus();
const stats = scene.querySystem.getStats();
console.log('\n🔍 系统信息:');
console.log(` 当前提供者: ${status.currentProvider}`);
console.log(` WebAssembly: ${status.wasmEnabled ? '已启用' : '未启用'}`);
console.log(` 可用提供者: ${status.availableProviders.join(', ')}`);
console.log(` 索引统计:`);
console.log(` 组件掩码索引: ${stats.indexStats.maskIndexSize}`);
console.log(` 组件类型索引: ${stats.indexStats.componentIndexSize}`);
console.log(` 标签索引: ${stats.indexStats.tagIndexSize}`);
console.log(` 名称索引: ${stats.indexStats.nameIndexSize}`);
if (status.performanceInfo?.cacheStats) {
console.log(` 查询缓存:`);
console.log(` 缓存大小: ${status.performanceInfo.cacheStats.size}`);
console.log(` 命中率: ${status.performanceInfo.cacheStats.hitRate}`);
}
}
/**
* 显示性能结果
*/
function displayResults(results: PerformanceResult[], scene: Scene): void {
console.log('\n📈 ECS框架性能测试结果');
console.log('='.repeat(130));
console.log('| 实体数量 | 单组件查询 | 双组件查询 | 三组件查询 | 多标签查询 | 单标签查询 | 实体更新 | 内存使用 |');
console.log('|' + '-'.repeat(128) + '|');
for (const result of results) {
const entityCount = result.entityCount.toLocaleString().padStart(9);
const singleQuery = `${result.singleQuery.toFixed(2)}ms`.padStart(10);
const multiQuery = `${result.multiQuery.toFixed(2)}ms`.padStart(10);
const complexQuery = `${result.complexQuery.toFixed(2)}ms`.padStart(10);
const tagQuery = `${result.tagQuery.toFixed(2)}ms`.padStart(10);
const singleTagQuery = `${result.singleTagQuery.toFixed(2)}ms`.padStart(10);
const entityUpdate = `${result.entityUpdate.toFixed(2)}ms`.padStart(9);
const memoryUsage = `${result.memoryUsage.toFixed(1)}MB`.padStart(9);
console.log(`| ${entityCount} | ${singleQuery} | ${multiQuery} | ${complexQuery} | ${tagQuery} | ${singleTagQuery} | ${entityUpdate} | ${memoryUsage} |`);
}
console.log('|' + '-'.repeat(128) + '|');
// 计算性能指标
const maxEntities = Math.max(...results.map(r => r.entityCount));
const maxResult = results.find(r => r.entityCount === maxEntities)!;
console.log(`\n🎯 性能峰值 (${maxEntities.toLocaleString()} 个实体):`);
console.log(` 单组件查询: ${(TEST_CONFIG.queryIterations / maxResult.singleQuery * 1000).toFixed(0)} 次/秒`);
console.log(` 双组件查询: ${(TEST_CONFIG.queryIterations / maxResult.multiQuery * 1000).toFixed(0)} 次/秒`);
console.log(` 三组件查询: ${(TEST_CONFIG.queryIterations / maxResult.complexQuery * 1000).toFixed(0)} 次/秒`);
console.log(` 多标签查询: ${(TEST_CONFIG.queryIterations * 10 / maxResult.tagQuery * 1000).toFixed(0)} 次/秒`);
console.log(` 单标签查询: ${(TEST_CONFIG.queryIterations / maxResult.singleTagQuery * 1000).toFixed(0)} 次/秒`);
console.log(` 实体更新: ${(maxResult.entityCount * TEST_CONFIG.updateIterations / maxResult.entityUpdate * 1000).toFixed(0)} 个/秒`);
console.log(` 内存效率: ${(maxResult.entityCount / (maxResult.memoryUsage || 1)).toFixed(0)} 实体/MB`);
// 性能评级
const avgQueryTime = (maxResult.singleQuery + maxResult.multiQuery + maxResult.complexQuery + maxResult.singleTagQuery) / 4;
let rating = '';
if (avgQueryTime < 50) rating = '🚀 优秀';
else if (avgQueryTime < 100) rating = '✅ 良好';
else if (avgQueryTime < 200) rating = '⚠️ 一般';
else rating = '❌ 需要优化';
console.log(`\n📊 性能评级: ${rating}`);
console.log(` 平均查询时间: ${avgQueryTime.toFixed(2)}ms`);
// 显示查询统计信息
const queryStats = scene.querySystem.getStats().queryStats;
console.log(`\n🔍 查询统计:`);
console.log(` 总查询次数: ${queryStats.totalQueries.toLocaleString()}`);
console.log(` 缓存命中: ${queryStats.cacheHits.toLocaleString()}`);
console.log(` 索引命中: ${queryStats.indexHits.toLocaleString()}`);
console.log(` 线性扫描: ${queryStats.linearScans.toLocaleString()}`);
console.log(` 缓存命中率: ${queryStats.cacheHitRate}`);
// 标签查询性能分析
console.log(`\n🏷 标签查询分析:`);
const tagQueryRatio = maxResult.tagQuery / maxResult.singleTagQuery;
console.log(` 多标签查询 vs 单标签查询: ${tagQueryRatio.toFixed(2)}x (预期约10x)`);
if (tagQueryRatio > 15) {
console.log(` ⚠️ 多标签查询性能异常,可能存在缓存问题`);
} else if (tagQueryRatio < 5) {
console.log(` ✅ 标签查询缓存效果良好`);
} else {
console.log(` 📊 标签查询性能正常`);
}
// 性能改进分析
const improvement = calculatePerformanceImprovement(results);
if (improvement) {
console.log(`\n📈 性能改进分析:`);
console.log(` 双组件查询改进: ${improvement.multiQuery}x`);
console.log(` 三组件查询改进: ${improvement.complexQuery}x`);
console.log(` 整体查询改进: ${improvement.overall}x`);
}
// 扩展性分析
console.log(`\n📊 扩展性分析:`);
analyzeScalability(results);
}
/**
* 计算性能改进(与优化前对比)
*/
function calculatePerformanceImprovement(results: PerformanceResult[]): {
multiQuery: string;
complexQuery: string;
overall: string;
} | null {
// 基于50,000实体的结果进行分析
const maxResult = results.find(r => r.entityCount === 50000);
if (!maxResult) return null;
// 优化前的基准时间(基于之前的测试结果)
const baselineMultiQuery = 1270.54; // ms
const baselineComplexQuery = 981.76; // ms
const multiImprovement = (baselineMultiQuery / maxResult.multiQuery).toFixed(2);
const complexImprovement = (baselineComplexQuery / maxResult.complexQuery).toFixed(2);
const overallImprovement = ((baselineMultiQuery + baselineComplexQuery) /
(maxResult.multiQuery + maxResult.complexQuery)).toFixed(2);
return {
multiQuery: multiImprovement,
complexQuery: complexImprovement,
overall: overallImprovement
};
}
/**
* 分析系统扩展性
*/
function analyzeScalability(results: PerformanceResult[]): void {
if (results.length < 2) return;
// 分析查询时间随实体数量的变化趋势
const first = results[0];
const last = results[results.length - 1];
const entityRatio = last.entityCount / first.entityCount;
const singleQueryRatio = last.singleQuery / first.singleQuery;
const multiQueryRatio = last.multiQuery / first.multiQuery;
const complexQueryRatio = last.complexQuery / first.complexQuery;
console.log(` 实体数量增长: ${entityRatio.toFixed(1)}x (${first.entityCount.toLocaleString()}${last.entityCount.toLocaleString()})`);
console.log(` 单组件查询时间增长: ${singleQueryRatio.toFixed(2)}x`);
console.log(` 双组件查询时间增长: ${multiQueryRatio.toFixed(2)}x`);
console.log(` 三组件查询时间增长: ${complexQueryRatio.toFixed(2)}x`);
// 计算复杂度
const avgComplexity = (singleQueryRatio + multiQueryRatio + complexQueryRatio) / 3;
let complexityRating = '';
if (avgComplexity < entityRatio * 0.1) complexityRating = '🚀 近似O(1) - 优秀';
else if (avgComplexity < entityRatio * 0.5) complexityRating = '✅ 亚线性 - 良好';
else if (avgComplexity < entityRatio) complexityRating = '⚠️ 接近线性 - 一般';
else complexityRating = '❌ 超线性 - 需要优化';
console.log(` 时间复杂度评估: ${complexityRating}`);
// 内存效率分析
const memoryEfficiencyFirst = first.entityCount / first.memoryUsage;
const memoryEfficiencyLast = last.entityCount / last.memoryUsage;
const memoryEfficiencyRatio = memoryEfficiencyLast / memoryEfficiencyFirst;
console.log(` 内存效率变化: ${memoryEfficiencyRatio.toFixed(2)}x (${memoryEfficiencyFirst.toFixed(0)}${memoryEfficiencyLast.toFixed(0)} 实体/MB)`);
}
/**
* 专门测试实体创建性能
*/
async function runEntityCreationBenchmark(): Promise<void> {
console.log('\n🚀 实体创建性能基准测试');
console.log('='.repeat(60));
const testCounts = [1000, 5000, 10000, 50000, 100000];
for (const count of testCounts) {
console.log(`\n📊 测试创建 ${count.toLocaleString()} 个实体:`);
// 创建新场景
const scene = new Scene();
// 测试创建性能
const stats = testEntityCreation(scene, count);
console.log(` 总时间: ${stats.totalTime.toFixed(2)}ms`);
console.log(` 平均时间: ${stats.averageTime.toFixed(4)}ms/实体`);
console.log(` 创建速度: ${stats.entitiesPerSecond.toFixed(0)} 实体/秒`);
console.log(` 时间分解:`);
console.log(` - 实体创建: ${stats.breakdown.entityCreation.toFixed(2)}ms (${(stats.breakdown.entityCreation / stats.totalTime * 100).toFixed(1)}%)`);
console.log(` - 组件添加: ${stats.breakdown.componentAddition.toFixed(2)}ms (${(stats.breakdown.componentAddition / stats.totalTime * 100).toFixed(1)}%)`);
console.log(` - 标签分配: ${stats.breakdown.tagAssignment.toFixed(2)}ms (${(stats.breakdown.tagAssignment / stats.totalTime * 100).toFixed(1)}%)`);
// 分析性能瓶颈
const { entityCreation, componentAddition, tagAssignment } = stats.breakdown;
const total = stats.totalTime;
console.log(` 性能瓶颈分析:`);
if (componentAddition / total > 0.5) {
console.log(` ⚠️ 组件添加是主要瓶颈 (${(componentAddition / total * 100).toFixed(1)}%)`);
}
if (entityCreation / total > 0.3) {
console.log(` ⚠️ 实体创建开销较高 (${(entityCreation / total * 100).toFixed(1)}%)`);
}
if (tagAssignment / total > 0.1) {
console.log(` ⚠️ 标签分配开销异常 (${(tagAssignment / total * 100).toFixed(1)}%)`);
}
// 分析组件添加性能(仅对较小的测试集)
if (count <= 10000) {
analyzeComponentAdditionPerformance(new Scene(), Math.min(count, 5000));
}
// 清理场景
scene.end();
}
console.log('\n📈 实体创建性能总结:');
console.log(' 主要性能瓶颈通常在组件添加阶段');
console.log(' 建议优化方向:');
console.log(' 1. 减少组件注册开销');
console.log(' 2. 优化位掩码计算');
console.log(' 3. 减少内存分配次数');
console.log(' 4. 使用对象池复用组件实例');
}
/**
* 测试组件添加性能的详细分析
*/
function analyzeComponentAdditionPerformance(scene: Scene, count: number): void {
console.log(`\n🔬 组件添加性能详细分析 (${count.toLocaleString()} 个实体):`);
// 创建实体但不添加组件
const entities = scene.createEntities(count, "TestEntity");
// 分别测试每种组件的添加性能
const componentTests = [
{
name: "PositionComponent",
create: () => new PositionComponent(Math.random() * 1000, Math.random() * 1000),
probability: 1.0
},
{
name: "VelocityComponent",
create: () => new VelocityComponent((Math.random() - 0.5) * 10, (Math.random() - 0.5) * 10),
probability: 0.7
},
{
name: "HealthComponent",
create: () => new HealthComponent(Math.floor(Math.random() * 100) + 50),
probability: 0.5
},
{
name: "RenderComponent",
create: () => new RenderComponent(`sprite_${Math.floor(Math.random() * 10)}`),
probability: 0.3
},
{
name: "AIComponent",
create: () => new AIComponent(['idle', 'patrol', 'chase'][Math.floor(Math.random() * 3)]),
probability: 0.2
}
];
for (const test of componentTests) {
const startTime = performance.now();
let addedCount = 0;
for (const entity of entities) {
if (Math.random() < test.probability) {
entity.addComponent(test.create());
addedCount++;
}
}
const endTime = performance.now();
const totalTime = endTime - startTime;
console.log(` ${test.name}:`);
console.log(` 添加数量: ${addedCount.toLocaleString()}`);
console.log(` 总时间: ${totalTime.toFixed(2)}ms`);
console.log(` 平均时间: ${(totalTime / addedCount).toFixed(4)}ms/组件`);
console.log(` 添加速度: ${(addedCount / (totalTime / 1000)).toFixed(0)} 组件/秒`);
}
}
/**
* 主测试函数
*/
async function runBenchmarks(): Promise<void> {
console.log('🎯 ECS框架性能基准测试');
console.log('='.repeat(60));
// 先运行实体创建性能测试
await runEntityCreationBenchmark();
// 然后运行完整的框架测试
console.log('\n🚀 完整框架性能测试');
console.log('='.repeat(60));
console.log(`\n⚙ 测试配置:`);
console.log(` 实体数量: ${TEST_CONFIG.entityCounts.map(n => n.toLocaleString()).join(', ')}`);
console.log(` 查询迭代: ${TEST_CONFIG.queryIterations.toLocaleString()}`);
console.log(` 更新迭代: ${TEST_CONFIG.updateIterations.toLocaleString()}`);
console.log(` 预计测试时间: ${(TEST_CONFIG.entityCounts.length * 2).toFixed(0)}-${(TEST_CONFIG.entityCounts.length * 5).toFixed(0)} 分钟`);
console.log('\n🔧 初始化ECS框架...');
// 初始化WebAssembly模块
try {
const { ecsCore } = await import('../../Utils/WasmCore');
await ecsCore.initialize();
console.log(`✅ WebAssembly模块: ${ecsCore.isUsingWasm() ? '已加载' : '未加载'}`);
} catch (error) {
console.log('⚠️ WebAssembly模块加载失败使用JavaScript实现');
}
const scene = new Scene();
// 等待初始化完成
await new Promise(resolve => setTimeout(resolve, 1000));
displaySystemInfo(scene);
const results: PerformanceResult[] = [];
const totalTests = TEST_CONFIG.entityCounts.length;
// 运行不同规模的测试
for (let i = 0; i < TEST_CONFIG.entityCounts.length; i++) {
const entityCount = TEST_CONFIG.entityCounts[i];
console.log(`\n🔄 进度: ${i + 1}/${totalTests} (${((i + 1) / totalTests * 100).toFixed(1)}%)`);
const result = runPerformanceTest(scene, entityCount, TEST_CONFIG);
results.push(result);
// 清理场景,准备下一轮测试
console.log(` 🧹 清理内存...`);
scene.end();
scene.begin();
// 强制垃圾回收
if (typeof global !== 'undefined' && global.gc) {
global.gc();
}
// 大规模测试间隔稍作休息
if (entityCount >= 100000) {
console.log(` ⏱️ 等待系统稳定...`);
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
displayResults(results, scene);
scene.end();
console.log('\n✅ 性能测试完成!');
console.log(`📊 总测试时间: ${((Date.now() - startTime) / 1000 / 60).toFixed(1)} 分钟`);
}
// 记录开始时间
const startTime = Date.now();
// 运行测试
runBenchmarks().catch(error => {
console.error('❌ 测试失败:', error);
});

View File

@@ -0,0 +1,53 @@
const { Scene } = require('./bin/ECS/Scene.js');
const { Component } = require('./bin/ECS/Component.js');
// 简单的组件类
class TestComponent extends Component {
constructor(value) {
super();
this.value = value;
}
}
console.log('🔬 组件添加性能分析');
// 创建场景和实体
const scene = new Scene();
console.log('✅ 创建场景完成');
const startCreate = performance.now();
const entities = scene.createEntities(5000, 'TestEntity');
const endCreate = performance.now();
console.log(`✅ 创建了 ${entities.length} 个实体,耗时: ${(endCreate - startCreate).toFixed(2)}ms`);
// 测试单个组件添加性能
console.log('\n📊 测试组件添加性能:');
const startAdd = performance.now();
for (let i = 0; i < entities.length; i++) {
const entity = entities[i];
entity.addComponent(new TestComponent(i));
}
const endAdd = performance.now();
const addTime = endAdd - startAdd;
console.log(`添加 ${entities.length} 个组件耗时: ${addTime.toFixed(2)}ms`);
console.log(`平均每个组件: ${(addTime / entities.length).toFixed(4)}ms`);
console.log(`添加速度: ${(entities.length / (addTime / 1000)).toFixed(0)} 组件/秒`);
// 测试组件获取性能
console.log('\n📊 测试组件获取性能:');
const startGet = performance.now();
for (let i = 0; i < entities.length; i++) {
const entity = entities[i];
const component = entity.getComponent(TestComponent);
}
const endGet = performance.now();
const getTime = endGet - startGet;
console.log(`获取 ${entities.length} 个组件耗时: ${getTime.toFixed(2)}ms`);
console.log(`平均每个组件: ${(getTime / entities.length).toFixed(4)}ms`);
console.log(`获取速度: ${(entities.length / (getTime / 1000)).toFixed(0)} 组件/秒`);

View File

@@ -0,0 +1,199 @@
import { BitMaskOptimizer } from '../../ECS/Core/BitMaskOptimizer';
/**
* 位掩码优化器测试
*/
function testBitMaskOptimizer(): void {
console.log('🧪 测试位掩码优化器');
const optimizer = BitMaskOptimizer.getInstance();
optimizer.reset();
// 测试组件类型注册
console.log(' 📝 测试组件类型注册...');
const positionId = optimizer.registerComponentType('Position');
const velocityId = optimizer.registerComponentType('Velocity');
const healthId = optimizer.registerComponentType('Health');
console.log(` Position ID: ${positionId}`);
console.log(` Velocity ID: ${velocityId}`);
console.log(` Health ID: ${healthId}`);
// 测试单个组件掩码
console.log(' 🎯 测试单个组件掩码...');
const positionMask = optimizer.createSingleComponentMask('Position');
const velocityMask = optimizer.createSingleComponentMask('Velocity');
console.log(` Position掩码: ${positionMask.toString(2)}`);
console.log(` Velocity掩码: ${velocityMask.toString(2)}`);
// 测试组合掩码
console.log(' 🔗 测试组合掩码...');
const combinedMask = optimizer.createCombinedMask(['Position', 'Velocity']);
console.log(` Position+Velocity掩码: ${combinedMask.toString(2)}`);
// 测试掩码包含检查
console.log(' ✅ 测试掩码包含检查...');
const hasPosition = optimizer.maskContainsComponent(combinedMask, 'Position');
const hasVelocity = optimizer.maskContainsComponent(combinedMask, 'Velocity');
const hasHealth = optimizer.maskContainsComponent(combinedMask, 'Health');
console.log(` 包含Position: ${hasPosition}`);
console.log(` 包含Velocity: ${hasVelocity}`);
console.log(` 包含Health: ${hasHealth}`);
// 测试掩码操作
console.log(' 🔧 测试掩码操作...');
let entityMask = 0n;
entityMask = optimizer.addComponentToMask(entityMask, 'Position');
entityMask = optimizer.addComponentToMask(entityMask, 'Health');
console.log(` 添加Position和Health后: ${entityMask.toString(2)}`);
const hasAll = optimizer.maskContainsAllComponents(entityMask, ['Position', 'Health']);
const hasAny = optimizer.maskContainsAnyComponent(entityMask, ['Position', 'Velocity']);
console.log(` 包含Position和Health: ${hasAll}`);
console.log(` 包含Position或Velocity: ${hasAny}`);
// 测试掩码分析
console.log(' 📊 测试掩码分析...');
const componentNames = optimizer.maskToComponentNames(entityMask);
const componentCount = optimizer.getComponentCount(entityMask);
console.log(` 掩码包含的组件: ${componentNames.join(', ')}`);
console.log(` 组件数量: ${componentCount}`);
// 测试缓存统计
console.log(' 📈 测试缓存统计...');
const stats = optimizer.getCacheStats();
console.log(` 缓存大小: ${stats.size}`);
console.log(` 组件类型数量: ${stats.componentTypes}`);
// 测试预计算常用掩码
console.log(' ⚡ 测试预计算常用掩码...');
const commonCombinations = [
['Position', 'Velocity'],
['Position', 'Health'],
['Position', 'Velocity', 'Health']
];
optimizer.precomputeCommonMasks(commonCombinations);
const statsAfterPrecompute = optimizer.getCacheStats();
console.log(` 预计算后缓存大小: ${statsAfterPrecompute.size}`);
console.log('✅ 位掩码优化器测试完成');
}
/**
* 性能测试
*/
function testBitMaskPerformance(): void {
console.log('\n🚀 位掩码优化器性能测试');
const optimizer = BitMaskOptimizer.getInstance();
optimizer.reset();
// 注册组件类型
const componentTypes = ['Position', 'Velocity', 'Health', 'Render', 'AI', 'Physics', 'Audio', 'Network'];
for (const type of componentTypes) {
optimizer.registerComponentType(type);
}
const iterations = 100000;
// 测试单个掩码创建性能
console.log(' 🔥 测试单个掩码创建性能...');
let start = performance.now();
for (let i = 0; i < iterations; i++) {
optimizer.createSingleComponentMask('Position');
}
let end = performance.now();
console.log(` ${iterations}次单个掩码创建: ${(end - start).toFixed(2)}ms`);
// 测试组合掩码创建性能
console.log(' 🔥 测试组合掩码创建性能...');
start = performance.now();
for (let i = 0; i < iterations; i++) {
optimizer.createCombinedMask(['Position', 'Velocity', 'Health']);
}
end = performance.now();
console.log(` ${iterations}次组合掩码创建: ${(end - start).toFixed(2)}ms`);
// 测试掩码检查性能
console.log(' 🔥 测试掩码检查性能...');
const testMask = optimizer.createCombinedMask(['Position', 'Velocity', 'Health']);
start = performance.now();
for (let i = 0; i < iterations; i++) {
optimizer.maskContainsComponent(testMask, 'Position');
optimizer.maskContainsComponent(testMask, 'AI');
}
end = performance.now();
console.log(` ${iterations * 2}次掩码检查: ${(end - start).toFixed(2)}ms`);
// 对比原生位操作性能
console.log(' ⚖️ 对比原生位操作性能...');
const positionBit = 1n << 0n;
const velocityBit = 1n << 1n;
const healthBit = 1n << 2n;
const nativeMask = positionBit | velocityBit | healthBit;
start = performance.now();
for (let i = 0; i < iterations; i++) {
(nativeMask & positionBit) !== 0n;
(nativeMask & (1n << 7n)) !== 0n; // AI位
}
end = performance.now();
console.log(` ${iterations * 2}次原生位操作: ${(end - start).toFixed(2)}ms`);
console.log('✅ 性能测试完成');
}
/**
* 内存使用测试
*/
function testBitMaskMemoryUsage(): void {
console.log('\n💾 位掩码优化器内存使用测试');
const optimizer = BitMaskOptimizer.getInstance();
optimizer.reset();
// 注册大量组件类型
console.log(' 📝 注册组件类型...');
for (let i = 0; i < 100; i++) {
optimizer.registerComponentType(`Component${i}`);
}
// 创建大量掩码组合
console.log(' 🔗 创建掩码组合...');
const maskCount = 1000;
for (let i = 0; i < maskCount; i++) {
const componentCount = Math.floor(Math.random() * 5) + 1;
const components: string[] = [];
for (let j = 0; j < componentCount; j++) {
components.push(`Component${Math.floor(Math.random() * 100)}`);
}
optimizer.createCombinedMask(components);
}
const stats = optimizer.getCacheStats();
console.log(` 📊 最终统计:`);
console.log(` 组件类型数量: ${stats.componentTypes}`);
console.log(` 缓存掩码数量: ${stats.size}`);
console.log(` 平均每个掩码占用: ~${(stats.size * 64 / 1024).toFixed(2)} KB`);
console.log('✅ 内存使用测试完成');
}
// 运行所有测试
export function runBitMaskOptimizerTests(): void {
console.log('🧪 位掩码优化器测试套件');
console.log('='.repeat(50));
testBitMaskOptimizer();
testBitMaskPerformance();
testBitMaskMemoryUsage();
console.log('\n✅ 所有测试完成');
}

View File

@@ -0,0 +1,189 @@
import { ComponentPool, ComponentPoolManager } from '../../ECS/Core/ComponentPool';
import { Component } from '../../ECS/Component';
/**
* 测试用组件
*/
class TestComponent extends Component {
public value: number = 0;
constructor(value: number = 0) {
super();
this.value = value;
}
reset(): void {
this.value = 0;
}
}
/**
* 运行组件对象池测试
*/
export function runComponentPoolTests(): void {
console.log('🧪 组件对象池测试');
console.log('='.repeat(50));
testBasicFunctionality();
testPoolManager();
testPerformance();
console.log('✅ 组件对象池测试完成');
}
/**
* 基础功能测试
*/
function testBasicFunctionality(): void {
console.log('\n📝 基础功能测试...');
const pool = new ComponentPool(
() => new TestComponent(),
(component) => component.reset(),
10
);
// 测试获取新组件实例
console.log(' 测试获取新组件实例...');
const component = pool.acquire();
console.assert(component instanceof TestComponent, '应该返回TestComponent实例');
console.assert(component.value === 0, '新组件的值应该为0');
// 测试释放和复用
console.log(' 测试组件释放和复用...');
component.value = 42;
pool.release(component);
console.assert(pool.getAvailableCount() === 1, '池中应该有1个可用组件');
const reusedComponent = pool.acquire();
console.assert(reusedComponent === component, '应该复用同一个组件实例');
console.assert(reusedComponent.value === 0, '复用的组件应该被重置');
// 测试预填充
console.log(' 测试对象池预填充...');
pool.prewarm(5);
console.assert(pool.getAvailableCount() === 5, '预填充后应该有5个可用组件');
const components: TestComponent[] = [];
for (let i = 0; i < 5; i++) {
components.push(pool.acquire());
}
console.assert(pool.getAvailableCount() === 0, '获取5个组件后池应该为空');
// 测试最大容量限制
console.log(' 测试最大容量限制...');
pool.prewarm(10);
const extraComponent = new TestComponent();
pool.release(extraComponent);
console.assert(pool.getAvailableCount() === 10, '不应该超过最大容量');
// 测试清空池
console.log(' 测试清空对象池...');
pool.clear();
console.assert(pool.getAvailableCount() === 0, '清空后池应该为空');
console.log(' ✅ 基础功能测试通过');
}
/**
* 池管理器测试
*/
function testPoolManager(): void {
console.log('\n📝 池管理器测试...');
const manager = ComponentPoolManager.getInstance();
manager.clearAll();
// 测试单例模式
console.log(' 测试单例模式...');
const manager1 = ComponentPoolManager.getInstance();
const manager2 = ComponentPoolManager.getInstance();
console.assert(manager1 === manager2, '应该返回同一个实例');
// 测试注册组件池
console.log(' 测试注册组件池...');
manager.registerPool(
'TestComponent',
() => new TestComponent(),
(component) => component.reset(),
5
);
const stats = manager.getPoolStats();
console.assert(stats.has('TestComponent'), '应该包含已注册的组件类型');
console.assert(stats.get('TestComponent')?.maxSize === 5, '最大容量应该为5');
// 测试获取和释放组件
console.log(' 测试获取和释放组件...');
const component = manager.acquireComponent<TestComponent>('TestComponent');
console.assert(component instanceof TestComponent, '应该返回TestComponent实例');
if (component) {
component.value = 42;
manager.releaseComponent('TestComponent', component);
const reusedComponent = manager.acquireComponent<TestComponent>('TestComponent');
console.assert(reusedComponent === component, '应该复用同一个组件');
console.assert(reusedComponent?.value === 0, '复用的组件应该被重置');
}
// 测试预热所有池
console.log(' 测试预热所有池...');
manager.registerPool('TestComponent1', () => new TestComponent());
manager.registerPool('TestComponent2', () => new TestComponent());
manager.prewarmAll(3);
const finalStats = manager.getPoolStats();
console.assert(finalStats.get('TestComponent1')?.available === 3, 'TestComponent1应该有3个可用组件');
console.assert(finalStats.get('TestComponent2')?.available === 3, 'TestComponent2应该有3个可用组件');
// 测试未注册的组件类型
console.log(' 测试未注册的组件类型...');
const nullComponent = manager.acquireComponent('NonExistentComponent');
console.assert(nullComponent === null, '未注册的组件类型应该返回null');
manager.clearAll();
console.log(' ✅ 池管理器测试通过');
}
/**
* 性能测试
*/
function testPerformance(): void {
console.log('\n📝 性能测试...');
const pool = new ComponentPool(() => new TestComponent());
const iterations = 10000;
// 预热池
pool.prewarm(100);
// 测试对象池性能
const poolStart = performance.now();
for (let i = 0; i < iterations; i++) {
const component = pool.acquire();
pool.release(component);
}
const poolEnd = performance.now();
const poolTime = poolEnd - poolStart;
// 测试直接创建性能
const directStart = performance.now();
for (let i = 0; i < iterations; i++) {
new TestComponent();
}
const directEnd = performance.now();
const directTime = directEnd - directStart;
console.log(` 对象池时间: ${poolTime.toFixed(2)}ms`);
console.log(` 直接创建时间: ${directTime.toFixed(2)}ms`);
const improvement = ((directTime - poolTime) / directTime * 100);
console.log(` 性能提升: ${improvement.toFixed(1)}%`);
if (poolTime < directTime) {
console.log(' ✅ 对象池性能测试通过 - 比直接创建更快');
} else {
console.log(' ⚠️ 对象池在小规模测试中可能不如直接创建快');
}
}

182
src/Testing/test-runner.ts Normal file
View File

@@ -0,0 +1,182 @@
import { runBitMaskOptimizerTests } from './Unit/bitmask-optimizer.test';
import { runComponentPoolTests } from './Unit/component-pool.test';
/**
* 测试运行器 - 统一运行所有测试
*/
export class TestRunner {
private results: Map<string, { passed: number; failed: number; duration: number }> = new Map();
/**
* 运行所有单元测试
*/
async runUnitTests(): Promise<void> {
console.log('🧪 运行单元测试');
console.log('='.repeat(50));
await this.runTest('组件对象池', runComponentPoolTests);
await this.runTest('位掩码优化器', runBitMaskOptimizerTests);
console.log('\n📊 单元测试总结:');
this.printSummary();
}
/**
* 运行性能测试
*/
async runPerformanceTests(): Promise<void> {
console.log('\n🚀 运行性能测试');
console.log('='.repeat(50));
// 性能测试需要从benchmark.ts文件中导入
console.log('⚠️ 性能测试需要单独运行 - 请使用: node benchmark.ts');
console.log('\n📊 性能测试总结:');
this.printSummary();
}
/**
* 运行集成测试
*/
async runIntegrationTests(): Promise<void> {
console.log('\n🔗 运行集成测试');
console.log('='.repeat(50));
// 集成测试待实现
console.log('⚠️ 集成测试尚未实现');
}
/**
* 运行所有测试
*/
async runAllTests(): Promise<void> {
console.log('🎯 ECS框架完整测试套件');
console.log('='.repeat(60));
const startTime = performance.now();
await this.runUnitTests();
await this.runPerformanceTests();
await this.runIntegrationTests();
const endTime = performance.now();
const totalDuration = endTime - startTime;
console.log('\n✅ 所有测试完成');
console.log(`🕐 总测试时间: ${(totalDuration / 1000).toFixed(2)}`);
this.printFinalSummary();
}
/**
* 运行单个测试
*/
private async runTest(testName: string, testFunction: () => void | Promise<void>): Promise<void> {
console.log(`\n▶ 开始测试: ${testName}`);
const startTime = performance.now();
let passed = 0;
let failed = 0;
try {
await testFunction();
passed = 1;
console.log(`${testName} 测试通过`);
} catch (error) {
failed = 1;
console.error(`${testName} 测试失败:`, error);
}
const endTime = performance.now();
const duration = endTime - startTime;
this.results.set(testName, { passed, failed, duration });
console.log(`⏱️ 耗时: ${duration.toFixed(2)}ms`);
}
/**
* 打印测试摘要
*/
private printSummary(): void {
let totalPassed = 0;
let totalFailed = 0;
let totalDuration = 0;
for (const [name, result] of this.results) {
totalPassed += result.passed;
totalFailed += result.failed;
totalDuration += result.duration;
const status = result.failed > 0 ? '❌' : '✅';
console.log(` ${status} ${name}: ${result.duration.toFixed(2)}ms`);
}
console.log(`\n📈 测试统计:`);
console.log(` 通过: ${totalPassed}`);
console.log(` 失败: ${totalFailed}`);
console.log(` 总时间: ${totalDuration.toFixed(2)}ms`);
console.log(` 成功率: ${totalPassed + totalFailed > 0 ? (totalPassed / (totalPassed + totalFailed) * 100).toFixed(1) : 0}%`);
}
/**
* 打印最终测试摘要
*/
private printFinalSummary(): void {
console.log('\n📋 最终测试报告');
console.log('='.repeat(60));
let totalPassed = 0;
let totalFailed = 0;
for (const [, result] of this.results) {
totalPassed += result.passed;
totalFailed += result.failed;
}
if (totalFailed === 0) {
console.log('🎉 所有测试都通过了!');
} else {
console.log(`⚠️ 有 ${totalFailed} 个测试失败`);
}
console.log(`📊 测试覆盖率: ${this.results.size} 个测试模块`);
console.log(`✅ 通过率: ${totalPassed + totalFailed > 0 ? (totalPassed / (totalPassed + totalFailed) * 100).toFixed(1) : 0}%`);
}
/**
* 清除测试结果
*/
clearResults(): void {
this.results.clear();
}
}
/**
* 便捷函数:运行所有测试
*/
export async function runAllTests(): Promise<void> {
const runner = new TestRunner();
await runner.runAllTests();
}
/**
* 便捷函数:仅运行单元测试
*/
export async function runUnitTests(): Promise<void> {
const runner = new TestRunner();
await runner.runUnitTests();
}
/**
* 便捷函数:仅运行性能测试
*/
export async function runPerformanceTests(): Promise<void> {
const runner = new TestRunner();
await runner.runPerformanceTests();
}
// 如果直接运行此文件,执行所有测试
if (require.main === module) {
runAllTests().catch(console.error);
}

577
src/Types/index.ts Normal file
View File

@@ -0,0 +1,577 @@
/**
* 框架核心类型定义
*/
/** 更新顺序比较器接口 */
export interface IUpdateOrderComparable {
updateOrder: number;
}
/** 日志类型枚举 */
export enum LogType {
Error = 0,
Assert = 1,
Warning = 2,
Log = 3,
Exception = 4
}
/** 组件变换类型枚举 */
export enum ComponentTransform {
Position = 1,
Scale = 2,
Rotation = 4
}
/**
* 组件接口
*
* 定义组件的基本契约,所有组件都应该实现此接口
*/
export interface IComponent {
/** 组件唯一标识符 */
readonly id: number;
/** 组件所属的实体ID */
entityId?: string | number;
/** 组件启用状态 */
enabled: boolean;
/** 更新顺序 */
updateOrder: number;
/** 组件添加到实体时的回调 */
onAddedToEntity(): void;
/** 组件从实体移除时的回调 */
onRemovedFromEntity(): void;
/** 组件启用时的回调 */
onEnabled(): void;
/** 组件禁用时的回调 */
onDisabled(): void;
/** 更新组件 */
update(): void;
}
/**
* 实体接口
*
* 定义实体的基本契约,所有实体都应该实现此接口
*/
export interface IEntity {
/** 实体唯一标识符 */
readonly id: string | number;
/** 实体名称 */
name: string;
/** 实体激活状态 */
active: boolean;
/** 实体启用状态 */
enabled: boolean;
/** 实体是否已销毁 */
readonly isDestroyed: boolean;
/** 更新顺序 */
updateOrder: number;
/** 实体标签 */
tag: number;
/** 添加组件 */
addComponent<T extends IComponent>(component: T): T;
/** 创建并添加组件 */
createComponent<T extends IComponent>(componentType: ComponentType<T>, ...args: any[]): T;
/** 获取组件 */
getComponent<T extends IComponent>(type: ComponentType<T>): T | null;
/** 获取或创建组件 */
getOrCreateComponent<T extends IComponent>(type: ComponentType<T>, ...args: any[]): T;
/** 移除组件 */
removeComponent(component: IComponent): void;
/** 通过类型移除组件 */
removeComponentByType<T extends IComponent>(type: ComponentType<T>): T | null;
/** 检查是否有组件 */
hasComponent<T extends IComponent>(type: ComponentType<T>): boolean;
/** 获取所有指定类型的组件 */
getComponents<T extends IComponent>(type: ComponentType<T>): T[];
/** 添加子实体 */
addChild(child: IEntity): IEntity;
/** 移除子实体 */
removeChild(child: IEntity): boolean;
/** 查找子实体 */
findChild(name: string, recursive?: boolean): IEntity | null;
/** 更新实体 */
update(): void;
/** 销毁实体 */
destroy(): void;
}
/**
* 实体基础接口(向后兼容)
*
* 为现有的Entity类提供更灵活的类型定义
*/
export interface IEntityBase {
/** 实体唯一标识符 */
readonly id: string | number;
/** 实体名称 */
name: string;
/** 实体激活状态 */
active: boolean;
/** 实体启用状态 */
enabled: boolean;
/** 实体是否已销毁 */
readonly isDestroyed: boolean;
/** 更新顺序 */
updateOrder: number;
/** 实体标签 */
tag: number;
/** 添加组件(泛型版本) */
addComponent<T>(component: T): T;
/** 获取组件(泛型版本) */
getComponent<T>(type: ComponentClass<T>): T | null;
/** 检查是否有组件(泛型版本) */
hasComponent<T>(type: ComponentClass<T>): boolean;
/** 添加子实体 */
addChild(child: any): any;
/** 移除子实体 */
removeChild(child: any): boolean;
/** 查找子实体 */
findChild(name: string, recursive?: boolean): any;
/** 更新实体 */
update(): void;
/** 销毁实体 */
destroy(): void;
}
/**
* 系统接口
*
* 定义系统的基本契约,所有系统都应该实现此接口
*/
export interface ISystem {
/** 系统名称 */
readonly systemName: string;
/** 系统处理的实体列表 */
readonly entities: readonly IEntity[];
/** 更新顺序/优先级 */
updateOrder: number;
/** 系统启用状态 */
enabled: boolean;
/** 系统初始化 */
initialize(): void;
/** 更新系统(主要处理阶段) */
update(): void;
/** 延迟更新系统 */
lateUpdate?(): void;
/** 当实体添加到系统时的回调 */
onEntityAdded?(entity: IEntity): void;
/** 当实体从系统移除时的回调 */
onEntityRemoved?(entity: IEntity): void;
/** 当实体组件发生变化时的回调 */
onEntityChanged?(entity: IEntity): void;
}
/**
* 系统基础接口(向后兼容)
*
* 为现有的EntitySystem类提供更灵活的类型定义
*/
export interface ISystemBase {
/** 系统名称 */
readonly systemName: string;
/** 系统处理的实体列表(泛型版本) */
readonly entities: readonly any[];
/** 更新顺序/优先级 */
updateOrder: number;
/** 系统启用状态 */
enabled: boolean;
/** 系统初始化 */
initialize(): void;
/** 更新系统(主要处理阶段) */
update(): void;
/** 延迟更新系统 */
lateUpdate?(): void;
}
/**
* 场景接口
*
* 定义场景的基本契约
*/
export interface IScene {
/** 场景名称 */
name: string;
/** 场景中的实体列表 */
readonly entities: readonly IEntity[];
/** 场景中的系统列表 */
readonly systems: readonly ISystem[];
/** 创建实体 */
createEntity(name: string): IEntity;
/** 添加实体到场景 */
addEntity(entity: IEntity): void;
/** 从场景移除实体 */
removeEntity(entity: IEntity): void;
/** 查找实体 */
findEntity(name: string): IEntity | null;
/** 添加系统到场景 */
addSystem<T extends ISystem>(system: T): T;
/** 从场景移除系统 */
removeSystem(system: ISystem): void;
/** 获取系统 */
getSystem<T extends ISystem>(systemType: new (...args: any[]) => T): T | null;
/** 更新场景 */
update(): void;
}
/**
* 组件类型定义
*
* 用于类型安全的组件操作
*/
export type ComponentType<T extends IComponent = IComponent> = new (...args: any[]) => T;
/**
* 原始组件类型(向后兼容)
*
* 用于与现有Component类的兼容
*/
export type ComponentClass<T = any> = new (...args: any[]) => T;
/**
* 实体查询匹配器接口
*
* 用于查询符合特定条件的实体
*/
export interface IMatcher {
/** 必须包含的组件类型 */
all(...componentTypes: ComponentType[]): IMatcher;
/** 至少包含其中一个组件类型 */
any(...componentTypes: ComponentType[]): IMatcher;
/** 不能包含的组件类型 */
exclude(...componentTypes: ComponentType[]): IMatcher;
/** 检查实体是否匹配 */
isInterestedEntity(entity: IEntity): boolean;
}
/**
* 性能监控接口
*/
export interface IPerformanceData {
/** 执行时间(毫秒) */
executionTime: number;
/** 调用次数 */
callCount: number;
/** 平均执行时间 */
averageTime: number;
/** 最大执行时间 */
maxTime: number;
/** 最小执行时间 */
minTime: number;
}
/**
* 生命周期管理接口
*/
export interface ILifecycle {
/** 初始化 */
initialize?(): void;
/** 启动 */
start?(): void;
/** 更新 */
update?(): void;
/** 延迟更新 */
lateUpdate?(): void;
/** 停止 */
stop?(): void;
/** 销毁 */
destroy?(): void;
}
/**
* 实体管理器接口
*
* 提供统一的实体管理和查询机制,支持高效的实体操作
*/
export interface IEntityManager {
/** 所有实体数量 */
readonly entityCount: number;
/** 激活的实体数量 */
readonly activeEntityCount: number;
/** 创建实体 */
createEntity(name?: string): IEntity;
/** 销毁实体 */
destroyEntity(entity: IEntity | string | number): boolean;
/** 批量销毁实体 */
destroyEntities(entities: (IEntity | string | number)[]): number;
/** 销毁所有实体 */
destroyAllEntities(): number;
/** 根据ID获取实体 */
getEntity(id: string | number): IEntity | null;
/** 根据名称获取实体 */
getEntityByName(name: string): IEntity | null;
/** 根据名称获取所有实体 */
getEntitiesByName(name: string): IEntity[];
/** 根据标签获取实体 */
getEntitiesByTag(tag: number): IEntity[];
/** 获取所有实体 */
getAllEntities(): IEntity[];
/** 获取所有激活的实体 */
getActiveEntities(): IEntity[];
/** 获取拥有指定组件的实体 */
getEntitiesWithComponent<T extends IComponent>(componentType: ComponentType<T>): IEntity[];
/** 获取拥有指定组件的实体及其组件 */
getEntitiesWithComponentData<T extends IComponent>(componentType: ComponentType<T>): Array<{entity: IEntity, component: T}>;
/** 获取拥有所有指定组件的实体 */
getEntitiesWithComponents(...componentTypes: ComponentType[]): IEntity[];
/** 获取拥有任一指定组件的实体 */
getEntitiesWithAnyComponent(...componentTypes: ComponentType[]): IEntity[];
/** 获取不包含指定组件的实体 */
getEntitiesWithoutComponent<T extends IComponent>(componentType: ComponentType<T>): IEntity[];
/** 对所有实体执行操作 */
forEachEntity(action: (entity: IEntity) => void): void;
/** 对符合条件的实体执行操作 */
forEachEntityWhere(predicate: (entity: IEntity) => boolean, action: (entity: IEntity) => void): void;
/** 对拥有指定组件的实体执行操作 */
forEachEntityWithComponent<T extends IComponent>(
componentType: ComponentType<T>,
action: (entity: IEntity, component: T) => void
): void;
/** 查找第一个符合条件的实体 */
findEntity(predicate: (entity: IEntity) => boolean): IEntity | null;
/** 查找所有符合条件的实体 */
findEntities(predicate: (entity: IEntity) => boolean): IEntity[];
/** 获取统计信息 */
getStatistics(): {
totalEntities: number;
activeEntities: number;
destroyedEntities: number;
entitiesByTag: Map<number, number>;
componentsCount: Map<string, number>;
};
/** 清理已销毁的实体 */
cleanup(): number;
/** 压缩存储空间 */
compact(): void;
}
/**
* 实体查询构建器接口
*
* 提供流式API构建复杂的实体查询条件
*/
export interface IEntityQueryBuilder {
/** 必须包含所有指定组件 */
withAll(...componentTypes: ComponentType[]): IEntityQueryBuilder;
/** 必须包含任一指定组件 */
withAny(...componentTypes: ComponentType[]): IEntityQueryBuilder;
/** 必须不包含指定组件 */
without(...componentTypes: ComponentType[]): IEntityQueryBuilder;
/** 必须包含指定标签 */
withTag(tag: number): IEntityQueryBuilder;
/** 必须不包含指定标签 */
withoutTag(tag: number): IEntityQueryBuilder;
/** 必须处于激活状态 */
active(): IEntityQueryBuilder;
/** 必须处于启用状态 */
enabled(): IEntityQueryBuilder;
/** 自定义过滤条件 */
where(predicate: (entity: IEntity) => boolean): IEntityQueryBuilder;
/** 执行查询,返回所有匹配的实体 */
execute(): IEntity[];
/** 执行查询,返回第一个匹配的实体 */
first(): IEntity | null;
/** 执行查询,返回匹配实体的数量 */
count(): number;
/** 对查询结果执行操作 */
forEach(action: (entity: IEntity) => void): void;
}
/**
* 事件总线接口
* 提供类型安全的事件发布订阅机制
*/
export interface IEventBus {
/**
* 发射事件
* @param eventType 事件类型
* @param data 事件数据
*/
emit<T>(eventType: string, data: T): void;
/**
* 异步发射事件
* @param eventType 事件类型
* @param data 事件数据
*/
emitAsync<T>(eventType: string, data: T): Promise<void>;
/**
* 监听事件
* @param eventType 事件类型
* @param handler 事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
on<T>(eventType: string, handler: (data: T) => void, config?: IEventListenerConfig): string;
/**
* 监听事件(一次性)
* @param eventType 事件类型
* @param handler 事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
once<T>(eventType: string, handler: (data: T) => void, config?: IEventListenerConfig): string;
/**
* 异步监听事件
* @param eventType 事件类型
* @param handler 异步事件处理器
* @param config 监听器配置
* @returns 监听器ID
*/
onAsync<T>(eventType: string, handler: (data: T) => Promise<void>, config?: IEventListenerConfig): string;
/**
* 移除事件监听器
* @param eventType 事件类型
* @param listenerId 监听器ID
*/
off(eventType: string, listenerId: string): boolean;
/**
* 移除指定事件类型的所有监听器
* @param eventType 事件类型
*/
offAll(eventType: string): void;
/**
* 检查是否有指定事件的监听器
* @param eventType 事件类型
*/
hasListeners(eventType: string): boolean;
/**
* 获取事件统计信息
* @param eventType 事件类型(可选)
*/
getStats(eventType?: string): IEventStats | Map<string, IEventStats>;
/**
* 清空所有监听器
*/
clear(): void;
}
/**
* 事件监听器配置接口
*/
export interface IEventListenerConfig {
/** 是否只执行一次 */
once?: boolean;
/** 优先级(数字越大优先级越高) */
priority?: number;
/** 是否异步执行 */
async?: boolean;
/** 执行上下文 */
context?: any;
}
/**
* 事件统计信息接口
*/
export interface IEventStats {
/** 事件类型 */
eventType: string;
/** 监听器数量 */
listenerCount: number;
/** 触发次数 */
triggerCount: number;
/** 总执行时间(毫秒) */
totalExecutionTime: number;
/** 平均执行时间(毫秒) */
averageExecutionTime: number;
/** 最后触发时间 */
lastTriggerTime: number;
}
/**
* 事件数据基类接口
*/
export interface IEventData {
/** 事件时间戳 */
timestamp: number;
/** 事件来源 */
source?: string;
/** 事件ID */
eventId?: string;
}
/**
* 实体事件数据接口
*/
export interface IEntityEventData extends IEventData {
/** 实体ID */
entityId: number;
/** 实体名称 */
entityName?: string;
/** 实体标签 */
entityTag?: string;
}
/**
* 组件事件数据接口
*/
export interface IComponentEventData extends IEntityEventData {
/** 组件类型名称 */
componentType: string;
/** 组件实例 */
component?: IComponent;
}
/**
* 系统事件数据接口
*/
export interface ISystemEventData extends IEventData {
/** 系统名称 */
systemName: string;
/** 系统类型 */
systemType: string;
}
/**
* 场景事件数据接口
*/
export interface ISceneEventData extends IEventData {
/** 场景名称 */
sceneName: string;
/** 前一个场景名称 */
previousSceneName?: string;
}
/**
* 性能事件数据接口
*/
export interface IPerformanceEventData extends IEventData {
/** 操作类型 */
operation: string;
/** 执行时间(毫秒) */
executionTime: number;
/** 内存使用量 */
memoryUsage?: number;
/** 额外数据 */
metadata?: Record<string, any>;
}

81
src/Utils/Emitter.ts Normal file
View File

@@ -0,0 +1,81 @@
/**
* 用于包装事件的一个小类
*/
export class FuncPack {
/** 函数 */
public func: Function;
/** 上下文 */
public context: any;
constructor(func: Function, context: any) {
this.func = func;
this.context = context;
}
}
/**
* 用于事件管理
*/
export class Emitter<T> {
private _messageTable: Map<T, FuncPack[]>;
constructor() {
this._messageTable = new Map<T, FuncPack[]>();
}
/**
* 开始监听项
* @param eventType 监听类型
* @param handler 监听函数
* @param context 监听上下文
*/
public addObserver(eventType: T, handler: Function, context: any) {
let list = this._messageTable.get(eventType);
if (!list) {
list = [];
this._messageTable.set(eventType, list);
}
if (!this.hasObserver(eventType, handler)) {
list.push(new FuncPack(handler, context));
}
}
/**
* 移除监听项
* @param eventType 事件类型
* @param handler 事件函数
*/
public removeObserver(eventType: T, handler: Function) {
let messageData = this._messageTable.get(eventType);
if (messageData) {
let index = messageData.findIndex(data => data.func == handler);
if (index != -1)
messageData.splice(index, 1);
}
}
/**
* 触发该事件
* @param eventType 事件类型
* @param data 事件数据
*/
public emit(eventType: T, ...data: any[]) {
let list = this._messageTable.get(eventType);
if (list) {
for (let observer of list) {
observer.func.call(observer.context, ...data);
}
}
}
/**
* 判断是否存在该类型的观察者
* @param eventType 事件类型
* @param handler 事件函数
*/
public hasObserver(eventType: T, handler: Function): boolean {
let list = this._messageTable.get(eventType);
return list ? list.some(observer => observer.func === handler) : false;
}
}

View File

@@ -0,0 +1,15 @@
/**
* 数字扩展工具类
* 提供数字转换的实用方法
*/
export class NumberExtension {
/**
* 将值转换为数字
* @param value 要转换的值
* @returns 转换后的数字如果值为undefined则返回0
*/
public static toNumber(value: any): number {
if (value == undefined) return 0;
return Number(value);
}
}

View File

@@ -0,0 +1,14 @@
/**
* 类型工具类
* 提供类型相关的实用方法
*/
export class TypeUtils {
/**
* 获取对象的类型
* @param obj 对象
* @returns 对象的构造函数
*/
public static getType(obj: any) {
return obj.constructor;
}
}

View File

@@ -0,0 +1,3 @@
// 扩展工具类导出
export { TypeUtils } from './TypeUtils';
export { NumberExtension } from './NumberExtension';

View File

@@ -0,0 +1,55 @@
/**
* 全局管理器的基类。所有全局管理器都应该从此类继承。
*/
export class GlobalManager {
/**
* 表示管理器是否启用
*/
public _enabled: boolean = false;
/**
* 获取或设置管理器是否启用
*/
public get enabled() {
return this._enabled;
}
public set enabled(value: boolean) {
this.setEnabled(value);
}
/**
* 设置管理器是否启用
* @param isEnabled 如果为true则启用管理器否则禁用管理器
*/
public setEnabled(isEnabled: boolean) {
if (this._enabled != isEnabled) {
this._enabled = isEnabled;
if (this._enabled) {
// 如果启用了管理器则调用onEnabled方法
this.onEnabled();
} else {
// 如果禁用了管理器则调用onDisabled方法
this.onDisabled();
}
}
}
/**
* 在启用管理器时调用的回调方法
*/
protected onEnabled() {
}
/**
* 在禁用管理器时调用的回调方法
*/
protected onDisabled() {
}
/**
* 更新管理器状态的方法
*/
public update() {
}
}

View File

@@ -0,0 +1,403 @@
/**
* 性能监控数据
*/
export interface PerformanceData {
/** 系统名称 */
name: string;
/** 执行时间(毫秒) */
executionTime: number;
/** 处理的实体数量 */
entityCount: number;
/** 平均每个实体的处理时间 */
averageTimePerEntity: number;
/** 最后更新时间戳 */
lastUpdateTime: number;
/** 内存使用量(字节) */
memoryUsage?: number;
/** CPU使用率百分比 */
cpuUsage?: number;
}
/**
* 性能统计信息
*/
export interface PerformanceStats {
/** 总执行时间 */
totalTime: number;
/** 平均执行时间 */
averageTime: number;
/** 最小执行时间 */
minTime: number;
/** 最大执行时间 */
maxTime: number;
/** 执行次数 */
executionCount: number;
/** 最近的执行时间列表 */
recentTimes: number[];
/** 标准差 */
standardDeviation: number;
/** 95百分位数 */
percentile95: number;
/** 99百分位数 */
percentile99: number;
}
/**
* 性能警告类型
*/
export enum PerformanceWarningType {
HIGH_EXECUTION_TIME = 'high_execution_time',
HIGH_MEMORY_USAGE = 'high_memory_usage',
HIGH_CPU_USAGE = 'high_cpu_usage',
FREQUENT_GC = 'frequent_gc',
LOW_FPS = 'low_fps',
HIGH_ENTITY_COUNT = 'high_entity_count'
}
/**
* 性能警告
*/
export interface PerformanceWarning {
type: PerformanceWarningType;
systemName: string;
message: string;
severity: 'low' | 'medium' | 'high' | 'critical';
timestamp: number;
value: number;
threshold: number;
suggestion?: string;
}
/**
* 性能阈值配置
*/
export interface PerformanceThresholds {
/** 执行时间阈值(毫秒) */
executionTime: {
warning: number;
critical: number;
};
/** 内存使用阈值MB */
memoryUsage: {
warning: number;
critical: number;
};
/** CPU使用率阈值百分比 */
cpuUsage: {
warning: number;
critical: number;
};
/** FPS阈值 */
fps: {
warning: number;
critical: number;
};
/** 实体数量阈值 */
entityCount: {
warning: number;
critical: number;
};
}
/**
* 高性能监控器
* 用于监控ECS系统的性能表现提供详细的分析和优化建议
*/
export class PerformanceMonitor {
private static _instance: PerformanceMonitor;
private _systemData = new Map<string, PerformanceData>();
private _systemStats = new Map<string, PerformanceStats>();
private _warnings: PerformanceWarning[] = [];
private _isEnabled = false;
private _maxRecentSamples = 60; // 保留最近60帧的数据
private _maxWarnings = 100; // 最大警告数量
// 性能阈值配置
private _thresholds: PerformanceThresholds = {
executionTime: { warning: 16.67, critical: 33.33 }, // 60fps和30fps对应的帧时间
memoryUsage: { warning: 100, critical: 200 }, // MB
cpuUsage: { warning: 70, critical: 90 }, // 百分比
fps: { warning: 45, critical: 30 },
entityCount: { warning: 1000, critical: 5000 }
};
// FPS监控
private _fpsHistory: number[] = [];
private _lastFrameTime = 0;
private _frameCount = 0;
private _fpsUpdateInterval = 1000; // 1秒更新一次FPS
private _lastFpsUpdate = 0;
private _currentFps = 60;
// 内存监控
private _memoryCheckInterval = 5000; // 5秒检查一次内存
private _lastMemoryCheck = 0;
private _memoryHistory: number[] = [];
// GC监控
private _gcCount = 0;
private _lastGcCheck = 0;
private _gcCheckInterval = 1000;
/**
* 获取单例实例
*/
public static get instance(): PerformanceMonitor {
if (!PerformanceMonitor._instance) {
PerformanceMonitor._instance = new PerformanceMonitor();
}
return PerformanceMonitor._instance;
}
private constructor() {}
/**
* 启用性能监控
*/
public enable(): void {
this._isEnabled = true;
}
/**
* 禁用性能监控
*/
public disable(): void {
this._isEnabled = false;
}
/**
* 检查是否启用了性能监控
*/
public get isEnabled(): boolean {
return this._isEnabled;
}
/**
* 开始监控系统性能
* @param systemName 系统名称
* @returns 开始时间戳
*/
public startMonitoring(systemName: string): number {
if (!this._isEnabled) {
return 0;
}
return performance.now();
}
/**
* 结束监控并记录性能数据
* @param systemName 系统名称
* @param startTime 开始时间戳
* @param entityCount 处理的实体数量
*/
public endMonitoring(systemName: string, startTime: number, entityCount: number = 0): void {
if (!this._isEnabled || startTime === 0) {
return;
}
const endTime = performance.now();
const executionTime = endTime - startTime;
const averageTimePerEntity = entityCount > 0 ? executionTime / entityCount : 0;
// 更新当前性能数据
const data: PerformanceData = {
name: systemName,
executionTime,
entityCount,
averageTimePerEntity,
lastUpdateTime: endTime
};
this._systemData.set(systemName, data);
// 更新统计信息
this.updateStats(systemName, executionTime);
}
/**
* 更新系统统计信息
* @param systemName 系统名称
* @param executionTime 执行时间
*/
private updateStats(systemName: string, executionTime: number): void {
let stats = this._systemStats.get(systemName);
if (!stats) {
stats = {
totalTime: 0,
averageTime: 0,
minTime: Number.MAX_VALUE,
maxTime: 0,
executionCount: 0,
recentTimes: [],
standardDeviation: 0,
percentile95: 0,
percentile99: 0
};
this._systemStats.set(systemName, stats);
}
// 更新基本统计
stats.totalTime += executionTime;
stats.executionCount++;
stats.averageTime = stats.totalTime / stats.executionCount;
stats.minTime = Math.min(stats.minTime, executionTime);
stats.maxTime = Math.max(stats.maxTime, executionTime);
// 更新最近时间列表
stats.recentTimes.push(executionTime);
if (stats.recentTimes.length > this._maxRecentSamples) {
stats.recentTimes.shift();
}
// 计算高级统计信息
this.calculateAdvancedStats(stats);
}
/**
* 计算高级统计信息
* @param stats 统计信息对象
*/
private calculateAdvancedStats(stats: PerformanceStats): void {
if (stats.recentTimes.length === 0) return;
// 计算标准差
const mean = stats.recentTimes.reduce((a, b) => a + b, 0) / stats.recentTimes.length;
const variance = stats.recentTimes.reduce((acc, time) => acc + Math.pow(time - mean, 2), 0) / stats.recentTimes.length;
stats.standardDeviation = Math.sqrt(variance);
// 计算百分位数
const sortedTimes = [...stats.recentTimes].sort((a, b) => a - b);
const len = sortedTimes.length;
stats.percentile95 = sortedTimes[Math.floor(len * 0.95)] || 0;
stats.percentile99 = sortedTimes[Math.floor(len * 0.99)] || 0;
}
/**
* 获取系统的当前性能数据
* @param systemName 系统名称
* @returns 性能数据或undefined
*/
public getSystemData(systemName: string): PerformanceData | undefined {
return this._systemData.get(systemName);
}
/**
* 获取系统的统计信息
* @param systemName 系统名称
* @returns 统计信息或undefined
*/
public getSystemStats(systemName: string): PerformanceStats | undefined {
return this._systemStats.get(systemName);
}
/**
* 获取所有系统的性能数据
* @returns 所有系统的性能数据
*/
public getAllSystemData(): Map<string, PerformanceData> {
return new Map(this._systemData);
}
/**
* 获取所有系统的统计信息
* @returns 所有系统的统计信息
*/
public getAllSystemStats(): Map<string, PerformanceStats> {
return new Map(this._systemStats);
}
/**
* 获取性能报告
* @returns 格式化的性能报告字符串
*/
public getPerformanceReport(): string {
if (!this._isEnabled) {
return "Performance monitoring is disabled.";
}
const lines: string[] = [];
lines.push("=== ECS Performance Report ===");
lines.push("");
// 按平均执行时间排序
const sortedSystems = Array.from(this._systemStats.entries())
.sort((a, b) => b[1].averageTime - a[1].averageTime);
for (const [systemName, stats] of sortedSystems) {
const data = this._systemData.get(systemName);
lines.push(`System: ${systemName}`);
lines.push(` Current: ${data?.executionTime.toFixed(2)}ms (${data?.entityCount} entities)`);
lines.push(` Average: ${stats.averageTime.toFixed(2)}ms`);
lines.push(` Min/Max: ${stats.minTime.toFixed(2)}ms / ${stats.maxTime.toFixed(2)}ms`);
lines.push(` Total: ${stats.totalTime.toFixed(2)}ms (${stats.executionCount} calls)`);
if (data?.averageTimePerEntity && data.averageTimePerEntity > 0) {
lines.push(` Per Entity: ${data.averageTimePerEntity.toFixed(4)}ms`);
}
lines.push("");
}
// 总体统计
const totalCurrentTime = Array.from(this._systemData.values())
.reduce((sum, data) => sum + data.executionTime, 0);
lines.push(`Total Frame Time: ${totalCurrentTime.toFixed(2)}ms`);
lines.push(`Systems Count: ${this._systemData.size}`);
return lines.join('\n');
}
/**
* 重置所有性能数据
*/
public reset(): void {
this._systemData.clear();
this._systemStats.clear();
}
/**
* 重置指定系统的性能数据
* @param systemName 系统名称
*/
public resetSystem(systemName: string): void {
this._systemData.delete(systemName);
this._systemStats.delete(systemName);
}
/**
* 获取性能警告
* @param thresholdMs 警告阈值(毫秒)
* @returns 超过阈值的系统列表
*/
public getPerformanceWarnings(thresholdMs: number = 16.67): string[] {
const warnings: string[] = [];
for (const [systemName, data] of this._systemData.entries()) {
if (data.executionTime > thresholdMs) {
warnings.push(`${systemName}: ${data.executionTime.toFixed(2)}ms (>${thresholdMs}ms)`);
}
}
return warnings;
}
/**
* 设置最大保留样本数
* @param maxSamples 最大样本数
*/
public setMaxRecentSamples(maxSamples: number): void {
this._maxRecentSamples = maxSamples;
// 裁剪现有数据
for (const stats of this._systemStats.values()) {
while (stats.recentTimes.length > maxSamples) {
stats.recentTimes.shift();
}
}
}
}

565
src/Utils/Pool.ts Normal file
View File

@@ -0,0 +1,565 @@
/**
* 可池化对象接口
*/
export interface IPoolable {
/**
* 重置对象状态,准备重用
*/
reset(): void;
}
/**
* 对象池统计信息
*/
export interface PoolStats {
/** 池中对象数量 */
size: number;
/** 池的最大大小 */
maxSize: number;
/** 总共创建的对象数量 */
totalCreated: number;
/** 总共获取的次数 */
totalObtained: number;
/** 总共释放的次数 */
totalReleased: number;
/** 命中率(从池中获取的比例) */
hitRate: number;
/** 内存使用估算(字节) */
estimatedMemoryUsage: number;
}
/**
* 高性能通用对象池
* 支持任意类型的对象池化,包含详细的统计信息
*/
export class Pool<T extends IPoolable> {
private static _pools = new Map<Function, Pool<any>>();
private _objects: T[] = [];
private _createFn: () => T;
private _maxSize: number;
private _stats: PoolStats;
private _objectSize: number; // 估算的单个对象大小
/**
* 构造函数
* @param createFn 创建对象的函数
* @param maxSize 池的最大大小默认100
* @param estimatedObjectSize 估算的单个对象大小字节默认1024
*/
constructor(createFn: () => T, maxSize: number = 100, estimatedObjectSize: number = 1024) {
this._createFn = createFn;
this._maxSize = maxSize;
this._objectSize = estimatedObjectSize;
this._stats = {
size: 0,
maxSize,
totalCreated: 0,
totalObtained: 0,
totalReleased: 0,
hitRate: 0,
estimatedMemoryUsage: 0
};
}
/**
* 获取指定类型的对象池
* @param type 对象类型
* @param maxSize 池的最大大小
* @param estimatedObjectSize 估算的单个对象大小
* @returns 对象池实例
*/
public static getPool<T extends IPoolable>(
type: new (...args: any[]) => T,
maxSize: number = 100,
estimatedObjectSize: number = 1024
): Pool<T> {
let pool = this._pools.get(type);
if (!pool) {
pool = new Pool<T>(() => new type(), maxSize, estimatedObjectSize);
this._pools.set(type, pool);
}
return pool;
}
/**
* 从池中获取对象
* @returns 对象实例
*/
public obtain(): T {
this._stats.totalObtained++;
if (this._objects.length > 0) {
const obj = this._objects.pop()!;
this._stats.size--;
this._updateHitRate();
this._updateMemoryUsage();
return obj;
}
// 池中没有对象,创建新的
const obj = this._createFn();
this._stats.totalCreated++;
this._updateHitRate();
return obj;
}
/**
* 将对象归还到池中
* @param obj 要归还的对象
*/
public free(obj: T): void {
if (this._objects.length < this._maxSize) {
obj.reset();
this._objects.push(obj);
this._stats.size++;
this._stats.totalReleased++;
this._updateMemoryUsage();
}
// 如果池已满对象会被丢弃由GC回收
}
/**
* 预热池,创建指定数量的对象
* @param count 要创建的对象数量
*/
public warmUp(count: number): void {
const targetSize = Math.min(count, this._maxSize);
while (this._objects.length < targetSize) {
const obj = this._createFn();
this._stats.totalCreated++;
this._objects.push(obj);
this._stats.size++;
}
this._updateMemoryUsage();
}
/**
* 清空池
*/
public clear(): void {
this._objects.length = 0;
this._stats.size = 0;
this._updateMemoryUsage();
}
/**
* 获取池中对象数量
*/
public get size(): number {
return this._objects.length;
}
/**
* 获取池的最大大小
*/
public get maxSize(): number {
return this._maxSize;
}
/**
* 设置池的最大大小
*/
public set maxSize(value: number) {
this._maxSize = value;
this._stats.maxSize = value;
// 如果当前池大小超过新的最大值,则移除多余的对象
while (this._objects.length > this._maxSize) {
this._objects.pop();
this._stats.size--;
}
this._updateMemoryUsage();
}
/**
* 获取池的统计信息
*/
public getStats(): PoolStats {
return { ...this._stats };
}
/**
* 重置统计信息
*/
public resetStats(): void {
this._stats.totalCreated = 0;
this._stats.totalObtained = 0;
this._stats.totalReleased = 0;
this._stats.hitRate = 0;
}
/**
* 更新命中率
*/
private _updateHitRate(): void {
if (this._stats.totalObtained > 0) {
const hits = this._stats.totalObtained - this._stats.totalCreated;
this._stats.hitRate = hits / this._stats.totalObtained;
}
}
/**
* 更新内存使用估算
*/
private _updateMemoryUsage(): void {
this._stats.estimatedMemoryUsage = this._stats.size * this._objectSize;
}
/**
* 静态方法:从指定类型的池中获取对象
* @param type 对象类型
* @returns 对象实例
*/
public static obtain<T extends IPoolable>(type: new (...args: any[]) => T): T {
return this.getPool(type).obtain();
}
/**
* 静态方法:将对象归还到对应类型的池中
* @param type 对象类型
* @param obj 要归还的对象
*/
public static free<T extends IPoolable>(type: new (...args: any[]) => T, obj: T): void {
this.getPool(type).free(obj);
}
/**
* 静态方法:预热指定类型的池
* @param type 对象类型
* @param count 要创建的对象数量
*/
public static warmUp<T extends IPoolable>(type: new (...args: any[]) => T, count: number): void {
this.getPool(type).warmUp(count);
}
/**
* 静态方法:清空指定类型的池
* @param type 对象类型
*/
public static clearPool<T extends IPoolable>(type: new (...args: any[]) => T): void {
const pool = this._pools.get(type);
if (pool) {
pool.clear();
}
}
/**
* 静态方法:清空所有池
*/
public static clearAllPools(): void {
for (const pool of this._pools.values()) {
pool.clear();
}
this._pools.clear();
}
/**
* 静态方法:获取池的统计信息
* @returns 池的统计信息
*/
public static getStats(): { [typeName: string]: PoolStats } {
const stats: { [typeName: string]: PoolStats } = {};
for (const [type, pool] of this._pools.entries()) {
const typeName = (type as any).name || 'Unknown';
stats[typeName] = pool.getStats();
}
return stats;
}
/**
* 静态方法:获取所有池的总内存使用量
* @returns 总内存使用量(字节)
*/
public static getTotalMemoryUsage(): number {
let total = 0;
for (const pool of this._pools.values()) {
total += pool.getStats().estimatedMemoryUsage;
}
return total;
}
/**
* 静态方法:获取性能报告
* @returns 格式化的性能报告
*/
public static getPerformanceReport(): string {
const stats = this.getStats();
const lines: string[] = [];
lines.push('=== Object Pool Performance Report ===');
lines.push(`Total Memory Usage: ${(this.getTotalMemoryUsage() / 1024 / 1024).toFixed(2)} MB`);
lines.push('');
for (const [typeName, stat] of Object.entries(stats)) {
lines.push(`${typeName}:`);
lines.push(` Size: ${stat.size}/${stat.maxSize}`);
lines.push(` Hit Rate: ${(stat.hitRate * 100).toFixed(1)}%`);
lines.push(` Total Created: ${stat.totalCreated}`);
lines.push(` Total Obtained: ${stat.totalObtained}`);
lines.push(` Memory: ${(stat.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
lines.push('');
}
return lines.join('\n');
}
}
/**
* 分层对象池
* 使用多个不同大小的池来优化内存使用
*/
export class TieredObjectPool<T extends IPoolable> {
private pools: Pool<T>[] = [];
private createFn: () => T;
private resetFn: (obj: T) => void;
private tierSizes: number[];
private totalObtained = 0;
private totalReleased = 0;
/**
* 构造函数
* @param createFn 创建对象的函数
* @param resetFn 重置对象的函数
* @param tierSizes 各层级的大小,默认[10, 50, 200]
* @param estimatedObjectSize 估算的单个对象大小
*/
constructor(
createFn: () => T,
resetFn: (obj: T) => void,
tierSizes: number[] = [10, 50, 200],
estimatedObjectSize: number = 1024
) {
this.createFn = createFn;
this.resetFn = resetFn;
this.tierSizes = tierSizes;
// 初始化不同层级的池
for (const size of tierSizes) {
this.pools.push(new Pool(createFn, size, estimatedObjectSize));
}
}
/**
* 获取对象
* @returns 对象实例
*/
public obtain(): T {
this.totalObtained++;
// 从最小的池开始尝试获取
for (const pool of this.pools) {
if (pool.size > 0) {
return pool.obtain();
}
}
// 所有池都空了,创建新对象
return this.createFn();
}
/**
* 释放对象
* @param obj 要释放的对象
*/
public release(obj: T): void {
this.totalReleased++;
this.resetFn(obj);
// 放入第一个有空间的池
for (const pool of this.pools) {
if (pool.size < pool.maxSize) {
pool.free(obj);
return;
}
}
// 所有池都满了,直接丢弃
}
/**
* 预热所有池
* @param totalCount 总预热数量
*/
public warmUp(totalCount: number): void {
let remaining = totalCount;
for (const pool of this.pools) {
const warmUpCount = Math.min(remaining, pool.maxSize);
pool.warmUp(warmUpCount);
remaining -= warmUpCount;
if (remaining <= 0) break;
}
}
/**
* 清空所有池
*/
public clear(): void {
for (const pool of this.pools) {
pool.clear();
}
}
/**
* 获取统计信息
*/
public getStats(): {
totalSize: number;
totalMaxSize: number;
totalMemoryUsage: number;
tierStats: PoolStats[];
hitRate: number;
} {
let totalSize = 0;
let totalMaxSize = 0;
let totalMemoryUsage = 0;
const tierStats: PoolStats[] = [];
for (const pool of this.pools) {
const stats = pool.getStats();
tierStats.push(stats);
totalSize += stats.size;
totalMaxSize += stats.maxSize;
totalMemoryUsage += stats.estimatedMemoryUsage;
}
const hitRate = this.totalObtained > 0 ?
(this.totalObtained - this.getTotalCreated()) / this.totalObtained : 0;
return {
totalSize,
totalMaxSize,
totalMemoryUsage,
tierStats,
hitRate
};
}
/**
* 获取总创建数量
*/
private getTotalCreated(): number {
return this.pools.reduce((total, pool) => total + pool.getStats().totalCreated, 0);
}
}
/**
* 池管理器
* 统一管理所有对象池
*/
export class PoolManager {
private static instance: PoolManager;
private pools = new Map<string, Pool<any> | TieredObjectPool<any>>();
private autoCompactInterval = 60000; // 60秒
private lastCompactTime = 0;
public static getInstance(): PoolManager {
if (!PoolManager.instance) {
PoolManager.instance = new PoolManager();
}
return PoolManager.instance;
}
/**
* 注册池
* @param name 池名称
* @param pool 池实例
*/
public registerPool<T extends IPoolable>(name: string, pool: Pool<T> | TieredObjectPool<T>): void {
this.pools.set(name, pool);
}
/**
* 获取池
* @param name 池名称
* @returns 池实例
*/
public getPool<T extends IPoolable>(name: string): Pool<T> | TieredObjectPool<T> | null {
return this.pools.get(name) || null;
}
/**
* 更新池管理器(应在游戏循环中调用)
*/
public update(): void {
const now = Date.now();
if (now - this.lastCompactTime > this.autoCompactInterval) {
this.compactAllPools();
this.lastCompactTime = now;
}
}
/**
* 压缩所有池(清理碎片)
*/
public compactAllPools(): void {
// 对于标准池,可以考虑清理一些长时间未使用的对象
// 这里简单实现为重置统计信息
for (const pool of this.pools.values()) {
if (pool instanceof Pool) {
pool.resetStats();
}
}
}
/**
* 获取所有池的统计信息
*/
public getAllStats(): Map<string, any> {
const stats = new Map<string, any>();
for (const [name, pool] of this.pools.entries()) {
if (pool instanceof Pool) {
stats.set(name, pool.getStats());
} else if (pool instanceof TieredObjectPool) {
stats.set(name, pool.getStats());
}
}
return stats;
}
/**
* 生成性能报告
*/
public generateReport(): string {
const lines: string[] = [];
lines.push('=== Pool Manager Report ===');
let totalMemory = 0;
for (const [name, pool] of this.pools.entries()) {
lines.push(`\n${name}:`);
if (pool instanceof Pool) {
const stats = pool.getStats();
lines.push(` Type: Standard Pool`);
lines.push(` Size: ${stats.size}/${stats.maxSize}`);
lines.push(` Hit Rate: ${(stats.hitRate * 100).toFixed(1)}%`);
lines.push(` Memory: ${(stats.estimatedMemoryUsage / 1024).toFixed(1)} KB`);
totalMemory += stats.estimatedMemoryUsage;
} else if (pool instanceof TieredObjectPool) {
const stats = pool.getStats();
lines.push(` Type: Tiered Pool`);
lines.push(` Total Size: ${stats.totalSize}/${stats.totalMaxSize}`);
lines.push(` Hit Rate: ${(stats.hitRate * 100).toFixed(1)}%`);
lines.push(` Memory: ${(stats.totalMemoryUsage / 1024).toFixed(1)} KB`);
totalMemory += stats.totalMemoryUsage;
}
}
lines.push(`\nTotal Memory Usage: ${(totalMemory / 1024 / 1024).toFixed(2)} MB`);
return lines.join('\n');
}
}

92
src/Utils/Time.ts Normal file
View File

@@ -0,0 +1,92 @@
/**
* 时间管理工具类
* 提供游戏时间相关的功能,包括帧时间、总时间、时间缩放等
*/
export class Time {
/**
* 上一帧到当前帧的时间间隔(秒)
*/
public static deltaTime: number = 0;
/**
* 未缩放的帧时间间隔(秒)
*/
public static unscaledDeltaTime: number = 0;
/**
* 游戏开始以来的总时间(秒)
*/
public static totalTime: number = 0;
/**
* 未缩放的总时间(秒)
*/
public static unscaledTotalTime: number = 0;
/**
* 时间缩放比例
*/
public static timeScale: number = 1;
/**
* 当前帧数
*/
public static frameCount: number = 0;
/**
* 上一帧的时间戳
*/
private static _lastTime: number = 0;
/**
* 是否为第一次更新
*/
private static _isFirstUpdate: boolean = true;
/**
* 更新时间信息
* @param currentTime 当前时间戳(毫秒)
*/
public static update(currentTime: number = -1): void {
if (currentTime === -1) {
currentTime = Date.now();
}
if (this._isFirstUpdate) {
this._lastTime = currentTime;
this._isFirstUpdate = false;
return;
}
// 计算帧时间间隔(转换为秒)
this.unscaledDeltaTime = (currentTime - this._lastTime) / 1000;
this.deltaTime = this.unscaledDeltaTime * this.timeScale;
// 更新总时间
this.unscaledTotalTime += this.unscaledDeltaTime;
this.totalTime += this.deltaTime;
// 更新帧数
this.frameCount++;
// 记录当前时间
this._lastTime = currentTime;
}
/**
* 场景改变时重置时间
*/
public static sceneChanged(): void {
this._isFirstUpdate = true;
}
/**
* 检查指定的时间间隔是否已经过去
* @param interval 时间间隔(秒)
* @param lastTime 上次检查的时间
* @returns 是否已经过去指定时间
*/
public static checkEvery(interval: number, lastTime: number): boolean {
return this.totalTime - lastTime >= interval;
}
}

View File

@@ -0,0 +1,18 @@
export interface ITimer {
context: any;
/**
* 调用stop以停止此计时器再次运行。这对非重复计时器没有影响。
*/
stop(): void;
/**
* 将计时器的运行时间重置为0
*/
reset(): void;
/**
* 返回投向T的上下文作为方便
*/
getContext<T>(): T;
}

56
src/Utils/Timers/Timer.ts Normal file
View File

@@ -0,0 +1,56 @@
import { ITimer } from './ITimer';
import { Time } from '../Time';
/**
* 私有类隐藏ITimer的实现
*/
export class Timer implements ITimer{
public context: any;
public _timeInSeconds: number = 0;
public _repeats: boolean = false;
public _onTime!: (timer: ITimer) => void;
public _isDone: boolean = false;
public _elapsedTime: number = 0;
public getContext<T>(): T {
return this.context as T;
}
public reset(): void {
this._elapsedTime = 0;
}
public stop(): void {
this._isDone = true;
}
public tick(){
// 如果stop在tick之前被调用那么isDone将为true我们不应该再做任何事情
if (!this._isDone && this._elapsedTime > this._timeInSeconds){
this._elapsedTime -= this._timeInSeconds;
this._onTime(this);
if (!this._isDone && !this._repeats)
this._isDone = true;
}
this._elapsedTime += Time.deltaTime;
return this._isDone;
}
public initialize(timeInsSeconds: number, repeats: boolean, context: any, onTime: (timer: ITimer)=>void){
this._timeInSeconds = timeInsSeconds;
this._repeats = repeats;
this.context = context;
this._onTime = onTime.bind(context);
}
/**
* 空出对象引用以便在js需要时GC可以清理它们的引用
*/
public unload(){
this.context = null;
this._onTime = null as any;
}
}

View File

@@ -0,0 +1,34 @@
import { GlobalManager } from '../GlobalManager';
import { Timer } from './Timer';
import { ITimer } from './ITimer';
/**
* 允许动作的延迟和重复执行
*/
export class TimerManager extends GlobalManager {
public _timers: Timer[] = [];
public override update() {
for (let i = this._timers.length - 1; i >= 0; i --){
if (this._timers[i].tick()){
this._timers[i].unload();
this._timers.splice(i, 1);
}
}
}
/**
* 调度一个一次性或重复的计时器,该计时器将调用已传递的动作
* @param timeInSeconds
* @param repeats
* @param context
* @param onTime
*/
public schedule(timeInSeconds: number, repeats: boolean, context: any, onTime: (timer: ITimer)=>void){
let timer = new Timer();
timer.initialize(timeInSeconds, repeats, context, onTime);
this._timers.push(timer);
return timer;
}
}

8
src/Utils/WasmCore.ts Normal file
View File

@@ -0,0 +1,8 @@
/**
* WASM ECS核心模块
*
* 提供高性能的ECS操作支持WASM和JavaScript双重实现
*/
export * from './Wasm';
export type Query = import('./Wasm').QueryResult;

17
src/Utils/index.ts Normal file
View File

@@ -0,0 +1,17 @@
export * from './Extensions';
export * from './Pool';
export * from './Emitter';
export * from './GlobalManager';
export * from './PerformanceMonitor';
export { Time } from './Time';
export {
WasmEcsCore,
ecsCore,
initializeEcs,
EntityId,
ComponentMask,
QueryResult,
PerformanceStats as WasmPerformanceStats,
WasmLoader,
JavaScriptFallback
} from './Wasm';

22
src/index.ts Normal file
View File

@@ -0,0 +1,22 @@
/**
* ECS Framework - 轻量级实体组件系统框架
* 适用于Laya、Cocos等游戏引擎的小游戏开发
*/
// 核心模块
export { Core } from './Core';
// 核心事件和管理器
export { CoreEvents } from './ECS/CoreEvents';
export { Emitter, FuncPack } from './Utils/Emitter';
export { GlobalManager } from './Utils/GlobalManager';
export { TimerManager } from './Utils/Timers/TimerManager';
export { ITimer } from './Utils/Timers/ITimer';
export { Timer } from './Utils/Timers/Timer';
// ECS核心组件
export * from './ECS';
// 工具类和类型定义
export * from './Utils';
export * from './Types';

1
src/performance.ts Normal file
View File

@@ -0,0 +1 @@