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 { GamePause } from '../GamePause'; import { BlockTag } from './BlockTag'; 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(); console.log('GameBlockSelection.start() 初始化完成'); } // 绑定按钮事件 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() { if (!this.canSpendCoins(this.ADD_BALL_COST)) { this.showInsufficientCoinsUI(); return; } // 扣除金币 if (this.session.spendCoins(this.ADD_BALL_COST)) { this.updateCoinDisplay(); // 创建新的小球 if (this.ballControllerNode) { const ballController = this.ballControllerNode.getComponent(BallController); if (ballController) { // 使用createAdditionalBall方法创建额外的小球,而不是替换现有的小球 ballController.createAdditionalBall(); console.log(`新增小球成功,扣除${this.ADD_BALL_COST}金币`); } else { console.error('找不到BallController组件'); } } else { console.error('找不到BallController节点,无法创建小球'); } } } // 增加金币按钮点击 private onAddCoinClicked() { this.session.addCoins(this.ADD_COIN_AMOUNT); this.updateCoinDisplay(); console.log(`增加${this.ADD_COIN_AMOUNT}金币`); } // 刷新方块按钮点击 private onRefreshClicked() { if (!this.canSpendCoins(this.REFRESH_COST)) { this.showInsufficientCoinsUI(); return; } // 扣除金币 if (this.session.spendCoins(this.REFRESH_COST)) { this.updateCoinDisplay(); // 刷新方块 if (this.blockManager) { // 找到PlacedBlocks容器 const placedBlocksContainer = find('Canvas/GameLevelUI/PlacedBlocks'); if (placedBlocksContainer) { // 移除已放置方块的标签 BlockTag.removeTagsInContainer(placedBlocksContainer); } // 刷新方块 this.blockManager.refreshBlocks(); console.log(`刷新方块成功,扣除${this.REFRESH_COST}金币`); } else { console.error('找不到BlockManager,无法刷新方块'); } } } // 确认按钮点击(从GameManager迁移的onConfirmButtonClicked) public onConfirmButtonClicked() { // 检查是否有上阵方块 const hasBlocks = this.hasPlacedBlocks(); console.log(`[GameBlockSelection] 检查上阵方块: ${hasBlocks ? '有' : '无'}`); if (!hasBlocks) { this.showNoPlacedBlocksToast(); return; } // 使用统一的隐藏方法,包含动画 this.hideBlockSelection(); // 保存已放置的方块 this.preservePlacedBlocks(); // 回调通知GameManager if (this.onConfirmCallback) { this.onConfirmCallback(); } // 恢复游戏 const gamePause = GamePause.getInstance(); if (gamePause) { gamePause.resumeGame(); } } // 保存已放置的方块(从GameManager迁移) private preservePlacedBlocks() { if (this.blockManager) { this.blockManager.onGameStart(); } } // 检查是否有足够金币 private canSpendCoins(amount: number): boolean { return this.session.getCoins() >= amount; } // 更新金币显示 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) { // 检查游戏是否已结束,使用GamePause来检查状态 const gamePause = GamePause.getInstance(); if (gamePause && gamePause.isGameOver()) { console.warn('[GameBlockSelection] 游戏已经结束,不显示方块选择UI'); return; } // 首先显示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; // 移除隐藏GridContainer的代码,因为GridContainer应该在游戏过程中保持可见 // if (this.gridContainer) { // this.gridContainer.active = false; // } // 派发事件 EventBus.getInstance().emit(GameEvents.BLOCK_SELECTION_CLOSE); console.log('隐藏方块选择UI'); }); } // 播放显示动画 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; // 每次显示BlockSelectionUI时,摄像头下移182px this.gameStartMove.moveDownInstant(); console.log('摄像头下移182px'); // 使用GameStartMove的上滑入场动画 this.gameStartMove.slideUpFromBottom(300, 0.3); } } // 播放隐藏动画 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 }); // 每次隐藏BlockSelectionUI时,摄像头上移182px this.gameStartMove.moveUpSmooth(); console.log('摄像头上移182px'); // 播放下滑隐藏动画,动画完成后执行回调 this.gameStartMove.slideDibanDownAndHide(300, 0.3); // 由于slideDibanDownAndHide会自动隐藏blockSelectionUI和重置位置,我们需要在动画完成后执行回调 if (onComplete) { this.scheduleOnce(() => { onComplete(); }, 0.3); // 与动画时长一致 } } else { console.log('GameBlockSelection 条件检查失败,无法播放动画'); if (onComplete) { // 如果没有动画组件,直接执行回调 onComplete(); } } } // 设置确认回调 public setConfirmCallback(callback: () => void) { this.onConfirmCallback = callback; } // 检查是否有上阵方块 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() { 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('请至少上阵一个植物!'); } }