import { _decorator, Component, Node, Button, Label, find, UITransform, Sprite, Color, tween, Tween, Prefab, instantiate } from 'cc'; import { LevelSessionManager } from '../../Core/LevelSessionManager'; import { BallController } from '../BallController'; import { BlockManager } from '../BlockManager'; import { GameStartMove } from '../../Animations/GameStartMove'; import { BlockTag } from './BlockTag'; import { SkillManager } from '../SkillSelection/SkillManager'; import EventBus, { GameEvents } from '../../Core/EventBus'; const { ccclass, property } = _decorator; @ccclass('GameBlockSelection') export class GameBlockSelection extends Component { @property({ type: Node, tooltip: '拖拽BlockSelectionUI/diban/ann001按钮节点到这里' }) public addBallButton: Node = null; @property({ type: Node, tooltip: '拖拽BlockSelectionUI/diban/ann002按钮节点到这里' }) public addCoinButton: Node = null; @property({ type: Node, tooltip: '拖拽BlockSelectionUI/diban/ann003按钮节点到这里' }) public refreshButton: Node = null; @property({ type: Node, tooltip: '拖拽Canvas-001/TopArea/CoinNode/CoinLabel节点到这里' }) public coinLabelNode: Node = null; @property({ type: Prefab, tooltip: '拖拽Toast预制体到这里' }) public toastPrefab: Prefab = null; @property({ type: Node, tooltip: '拖拽Canvas/GameLevelUI/BallController节点到这里' }) public ballControllerNode: Node = null; @property({ type: Node, tooltip: '拖拽Canvas/GameLevelUI/BlockController节点到这里' }) public blockManagerNode: Node = null; @property({ type: Node, tooltip: '拖拽Canvas/Camera节点到这里' }) public cameraNode: Node = null; @property({ type: Node, tooltip: '拖拽Canvas/GameLevelUI/GameArea/GridContainer节点到这里' }) public gridContainer: Node = null; @property({ type: Node, tooltip: '拖拽confirm按钮节点到这里' }) public confirmButton: Node = null; @property({ type: Node, tooltip: '拖拽BlockSelectionUI根节点到这里' }) public blockSelectionUINode: Node = null; @property({ type: Node, tooltip: '拖拽BlockSelectionUI/diban节点到这里' }) public dibanNode: Node = null; // 按钮费用配置 private readonly ADD_BALL_COST = 80; private readonly ADD_COIN_AMOUNT = 80; private readonly REFRESH_COST = 5; private session: LevelSessionManager = null; private ballController: BallController = null; private blockManager: BlockManager = null; private gameStartMove: GameStartMove = null; // 回调函数,用于通知GameManager public onConfirmCallback: () => void = null; start() { console.log('GameBlockSelection.start() 开始初始化'); // 获取管理器实例 this.session = LevelSessionManager.inst; // 获取BallController if (this.ballControllerNode) { this.ballController = this.ballControllerNode.getComponent(BallController); } else { console.warn('BallController节点未绑定,请在Inspector中拖拽Canvas/GameLevelUI/BallController节点'); } // 获取BlockManager if (this.blockManagerNode) { this.blockManager = this.blockManagerNode.getComponent(BlockManager); } else { console.warn('BlockManager节点未绑定,请在Inspector中拖拽Canvas/GameLevelUI/BlockController节点'); } // 获取GameStartMove组件 if (this.cameraNode) { this.gameStartMove = this.cameraNode.getComponent(GameStartMove); console.log('GameStartMove组件获取结果:', !!this.gameStartMove); // 如果GameStartMove存在,设置BlockSelectionUI和diban引用,并更新原始位置 if (this.gameStartMove && this.blockSelectionUINode && this.dibanNode) { this.gameStartMove.blockSelectionUI = this.blockSelectionUINode; this.gameStartMove.dibanNode = this.dibanNode; this.gameStartMove.updateDibanOriginalPosition(); console.log('GameStartMove引用设置完成:', { blockSelectionUISet: !!this.gameStartMove.blockSelectionUI, dibanNodeSet: !!this.gameStartMove.dibanNode, blockSelectionUINodeName: this.blockSelectionUINode.name, dibanNodeName: this.dibanNode.name }); } else { console.warn('GameStartMove引用设置失败:', { gameStartMove: !!this.gameStartMove, blockSelectionUINode: !!this.blockSelectionUINode, dibanNode: !!this.dibanNode }); } } else { console.warn('Camera节点未绑定,请在Inspector中拖拽Canvas/Camera节点'); } // 如果没有指定coinLabelNode,尝试找到它 if (!this.coinLabelNode) { this.coinLabelNode = find('Canvas-001/TopArea/CoinNode/CoinLabel'); } // 绑定按钮事件 this.bindButtonEvents(); // 设置事件监听器 this.setupEventListeners(); console.log('GameBlockSelection.start() 初始化完成'); } // 设置事件监听器 private setupEventListeners() { const eventBus = EventBus.getInstance(); // 监听重置方块选择事件 eventBus.on(GameEvents.RESET_BLOCK_SELECTION, this.onResetBlockSelectionEvent, this); } // 处理重置方块选择事件 private onResetBlockSelectionEvent() { console.log('[GameBlockSelection] 接收到重置方块选择事件'); this.resetSelection(); } // 绑定按钮事件 private bindButtonEvents() { // 绑定新增小球按钮 if (this.addBallButton) { const btn = this.addBallButton.getComponent(Button); if (btn) { this.addBallButton.on(Button.EventType.CLICK, this.onAddBallClicked, this); } else { this.addBallButton.on(Node.EventType.TOUCH_END, this.onAddBallClicked, this); } } // 绑定增加金币按钮 if (this.addCoinButton) { const btn = this.addCoinButton.getComponent(Button); if (btn) { this.addCoinButton.on(Button.EventType.CLICK, this.onAddCoinClicked, this); } else { this.addCoinButton.on(Node.EventType.TOUCH_END, this.onAddCoinClicked, this); } } // 绑定刷新方块按钮 if (this.refreshButton) { const btn = this.refreshButton.getComponent(Button); if (btn) { this.refreshButton.on(Button.EventType.CLICK, this.onRefreshClicked, this); } else { this.refreshButton.on(Node.EventType.TOUCH_END, this.onRefreshClicked, this); } } // 绑定确认按钮 if (this.confirmButton) { const btn = this.confirmButton.getComponent(Button); if (btn) { this.confirmButton.on(Button.EventType.CLICK, this.onConfirmButtonClicked, this); } else { this.confirmButton.on(Node.EventType.TOUCH_END, this.onConfirmButtonClicked, this); } } } // 新增小球按钮点击 private onAddBallClicked() { // 应用便宜技能效果计算实际费用 const actualCost = this.getActualCost(this.ADD_BALL_COST); if (!this.canSpendCoins(actualCost)) { this.showInsufficientCoinsUI(); return; } // 扣除金币 if (this.session.spendCoins(actualCost)) { this.updateCoinDisplay(); // 通过事件系统创建新的小球 const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.BALL_CREATE_ADDITIONAL); console.log(`新增小球成功,扣除${actualCost}金币`); } } // 增加金币按钮点击 private onAddCoinClicked() { // 应用便宜技能效果计算实际费用 const actualCost = this.getActualCost(this.ADD_COIN_AMOUNT); if (!this.canSpendCoins(actualCost)) { this.showInsufficientCoinsUI(); return; } // 扣除金币 if (this.session.spendCoins(actualCost)) { this.updateCoinDisplay(); // 添加金币(这里可以根据需要调整添加的金币数量) const coinsToAdd = 100; // 可以根据需要调整 this.session.addCoins(coinsToAdd); console.log(`花费${actualCost}金币,获得${coinsToAdd}金币`); // 更新显示 this.updateCoinDisplay(); } } // 刷新方块按钮点击 private onRefreshClicked() { // 应用便宜技能效果计算实际费用 const actualCost = this.getActualCost(this.REFRESH_COST); if (!this.canSpendCoins(actualCost)) { this.showInsufficientCoinsUI(); return; } // 扣除金币 if (this.session.spendCoins(actualCost)) { this.updateCoinDisplay(); // 刷新方块 if (this.blockManager) { // 找到PlacedBlocks容器 const placedBlocksContainer = find('Canvas/GameLevelUI/PlacedBlocks'); if (placedBlocksContainer) { // 移除已放置方块的标签 BlockTag.removeTagsInContainer(placedBlocksContainer); } // 刷新方块 this.blockManager.refreshBlocks(); console.log(`刷新方块成功,扣除${actualCost}金币`); } else { console.error('找不到BlockManager,无法刷新方块'); } } } // 确认按钮点击(从GameManager迁移的onConfirmButtonClicked) public onConfirmButtonClicked() { // 检查是否有上阵方块 const hasBlocks = this.hasPlacedBlocks(); console.log(`[GameBlockSelection] 检查上阵方块: ${hasBlocks ? '有' : '无'}`); if (!hasBlocks) { this.showNoPlacedBlocksToast(); return; } // 保存已放置的方块 this.preservePlacedBlocks(); // 先回调通知GameManager,让它处理波次逻辑 if (this.onConfirmCallback) { this.onConfirmCallback(); } // 然后隐藏UI并恢复游戏 this.hideBlockSelection(); } // 保存已放置的方块(从GameManager迁移) private preservePlacedBlocks() { if (this.blockManager) { this.blockManager.onGameStart(); } } // 检查是否有足够金币 private canSpendCoins(amount: number): boolean { return this.session.getCoins() >= amount; } // 计算应用便宜技能效果后的实际费用 private getActualCost(baseCost: number): number { const skillManager = SkillManager.getInstance(); if (skillManager) { const cheaperSkillLevel = skillManager.getSkillLevel('cheaper_units'); return Math.ceil(SkillManager.calculateCheaperUnitsPrice(baseCost, cheaperSkillLevel)); } return baseCost; } // 更新金币显示 private updateCoinDisplay() { if (this.coinLabelNode) { const label = this.coinLabelNode.getComponent(Label); if (label) { label.string = this.session.getCoins().toString(); } } } // 显示金币不足UI private showInsufficientCoinsUI() { if (!this.toastPrefab) { console.error('Toast预制体未绑定,请在Inspector中拖拽Toast预制体'); return; } // 实例化Toast预制体 const toastNode = instantiate(this.toastPrefab); // 设置Toast的文本为"金币不足!" const labelNode = toastNode.getChildByName('label'); if (labelNode) { const label = labelNode.getComponent(Label); if (label) { label.string = '金币不足!'; } } // 将Toast添加到Canvas下 const canvas = find('Canvas'); if (canvas) { canvas.addChild(toastNode); } // 3秒后自动销毁Toast this.scheduleOnce(() => { if (toastNode && toastNode.isValid) { toastNode.destroy(); } }, 3.0); console.log('金币不足!'); } // === 公共方法:供GameManager调用 === // 显示方块选择UI(用于游戏开始或下一波) public showBlockSelection(isNextWave: boolean = false) { // 通过事件系统暂停游戏 const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.GAME_PAUSE); console.log('[GameBlockSelection] 显示方块选择UI,确保游戏暂停'); // 首先显示UI节点 this.node.active = true; if (this.gridContainer) { this.gridContainer.active = true; } // 如果有BlockSelectionUI节点,确保它可见 if (this.blockSelectionUINode) { this.blockSelectionUINode.active = true; } // 每次显示方块选择UI时,生成新的随机方块 if (this.blockManager) { this.blockManager.refreshBlocks(); console.log('[GameBlockSelection] 生成新的随机方块'); } else { console.warn('[GameBlockSelection] BlockManager未找到,无法生成随机方块'); } // 播放BlockSelectionUI出现动画 this.playShowAnimation(); // 派发事件 EventBus.getInstance().emit(GameEvents.BLOCK_SELECTION_OPEN); console.log(`[GameBlockSelection] ${isNextWave ? '显示下一波方块选择UI' : '显示游戏开始方块选择UI'}`); } // 隐藏方块选择UI public hideBlockSelection() { // 播放隐藏动画,动画完成后隐藏UI this.playHideAnimation(() => { this.node.active = false; // 派发事件 EventBus.getInstance().emit(GameEvents.BLOCK_SELECTION_CLOSE); // 发送游戏开始事件,确保GamePause正确设置isInGameMode状态 console.log('[GameBlockSelection] 隐藏方块选择UI、发送游戏开始事件'); EventBus.getInstance().emit(GameEvents.GAME_START); // 通过事件系统恢复游戏状态 console.log('[GameBlockSelection] 恢复游戏状态'); EventBus.getInstance().emit(GameEvents.GAME_RESUME); // 移除这里的波次提示调用,让GameManager统一控制波次提示的显示时机 // 显示波次提示Toast并开始敌人生成 // const enemyController = EnemyController.getInstance(); // if (enemyController) { // enemyController.showStartWavePromptUI(2); // 显示2秒Toast提示 // } }); } // 播放显示动画 private playShowAnimation() { console.log('播放显示动画playShowAnimation'); if (this.gameStartMove && this.blockSelectionUINode && this.dibanNode) { // 设置GameStartMove的blockSelectionUI和dibanNode引用 this.gameStartMove.blockSelectionUI = this.blockSelectionUINode; this.gameStartMove.dibanNode = this.dibanNode; // 使用GameStartMove的进入方块选择模式动画 this.gameStartMove.enterBlockSelectionMode(300, 0.3); console.log('进入方块选择模式动画已启动'); } } // 播放隐藏动画 private playHideAnimation(onComplete?: () => void) { console.log('播放隐藏动画playHideAnimation'); console.log('GameBlockSelection 引用检查:', { gameStartMove: !!this.gameStartMove, blockSelectionUINode: !!this.blockSelectionUINode, dibanNode: !!this.dibanNode, blockSelectionUINodeName: this.blockSelectionUINode?.name, dibanNodeName: this.dibanNode?.name }); if (this.gameStartMove && this.blockSelectionUINode && this.dibanNode) { // 设置GameStartMove的blockSelectionUI和dibanNode引用 this.gameStartMove.blockSelectionUI = this.blockSelectionUINode; this.gameStartMove.dibanNode = this.dibanNode; console.log('GameStartMove 引用设置后检查:', { gameStartMoveBlockSelectionUI: !!this.gameStartMove.blockSelectionUI, gameStartMoveDibanNode: !!this.gameStartMove.dibanNode }); // 使用GameStartMove的退出方块选择模式动画 this.gameStartMove.exitBlockSelectionMode(300, 0.3); console.log('退出方块选择模式动画已启动'); // 由于slideDibanDownAndHide会自动隐藏blockSelectionUI和重置位置,我们需要在动画完成后执行回调 if (onComplete) { this.scheduleOnce(() => { onComplete(); }, 0.3); // 与动画时长一致 } } else { console.log('GameBlockSelection 条件检查失败,无法播放动画'); if (onComplete) { // 如果没有动画组件,直接执行回调 onComplete(); } } } // 设置确认回调 public setConfirmCallback(callback: () => void) { this.onConfirmCallback = callback; } // 重置方块选择状态 public resetSelection() { console.log('[GameBlockSelection] 重置方块选择状态'); // 重置BlockManager状态 if (this.blockManager) { this.blockManager.onGameReset(); console.log('[GameBlockSelection] BlockManager状态已重置'); } // 清理所有方块标签 BlockTag.clearAllTags(); console.log('[GameBlockSelection] 方块标签已清理'); // 更新金币显示 this.updateCoinDisplay(); console.log('[GameBlockSelection] 金币显示已更新'); } // 检查是否有上阵方块 private hasPlacedBlocks(): boolean { // 优先使用BlockManager的方法检查 if (this.blockManager) { return this.blockManager.hasPlacedBlocks(); } // 备用方案:直接检查PlacedBlocks容器 const placedBlocksContainer = find('Canvas/GameLevelUI/PlacedBlocks'); if (!placedBlocksContainer) { console.warn('找不到PlacedBlocks容器'); return false; } // 检查容器中是否有子节点(方块) return placedBlocksContainer.children.length > 0; } // 显示没有上阵方块的Toast提示 private showNoPlacedBlocksToast() { console.log('[GameBlockSelection] 开始显示Toast提示'); if (!this.toastPrefab) { console.error('[GameBlockSelection] Toast预制体未绑定,请在Inspector中拖拽Toast预制体'); return; } console.log('[GameBlockSelection] Toast预制体已绑定'); // 实例化Toast预制体 const toastNode = instantiate(this.toastPrefab); console.log('[GameBlockSelection] Toast节点已实例化:', toastNode.name); // 设置Toast的文本为"请至少上阵一个植物!" const labelNode = toastNode.getChildByName('label'); console.log('[GameBlockSelection] 查找label子节点:', !!labelNode); if (labelNode) { const label = labelNode.getComponent(Label); console.log('[GameBlockSelection] 获取Label组件:', !!label); if (label) { label.string = '请至少上阵一个植物!'; } else { console.error('[GameBlockSelection] label节点没有Label组件'); } } else { console.error('[GameBlockSelection] 找不到名为"label"的子节点'); } // 将Toast添加到Canvas下 const canvas = find('Canvas'); if (canvas) { canvas.addChild(toastNode); } else { console.error('[GameBlockSelection] 找不到Canvas节点'); return; } // 3秒后自动销毁Toast this.scheduleOnce(() => { if (toastNode && toastNode.isValid) { toastNode.destroy(); } else { console.warn('[GameBlockSelection] Toast节点无效,无法销毁'); } }, 3.0); console.log('[GameBlockSelection] 请至少上阵一个植物!'); } onDestroy() { // 清理事件监听 const eventBus = EventBus.getInstance(); eventBus.off(GameEvents.RESET_BLOCK_SELECTION, this.onResetBlockSelectionEvent, this); } }