import { Application } from 'pixi.js';
import { Renderer, RendererOptions } from '../render/Renderer';
import { Camera } from '../render/Camera';
import { GameLoop } from './GameLoop';
import { EventBus } from './EventBus';
import { InputManager } from '../input/InputManager';
import { SceneManager } from '../scene/SceneManager';
/**
* Собирает подсистемы движка. Приложение создаёт Engine, добавляет стартовую
* сцену через scenes.replace() и вызывает start().
*/
export interface EngineOptions extends RendererOptions {
/** FPS фиксированного шага. */
fixedFps: number;
}
export class Engine {
readonly renderer: Renderer;
readonly camera: Camera;
readonly events = new EventBus();
readonly scenes = new SceneManager();
input!: InputManager;
private loop: GameLoop;
private started = false;
constructor(options: EngineOptions) {
this.renderer = new Renderer(options);
this.camera = new Camera(options.virtualWidth, options.virtualHeight);
this.loop = new GameLoop(options.fixedFps, {
update: (dt) => this.tick(dt),
render: () => this.render()
});
}
/**
* Инициализация WebGL и ввода. Вызвать до scenes.replace()/start().
* Возвращает готовый Application (для прямого доступа к Pixi при необходимости).
*/
async init(): Promise<Application> {
await this.renderer.setup();
this.input = new InputManager(
this.renderer.app.canvas,
this.renderer.virtualWidth,
this.renderer.virtualHeight
);
return this.renderer.app;
}
async start(): Promise<void> {
if (this.started) return;
this.started = true;
this.loop.start();
}
stop(): void {
this.loop.stop();
this.input?.dispose();
this.events.clear();
}
/** Один фиксированный шаг. */
private tick(dt: number): void {
this.scenes.update(dt);
this.input?.endTick();
}
private render(): void {
this.camera.apply(this.renderer.worldRoot);
this.scenes.render();
this.renderer.render();
}
}