Files
esengine/packages/core/src/ECS/SceneManager.ts

274 lines
7.1 KiB
TypeScript
Raw Normal View History

import { IScene } from './IScene';
import { ECSFluentAPI, createECSAPI } from './Core/FluentAPI';
import { Time } from '../Utils/Time';
import { createLogger } from '../Utils/Logger';
import type { IService } from '../Core/ServiceContainer';
2025-10-11 15:14:37 +08:00
import type { IUpdatable } from '../Types/IUpdatable';
import { World } from './World';
2025-10-11 15:14:37 +08:00
import { WorldManager } from './WorldManager';
import { Injectable, Inject, Updatable } from '../Core/DI';
/**
*
*
*
* -
* -
* - World隔离的项目
*
*
* -
* - API
* -
* - ECS API
2025-10-11 15:14:37 +08:00
* - WorldManager的默认World
*
* @example
* ```typescript
* // 初始化Core
* Core.create({ debug: true });
*
* // 设置场景
* class GameScene extends Scene {
* initialize() {
* const player = this.createEntity('Player');
* player.addComponent(new Transform(100, 100));
* }
* }
*
2025-10-11 15:14:37 +08:00
* Core.setScene(new GameScene());
*
* // 游戏循环
* function gameLoop(deltaTime: number) {
2025-10-11 15:14:37 +08:00
* Core.update(deltaTime); // 自动更新所有服务(包括SceneManager)
* }
*
* // 延迟切换场景(下一帧生效)
2025-10-11 15:14:37 +08:00
* Core.loadScene(new MenuScene());
* ```
*/
2025-10-11 15:14:37 +08:00
@Injectable()
@Updatable(10)
export class SceneManager implements IService, IUpdatable {
/**
2025-10-11 15:14:37 +08:00
* World(WorldManager获取)
*/
private _defaultWorld: World;
/**
*
*/
private _nextScene: IScene | null = null;
/**
* ECS流式API
*/
private _ecsAPI: ECSFluentAPI | null = null;
/**
*
*/
private _logger = createLogger('SceneManager');
2025-10-11 10:36:59 +08:00
/**
*
*/
private _onSceneChangedCallback?: () => void;
/**
* ID
*/
private static readonly DEFAULT_SCENE_ID = '__main__';
2025-10-11 15:14:37 +08:00
/**
*
*
* WorldManager通过依赖注入自动传入
*
* @param worldManager WorldManager实例,World
*/
constructor(
@Inject(WorldManager) worldManager: WorldManager
) {
// 使用WorldManager管理的默认World
this._defaultWorld = worldManager.getDefaultWorld();
}
2025-10-11 10:36:59 +08:00
/**
*
*
* @param callback
* @internal
*/
public setSceneChangedCallback(callback: () => void): void {
this._onSceneChangedCallback = callback;
}
/**
*
*
*
*
* @param scene -
* @returns 便
*
* @example
* ```typescript
* const gameScene = sceneManager.setScene(new GameScene());
* console.log(gameScene.name); // 可以立即使用返回的场景
* ```
*/
public setScene<T extends IScene>(scene: T): T {
// 移除旧场景
this._defaultWorld.removeAllScenes();
// 通过 World 创建新场景
this._defaultWorld.createScene(SceneManager.DEFAULT_SCENE_ID, scene);
this._defaultWorld.setSceneActive(SceneManager.DEFAULT_SCENE_ID, true);
// 重建ECS API
if (scene.querySystem && scene.eventSystem) {
this._ecsAPI = createECSAPI(scene, scene.querySystem, scene.eventSystem);
} else {
this._ecsAPI = null;
}
// 触发场景切换回调
Time.sceneChanged();
2025-10-11 10:36:59 +08:00
// 通知调试管理器(通过回调)
if (this._onSceneChangedCallback) {
this._onSceneChangedCallback();
}
this._logger.info(`Scene changed to: ${scene.name}`);
return scene;
}
/**
*
*
* update()
*
*
* @param scene -
*
* @example
* ```typescript
* // 在某个System中触发场景切换
* class GameOverSystem extends EntitySystem {
* process(entities: readonly Entity[]) {
* if (playerHealth <= 0) {
* sceneManager.loadScene(new GameOverScene());
* // 当前帧继续执行,场景将在下一帧切换
* }
* }
* }
* ```
*/
public loadScene<T extends IScene>(scene: T): void {
this._nextScene = scene;
this._logger.info(`Scheduled scene load: ${scene.name}`);
}
/**
*
*
* @returns null
*/
public get currentScene(): IScene | null {
return this._defaultWorld.getScene(SceneManager.DEFAULT_SCENE_ID);
}
/**
* ECS流式API
*
* 便
*
* @returns ECS API实例null
*
* @example
* ```typescript
* const api = sceneManager.api;
* if (api) {
* // 查询所有敌人
* const enemies = api.find(Enemy, Transform);
*
* // 发射事件
* api.emit('game:start', { level: 1 });
* }
* ```
*/
public get api(): ECSFluentAPI | null {
return this._ecsAPI;
}
/**
*
*
*
*
*
* @example
* ```typescript
* function gameLoop(deltaTime: number) {
* Core.update(deltaTime);
* sceneManager.update(); // 每帧调用
* }
* ```
*/
public update(): void {
// 处理延迟场景切换
if (this._nextScene) {
this.setScene(this._nextScene);
this._nextScene = null;
}
// 通过 World 统一更新
this._defaultWorld.updateGlobalSystems();
this._defaultWorld.updateScenes();
}
/**
*
*
*
*
*/
public destroy(): void {
this._logger.info('SceneManager destroying');
this._defaultWorld.destroy();
this._nextScene = null;
this._ecsAPI = null;
this._logger.info('SceneManager destroyed');
}
/**
*
*
* @returns truefalse
*/
public get hasScene(): boolean {
return this._defaultWorld.getScene(SceneManager.DEFAULT_SCENE_ID) !== null;
}
/**
*
*
* @returns truefalse
*/
public get hasPendingScene(): boolean {
return this._nextScene !== null;
}
/**
* IService接口
*/
public dispose(): void {
this.destroy();
}
}