import { _decorator, Button, Component, Node, tween, sys, Sprite, Color, instantiate, Label, v3 } from 'cc'; import ch_audio from 'db://assets/ch/audio/audio'; import { BlockLink } from '../../game/link/block/BlockLink'; import { Block, BlockState } from '../../game/link/block/Block'; import { UI_Main } from '../main/UI_Main'; import { MySdk, sdkMe } from '../../game/MySdk'; import { audioManager } from '../../Audio/AudioManager'; const { ccclass, property } = _decorator; @ccclass('layout_Buttom') export class layout_Buttom extends Component { @property(Button) sx_btn: Button @property(Button) cz_btn: Button @property(Button) xc_btn: Button @property(Button) js_btn: Button // 按钮状态标记 private isSxBtnBusy = false; private isCzBtnBusy = false; private isXcBtnBusy = false; private isJsBtnBusy = false; private globalLock = false; // 记录正在执行的动画数量 private activeAnimations = 0; // 标记是否有等待执行的刷新操作 private hasPendingShuffle = false; private highlightedBlocks: Node[] = []; blockLink: BlockLink | null = null; protected start() { this.blockLink = BlockLink.inti; //刷新 this.sx_btn.node.on(Button.EventType.CLICK, async () => { this.huifuhighlight(this.highlightedBlocks) this.guanbibtn(!1) if (this.isSxBtnBusy) return; audioManager.playOneShot('sound/click_Btn'); this.isSxBtnBusy = true; // 标记为忙碌 try { const ret = await sdkMe.playRewardAd('刷新'); if (ret) { // 如果有动画正在执行,标记等待状态 if (this.activeAnimations > 0) { this.hasPendingShuffle = true; } else { // 否则立即执行刷新 await this.asyncShuffleBlocks(); } this.guanbibtn(!0) } else { this.guanbibtn(!0) } } finally { this.guanbibtn(!0) // 无论操作成功与否,都重置状态 this.isSxBtnBusy = false; } }) //查找 this.cz_btn.node.on(Button.EventType.CLICK, async () => { this.guanbibtn(!1) if (this.isCzBtnBusy) return; audioManager.playOneShot('sound/click_Btn'); this.isCzBtnBusy = true; // 标记为忙碌 try { const ret = await sdkMe.playRewardAd('查找') if (ret) { this.findConnectableBlocks(); } else { this.guanbibtn(!0) } } finally { this.guanbibtn(!0) // 无论操作成功与否,都重置状态 this.isCzBtnBusy = false; } }) //消除 this.xc_btn.node.on(Button.EventType.CLICK, async () => { this.guanbibtn(!1) if (this.globalLock || this.isXcBtnBusy) return; this.globalLock = true; this.isXcBtnBusy = true; try { audioManager.playOneShot('sound/click_Btn'); const ret = await sdkMe.playRewardAd('消除'); if (ret) { await this.asyncEliminateConnectableBlocks(); } else { this.guanbibtn(!0) } } finally { setTimeout(() => { this.guanbibtn(!0) this.isXcBtnBusy = false; this.globalLock = false; }, 500); } }) //加时 this.js_btn.node.on(Button.EventType.CLICK, async () => { // 检查按钮状态,忙则不执行 if (this.isJsBtnBusy) return; audioManager.playOneShot('sound/click_Btn'); this.isJsBtnBusy = true; // 标记为忙碌 try { const ret = await sdkMe.playRewardAd('加时') if (ret) { const role = UI_Main.lt.role; if (role) { UI_Main.lt.title.addTime(50); await role.reviveMove(); // 复活移动 } } } finally { // 无论操作成功与否,都重置状态 this.isJsBtnBusy = false; } }) } //刷新 private async asyncShuffleBlocks(): Promise { BlockLink.inti.isMoving = true; //取消消除前选中状态 this.resetAllBlocksAnimation1() console.log('开始洗牌'); return new Promise((resolve) => { const blockLink = BlockLink.inti; const allBlocks = blockLink.node.children.filter(child => child.getComponent(Block)); if (allBlocks.length < 2) { resolve(false); return; } // 洗牌算法 const shuffledBlocks = this.fisherYatesShuffle([...allBlocks]); // 清空原始数组 BlockLink.blockArry = new Array(blockLink.mapConfig.rows) .fill(null) .map(() => new Array(blockLink.mapConfig.cols).fill(null)); // 记录原始位置用于动画 const originalPositions = allBlocks.map(block => block.getPosition().clone()); // 记录需要执行的动画总数 this.activeAnimations = allBlocks.length; // 遍历所有方块并播放移动动画 allBlocks.forEach((block, index) => { const targetBlock = shuffledBlocks[index]; const targetPosition = targetBlock.getPosition(); tween(block) .to(0.1, { position: targetPosition }, { easing: 'sineOut' }) .call(() => { // 动画完成后更新数组 const { i, j } = blockLink.getRowCol(block.position); BlockLink.blockArry[i][j] = block; // 减少活跃动画计数 this.activeAnimations--; // 如果所有动画都完成且有等待的刷新操作,则执行 if (this.activeAnimations === 0 && this.hasPendingShuffle) { this.hasPendingShuffle = false; this.asyncShuffleBlocks(); } // 如果是最后一个动画完成,解决Promise if (this.activeAnimations === 0) { BlockLink.inti.isMoving = false; resolve(true); } }) .start(); }); }); } // 洗牌方法 private fisherYatesShuffle(array: Node[]): Node[] { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; } //查找 findConnectableBlocks() { //取消消除前选中状态 //this.resetAllBlocksAnimation1() const blockLink = BlockLink.inti; const allBlocks = blockLink.node.children.filter(child => child.getComponent(Block)); let found = false; for (let i = 0; i < allBlocks.length; i++) { const blockA = allBlocks[i]; const blockAComp = blockA.getComponent(Block); for (let j = i + 1; j < allBlocks.length; j++) { const blockB = allBlocks[j]; const blockBComp = blockB.getComponent(Block); // 增加判断方块类型是否相同 if (blockAComp && blockBComp && blockAComp.isMatch(blockBComp)) { if (blockLink.isConnected(blockA, blockB, true)) { found = true; this.highlightedBlocks = [blockA, blockB] this.highlight(blockAComp, blockBComp) // this.tipNofind() return; // 找到一对就停止查找 } } } } if (!found) { this.tipNofind() } } //恢复 huifuhighlight(node: Node[]) { const node1 = node[0]; const node2 = node[1]; if (!node1 || !node1.isValid) return; node1.getComponent(Sprite).color = new Color(255, 255, 255); node2.getComponent(Sprite).color = new Color(255, 255, 255); } tipNofind() { const tipPrefab = UI_Main.lt.tip; const tip = instantiate(tipPrefab); tip.setPosition(0, 0, 0); tip.parent = this.node; tween(tip) .to(0.5, { scale: v3(1.2, 1.2, 1) }) .to(0.5, { scale: v3(0, 0, 1) }) .call(() => { if (tip && tip.isValid) { tip.destroy(); } }) .start(); } //异步消除方法,等待消除动画完成 private async asyncEliminateConnectableBlocks() { //取消消除前选中状态 this.resetAllBlocksAnimation1() // 创建一个Promise来等待消除完成 return new Promise((resolve) => { const blockLink = BlockLink.inti; const allBlocks = blockLink.node.children.filter(child => child.getComponent(Block)); let found = false; for (let i = 0; i < allBlocks.length; i++) { const blockA = allBlocks[i]; const blockAComp = blockA.getComponent(Block); for (let j = i + 1; j < allBlocks.length; j++) { const blockB = allBlocks[j]; const blockBComp = blockB.getComponent(Block); if (blockAComp && blockBComp && blockAComp.isMatch(blockBComp)) { if (blockLink.isConnected(blockA, blockB)) { found = true; // 执行匹配成功的消除逻辑 if (blockAComp.handleMatchSuccess instanceof Function) { // 执行消除并等待完成 blockAComp.handleMatchSuccess(blockBComp); // 等待一小段时间,确保动画开始 setTimeout(() => { setTimeout(resolve, 500); // 等待 0.5 秒后执行 resolve }, 100); // } else { // 如果没有动画,直接完成 resolve(); } return; } } } } if (!found) { this.tipNofind(); } // 如果没有找到可消除的方块,直接完成 resolve(); }); } highlight(node1: Block, node2: Block) { if (!node1 || !node1.isValid) return; node1.getComponent(Sprite).color = new Color(0, 255, 0); node2.getComponent(Sprite).color = new Color(0, 255, 0); } private resetAllBlocksAnimation1() { let blockNode = this.blockLink.sleeBlock; if (!blockNode || !blockNode.isValid) return; const blockComp = blockNode.getComponent(Block); if (blockComp && blockComp.isValid) { blockComp.stateBlock = BlockState.Normal; this.blockLink.sleeBlock = null; blockComp.applyStateStyle(); } } //关闭或打开按钮 guanbibtn(tiaojian: boolean) { this.sx_btn.interactable = tiaojian; this.cz_btn.interactable = tiaojian; this.xc_btn.interactable = tiaojian; this.js_btn.interactable = tiaojian; } }