| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601 |
- 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);
- }
- }
|