Newer
Older
rpg / packages / engine / src / scene / SceneManager.ts
/**
 * Сцена — экран игры (меню, локация, бой). Менеджер держит стек,
 * но в 2D-RPG чаще всего достаточно push/pop/replace.
 */
export interface Scene {
    /** Вызывается один раз при входе. */
    enter(): void | Promise<void>;
    exit(): void | Promise<void>;
    /** dt в секундах, фиксированный шаг. */
    update(dt: number): void;
    render(): void;
}

export class SceneManager {
    private stack: Scene[] = [];

    async push(scene: Scene): Promise<void> {
        this.stack.push(scene);
        await scene.enter();
    }

    async pop(): Promise<void> {
        const scene = this.stack.pop();
        if (scene) {
            await scene.exit();
        }
    }

    /** Заменить верхнюю сцену (например меню -> локация). */
    async replace(scene: Scene): Promise<void> {
        await this.pop();
        await this.push(scene);
    }

    get current(): Scene | undefined {
        return this.stack[this.stack.length - 1];
    }

    update(dt: number): void {
        this.current?.update(dt);
    }

    render(): void {
        for (const scene of this.stack) {
            scene.render();
        }
    }
}