Browse Source

refactor: 删除 src/Game 旧栈,页面与构建对齐规格

- 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
master
npmrun 2 months ago
parent
commit
8a72443aba
  1. 45
      src/Game/Assets.ts
  2. 200
      src/Game/Game.ts
  3. 5
      src/Game/Loader.ts
  4. 26
      src/Game/Position.ts
  5. 17
      src/Game/Sound.ts
  6. 141
      src/Game/Stage.ts
  7. 28
      src/Game/detectOrient.ts
  8. 157
      src/Game/index.ts
  9. 21
      src/Game/type.ts
  10. 16
      src/enums/index.ts
  11. 54
      src/init.ts
  12. 17
      src/main.ts
  13. 22
      src/scene/SceneManager.ts
  14. 5
      src/stages/_global/page_0global.ts
  15. 191
      src/stages/page_init.ts
  16. 1
      src/stages/welcome/circle.ts
  17. 46
      src/stages/welcome2/page_welcome2.ts
  18. 9
      vite.config.ts

45
src/Game/Assets.ts

@ -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)
}
}
}

200
src/Game/Game.ts

@ -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;
// }
}

5
src/Game/Loader.ts

@ -1,5 +0,0 @@
class Loader {
}

26
src/Game/Position.ts

@ -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>): 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()

17
src/Game/Sound.ts

@ -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;

141
src/Game/Stage.ts

@ -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<string,TStage>= {}
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
}
}

28
src/Game/detectOrient.ts

@ -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
}

157
src/Game/index.ts

@ -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<string, IWindow> = {}
const residentList: IWindow[] = []
function defineWindow(name: string, abstractClass: Constructor<IWindow>, type?: EP): any
function defineWindow(abstractClass: Constructor<IWindow>, type?: EP): any
function defineWindow(name: string | Constructor<IWindow>, abstractClass?: Constructor<IWindow> | 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<typeof defineWindow>
// 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<T> = new (...args: any[]) => T;
export interface IWindow {
_type?: EP;
_initLayout?: Boolean;
_initAssets?: Boolean;
stage: Container;
components: Record<string, any>;
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,
}

21
src/Game/type.ts

@ -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<string, any>;
_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;
}

16
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";

54
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<T> = new (...args: any[]) => T;
/** defineWindow() 返回的旧版模块形状 */
type DefineWindowModule = {
abstractClass: Constructor<IBaseScene & Record<string, unknown>>;
name?: string;
/** 与 SceneType 数值一致(旧 EP) */
type?: SceneType;
};
type Constructor<T> = new (...args: unknown[]) => T;
export async function initApp(): Promise<void> {
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<IBaseScene & Record<string, unknown>>;
let defineWindowName: string | undefined;
let defineWindowType: SceneType | undefined;
if (typeof raw === "function") {
SceneCtor = raw as Constructor<IBaseScene & Record<string, unknown>>;
} 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<IBaseScene & Record<string, unknown>>;
const scene = new SceneCtor();
if (!scene || typeof scene !== "object" || !("stage" in scene)) {
@ -67,16 +44,15 @@ export async function initApp(): Promise<void> {
}
const legacy = scene as IBaseScene &
Record<string, unknown> & { name?: string; type?: SceneType; _type?: SceneType };
// defineWindow / PWindow 实例缺少只读字段的运行时值,用可变写入兼容旧场景
Record<string, unknown> & { 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<void> {
}
}
// 启动更新循环
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<void> {
}
});
// 初始化常驻场景
const residentScenes: BaseScene[] = [];
for (const scene of sceneManager.getAllScenes()) {
if (scene.type === SceneType.Resident) {
@ -125,7 +96,6 @@ export async function initApp(): Promise<void> {
}
}
// 初始化常驻场景
for (const scene of residentScenes) {
try {
if (!scene._assetsLoaded) {
@ -142,7 +112,6 @@ export async function initApp(): Promise<void> {
}
}
// 初始化入口场景
const entryScene = "init";
if (sceneManager.hasScene(entryScene)) {
await sceneManager.initScene(entryScene);
@ -150,7 +119,6 @@ export async function initApp(): Promise<void> {
logger.error(`initApp: entry scene "${entryScene}" not found`);
}
// 场景变化监听 - 日志
sceneManager.onStageChange((current) => {
logger.debug("Scene changed to", current.name);
});

17
src/main.ts

@ -1,16 +1,17 @@
import { Orientation } from "./enums/Orientation";
import { initApp, game, sceneManager } from "./init";
// 初始化应用
setTimeout(async () => {
void (async () => {
try {
await initApp();
game.setOrientation(Orientation.Landscape);
// 入口场景会自动由 SceneManager 发现和初始化
// 如果你的入口场景叫 "init",它会被自动初始化
}, 200);
} catch (e) {
console.error("initApp failed", e);
}
})();
// 导出供全局调试
if (import.meta.env.DEV) {
(window as any).game = game;
(window as any).sceneManager = sceneManager;
(window as unknown as { game: typeof game; sceneManager: typeof sceneManager }).game = game;
(window as unknown as { game: typeof game; sceneManager: typeof sceneManager }).sceneManager =
sceneManager;
}

22
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;
}

5
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);

191
src/stages/page_init.ts

@ -1,56 +1,58 @@
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() {
export default class InitScene extends BaseScene {
stage = new Container();
startBtn?: Button;
pixie?: AnimatedSprite;
private assets: Record<string, Texture> = {} as Record<string, Texture>;
constructor() {
super("init", SceneType.Normal);
}
async loadBundle(): Promise<void> {
const btn = new Button({
text: "加载中",
position: () => Position.get("center", "center"),
position: () => position.get("center", "center"),
onClick: () => {
console.log("Loading button clicked");
}
},
});
btn._comp.zIndex = 111111
btn._comp.zIndex = 111111;
this.stage.addChild(btn.getView());
this.assets = await loadAsset("load-screen", (progress: number) => {
const bundle = await assetManager.loadBundle("load-screen", (progress: number) => {
console.log(progress);
btn.textObj.text = "进度:" + progress
if (progress == 1) {
this.stage.removeChild(btn._comp)
btn.textObj.text = `进度:${progress}`;
if (progress === 1) {
this.stage.removeChild(btn._comp);
}
});
if (bundle) {
this.assets = bundle as unknown as Record<string, Texture>;
}
})
}
async unLoadBundle() {
// await unLoadAsset("load-screen");
// this.assets = undefined
async unLoadBundle(): Promise<void> {
await assetManager.unloadBundle("load-screen");
}
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);
async layout(): Promise<void> {
const allChild: Container[] = [];
const plane9 = new NineSliceSprite({
texture: this.assets["btn-bg"],
@ -59,93 +61,58 @@ export default defineWindow(
rightWidth: 10,
bottomHeight: 10,
});
plane9.width = 100
plane9.height = 50
allChild.push(plane9)
plane9.width = 100;
plane9.height = 50;
allChild.push(plane9);
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 }),
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);
// 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);
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)
})
this.changeScene("welcome", { isHolderLast: false });
},
});
allChild.push(this.startBtn.getView());
//创建纹理数组
let textures = [texture0, texture1, texture2, texture3];
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)
this.pixie.y = 200;
allChild.push(this.pixie);
this.stage.addChild(...allChild);
}
onLoad() {
onLoad(): void {
console.log("onLoad init");
}
onUnLoad() {
Sound.stop("my-sound");
onUnLoad(): void {
soundManager.stop("my-sound");
console.log("onUnLoad loading");
}
update(_dt: number, _name: string, ticker: Ticker) {
if (this.pixie) {
this.pixie.update(ticker)
update(_dt: number, _name: string, ticker: Ticker): void {
this.pixie?.update(ticker);
}
// this.title.rotation -= 0.01 * dt;
}
},
);
}

1
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(){

46
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() {
constructor() {
super("welcome2", SceneType.Normal);
}
layout(): void {
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;
circle.eventMode = "static";
circle.cursor = "pointer";
circle.on("touchend", () => {
const goWelcome = (_e: FederatedPointerEvent) => {
circle.x += 10;
this.changeStage("welcome")
})
circle.on("mousedown", () => {
circle.x += 10;
// GG('0global')
// this.changeStage("welcome")
})
this.stage.addChild(circle)
this.changeScene("welcome");
};
circle.on("touchend", goWelcome);
circle.on("mousedown", goWelcome);
this.stage.addChild(circle);
}
onLoad() {
onLoad(): void {
console.log("onLoad 2");
}
onUnLoad() {
onUnLoad(): void {
console.log("onUnLoad 2");
}
update() {
}
})
}

9
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()],
});

Loading…
Cancel
Save