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. 49
      src/scene/SceneManager.ts

45
src/core/Game.ts

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

49
src/scene/SceneManager.ts

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

Loading…
Cancel
Save