import type Phaser from 'phaser' import { MAP_COLS, MAP_ROWS, HUD_HEIGHT, GAME_HEIGHT, GAME_WIDTH } from './constants' import { GameManager } from './GameManager' import { PATH_TILES, getCellSize, drawAllTiles, renderMapLabels, renderHUD, updateKPIBar, BAR_X, BAR_Y, BAR_W, BAR_H, } from './mapRenderer' /** * 创建主游戏场景类(工厂函数,接收动态导入的 Phaser 实例) * 这样可以保证 SSR 安全(只在客户端执行) */ export function createGameScene(PhaserLib: typeof Phaser): typeof Phaser.Scene { class GameScene extends PhaserLib.Scene { private manager!: GameManager private kpiBar!: Phaser.GameObjects.Graphics private kpiText!: Phaser.GameObjects.Text private hcText!: Phaser.GameObjects.Text private hoveredTile: { col: number; row: number } | null = null private tileGraphics!: Phaser.GameObjects.Graphics constructor() { super({ key: 'GameScene' }) } create(): void { this.manager = GameManager.getInstance() this.manager.reset() this.manager.gameState = 'playing' // 渲染地图 this.tileGraphics = this.add.graphics() drawAllTiles(this.tileGraphics, null) // 地图装饰标签 renderMapLabels(this) // HUD(在地图之上) const hud = renderHUD(this) this.kpiBar = hud.kpiBar this.kpiText = hud.kpiText this.hcText = hud.hcText // 鼠标交互 this.setupInteraction() // GameManager 事件回调 → 更新 HUD this.manager.onKPIChange.push((kpi: number) => { updateKPIBar(this.kpiBar, kpi) this.kpiText.setText(`${kpi}%`) }) this.manager.onHCChange.push((hc: number) => { this.hcText.setText(`HC: ${hc}`) }) } /** 注册鼠标悬停 + 点击事件 */ private setupInteraction(): void { const { cellW, cellH } = getCellSize() this.input.on( 'pointermove', (pointer: Phaser.Input.Pointer) => { const col = Math.floor(pointer.x / cellW) const row = Math.floor((pointer.y - HUD_HEIGHT) / cellH) if (col >= 0 && col < MAP_COLS && row >= 0 && row < MAP_ROWS) { if (!PATH_TILES.has(`${col},${row}`)) { if ( !this.hoveredTile || this.hoveredTile.col !== col || this.hoveredTile.row !== row ) { this.hoveredTile = { col, row } drawAllTiles(this.tileGraphics, this.hoveredTile) } return } } if (this.hoveredTile !== null) { this.hoveredTile = null drawAllTiles(this.tileGraphics, null) } } ) this.input.on( 'pointerdown', (pointer: Phaser.Input.Pointer) => { const col = Math.floor(pointer.x / cellW) const row = Math.floor((pointer.y - HUD_HEIGHT) / cellH) if ( col >= 0 && col < MAP_COLS && row >= 0 && row < MAP_ROWS && !PATH_TILES.has(`${col},${row}`) ) { this.showBuildPrompt(col, row, cellW, cellH) } } ) } /** 点击可建格子时的占位提示(Phase 1) */ private showBuildPrompt( col: number, row: number, cellW: number, cellH: number ): void { const x = col * cellW + cellW / 2 const y = HUD_HEIGHT + row * cellH + cellH / 2 const tip = this.add .text(x, y - 20, '建塔 (即将开放)', { fontFamily: 'VT323, monospace', fontSize: '18px', color: '#F43F5E', backgroundColor: '#0a1628', padding: { x: 8, y: 4 }, }) .setOrigin(0.5, 1) .setDepth(20) this.time.delayedCall(1500, () => { tip.destroy() }) } } // 避免 unused variable 警告 void MAP_ROWS void GAME_HEIGHT void GAME_WIDTH void BAR_X void BAR_Y void BAR_W void BAR_H return GameScene }