boardgame-phaser/packages/sample-game/src/scenes/MenuScene.ts

156 lines
3.7 KiB
TypeScript
Raw Normal View History

2026-04-12 16:52:53 +08:00
import { ReactiveScene } from 'boardgame-phaser';
2026-04-12 17:54:46 +08:00
/** 菜单场景配置 */
const MENU_CONFIG = {
colors: {
title: '#1f2937',
buttonText: '#ffffff',
buttonBg: 0x3b82f6,
buttonBgHover: 0x2563eb,
subtitle: '#6b7280',
},
fontSize: {
title: '48px',
button: '24px',
subtitle: '16px',
},
button: {
width: 200,
height: 60,
},
positions: {
titleY: -100,
buttonY: 40,
subtitleY: 140,
},
} as const;
2026-04-12 16:52:53 +08:00
export class MenuScene extends ReactiveScene {
private titleText!: Phaser.GameObjects.Text;
2026-04-12 17:54:46 +08:00
private startButtonContainer!: Phaser.GameObjects.Container;
2026-04-12 16:52:53 +08:00
private startButtonBg!: Phaser.GameObjects.Rectangle;
2026-04-12 17:54:46 +08:00
private startButtonText!: Phaser.GameObjects.Text;
2026-04-12 16:52:53 +08:00
constructor() {
super('MenuScene');
}
create(): void {
super.create();
2026-04-12 17:54:46 +08:00
const center = this.getCenterPosition();
this.createTitle(center);
this.createStartButton(center);
this.createSubtitle(center);
}
/** 获取屏幕中心位置 */
private getCenterPosition(): { x: number; y: number } {
return {
x: this.game.scale.width / 2,
y: this.game.scale.height / 2,
};
}
2026-04-12 16:52:53 +08:00
2026-04-12 17:54:46 +08:00
/** 创建标题文本 */
private createTitle(center: { x: number; y: number }): void {
this.titleText = this.add.text(
center.x,
center.y + MENU_CONFIG.positions.titleY,
'Tic-Tac-Toe',
{
fontSize: MENU_CONFIG.fontSize.title,
fontFamily: 'Arial',
color: MENU_CONFIG.colors.title,
}
).setOrigin(0.5);
2026-04-12 16:52:53 +08:00
2026-04-12 17:54:46 +08:00
// 标题入场动画
2026-04-12 16:52:53 +08:00
this.titleText.setScale(0);
this.tweens.add({
targets: this.titleText,
scale: 1,
duration: 600,
ease: 'Back.easeOut',
});
2026-04-12 17:54:46 +08:00
}
/** 创建开始按钮 */
private createStartButton(center: { x: number; y: number }): void {
const { button, colors } = MENU_CONFIG;
2026-04-12 16:52:53 +08:00
2026-04-12 17:54:46 +08:00
this.startButtonBg = this.add.rectangle(
center.x,
center.y + MENU_CONFIG.positions.buttonY,
button.width,
button.height,
colors.buttonBg
).setInteractive({ useHandCursor: true });
2026-04-12 16:52:53 +08:00
2026-04-12 17:54:46 +08:00
this.startButtonText = this.add.text(
center.x,
center.y + MENU_CONFIG.positions.buttonY,
'Start Game',
{
fontSize: MENU_CONFIG.fontSize.button,
fontFamily: 'Arial',
color: colors.buttonText,
}
).setOrigin(0.5);
2026-04-12 16:52:53 +08:00
2026-04-12 17:54:46 +08:00
this.startButtonContainer = this.add.container(
center.x,
center.y + MENU_CONFIG.positions.buttonY,
[this.startButtonBg, this.startButtonText]
);
2026-04-12 16:52:53 +08:00
// 按钮交互
2026-04-12 17:54:46 +08:00
this.setupButtonInteraction();
}
/** 设置按钮交互效果 */
private setupButtonInteraction(): void {
2026-04-12 16:52:53 +08:00
this.startButtonBg.on('pointerover', () => {
2026-04-12 17:54:46 +08:00
this.startButtonBg.setFillStyle(MENU_CONFIG.colors.buttonBgHover);
2026-04-12 16:52:53 +08:00
this.tweens.add({
2026-04-12 17:54:46 +08:00
targets: this.startButtonContainer,
2026-04-12 16:52:53 +08:00
scale: 1.05,
duration: 100,
});
});
this.startButtonBg.on('pointerout', () => {
2026-04-12 17:54:46 +08:00
this.startButtonBg.setFillStyle(MENU_CONFIG.colors.buttonBg);
2026-04-12 16:52:53 +08:00
this.tweens.add({
2026-04-12 17:54:46 +08:00
targets: this.startButtonContainer,
2026-04-12 16:52:53 +08:00
scale: 1,
duration: 100,
});
});
this.startButtonBg.on('pointerdown', () => {
this.startGame();
});
2026-04-12 17:54:46 +08:00
}
2026-04-12 16:52:53 +08:00
2026-04-12 17:54:46 +08:00
/** 创建副标题 */
private createSubtitle(center: { x: number; y: number }): void {
this.add.text(
center.x,
center.y + MENU_CONFIG.positions.subtitleY,
'Click to start playing',
{
fontSize: MENU_CONFIG.fontSize.subtitle,
fontFamily: 'Arial',
color: MENU_CONFIG.colors.subtitle,
}
).setOrigin(0.5);
2026-04-12 16:52:53 +08:00
}
2026-04-12 17:54:46 +08:00
/** 开始游戏 */
2026-04-12 16:52:53 +08:00
private async startGame(): Promise<void> {
2026-04-12 17:21:49 +08:00
await this.sceneController.launch('GameScene');
2026-04-12 16:52:53 +08:00
}
}