| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- 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('请至少上阵一个植物!');
- }
- }
|