diff --git a/src/stages/page_init.ts b/src/stages/page_init.ts index a3287e7..2a0f253 100644 --- a/src/stages/page_init.ts +++ b/src/stages/page_init.ts @@ -1,5 +1,6 @@ import { Button } from "@/components/Button"; import { assetManager } from "@/core/AssetManager"; +import Game from "@/core/Game"; import { BaseScene } from "@/scene/BaseScene"; import { SceneType } from "@/enums/SceneType"; import position from "@/utils/Position"; @@ -7,44 +8,60 @@ import soundManager from "@/utils/Sound"; import { AnimatedSprite, Container, - NineSliceSprite, Rectangle, - Ticker, + Sprite, + Text, + TextStyle, Texture, + Ticker, } from "pixi.js"; +const Z_BG = 0; +const Z_HERO = 2; +const Z_TEXT = 3; + export default class InitScene extends BaseScene { stage = new Container(); - startBtn?: Button; - pixie?: AnimatedSprite; + private game = Game.getInstance(); private assets: Record = {} as Record; + private bg?: Sprite; + private titleText?: Text; + private subtitleText?: Text; + private pixie?: AnimatedSprite; + private startBtn?: Button; + private loadingBtn?: Button; + + private readonly onResize = (): void => { + this.placeHeroElements(); + }; + constructor() { super("init", SceneType.Normal); } async loadBundle(): Promise { - const btn = new Button({ - text: "加载中", + this.loadingBtn = new Button({ + text: "加载中…", position: () => position.get("center", "center"), - onClick: () => { - console.log("Loading button clicked"); - }, + onClick: () => {}, + fontSize: 22, + padding: { x: 48, y: 28 }, }); - btn._comp.zIndex = 111111; - this.stage.addChild(btn.getView()); + this.loadingBtn._comp.zIndex = 100; + this.stage.addChild(this.loadingBtn.getView()); const bundle = await assetManager.loadBundle("load-screen", (progress: number) => { - console.log(progress); - btn.textObj.text = `进度:${progress}`; - if (progress === 1) { - this.stage.removeChild(btn._comp); - } + this.loadingBtn!.textObj.text = + progress >= 1 ? "即将就绪" : `加载中 ${Math.round(progress * 100)}%`; }); if (bundle) { this.assets = bundle as unknown as Record; } + + this.stage.removeChild(this.loadingBtn._comp); + this.loadingBtn = undefined; } async unLoadBundle(): Promise { @@ -52,67 +69,124 @@ export default class InitScene extends BaseScene { } async layout(): Promise { - const allChild: Container[] = []; - - const plane9 = new NineSliceSprite({ - texture: this.assets["btn-bg"], - leftWidth: 10, - topHeight: 10, - rightWidth: 10, - bottomHeight: 10, + this.stage.sortableChildren = true; + this.stage.eventMode = "passive"; + + const texBg = this.assets["bg"] ?? this.assets["cbg"]; + if (texBg) { + this.bg = Sprite.from(texBg); + this.bg.zIndex = Z_BG; + this.stage.addChild(this.bg); + } + + const titleStyle = new TextStyle({ + fontFamily: "'Microsoft YaHei', 'PingFang SC', system-ui, sans-serif", + fontSize: 44, + fontWeight: "700", + fill: 0xffffff, + align: "center", + dropShadow: { + alpha: 0.55, + angle: Math.PI / 4, + blur: 6, + color: 0x0a1628, + distance: 3, + }, + }); + this.titleText = new Text({ + text: "像素世界", + style: titleStyle, }); - plane9.width = 100; - plane9.height = 50; - allChild.push(plane9); + this.titleText.anchor.set(0.5); + this.titleText.zIndex = Z_TEXT; + this.stage.addChild(this.titleText); + + const subStyle = new TextStyle({ + fontFamily: "'Microsoft YaHei', 'PingFang SC', system-ui, sans-serif", + fontSize: 20, + fill: 0xe8f4ff, + align: "center", + letterSpacing: 1, + }); + this.subtitleText = new Text({ + text: "点击下方按钮,开始你的旅程", + style: subStyle, + }); + this.subtitleText.anchor.set(0.5); + this.subtitleText.alpha = 0.92; + this.subtitleText.zIndex = Z_TEXT; + this.stage.addChild(this.subtitleText); + + const base = this.assets["dnf"]; + if (base) { + const src = base as unknown as Texture["source"]; + const textures = [0, 80, 160, 240].map( + (x) => + new Texture({ + source: src, + frame: new Rectangle(x, 0, 80, 143), + }) + ); + this.pixie = new AnimatedSprite(textures, false); + this.pixie.animationSpeed = 0.12; + this.pixie.loop = true; + this.pixie.scale.set(1.35); + this.pixie.zIndex = Z_HERO; + this.stage.addChild(this.pixie); + } this.startBtn = new Button({ - text: "aaaa", + text: "开始游戏", bg: this.assets["btn-bg"], pressBg: this.assets["btn-bg-press"], - position: () => position.get("center", "center", { y: 200, x: 0 }), + fontSize: 28, + padding: { x: 72, y: 36 }, + position: () => position.get("center", "bottom", { y: -110, 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), - }); + this.startBtn._comp.zIndex = Z_TEXT; + this.stage.addChild(this.startBtn.getView()); - 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.placeHeroElements(); } onLoad(): void { - console.log("onLoad init"); + window.addEventListener("resize", this.onResize); + this.pixie?.gotoAndPlay(0); } onUnLoad(): void { + window.removeEventListener("resize", this.onResize); soundManager.stop("my-sound"); - console.log("onUnLoad loading"); } update(_dt: number, _name: string, ticker: Ticker): void { this.pixie?.update(ticker); } + + private placeHeroElements(): void { + const { width: W, height: H } = this.game.getInfo(); + + if (this.bg) { + const tw = this.bg.texture.width; + const th = this.bg.texture.height; + const scale = Math.max(W / tw, H / th); + this.bg.setSize(tw * scale, th * scale); + this.bg.anchor.set(0.5); + this.bg.position.set(W / 2, H / 2); + } + + if (this.titleText) { + this.titleText.position.set(W / 2, H * 0.12); + } + if (this.subtitleText) { + this.subtitleText.position.set(W / 2, H * 0.2); + } + if (this.pixie) { + this.pixie.anchor.set(0.5); + this.pixie.position.set(W / 2, H * 0.46); + } + } }