From 8a72443abacedf2f5e711f67eea77690fc006633 Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Sun, 19 Apr 2026 14:18:45 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=88=A0=E9=99=A4=20src/Game=20?= =?UTF-8?q?=E6=97=A7=E6=A0=88=EF=BC=8C=E9=A1=B5=E9=9D=A2=E4=B8=8E=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E5=AF=B9=E9=BD=90=E8=A7=84=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - page_init / welcome2: BaseScene + assetManager、utils 音频与定位 - init: 仅类默认导出;启动时注册 my-sound - SceneManager: 去掉 changeStage;修正 DynamicScene 构造 - enums: 移除 EP、EDirection - vite: 改用 esbuild 压缩并 drop console/debugger - main: 去掉 setTimeout,异步入口 try/catch - 删除整个 src/Game 目录 Made-with: Cursor --- src/Game/Assets.ts | 45 ------- src/Game/Game.ts | 200 ---------------------------- src/Game/Loader.ts | 5 - src/Game/Position.ts | 26 ---- src/Game/Sound.ts | 17 --- src/Game/Stage.ts | 141 -------------------- src/Game/detectOrient.ts | 28 ---- src/Game/index.ts | 157 ---------------------- src/Game/type.ts | 21 --- src/enums/index.ts | 16 +-- src/init.ts | 56 ++------ src/main.ts | 23 ++-- src/scene/SceneManager.ts | 22 +--- src/stages/_global/page_0global.ts | 5 +- src/stages/page_init.ts | 247 +++++++++++++++-------------------- src/stages/welcome/circle.ts | 1 - src/stages/welcome2/page_welcome2.ts | 70 +++++----- vite.config.ts | 11 +- 18 files changed, 181 insertions(+), 910 deletions(-) delete mode 100644 src/Game/Assets.ts delete mode 100644 src/Game/Game.ts delete mode 100644 src/Game/Loader.ts delete mode 100644 src/Game/Position.ts delete mode 100644 src/Game/Sound.ts delete mode 100644 src/Game/Stage.ts delete mode 100644 src/Game/detectOrient.ts delete mode 100644 src/Game/index.ts delete mode 100644 src/Game/type.ts diff --git a/src/Game/Assets.ts b/src/Game/Assets.ts deleted file mode 100644 index c4e7cd9..0000000 --- a/src/Game/Assets.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Assets } from "pixi.js"; - - -export async function initAssets() { - await Assets.init({ manifest: "/manifest.json" }) -} - -const catchMap = new Map() - -export async function loadAsset(name: string, cb?: (progress: number) => void) { - const check = () => { - if (catchMap.has(name)) { - const rr = catchMap.get(name) - rr.count++ - console.log(2211); - catchMap.set(name, rr) - cb?.(1) - return rr.data - } - } - check() - const res = await Assets.loadBundle(name, (progress: number) => { - cb?.(progress) - }) - let r = check() - if (r) return r - catchMap.set(name, { - data: res, - count: 1 - }) - return res -} -/** - * 没有场景加载时方会卸载 - */ -export async function unLoadAsset(name: string) { - if (catchMap.has(name)) { - const rr = catchMap.get(name) - rr.count-- - if (rr.count == 0) { - await Assets.unloadBundle(name) - catchMap.delete(name) - } - } -} \ No newline at end of file diff --git a/src/Game/Game.ts b/src/Game/Game.ts deleted file mode 100644 index adf861d..0000000 --- a/src/Game/Game.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { - autoDetectRenderer, - Container, - Renderer, - Ticker, - Loader, -} from "pixi.js"; -import detectOrient from "./detectOrient"; -import { EDirection } from "@/enums"; -import { initDevtools } from '@pixi/devtools'; - -export default class Game { - constructor() { - // this.init() - } - - private static instance: Game = new Game(); - public static getInstance(): Game { - if (Game.instance == null) { - Game.instance = new Game(); - } - return Game.instance; - } - - private _stage: Container; - private _renderer: Renderer; - private _ticker: Ticker; - private _loader: Loader; - private direction: EDirection = EDirection.Portrait; - - public get renderer(): Renderer { - return this._renderer; - } - public get stage(): Container { - return this._stage; - } - public get ticker(): Ticker { - return this._ticker; - } - public get loader(): Loader { - return this._loader; - } - - public info = { - width: 0, - height: 0, - }; - - private screenInfo() { - const curDirection = detectOrient(); - if (curDirection === EDirection.Portrait) { - // const width = document.documentElement.clientWidth * 1136 / 640 - // const height = document.documentElement.clientWidth - // return { - // widght: height, - // height: width, - // } - const width = document.documentElement.clientWidth - const height = document.documentElement.clientHeight - return { - widght: width, - height: height, - } - } - // const width = document.documentElement.clientHeight * 1136 / 640 - // const height = document.documentElement.clientHeight - // return { - // widght: width, - // height: height, - // } - const width = document.documentElement.clientWidth - const height = document.documentElement.clientHeight - return { - widght: width, - height: height, - } - } - - getInfo() { - return this.info; - } - - setDirection(direction: EDirection) { - this.direction = direction; - this.updateView() - } - - updateView() { - const screenInfo = this.screenInfo() - let screenWidght = screenInfo.widght; - let screenHeight = screenInfo.height; - this.renderer.resize(screenWidght, screenHeight); - let offsetWidth = 0; - let offsetHeight = 0; - const curDirection = detectOrient(); - if (curDirection === EDirection.Landscape) { - offsetWidth = screenHeight; - offsetHeight = screenWidght; - } else { - offsetWidth = screenWidght; - offsetHeight = screenHeight; - } - this.info.width = offsetWidth; - this.info.height = offsetHeight; - const designWidth = 750; - if (this.direction == EDirection.Landscape) { - /// 强制竖屏 - if (curDirection === "landscape") { - [screenWidght, screenHeight] = [screenHeight, screenWidght]; - this.stage.rotation = -Math.PI / 2; - this.stage.y = screenWidght; - } else { - this.stage.rotation = 0; - this.stage.y = 0; - } - let screenScaleRito = screenWidght / designWidth; - this.stage.scale.set(screenScaleRito, screenScaleRito); - // stage.position.set(0, 0); - this.info.width = offsetWidth / screenScaleRito; - this.info.height = offsetHeight / screenScaleRito; - } else { - /// 强制横屏 - if (curDirection === EDirection.Landscape) { - this.stage.rotation = 0; - this.stage.y = 0; - let screenScaleRito = offsetWidth / designWidth; - this.stage.scale.set(screenScaleRito, screenScaleRito); - - this.info.width = offsetHeight / screenScaleRito; - this.info.height = offsetWidth / screenScaleRito; - } else { - this.stage.rotation = -Math.PI / 2; - this.stage.y = offsetHeight; - let screenScaleRito = offsetWidth / designWidth; - this.stage.scale.set(screenScaleRito, screenScaleRito); - - this.info.width = offsetHeight / screenScaleRito; - this.info.height = offsetWidth / screenScaleRito; - } - } - } - - async init() { - const screenInfo = this.screenInfo() - let screenWidght = screenInfo.widght; - let screenHeight = screenInfo.height; - const stage = new Container(); - stage.label = "root"; - let renderer = await autoDetectRenderer({ - autoDensity: true, - width: screenWidght, - height: screenHeight, - antialias: true, - backgroundAlpha: 255, - resolution: 2, - backgroundColor: 0x1d9ce0, - }); - this._stage = stage; - this._renderer = renderer; - // https://www.cnblogs.com/haqiao/p/12515775.html - this.renderer.resize(screenWidght, screenHeight) - document.body.appendChild(renderer.canvas); - - window.addEventListener("resize", () => { - this.updateView(); - }); - - // const ticker = new Ticker(); - const ticker = Ticker.shared; // 单例 - ticker.autoStart = true; - this._ticker = ticker; - - const loader = new Loader(); - this._loader = loader; - - initDevtools({ stage, renderer }); - } - - render() { - this.renderer.render(this.stage); - } - - // init(): Application { - // let screenWidght = document.documentElement.clientWidth; - // let screenHeight = document.documentElement.clientHeight; - // const app = new Application({ - // width: screenWidght, - // height: screenHeight, - // antialias: true, - // backgroundAlpha: 255, - // resolution: 1, - // backgroundColor: 0x1d9ce0, - // }); - // document.body.appendChild(app.view); - // window.addEventListener("resize", function () { - // app.resizeTo = document.body; - // }); - // return app; - // } -} diff --git a/src/Game/Loader.ts b/src/Game/Loader.ts deleted file mode 100644 index e411421..0000000 --- a/src/Game/Loader.ts +++ /dev/null @@ -1,5 +0,0 @@ - - -class Loader { - -} \ No newline at end of file diff --git a/src/Game/Position.ts b/src/Game/Position.ts deleted file mode 100644 index 3738d1e..0000000 --- a/src/Game/Position.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { gameManager } from "@/Game"; -import { PointData } from "pixi.js"; - -class Position { - static instance: Position = null - private constructor() { } - static getInstance() { - if (Position.instance == null) { - Position.instance = new Position - } - return Position.instance - } - - get(xType: "center", yType: "center", offset?: Partial): PointData { - let x, y - if (xType === 'center') { - x = gameManager.getInfo().width / 2 + (offset?.x ?? 0) - } - if (yType === 'center') { - y = gameManager.getInfo().height / 2 + (offset?.y ?? 0) - } - return { x, y } - } -} - -export default Position.getInstance() \ No newline at end of file diff --git a/src/Game/Sound.ts b/src/Game/Sound.ts deleted file mode 100644 index 3ec1951..0000000 --- a/src/Game/Sound.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { sound } from "@pixi/sound"; -// import { LoaderResource } from "pixi.js"; - -sound.add('my-sound', { - url: "/bg.mp3", - singleInstance: true, - autoPlay: false, -}); -// export function addSound(e: LoaderResource) { -// console.log(e); -// sound.add(e.name, { -// source: e.data, -// singleInstance: true, -// autoPlay: false, -// }); -// } -export default sound; diff --git a/src/Game/Stage.ts b/src/Game/Stage.ts deleted file mode 100644 index 8d83e9b..0000000 --- a/src/Game/Stage.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { EP } from "@/enums"; -import { Container } from "pixi.js"; -import Game from "./Game"; - -type TStage = { - type: EP, - name: string, - stage: Container -} - -export default class Stage { - private static instance: Stage = null - private _stages: Record= {} - curStage: TStage = null - - static getInstance(){ - if(Stage.instance == null){ - Stage.instance = new Stage() - } - return Stage.instance - } - gameManager: Game = null - constructor(){ - this.gameManager = Game.getInstance(); - } - - private _wscb: ((stage: TStage, lastStage?:TStage)=>void)[]= [] - watchStageChange(cb: (stage: TStage, lastStage?:TStage)=>void){ - this._wscb.push(cb) - } - async runStageChange(stage: TStage, lastStage?: TStage){ - for (let i = 0; i < this._wscb.length; i++) { - const cb = this._wscb[i]; - await cb(stage, lastStage) - } - } - - initStage(name: string){ - if(!this._stages[name]){ - throw new Error("不存在该舞台: " + name) - } - let curStage = this._stages[name]; - this.curStage = curStage - // this.gameManager.stage.children.forEach(stage=>{ - // stage.destroy() - // this.gameManager.stage.removeChild(stage) - // }) - if(curStage&&curStage.type === EP.Normal){ - this.gameManager.stage.addChild(curStage.stage) - }else if(curStage&&curStage.type === EP.Resident){ - curStage.stage.visible = true - } - this.runStageChange(curStage) - } - - changeStage(name: string, opts?: {isHolderLast?: boolean}){ - if(!this._stages[name]){ - throw new Error("不存在该舞台: " + name) - } - if(!this.curStage){ - console.warn("请先初始化一个场景") - return - } - let lastStage = this.curStage - if(lastStage&&lastStage.type === EP.Normal){ - if(opts?.isHolderLast) { - lastStage.stage.visible = false - // @ts-ignore - lastStage.stage.$isHolderLast = opts.isHolderLast - } else { - lastStage.stage.destroy({ - children: true - }) - this.gameManager.stage.removeChild(lastStage.stage) - } - }else if(lastStage&&lastStage.type === EP.Resident){ - lastStage.stage.visible = false - } - let curStage = this._stages[name]; - if(curStage && typeof curStage === "string" && curStage === "已销毁"){ - this.create(name, EP.Normal) - curStage = this._stages[name] - console.log(curStage); - } - this.curStage = curStage - if(curStage&&curStage.type === EP.Normal){ - // @ts-ignore - if(curStage.stage.$isHolderLast) { - curStage.stage.visible = true - } else { - this.gameManager.stage.addChild(curStage.stage) - } - }else if(curStage&&curStage.type === EP.Resident){ - curStage.stage.visible = true - } - this.runStageChange(curStage, lastStage) - - if(lastStage&&lastStage.type === EP.Normal && !opts?.isHolderLast){ - lastStage.stage.destroy() - this._stages[lastStage.name] = "已销毁" as any - } - } - - getStage(name: string): Container{ - return this._stages[name].stage - } - - checkStageMustExist(name: string, type: EP = EP.Normal){ - if(!this._stages[name]){ - this.create(name, type) - } - } - - getInitStage(name: string, type: EP = EP.Normal): Container{ - if(name === "root"){ - throw new Error("最好换过一个名字") - } - if(this._stages[name]){ - throw new Error("已存在该舞台") - } - if(!this._stages[name]){ - this.create(name, type) - } - return this._stages[name].stage - } - - private create(name: string, type: EP = EP.Normal): Container{ - const stage = new Container(); - stage.label = name - this._stages[name] = { - type: type, - stage: stage, - name: name - } - if(type === EP.Resident){ - stage.visible = true - this.gameManager.stage.addChild(stage) - } - return stage - } -} \ No newline at end of file diff --git a/src/Game/detectOrient.ts b/src/Game/detectOrient.ts deleted file mode 100644 index 48c7ade..0000000 --- a/src/Game/detectOrient.ts +++ /dev/null @@ -1,28 +0,0 @@ -export default function detectOrient() { - let storage = localStorage; // 不一定要使用localStorage,其他存储数据的手段都可以 - // let data = storage.getItem('J-recordOrientX'); - let cw = document.documentElement.clientWidth; - let _Width = 0, - _Height = 0; - // if (!data) { - var sw = document.documentElement.clientWidth//window.screen.width; - var sh = document.documentElement.clientHeight//window.screen.height; - // 2.在某些机型(如华为P9)下出现 screen.width/height 值交换,所以进行大小值比较判断 - _Width = sw < sh ? sw : sh; - _Height = sw >= sh ? sw : sh; - storage.setItem('J-recordOrientX', _Width + ',' + _Height); - // } else { - // var str = data.split(','); - // _Width = +str[0]; - // _Height = +str[1]; - // } - if (cw == _Width) { - // 竖屏 - return 'portrait'; - } - if (cw == _Height) { - // 横屏 - return 'landscape'; - } - return cw+','+_Width+ "||"+cw+','+_Height -} \ No newline at end of file diff --git a/src/Game/index.ts b/src/Game/index.ts deleted file mode 100644 index 683a9cf..0000000 --- a/src/Game/index.ts +++ /dev/null @@ -1,157 +0,0 @@ -import Game from "./Game"; -import Stage from "./Stage"; -import { Container, Ticker } from "pixi.js"; -import { EP } from "@/enums"; - -const gameManager = Game.getInstance(); -const stageManager = Stage.getInstance(); - -const windows: Record = {} -const residentList: IWindow[] = [] - -function defineWindow(name: string, abstractClass: Constructor, type?: EP): any -function defineWindow(abstractClass: Constructor, type?: EP): any -function defineWindow(name: string | Constructor, abstractClass?: Constructor | EP, type?: EP) { - if (typeof name === "string") { - return { name, abstractClass, type } - } - return { abstractClass: name, type: abstractClass } -} - -function initStage() { - const t = import.meta.glob("../stages/**/page_*.ts", { eager: true }); - for (const tKey in t) { - const mod = (t[tKey] as any).default || t[tKey] - const [_, tKeyName] = tKey.match(/page_(.*?)\.ts$/) - const { name, abstractClass, type } = mod as ReturnType - // stageManager.getInitStage(name || tKeyName, type); - const stageClass = new abstractClass() - if ((name || tKeyName) == "init") { - setTimeout(() => { - // 延迟,等其他逻辑完成之后再执行 - stageManager.checkStageMustExist(name || tKeyName, type) - stageManager.initStage(name || tKeyName) - }, 0); - } - stageClass.changeStage = (name: string, opts?: { isHolderLast?: boolean }) => { - stageManager.checkStageMustExist(name, type) - stageManager.changeStage(name, opts) - } - stageClass._type = type - stageClass._initLayout = false - stageClass.$name = name || tKeyName - if (EP.Resident === type) { - stageClass.stage = stageManager.getInitStage(name || tKeyName, type) - residentList.push(stageClass) - } else windows[name || tKeyName] = stageClass - } - // @ts-ignore - residentList.sort((a, b) => a.$name.localeCompare(b.$name, 'en')) - -} - -type Constructor = new (...args: any[]) => T; -export interface IWindow { - _type?: EP; - _initLayout?: Boolean; - _initAssets?: Boolean; - stage: Container; - components: Record; - changeStage?(name: string, opts?: { isHolderLast?: boolean }): void; - loadBundle?(): void; - unLoadBundle?(): void; - layout?(): void; - onLoad?(): void; - onUnLoad?(): void; - lateUpdate?(dt: number, name: string, ticker: Ticker): void; - update?(dt: number, name: string, ticker: Ticker): void; -} - -export function GG(name: string){ - console.log(windows); - console.log(residentList); - const win = windows[name] - return win -} - -function initGame() { - initStage() - - // 场景切换监听 - stageManager.watchStageChange(async (stage, lastStage) => { - if (stage && stage.type === EP.Normal) { - let curWindow = windows[stage.name]; - if (lastStage && lastStage.type === EP.Normal) { - let lastWindow = windows[lastStage.name]; - // @ts-ignore - if (lastWindow._initAssets && lastWindow.stage && !lastWindow.stage.$isHolderLast) { - await lastWindow.unLoadBundle?.() - lastWindow._initAssets = false - } - lastWindow.onUnLoad && await lastWindow.onUnLoad(); - lastWindow.stage = stageManager.getStage(lastStage.name) - } - const isSameStage = curWindow.stage === stage.stage - !isSameStage && (curWindow.stage = stage.stage) - if (!curWindow._initAssets) { - await curWindow.loadBundle?.() - curWindow._initAssets = true - } - if (!curWindow._initLayout || !isSameStage) { - // console.log("不同的舞台"); - await curWindow.layout?.() - curWindow._initLayout = true - } - curWindow.onLoad && await curWindow.onLoad(); - console.log(curWindow); - console.log(windows); - console.log(stageManager); - } - }); - (async () => { - for (let i = 0; i < residentList.length; i++) { - const v = residentList[i]; - if (!v._initAssets) { - await v.loadBundle?.() - v._initAssets = true - } - if (!v._initLayout) { - await v.layout?.() - v._initLayout = true - } - v.onLoad && await v.onLoad() - } - })() - gameManager.ticker.add(async (ticker: Ticker) => { - const dt = ticker.deltaTime - if (!stageManager.curStage) return; - let curWindow = windows[stageManager.curStage.name]; - if (!curWindow.stage) return; - for (let i = 0; i < residentList.length; i++) { - const v = residentList[i]; - v.update && await v.update(dt, v.stage.label, ticker) - } - stageManager.curStage && - curWindow && - curWindow.update && - await curWindow.update(dt, curWindow.stage.label, ticker); - gameManager.render(); - stageManager.curStage && - curWindow && - curWindow.lateUpdate && - await curWindow.lateUpdate(dt, curWindow.stage.label, ticker); - for (let i = 0; i < residentList.length; i++) { - const v = residentList[i]; - v.update && await v.lateUpdate && v.lateUpdate(dt, v.stage.label, ticker) - } - }); -} - -export { - initGame, - gameManager, - stageManager, - defineWindow, - windows, - residentList, -} \ No newline at end of file diff --git a/src/Game/type.ts b/src/Game/type.ts deleted file mode 100644 index f3ea50b..0000000 --- a/src/Game/type.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { EP } from "@/enums"; -import { IWindow } from "."; -import { Container, Ticker } from "pixi.js"; - -export abstract class PWindow implements IWindow { - components: Record; - _type?: EP; - _initLayout?: Boolean; - _initAssets?: Boolean; - _layoutChild?: void | any[]; - stage: Container; - loader?: Loader; - changeStage?(name: string, opts?: {isHolderLast?: boolean}): void; - loadBundle?(): void; - unLoadBundle?(): void; - layout?(): void; - onLoad?(): void; - onUnLoad?(): void; - lateUpdate?(dt: number, name: string, ticker: Ticker): void; - update?(dt: number, name: string, ticker: Ticker): void; -} \ No newline at end of file diff --git a/src/enums/index.ts b/src/enums/index.ts index 13aeaef..6066961 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -1,14 +1,2 @@ -export { Orientation } from './Orientation'; -export { SceneType } from './SceneType'; - -// Legacy exports for backward compatibility -// These are maintained for existing code that uses the old enum names -export enum EDirection { - Landscape = "landscape", - Portrait = "portrait", -} - -export enum EP { - Normal, // 普通场景 - 退出时销毁 - Resident, // 常驻场景 - 只隐藏不销毁 -} +export { Orientation } from "./Orientation"; +export { SceneType } from "./SceneType"; diff --git a/src/init.ts b/src/init.ts index 3d1e7f2..4559ae1 100644 --- a/src/init.ts +++ b/src/init.ts @@ -6,59 +6,36 @@ import { SceneType } from "./enums/SceneType"; import { assetManager } from "./core/AssetManager"; import { logger } from "./core/Logger"; import eventBus from "./core/EventBus"; +import soundManager from "./utils/Sound"; import { Container } from "pixi.js"; const game = Game.getInstance(); const sceneManager = SceneManager.getInstance(); -// 定义构造函数类型 -type Constructor = new (...args: any[]) => T; - -/** defineWindow() 返回的旧版模块形状 */ -type DefineWindowModule = { - abstractClass: Constructor>; - name?: string; - /** 与 SceneType 数值一致(旧 EP) */ - type?: SceneType; -}; +type Constructor = new (...args: unknown[]) => T; export async function initApp(): Promise { await assetManager.init(); await game.init(); - // 自动导入所有场景文件 src/stages/**/page_*.ts + soundManager.add("my-sound", "/bg.mp3", { singleInstance: true, autoPlay: false }); + const sceneModules = import.meta.glob("./stages/**/page_*.ts", { eager: true }); for (const path in sceneModules) { try { const mod = sceneModules[path]; - // 文件名匹配提取场景名称 const match = path.match(/page_(.*?)\.ts$/); if (!match) continue; const fileSceneName = match[1]; const raw = (mod as { default: unknown }).default; - let SceneCtor: Constructor>; - let defineWindowName: string | undefined; - let defineWindowType: SceneType | undefined; - - if (typeof raw === "function") { - SceneCtor = raw as Constructor>; - } else if ( - raw && - typeof raw === "object" && - "abstractClass" in raw && - typeof (raw as DefineWindowModule).abstractClass === "function" - ) { - const dw = raw as DefineWindowModule; - SceneCtor = dw.abstractClass; - defineWindowName = dw.name; - defineWindowType = dw.type; - } else { - logger.warn(`initApp: invalid scene file ${path}, skipping`); + if (typeof raw !== "function") { + logger.warn(`initApp: invalid scene file ${path}, expected default class export, skipping`); continue; } + const SceneCtor = raw as Constructor>; const scene = new SceneCtor(); if (!scene || typeof scene !== "object" || !("stage" in scene)) { @@ -67,16 +44,15 @@ export async function initApp(): Promise { } const legacy = scene as IBaseScene & - Record & { name?: string; type?: SceneType; _type?: SceneType }; - // defineWindow / PWindow 实例缺少只读字段的运行时值,用可变写入兼容旧场景 + Record & { name?: string; type?: SceneType }; const mutable = legacy as { name?: string; type?: SceneType; stage: Container | null }; if (!mutable.name) { - mutable.name = defineWindowName ?? fileSceneName; + mutable.name = fileSceneName; } if (mutable.type === undefined) { - mutable.type = defineWindowType ?? legacy._type ?? SceneType.Normal; + mutable.type = SceneType.Normal; } - if (!mutable.stage || mutable.stage === null) { + if (!mutable.stage) { mutable.stage = new Container(); } @@ -86,26 +62,22 @@ export async function initApp(): Promise { } } - // 启动更新循环 game.ticker.add((ticker) => { const dt = ticker.deltaTime; const current = sceneManager.currentScene; - // 更新常驻场景 for (const scene of sceneManager.getAllScenes()) { if (scene.type === SceneType.Resident && scene.stage.visible) { scene.update?.(dt, scene.name, ticker); } } - // 更新当前场景 if (current) { current.update?.(dt, current.name, ticker); } game.render(); - // lateUpdate for (const scene of sceneManager.getAllScenes()) { if (scene.type === SceneType.Resident && scene.stage.visible && scene.lateUpdate) { scene.lateUpdate(dt, scene.name, ticker); @@ -117,7 +89,6 @@ export async function initApp(): Promise { } }); - // 初始化常驻场景 const residentScenes: BaseScene[] = []; for (const scene of sceneManager.getAllScenes()) { if (scene.type === SceneType.Resident) { @@ -125,7 +96,6 @@ export async function initApp(): Promise { } } - // 初始化常驻场景 for (const scene of residentScenes) { try { if (!scene._assetsLoaded) { @@ -142,7 +112,6 @@ export async function initApp(): Promise { } } - // 初始化入口场景 const entryScene = "init"; if (sceneManager.hasScene(entryScene)) { await sceneManager.initScene(entryScene); @@ -150,7 +119,6 @@ export async function initApp(): Promise { logger.error(`initApp: entry scene "${entryScene}" not found`); } - // 场景变化监听 - 日志 sceneManager.onStageChange((current) => { logger.debug("Scene changed to", current.name); }); @@ -158,4 +126,4 @@ export async function initApp(): Promise { logger.info("App initialized"); } -export { game, sceneManager, eventBus, assetManager, logger }; \ No newline at end of file +export { game, sceneManager, eventBus, assetManager, logger }; diff --git a/src/main.ts b/src/main.ts index 4703535..f11a287 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,16 +1,17 @@ import { Orientation } from "./enums/Orientation"; import { initApp, game, sceneManager } from "./init"; -// 初始化应用 -setTimeout(async () => { - await initApp(); - game.setOrientation(Orientation.Landscape); - // 入口场景会自动由 SceneManager 发现和初始化 - // 如果你的入口场景叫 "init",它会被自动初始化 -}, 200); +void (async () => { + try { + await initApp(); + game.setOrientation(Orientation.Landscape); + } catch (e) { + console.error("initApp failed", e); + } +})(); -// 导出供全局调试 if (import.meta.env.DEV) { - (window as any).game = game; - (window as any).sceneManager = sceneManager; -} \ No newline at end of file + (window as unknown as { game: typeof game; sceneManager: typeof sceneManager }).game = game; + (window as unknown as { game: typeof game; sceneManager: typeof sceneManager }).sceneManager = + sceneManager; +} diff --git a/src/scene/SceneManager.ts b/src/scene/SceneManager.ts index 9441e5d..5a40f6c 100644 --- a/src/scene/SceneManager.ts +++ b/src/scene/SceneManager.ts @@ -78,19 +78,10 @@ class SceneManager { } this.scenes.set(scene.name, scene); - // 注入 changeScene 方法 scene.changeScene = (name: string, options) => { this.changeScene(name, options); }; - // 兼容旧 PWindow:defineWindow 场景里仍使用 changeStage - (scene as IBaseScene & { changeStage?: typeof scene.changeScene }).changeStage = ( - name: string, - options?: { isHolderLast?: boolean } - ) => { - scene.changeScene(name, options); - }; - if (scene.type === SceneType.Resident) { this.game.stage.addChild(scene.stage); logger.debug(`SceneManager: registered resident scene "${scene.name}"`); @@ -238,15 +229,16 @@ class SceneManager { const container = new Container(); container.label = name; - // 动态创建一个简单场景 - // 这个功能主要用于兼容旧的代码风格 + class DynamicScene extends BaseScene { - stage = container; - name = name; - type = type; + stage: Container; + constructor(sceneName: string, sceneType: SceneType, root: Container) { + super(sceneName, sceneType); + this.stage = root; + } } - const scene = new DynamicScene(name); + const scene = new DynamicScene(name, type, container); this.registerScene(scene); return container; } diff --git a/src/stages/_global/page_0global.ts b/src/stages/_global/page_0global.ts index 66dcc18..14fb1ab 100644 --- a/src/stages/_global/page_0global.ts +++ b/src/stages/_global/page_0global.ts @@ -1,12 +1,9 @@ -import Button from "@/components/Button"; import { SceneType } from "@/enums/SceneType"; -import position from "@/utils/Position"; import { BaseScene } from "@/scene/BaseScene"; -import { Assets, Container, Texture } from "pixi.js"; +import { Assets, Container } from "pixi.js"; export default class Global extends BaseScene { stage: Container = new Container(); - btn?: Button; constructor() { super("0global", SceneType.Resident); diff --git a/src/stages/page_init.ts b/src/stages/page_init.ts index ec342bf..a3287e7 100644 --- a/src/stages/page_init.ts +++ b/src/stages/page_init.ts @@ -1,151 +1,118 @@ import { Button } from "@/components/Button"; -import { defineWindow } from "@/Game"; -import Position from "@/Game/Position"; -import Sound from "@/Game/Sound"; -import { Container, Text, NineSliceSprite, AnimatedSprite, Rectangle, Ticker, Texture } from "pixi.js"; -import { PWindow } from "@/Game/type"; -import { loadAsset } from "@/Game/Assets"; -// import { Button } from '@pixi/ui'; +import { assetManager } from "@/core/AssetManager"; +import { BaseScene } from "@/scene/BaseScene"; +import { SceneType } from "@/enums/SceneType"; +import position from "@/utils/Position"; +import soundManager from "@/utils/Sound"; +import { + AnimatedSprite, + Container, + NineSliceSprite, + Rectangle, + Ticker, + Texture, +} from "pixi.js"; -export default defineWindow( - class extends PWindow { - stage: Container = new Container(); - title: Text; // 标题 - startBtn: Button; // 标题 - pixie: AnimatedSprite; // 标题 - assets: any; // 标题 - async loadBundle() { - const btn = new Button({ - text: "加载中", - position: () => Position.get("center", "center"), - onClick: () => { - console.log("Loading button clicked"); - } - }); - btn._comp.zIndex = 111111 - this.stage.addChild(btn.getView()); - this.assets = await loadAsset("load-screen", (progress: number) => { - console.log(progress); - btn.textObj.text = "进度:" + progress - if (progress == 1) { - this.stage.removeChild(btn._comp) - } - }) - } - async unLoadBundle() { - // await unLoadAsset("load-screen"); - // this.assets = undefined - } - layout() { - const allChild = [] - // const bg = new Sprite(this.assets["cbg"]); - // bg.width = gameManager.getInfo().width - // bg.height = gameManager.getInfo().height - // allChild.push(bg) - // this.title = new Text("时间魔法", { - // fontSize: 80, - // fill: "red", - // }); - // this.title.x = gameManager.getInfo().width / 2; - // this.title.y = gameManager.getInfo().height / 2 - 200; - // this.title.position = Position.get("center", "center", { y: -200, x: 0 }) - // this.title.anchor.set(0.5, 0.5); - // this.stage.addChild(this.title); +export default class InitScene extends BaseScene { + stage = new Container(); + startBtn?: Button; + pixie?: AnimatedSprite; + private assets: Record = {} as Record; - const plane9 = new NineSliceSprite({ - texture: this.assets["btn-bg"], - leftWidth: 10, - topHeight: 10, - rightWidth: 10, - bottomHeight: 10, - }); - plane9.width = 100 - plane9.height = 50 - allChild.push(plane9) + constructor() { + super("init", SceneType.Normal); + } - this.startBtn = new Button({ - text: "aaaa", - bg: this.assets["btn-bg"], - pressBg: this.assets["btn-bg-press"], - position: () => Position.get("center", "center", { y: 200, x: 0 }), - onClick: () => { - this.changeStage("welcome", { isHolderLast: false }) - // this.pixie.gotoAndPlay(0); - // this.startBtn.textObj.text = "1111111111111111111111111111111111111" - } - }) - allChild.push(this.startBtn.getView()) - // console.log(button); + async loadBundle(): Promise { + const btn = new Button({ + text: "加载中", + position: () => position.get("center", "center"), + onClick: () => { + console.log("Loading button clicked"); + }, + }); + btn._comp.zIndex = 111111; + this.stage.addChild(btn.getView()); - // this.startBtn = Button({ - // text: "开始游戏", - // bg: this.assets["btn-bg"], - // pressBg: this.assets["btn-bg-press"], - // click: () => { - // // Sound.play("my-sound") - // // new gameManager.tween.Tween(btn.position).interpolation(gameManager.tween.Interpolation.Bezier) - // // .to({ alpha: .2, x: btn.width / 2, y: btn.height / 2 }, 1300) - // // .onComplete(() => { - // (this.startBtn.getChildByLabel("text") as Text).text = "1111111111111111111111111111111111111111111111111" - // // this.changeStage("welcome", { isHolderLast: false }) - // //播放动画精灵 - // // this.pixie.gotoAndPlay(0); - // // }) - // // .start() - // }, - // }); - // this.stage.addChild(this.startBtn); - // console.log(this.stage); + const bundle = await assetManager.loadBundle("load-screen", (progress: number) => { + console.log(progress); + btn.textObj.text = `进度:${progress}`; + if (progress === 1) { + this.stage.removeChild(btn._comp); + } + }); - let base = this.assets["dnf"]; - //第一个纹理 - let texture0 = new Texture({ - source: base as any, - frame: new Rectangle(0, 0, 80, 143) - }) - //第二个纹理 - let texture1 = new Texture({ - source: base as any, - frame: new Rectangle(80, 0, 80, 143) - }) - //第三个纹理 - let texture2 = new Texture({ - source: base as any, - frame: new Rectangle(160, 0, 80, 143) - }) - //第四个纹理 - let texture3 = new Texture({ - source: base as any, - frame: new Rectangle(240, 0, 80, 143) - }) + if (bundle) { + this.assets = bundle as unknown as Record; + } + } - //创建纹理数组 - let textures = [texture0, texture1, texture2, texture3]; + async unLoadBundle(): Promise { + await assetManager.unloadBundle("load-screen"); + } - //创建动画精灵 - this.pixie = new AnimatedSprite(textures, false); - //设置动画精灵的速度 - this.pixie.animationSpeed = 0.1; - this.pixie.loop = true; - this.pixie.y = 200 - allChild.push(this.pixie) - this.stage.addChild(...allChild) - } - onLoad() { - console.log("onLoad init"); - } + async layout(): Promise { + const allChild: Container[] = []; - onUnLoad() { - Sound.stop("my-sound"); - console.log("onUnLoad loading"); - } + const plane9 = new NineSliceSprite({ + texture: this.assets["btn-bg"], + leftWidth: 10, + topHeight: 10, + rightWidth: 10, + bottomHeight: 10, + }); + plane9.width = 100; + plane9.height = 50; + allChild.push(plane9); - update(_dt: number, _name: string, ticker: Ticker) { - if (this.pixie) { - this.pixie.update(ticker) - } - // this.title.rotation -= 0.01 * dt; - } + this.startBtn = new Button({ + text: "aaaa", + bg: this.assets["btn-bg"], + pressBg: this.assets["btn-bg-press"], + position: () => position.get("center", "center", { y: 200, x: 0 }), + onClick: () => { + this.changeScene("welcome", { isHolderLast: false }); + }, + }); + allChild.push(this.startBtn.getView()); - }, -); + const base = this.assets["dnf"]; + const texture0 = new Texture({ + source: base as unknown as Texture["source"], + frame: new Rectangle(0, 0, 80, 143), + }); + const texture1 = new Texture({ + source: base as unknown as Texture["source"], + frame: new Rectangle(80, 0, 80, 143), + }); + const texture2 = new Texture({ + source: base as unknown as Texture["source"], + frame: new Rectangle(160, 0, 80, 143), + }); + const texture3 = new Texture({ + source: base as unknown as Texture["source"], + frame: new Rectangle(240, 0, 80, 143), + }); + + const textures = [texture0, texture1, texture2, texture3]; + this.pixie = new AnimatedSprite(textures, false); + this.pixie.animationSpeed = 0.1; + this.pixie.loop = true; + this.pixie.y = 200; + allChild.push(this.pixie); + this.stage.addChild(...allChild); + } + + onLoad(): void { + console.log("onLoad init"); + } + + onUnLoad(): void { + soundManager.stop("my-sound"); + console.log("onUnLoad loading"); + } + + update(_dt: number, _name: string, ticker: Ticker): void { + this.pixie?.update(ticker); + } +} diff --git a/src/stages/welcome/circle.ts b/src/stages/welcome/circle.ts index 6bd0342..a9b7d63 100644 --- a/src/stages/welcome/circle.ts +++ b/src/stages/welcome/circle.ts @@ -1,5 +1,4 @@ import { Graphics} from "pixi.js" -// import Sound from "@/Game/Sound"; export default new (class Circle{ render(){ diff --git a/src/stages/welcome2/page_welcome2.ts b/src/stages/welcome2/page_welcome2.ts index c15416a..f851b27 100644 --- a/src/stages/welcome2/page_welcome2.ts +++ b/src/stages/welcome2/page_welcome2.ts @@ -1,37 +1,39 @@ -import { defineWindow } from "@/Game"; -import { Container, Graphics } from "pixi.js"; -import { PWindow } from "@/Game/type"; +import { BaseScene } from "@/scene/BaseScene"; +import { SceneType } from "@/enums/SceneType"; +import { Container, FederatedPointerEvent, Graphics } from "pixi.js"; -export default defineWindow("welcome2", class extends PWindow { - stage: Container = new Container(); +export default class Welcome2Scene extends BaseScene { + stage = new Container(); - layout() { - const circle = new Graphics(); - circle.label = "circle"; - circle.circle(0, 0, 32); - circle.fill(0xfb6a8f); - circle.x = 130; - circle.y = 300; - circle.interactive = true; - // circle.buttonMode = true; + constructor() { + super("welcome2", SceneType.Normal); + } - circle.on("touchend", () => { - circle.x += 10; - this.changeStage("welcome") - }) - circle.on("mousedown", () => { - circle.x += 10; - // GG('0global') - // this.changeStage("welcome") - }) - this.stage.addChild(circle) - } - onLoad() { - console.log("onLoad 2"); - } - onUnLoad() { - console.log("onUnLoad 2"); - } - update() { - } -}) \ No newline at end of file + layout(): void { + const circle = new Graphics(); + circle.label = "circle"; + circle.circle(0, 0, 32); + circle.fill(0xfb6a8f); + circle.x = 130; + circle.y = 300; + circle.eventMode = "static"; + circle.cursor = "pointer"; + + const goWelcome = (_e: FederatedPointerEvent) => { + circle.x += 10; + this.changeScene("welcome"); + }; + + circle.on("touchend", goWelcome); + circle.on("mousedown", goWelcome); + this.stage.addChild(circle); + } + + onLoad(): void { + console.log("onLoad 2"); + } + + onUnLoad(): void { + console.log("onUnLoad 2"); + } +} diff --git a/vite.config.ts b/vite.config.ts index 652a3d3..7cc3c54 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -19,13 +19,10 @@ export default defineConfig({ entryFileNames: 'game.js', }, }, - minify: "terser", - terserOptions: { - compress: { - drop_console: true, - drop_debugger: true, - }, - }, + minify: "esbuild", + }, + esbuild: { + drop: ["console", "debugger"], }, plugins: [tsconfigPaths()], });