- {/* 中间行:游戏画布 + PUA面板 */}
+ {/* 中间行:游戏画布 + 右侧控制面板 */}
{/* 游戏画布 */}
- {/* PUA 激励台(右侧) */}
-
+
+ {/* 右侧面板:HC + 召唤按钮 + PUA激励台 */}
+
+ {/* HC 数量显示 */}
+
+
+
+ 人才储备
+
+
+ {hc} HC
+
+
+
+
+ {/* 召唤下一波按钮 */}
+
+
+
+
+ {/* PUA 激励台 */}
+
+
{/* 底部塔选择面板 */}
diff --git a/game/ui/HUD.ts b/game/ui/HUD.ts
index e68824d..1f2a0d2 100644
--- a/game/ui/HUD.ts
+++ b/game/ui/HUD.ts
@@ -5,74 +5,62 @@ import { showVictoryModal, showDefeatModal } from './EndScreenModal'
/**
* 游戏 HUD 辅助工具
- * 负责管理"召唤下一波"按钮、波次提示横幅、胜利/失败结算弹窗
+ * 召唤下一波按钮已移至 React 右侧面板,HUD 只负责横幅提示和结算弹窗
*/
export class HUD {
private scene: Phaser.Scene
- private waveBtn: Phaser.GameObjects.Text | null = null
private waveBannerTimeout: (() => void) | null = null
- private _onClick: (() => void) | null = null
+ // 按钮状态通过 window 回调同步到 React
+ private _onWaveClick: (() => void) | null = null
constructor(scene: Phaser.Scene) {
this.scene = scene
}
/**
- * 创建"召唤下一波"按钮
- * @param onClick 点击回调
+ * 注册"召唤下一波"逻辑,并把控制接口暴露给 React 层
*/
createWaveButton(onClick: () => void): void {
- if (this.waveBtn) this.waveBtn.destroy()
- this._onClick = onClick
+ this._onWaveClick = onClick
+ if (typeof window === 'undefined') return
- this.waveBtn = this.scene.add
- .text(GAME_WIDTH / 2, HUD_HEIGHT + 16, '▶ 召唤下一波', {
- fontFamily: 'VT323, monospace',
- fontSize: '26px',
- color: '#A78BFA',
- backgroundColor: '#1e3a5f',
- padding: { x: 20, y: 8 },
- stroke: '#7C3AED',
- strokeThickness: 1,
- })
- .setOrigin(0.5, 0)
- .setDepth(20)
- .setInteractive({ useHandCursor: true })
-
- this.waveBtn.on('pointerover', () => {
- if (this.waveBtn) this.waveBtn.setStyle({ backgroundColor: '#2d5a8e', color: '#C4B5FD' })
- })
- this.waveBtn.on('pointerout', () => {
- if (this.waveBtn) this.waveBtn.setStyle({ backgroundColor: '#1e3a5f', color: '#A78BFA' })
- })
- this.waveBtn.on('pointerdown', () => onClick())
+ // React 层通过 window.__gameOnWaveClick() 触发
+ ;(window as any).__gameOnWaveClick = () => {
+ this._onWaveClick?.()
+ }
+ // 初始状态:可用
+ this._notifyReact('▶ 召唤下一波', false)
+ }
+
+ private _notifyReact(text: string, disabled: boolean): void {
+ if (typeof window !== 'undefined') {
+ ;(window as any).__gameSetWaveBtn?.({ text, disabled })
+ }
}
- /** 更新按钮文字(如禁用状态) */
setWaveButtonText(text: string): void {
- this.waveBtn?.setText(text)
+ // 保持当前 disabled 状态,只更新文字
+ if (typeof window !== 'undefined') {
+ const cur = (window as any).__gameWaveBtnState
+ const disabled = cur?.disabled ?? false
+ this._notifyReact(text, disabled)
+ }
}
disableWaveButton(): void {
- if (!this.waveBtn) return
- this.waveBtn.setStyle({ color: '#4B5563', backgroundColor: '#0F172A' })
- this.waveBtn.removeAllListeners('pointerdown')
+ this._notifyReact((typeof window !== 'undefined'
+ ? (window as any).__gameWaveBtnState?.text ?? '波次进行中...'
+ : '波次进行中...'), true)
}
enableWaveButton(): void {
- if (!this.waveBtn) return
- this.waveBtn.setStyle({ color: '#A78BFA', backgroundColor: '#1e3a5f' })
- // 重新绑定点击事件(disableWaveButton 会 removeAllListeners)
- this.waveBtn.removeAllListeners('pointerdown')
- if (this._onClick) {
- this.waveBtn.on('pointerdown', () => this._onClick!())
- }
+ this._notifyReact((typeof window !== 'undefined'
+ ? (window as any).__gameWaveBtnState?.text ?? '▶ 召唤下一波'
+ : '▶ 召唤下一波'), false)
}
/**
* 显示波次开始横幅
- * @param waveNumber 当前波次(1-based)
- * @param totalWaves 总波次数
*/
showWaveBanner(waveNumber: number, totalWaves: number): void {
const isBoss = waveNumber === totalWaves
@@ -128,7 +116,7 @@ export class HUD {
})
}
- /** 显示胜利画面(完整绩效评级弹窗,委托给 EndScreenModal) */
+ /** 显示胜利画面 */
showVictory(): void {
const manager = GameManager.getInstance()
const kpi = manager.kpi
@@ -159,13 +147,18 @@ export class HUD {
showVictoryModal({ kpi, hc, grade, gradeColor, gradeDesc })
}
- /** 显示失败画面(仿钉钉退群通知,委托给 EndScreenModal) */
+ /** 显示失败画面 */
showGameOver(): void {
showDefeatModal()
}
destroy(): void {
- this.waveBtn?.destroy()
if (this.waveBannerTimeout) this.waveBannerTimeout()
+ if (typeof window !== 'undefined') {
+ delete (window as any).__gameOnWaveClick
+ delete (window as any).__gameSetWaveBtn
+ delete (window as any).__gameWaveBtnState
+ }
}
}
+