Browse Source

fix: improve SceneManager type safety and code quality

master
npmrun 3 weeks ago
parent
commit
0ba0bf4d44
  1. 45
      src/core/Game.ts
  2. 51
      src/scene/SceneManager.ts

45
src/core/Game.ts

@ -17,7 +17,7 @@ class Game {
public designWidth: number = 750;
public info = {
public info: { width: number; height: number } = {
width: 0,
height: 0,
};
@ -55,8 +55,8 @@ class Game {
width: screenWidth,
height: screenHeight,
antialias: true,
backgroundAlpha: 255,
resolution: 2,
backgroundAlpha: 1,
resolution: window.devicePixelRatio || 1,
backgroundColor: 0x1d9ce0,
});
@ -100,36 +100,37 @@ class Game {
const currentOrientation = this.detectCurrentOrientation();
let offsetWidth = clientWidth;
let offsetHeight = clientHeight;
if (this.orientation === Orientation.Landscape) {
if (currentOrientation === Orientation.Landscape) {
this._stage.rotation = 0;
this._stage.y = 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.y = clientHeight;
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;
}
const scaleRatio = clientWidth / this.designWidth;
this._stage.scale.set(scaleRatio, scaleRatio);
this.info.width = offsetWidth / scaleRatio;
this.info.height = offsetHeight / scaleRatio;
} else {
if (currentOrientation === Orientation.Landscape) {
if (currentOrientation === Orientation.Portrait) {
this._stage.rotation = 0;
this._stage.y = 0;
const scaleRatio = offsetWidth / this.designWidth;
this._stage.position.set(0, 0);
const scaleRatio = clientWidth / this.designWidth;
this._stage.scale.set(scaleRatio, scaleRatio);
this.info.width = offsetHeight / scaleRatio;
this.info.height = offsetWidth / scaleRatio;
this.info.width = clientWidth / scaleRatio;
this.info.height = clientHeight / scaleRatio;
} else {
this._stage.rotation = -Math.PI / 2;
this._stage.y = offsetHeight;
const scaleRatio = offsetWidth / this.designWidth;
this._stage.position.set(0, clientWidth);
const scaleRatio = clientHeight / this.designWidth;
this._stage.scale.set(scaleRatio, scaleRatio);
this.info.width = offsetHeight / scaleRatio;
this.info.height = offsetWidth / scaleRatio;
this.info.width = clientHeight / scaleRatio;
this.info.height = clientWidth / scaleRatio;
}
}

51
src/scene/SceneManager.ts

@ -6,6 +6,12 @@ import { SceneType } from "@/enums/SceneType";
import { BaseScene } from "./BaseScene";
import type { SceneConfig, IBaseScene } from "./types";
declare global {
interface Container {
_isHolderLast?: boolean;
}
}
type StageChangeCallback = (
current: IBaseScene,
previous: IBaseScene | undefined
@ -56,6 +62,11 @@ class SceneManager {
/** 注册场景 */
registerScene(scene: IBaseScene): void {
if (!scene.name) {
logger.warn("SceneManager: scene name cannot be empty");
return;
}
if (this.scenes.has(scene.name)) {
logger.warn(`SceneManager: scene "${scene.name}" already registered`);
}
@ -76,6 +87,11 @@ class SceneManager {
/** 初始化入口场景 */
initScene(name: string): void {
if (!name) {
logger.warn("SceneManager: scene name cannot be empty");
return;
}
const scene = this.getSceneOrThrow(name);
this._currentScene = scene;
@ -89,6 +105,11 @@ class SceneManager {
/** 切换场景 */
async changeScene(name: string, options?: { isHolderLast?: boolean }): Promise<void> {
if (!name) {
logger.warn("SceneManager: scene name cannot be empty");
return;
}
const previous = this._currentScene;
if (!previous) {
throw new Error(`SceneManager: no current scene, call initScene first`);
@ -100,7 +121,6 @@ class SceneManager {
if (previous.type === SceneType.Normal) {
if (options?.isHolderLast) {
previous.stage.visible = false;
// @ts-ignore 标记保留
previous.stage._isHolderLast = true;
} else {
// 销毁场景
@ -123,11 +143,12 @@ class SceneManager {
// 处理目标场景
if (target.type === SceneType.Normal) {
// @ts-ignore
if (target.stage._isHolderLast) {
target.stage.visible = true;
} else {
this.game.stage.addChild(target.stage);
if (!this.game.stage.children.includes(target.stage)) {
this.game.stage.addChild(target.stage);
}
}
} else if (target.type === SceneType.Resident) {
target.stage.visible = true;
@ -139,7 +160,7 @@ class SceneManager {
target._assetsLoaded = true;
}
if (!target._layoutDone || target.stage !== this.getSceneOrThrow(name).stage) {
if (!target._layoutDone) {
await target.layout?.();
target._layoutDone = true;
}
@ -149,15 +170,25 @@ class SceneManager {
// 触发回调
await this.emitStageChange(target, previous);
logger.debug(`SceneManager: changed from "${previous?.name}" to "${name}"`);
logger.debug(`SceneManager: changed from "${previous.name}" to "${name}"`);
}
/** 获取已注册场景 */
getScene(name: string): IBaseScene | undefined {
if (!name) {
logger.warn("SceneManager: scene name cannot be empty");
return undefined;
}
return this.scenes.get(name);
}
getSceneOrThrow(name: string): IBaseScene {
if (!name) {
logger.warn("SceneManager: scene name cannot be empty");
throw new Error("SceneManager: scene name cannot be empty");
}
const scene = this.scenes.get(name);
if (!scene) {
throw new Error(`SceneManager: scene "${name}" not registered`);
@ -167,6 +198,11 @@ class SceneManager {
/** 确保场景存在,不存在则创建容器 */
ensureSceneExists(name: string, type: SceneType = SceneType.Normal): Container {
if (!name) {
logger.warn("SceneManager: scene name cannot be empty");
return new Container();
}
if (this.scenes.has(name)) {
return this.getSceneOrThrow(name).stage;
}
@ -187,6 +223,11 @@ class SceneManager {
}
hasScene(name: string): boolean {
if (!name) {
logger.warn("SceneManager: scene name cannot be empty");
return false;
}
return this.scenes.has(name);
}
}

Loading…
Cancel
Save