import * as THREE from "three"; import type { SceneKey } from "../SceneKeys"; export type SceneTransitionFn = (targetKey: SceneKey) => void; /** * 所有场景的基类,提供统一的生命周期接口。 * * 生命周期: * init() → 首次进入时调用,初始化 Three.js 对象 * enter() → 每次切到此场景时调用(含首次) * update(dt, elapsed) → 每帧调用 * exit() → 离开此场景时调用 * dispose() → 销毁场景资源 */ export abstract class BaseScene { readonly key: SceneKey; readonly scene: THREE.Scene; protected _camera: THREE.PerspectiveCamera | null = null; protected _initialized = false; protected _goToScene: SceneTransitionFn = () => {}; constructor(key: SceneKey) { this.key = key; this.scene = new THREE.Scene(); } get camera(): THREE.PerspectiveCamera | null { return this._camera; } /** SceneManager 注入,子类不要覆盖 */ _bind(goToScene: SceneTransitionFn): void { this._goToScene = goToScene; } /** 首次进入时由 SceneManager 调用 */ init(camera: THREE.PerspectiveCamera): void { this._camera = camera; this._initialized = true; this.onInit(); } /** 每次切入场景时调用 */ enter(): void { this.onEnter(); } /** 每帧由 SceneManager 调用,dt 单位秒 */ update(dt: number, elapsed: number): void { this.onUpdate(dt, elapsed); } /** 离开场景时调用 */ exit(): void { this.onExit(); } /** 销毁场景,释放 GPU 资源 */ dispose(): void { this.onDispose(); this.scene.traverse((obj) => { if (obj instanceof THREE.Mesh) { obj.geometry?.dispose(); const materials = Array.isArray(obj.material) ? obj.material : [obj.material]; for (const mat of materials) { if (mat && typeof mat.dispose === "function") { mat.dispose(); } } } }); this.scene.clear(); } protected goToScene(key: SceneKey): void { this._goToScene(key); } // ─── 子类覆盖 ─── protected onInit(): void {} protected onEnter(): void {} protected onUpdate(_dt: number, _elapsed: number): void {} protected onExit(): void {} protected onDispose(): void {} }