144 lines
4.5 KiB
JavaScript
144 lines
4.5 KiB
JavaScript
import * as Phaser from 'phaser';
|
|
import { GAME_HEIGHT, GAME_WIDTH, COLORS } from '../config.js';
|
|
import { auth } from '../services/auth.js';
|
|
import { Button } from '../ui/Button.js';
|
|
import { Plaque } from '../ui/Plaque.js';
|
|
import { addFullscreenButton } from '../ui/FullscreenButton.js';
|
|
import { playMenuMusic } from '../ui/MenuMusic.js';
|
|
|
|
export default class LandingScene extends Phaser.Scene {
|
|
constructor() { super('Landing'); }
|
|
|
|
create() {
|
|
playMenuMusic();
|
|
const cx = GAME_WIDTH / 2;
|
|
|
|
this.add.image(cx, GAME_HEIGHT / 2, 'bg-menu').setDisplaySize(GAME_WIDTH, GAME_HEIGHT);
|
|
|
|
const logo = this.add.image(cx, 290, 'main-title').setOrigin(0.5, 0.5).setAlpha(0);
|
|
logo.postFX.addShadow(3, 6, 0.005, 2, 0x000000, 10, 0.75);
|
|
this._logo = logo;
|
|
this._transitioning = false;
|
|
|
|
this.tweens.add({
|
|
targets: logo,
|
|
alpha: 1,
|
|
y: 260,
|
|
duration: 900,
|
|
ease: 'Power2',
|
|
onComplete: () => {
|
|
this.tweens.add({
|
|
targets: logo,
|
|
scaleX: 1.025,
|
|
scaleY: 1.025,
|
|
duration: 2200,
|
|
yoyo: true,
|
|
repeat: -1,
|
|
ease: 'Sine.easeInOut',
|
|
});
|
|
},
|
|
});
|
|
|
|
this.renderButtons();
|
|
addFullscreenButton(this);
|
|
|
|
if (this._authUnsub) this._authUnsub();
|
|
this._authUnsub = auth.subscribe(() => {
|
|
if (!this.scene.isActive('Landing')) return;
|
|
this.children.removeAll();
|
|
this.create();
|
|
});
|
|
this.events.once(Phaser.Scenes.Events.SHUTDOWN, () => {
|
|
if (this._authUnsub) { this._authUnsub(); this._authUnsub = null; }
|
|
});
|
|
}
|
|
|
|
renderButtons() {
|
|
const cx = GAME_WIDTH / 2;
|
|
const user = auth.user;
|
|
this._avatar = null;
|
|
|
|
const avatarR = 28;
|
|
const avatarGap = 18;
|
|
const pad = { x: 32, y: 14 };
|
|
const y = 630;
|
|
const name = user?.displayName ?? user?.username ?? 'Player';
|
|
|
|
const welcomeText = this.add.text(0, y, `Welcome, ${name}`, {
|
|
fontFamily: 'Righteous',
|
|
fontSize: '36px',
|
|
color: COLORS.accentHex,
|
|
}).setOrigin(0.5).setDepth(1);
|
|
this._welcomeText = welcomeText;
|
|
welcomeText.setShadow(0, 3, 'rgba(0,0,0,0.8)', 5);
|
|
|
|
const hasAvatar = !!user?.avatarPath;
|
|
const totalW = hasAvatar ? avatarR * 2 + avatarGap + welcomeText.width : welcomeText.width;
|
|
const groupLeft = cx - totalW / 2;
|
|
|
|
welcomeText.setX(hasAvatar ? groupLeft + avatarR * 2 + avatarGap + welcomeText.width / 2 : cx);
|
|
|
|
this._welcomeBg = new Plaque(this, totalW + pad.x * 2, welcomeText.height + pad.y * 2, { radius: 16 })
|
|
.setPosition(cx, y);
|
|
|
|
if (hasAvatar) {
|
|
const avatarCx = groupLeft + avatarR;
|
|
const key = `landing-avatar-${user.id}`;
|
|
(async () => {
|
|
try {
|
|
if (!this.textures.exists(key)) {
|
|
await new Promise((resolve) => {
|
|
this.load.image(key, user.avatarPath);
|
|
this.load.once('complete', resolve);
|
|
this.load.start();
|
|
});
|
|
}
|
|
if (this._transitioning || !this.scene.isActive('Landing')) return;
|
|
const maskG = this.make.graphics({ x: 0, y: 0, add: false });
|
|
maskG.fillStyle(0xffffff);
|
|
maskG.fillCircle(avatarCx, y, avatarR);
|
|
this._avatar = this.add.image(avatarCx, y, key)
|
|
.setDisplaySize(avatarR * 2, avatarR * 2)
|
|
.setMask(maskG.createGeometryMask())
|
|
.setDepth(1);
|
|
} catch { /* no avatar shown */ }
|
|
})();
|
|
}
|
|
|
|
this.playBtn = new Button(this, cx, 810, 'Play', () => this.goToGameMenu(), { width: 480 });
|
|
this.profileBtn = new Button(this, cx, 890, 'Profile', () => this.scene.start('Profile'), { width: 480 });
|
|
}
|
|
|
|
goToGameMenu() {
|
|
if (this._transitioning) return;
|
|
this._transitioning = true;
|
|
|
|
this.playBtn.disableInteractive();
|
|
this.profileBtn.disableInteractive();
|
|
|
|
// Fade the landing buttons out while the logo zooms past the camera.
|
|
const fadeOut = [this.playBtn, this.profileBtn, this._welcomeText, this._welcomeBg].filter(Boolean);
|
|
if (this._avatar) fadeOut.push(this._avatar);
|
|
this.tweens.add({
|
|
targets: fadeOut,
|
|
alpha: 0,
|
|
duration: 350,
|
|
ease: 'Power2.easeOut',
|
|
});
|
|
|
|
if (!this._logo) { this.scene.start('GameMenu'); return; }
|
|
this.tweens.killTweensOf(this._logo);
|
|
this.tweens.add({
|
|
targets: this._logo,
|
|
x: GAME_WIDTH / 2,
|
|
y: GAME_HEIGHT / 2,
|
|
scaleX: 2.4,
|
|
scaleY: 2.4,
|
|
alpha: 0,
|
|
duration: 700,
|
|
ease: 'Cubic.easeIn',
|
|
onComplete: () => this.scene.start('GameMenu'),
|
|
});
|
|
}
|
|
}
|