You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

150 lines
4.1 KiB

import {
autoDetectRenderer,
Container,
Renderer,
Ticker,
} from "pixi.js";
import { Orientation } from "@/enums/Orientation";
import { initDevtools } from "@pixi/devtools";
import { logger } from "./Logger";
import { tweenManager } from "@/utils/Tween";
class Game {
private static instance: Game;
private _stage: Container;
private _renderer: Renderer;
private _ticker: Ticker;
private orientation: Orientation = Orientation.Portrait;
public designWidth: number = 750;
public info: { width: number; height: number } = {
width: 0,
height: 0,
};
private constructor() {}
static getInstance(): Game {
if (!Game.instance) {
Game.instance = new Game();
}
return Game.instance;
}
public get renderer(): Renderer {
return this._renderer;
}
public get stage(): Container {
return this._stage;
}
public get ticker(): Ticker {
return this._ticker;
}
async init(): Promise<void> {
const screenWidth = document.documentElement.clientWidth;
const screenHeight = document.documentElement.clientHeight;
this._stage = new Container();
this._stage.label = "root";
this._renderer = await autoDetectRenderer({
autoDensity: true,
width: screenWidth,
height: screenHeight,
antialias: true,
backgroundAlpha: 1,
resolution: window.devicePixelRatio || 1,
backgroundColor: 0x1d9ce0,
});
this.renderer.resize(screenWidth, screenHeight);
document.body.appendChild(this.renderer.canvas);
window.addEventListener("resize", () => {
this.updateView();
});
this._ticker = Ticker.shared;
this._ticker.autoStart = true;
this._ticker.add(() => {
tweenManager.update();
});
if (import.meta.env.DEV) {
initDevtools({ stage: this._stage, renderer: this._renderer });
}
this.updateView();
logger.info("Game initialized", { screenWidth, screenHeight });
}
getInfo(): { width: number; height: number } {
return { ...this.info };
}
setOrientation(orientation: Orientation): void {
this.orientation = orientation;
this.updateView();
}
private detectCurrentOrientation(): Orientation {
const isLandscape = window.innerWidth > window.innerHeight;
return isLandscape ? Orientation.Landscape : Orientation.Portrait;
}
updateView(): void {
const clientWidth = document.documentElement.clientWidth;
const clientHeight = document.documentElement.clientHeight;
this.renderer.resize(clientWidth, clientHeight);
const currentOrientation = this.detectCurrentOrientation();
if (this.orientation === Orientation.Landscape) {
if (currentOrientation === Orientation.Landscape) {
this._stage.rotation = 0;
this._stage.position.set(0, 0);
const scaleRatio = clientWidth / this.designWidth;
this._stage.scale.set(scaleRatio, scaleRatio);
this.info.width = clientWidth / scaleRatio;
this.info.height = clientHeight / scaleRatio;
} else {
this._stage.rotation = Math.PI / 2;
this._stage.position.set(0, 0);
const scaleRatio = clientHeight / this.designWidth;
this._stage.scale.set(scaleRatio, scaleRatio);
this.info.width = clientHeight / scaleRatio;
this.info.height = clientWidth / scaleRatio;
}
} else {
if (currentOrientation === Orientation.Portrait) {
this._stage.rotation = 0;
this._stage.position.set(0, 0);
const scaleRatio = clientWidth / this.designWidth;
this._stage.scale.set(scaleRatio, scaleRatio);
this.info.width = clientWidth / scaleRatio;
this.info.height = clientHeight / scaleRatio;
} else {
this._stage.rotation = -Math.PI / 2;
this._stage.position.set(0, clientWidth);
const scaleRatio = clientHeight / this.designWidth;
this._stage.scale.set(scaleRatio, scaleRatio);
this.info.width = clientHeight / scaleRatio;
this.info.height = clientWidth / scaleRatio;
}
}
this.render();
}
render(): void {
this.renderer.render(this.stage);
}
}
export default Game;