import { _decorator, Component, Mask, Node, Sprite, SpriteFrame, UITransform, v3, Vec3 } from 'cc'; import { IconFactory } from './IconFactory'; import { Roller } from './Roller'; import { GameData, ICON_HEIGHT, ICON_WIDTH, ROLLER_COMBINE_EVENT, ROLLER_EVENT } from './Define'; import { AudioManager } from '../../../Loading/scripts/manager/AudioManager'; import { BaseRoller } from './BaseRoller'; import { HRoller } from './HRoller'; let { ccclass, property, executeInEditMode } = _decorator; @ccclass('RollerManager') @executeInEditMode export class RollerManager extends Component { @property({ tooltip: '图标的宽度' }) iconWidth: number = ICON_WIDTH; @property({ tooltip: '图标的高度' }) iconHeight: number = ICON_HEIGHT; @property({ tooltip: '图标之间的水平距离' }) iconHMerge: number = 0; @property({ type: IconFactory, tooltip: '图标工厂' }) iconFactory: IconFactory = null; @property(SpriteFrame) hMaskSpriteFrame: SpriteFrame = null; @property(SpriteFrame) vMaskSpriteFrame: SpriteFrame = null; rollerMsg: any[] = [ { row: 1, col: 4, isHorizontal: true }, { row: 5, col: 1, isHorizontal: false }, { row: 5, col: 1, isHorizontal: false }, { row: 5, col: 1, isHorizontal: false }, { row: 5, col: 1, isHorizontal: false }, { row: 5, col: 1, isHorizontal: false }, { row: 5, col: 1, isHorizontal: false }, ]; // 横向滚轮数组 hRollers: HRoller[] = []; // 竖向滚轮数组 vRollers: Roller[] = []; // 滚轮数组 allRollers: BaseRoller[] = []; // 是否快速旋转 _isFastSpin: boolean = false; // 是否手动停止 _isManualStop: boolean = false; // spinData _spinData: GameData = null; /** 分割过的数据,一位数组改为二维数组, 每个元素代表一个滚轮 */ _resultStopData: number[][] = []; // 是否是免费游戏 _isFreeSpin: boolean = false; // 不规则图标信息 _crossSymbols: any = null; // 处理过的不规则icon信息 _processedCrossSymbols: any = null; private hMaskNode: Node = null; private vMaskNode: Node = null; // 添加计数器 private _deletedRollerCount: number = 0; private _createdRollerCount: number = 0; private _fallenRollerCount: number = 0; @property _format = false; @property({ tooltip: '格式化' }) get format(): boolean { return this._format; } set format(a: boolean) { this._format = a; this.node.removeAllChildren(); this.allRollers = []; this.hRollers = []; this.vRollers = []; this.hMaskNode = this.createMaskNode('HMask', this.hMaskSpriteFrame); this.vMaskNode = this.createMaskNode('VMask', this.vMaskSpriteFrame); this.node.addChild(this.hMaskNode); this.node.addChild(this.vMaskNode); let rollerLength = this.rollerMsg.length; for (let i = 0; i < rollerLength; i++) { let rollerMsg = this.rollerMsg[i]; if (rollerMsg.isHorizontal) { let hRoller = HRoller.create(i, rollerMsg.col, this.iconWidth, this.iconHeight, this.iconFactory); // hRoller.format = true; this.hMaskNode.addChild(hRoller.node); let rollerPosition = new Vec3(0, 3 * this.iconHeight + 35, 0); this.hMaskNode.setPosition(rollerPosition); // hRoller.node.setPosition(rollerPosition); // 保存引用 this.hRollers.push(hRoller); this.allRollers.push(hRoller); } else { let roller = Roller.create(i, rollerMsg.row, this.iconWidth, this.iconHeight, this.iconFactory); // roller.format = true; this.vMaskNode.addChild(roller.node); let rollerPosition = this.getRollerPosition(i - 1); roller.node.setPosition(rollerPosition); this.vRollers.push(roller); this.allRollers.push(roller); } } } private createMaskNode(name: string, spriteFrame: SpriteFrame): Node { let maskNode = new Node(); maskNode.name = name; let comp = maskNode.addComponent(Mask); comp.type = Mask.Type.SPRITE_STENCIL; let spriteCom = maskNode.getComponent(Sprite); spriteCom.spriteFrame = spriteFrame; spriteCom.sizeMode = Sprite.SizeMode.CUSTOM; spriteCom.trim = true; return maskNode; } protected onLoad(): void { this.format = true; this.scatterPos = []; this.registerEvent(); // 重置计数器 this._deletedRollerCount = 0; this._createdRollerCount = 0; this._fallenRollerCount = 0; } protected update(dt: number): void { for (let i = 0; i < this.allRollers.length; i++) { let roller = this.allRollers[i]; roller.localUpdate(dt); } } registerEvent() { for (let lx = 0; lx < this.allRollers.length; lx++) { let roller = this.allRollers[lx]; roller.node.on(ROLLER_EVENT.ON_R_ICON_CREATE, this.onRollerRIconCreate, this); roller.node.on(ROLLER_EVENT.LAST_PAGE_CREATE, this.onRollerLastPageCreate, this); roller.node.on(ROLLER_EVENT.ROLLER_BOUNCE, this.onRollerBounce, this); roller.node.on(ROLLER_EVENT.ROLLER_DECELERATE, this.onRollerSlowDown, this); roller.node.on(ROLLER_EVENT.ROLLER_STOP, this.onRollerStop, this); roller.node.on(ROLLER_EVENT.ROLLER_UNIFORM, this.onRollerUniform, this); roller.node.on(ROLLER_EVENT.ICON_DELETED, this.onRollerIconDeleted, this); roller.node.on(ROLLER_EVENT.ICON_CREATE, this.onRollerIconCreate, this); roller.node.on(ROLLER_EVENT.ICON_FALLEN, this.onRollerIconFallen, this); } } setFastSpin(isFastSpin: boolean) { this._isFastSpin = isFastSpin; this.allRollers.forEach(roller => { roller.setFastSpin(isFastSpin); }) } getIsFastSpin(): boolean { return this._isFastSpin; } setIsFreeSpin(isFreeSpin: boolean) { this._isFreeSpin = isFreeSpin; } changeSpeedFast() { this.allRollers.forEach(roller => { if (roller.isScroll()) { roller.changeSpeed(); } }) } // 随机创建ICON回调 onRollerRIconCreate() { return; } // 最后一页创建的回调 onRollerLastPageCreate(rollerId: number) { if (this._isFastSpin) return; let isExpect = this.checkNextRollerExpect(rollerId); let nextStopRollerId = this.getNextRollerIndex(rollerId); let stopSpeedData = this._isFastSpin ? [[0, 6000]] : [[0.1, 3500]]; if (!this._isFastSpin) { stopSpeedData = isExpect ? [[1, 4000], [0.5], [0.1, 2500], [0.5], [0.5, 725]] : [[0.1, 3500]]; } if (nextStopRollerId != -1) { let nextStopRollerCrossSymbols = this._processedCrossSymbols[nextStopRollerId]; this.allRollers[nextStopRollerId].setCrossSymbols(nextStopRollerCrossSymbols); this.allRollers[nextStopRollerId].stopScroll(this._resultStopData[nextStopRollerId], stopSpeedData, this._spinData.XnInfo); } return; } scatterPos: number[] = []; checkNextRollerExpect(rollerId: number, needScatterCount: number = 3) { let curScatterCount = 0; this.scatterPos = []; let topData = this._resultStopData[0]; topData.forEach((iconIndex, index) => { if (iconIndex == 1) { curScatterCount++; this.scatterPos.push(index); } }) // 检查所有已经停止的垂直滚轮(包括当前滚轮) for (let i = 1; i <= rollerId; i++) { const rollerData = this._resultStopData[i]; if (!rollerData) continue; // 检查每个位置 for (let j = 0; j < rollerData.length; j++) { // 检查是否有交叉符号覆盖该位置 if (this._processedCrossSymbols && this._processedCrossSymbols[i] && this._processedCrossSymbols[i][j]) { const symbolInfo = this._processedCrossSymbols[i][j]; // 只计算开始位置,避免重复计数 if (symbolInfo.isStart && symbolInfo.iconIndex === 1) { curScatterCount++; this.scatterPos.push(4 + (i - 1) * 5 + symbolInfo.startPos); } } // 如果位置没有被交叉符号覆盖,且是scatter else if (rollerData[j] === 1) { curScatterCount++; this.scatterPos.push(4 + (i - 1) * 5 + j); } } } return curScatterCount >= needScatterCount; } getScatterPos(): number[] { return this.scatterPos; } // 滚轮回弹的回调 onRollerBounce(rollerId: number) { return; } // 滚轮减速的回调 onRollerSlowDown() { return; } // 滚轮停止的回调 onRollerStop(rollerId: number) { this.node.emit(ROLLER_COMBINE_EVENT.ONE_ROLLER_STOP, rollerId); // 检测当前滚轮的icon下标是否是8 let stopData = this._resultStopData[rollerId]; let isWild = stopData.indexOf(0) !== -1; let isScatter = stopData.indexOf(1) !== -1; if (!this._isFreeSpin && !this._isManualStop && !this._isFastSpin) { if (isWild && !isScatter) { AudioManager.instance.playSFX('Appear_Wild_Sound'); } if (isScatter) { AudioManager.instance.playSFX('Appear_Scatter_Sound'); } if (!isWild && !isScatter) { AudioManager.instance.playSFX('Scroll_Stop_Sound'); } } let allRollerStop = true; for (let i = 0; i < this.allRollers.length; i++) { let roller = this.allRollers[i]; if (roller.isScroll()) allRollerStop = false; } if (allRollerStop) { this.node.emit(ROLLER_COMBINE_EVENT.ALL_ROLLER_STOP); if (this._isFastSpin || this._isManualStop) { let hasScatter = this.scatterPos.length > 0; let hasWild = false; this._resultStopData.forEach(stopData => { if (stopData.indexOf(0) !== -1) { hasWild = true; } }) if (hasWild && !hasScatter) { AudioManager.instance.playSFX('Appear_Wild_Sound'); } if (hasScatter) { AudioManager.instance.playSFX('Appear_Scatter_Sound'); } if (!hasWild && !hasScatter) { AudioManager.instance.playSFX('Scroll_Stop_Sound'); } } } } // 滚轮匀速时候的回调 onRollerUniform() { return; } // 滚轮icon删除的回调 onRollerIconDeleted(rollerId: number) { this._deletedRollerCount++; if (this._deletedRollerCount >= this.allRollers.length) { this._deletedRollerCount = 0; // 重置计数器 this.node.emit(ROLLER_COMBINE_EVENT.ALL_ROLLER_ICONS_DELETED); } } // 滚轮icon创建的回调 onRollerIconCreate(rollerId: number) { this._createdRollerCount++; if (this._createdRollerCount >= this.allRollers.length) { this._createdRollerCount = 0; // 重置计数器 this.node.emit(ROLLER_COMBINE_EVENT.ALL_ROLLER_ICONS_CREATED); } } // 滚轮icon掉落的回调 onRollerIconFallen(rollerId: number) { this._fallenRollerCount++; if (this._fallenRollerCount >= this.allRollers.length) { this._fallenRollerCount = 0; // 重置计数器 this.node.emit(ROLLER_COMBINE_EVENT.ALL_ROLLER_ICONS_FALLEN); } } // 滚轮是否在滚动 isScroll(): boolean { for (let lx = 0; lx < this.allRollers.length; lx++) { let roller = this.allRollers[lx]; if (roller.isScroll()) return true; } return false; } // 初始化滚轮数据 initRollerWithIcon(data: GameData) { this._spinData = data; let topData = data.PanColor.Top; let bottomData = data.PanColor.Bottom; this._crossSymbols = data.CrossSymbols; // 分割数据 this._resultStopData = [topData, ...this.splitArray(bottomData, [5, 5, 5, 5, 5, 5])]; // 处理n*1符号 let processedCrossSymbols = this.processCrossSymbolsForRollers(); for (let i = 0; i < this.allRollers.length; i++) { let roller = this.allRollers[i]; let rollerCrossSymbols = processedCrossSymbols[i]; roller.initRollerWithIcon(i, this._resultStopData[i], rollerCrossSymbols, this._spinData.XnInfo); } } /** * 只处理竖向滚轮 * 处理n*1符号数据,为每个滚轮准备对应的n*1符号信息 * @returns 处理后的n*1符号数据数组,每个元素对应一个滚轮 */ private processCrossSymbolsForRollers(): any[] { this._processedCrossSymbols = []; let row = 5; let col = 6; // 如果没有交叉符号数据,返回空对象数组 if (!this._crossSymbols) { return new Array(col).fill({}); } // 为每个滚轮创建一个空对象 let rollerSymbols: any[] = []; for (let i = 0; i < col; i++) { rollerSymbols.push({}); } // 遍历所有交叉符号 for (let symbolId in this._crossSymbols) { let symbol = this._crossSymbols[symbolId]; // 计算符号所在的滚轮索引 let rollerIndex = Math.floor(symbol.PosFirst / 5); // 计算在滚轮中的起始和结束位置 let startPos = symbol.PosFirst % row; let endPos = symbol.PosLast % row; // 在滚轮的每个位置上设置符号信息 for (let pos = startPos; pos <= endPos; pos++) { rollerSymbols[rollerIndex][pos] = { id: symbolId, isStart: pos === startPos, isEnd: pos === endPos, startPos: startPos, endPos: endPos, lHeight: endPos - startPos + 1, frameType: symbol.FrameType, iconIndex: symbol.Color }; } } this._processedCrossSymbols = [{}, ...rollerSymbols]; return this._processedCrossSymbols; } // 滚轮Icon生成规则 setRollerIconRule(rollerIconRule: number[][]) { for (let i = 0; i < this.allRollers.length; i++) { this.allRollers[i].setRollerIconRule(rollerIconRule[i]); } } getIconNode(pos: number): Node { let lx = this.getLx(pos); let ly = this.getLy(pos); let roller = this.allRollers[lx]; return roller.getIconNode(ly); } getLx(pos: number): number { let currentPos = pos; for (let i = 0; i < this.rollerMsg.length; i++) { let roller = this.rollerMsg[i]; let rollerSize = roller.row * roller.col; if (currentPos < rollerSize) { return i; } currentPos -= rollerSize; } return -1; // 如果位置超出范围,返回-1 } getLy(pos: number): number { let currentPos = pos; // 先找到对应的滚轮 let rollerId = this.getLx(pos); if (rollerId === -1) return -1; // 计算在当前滚轮之前的所有位置数 for (let i = 0; i < rollerId; i++) { let roller = this.rollerMsg[i]; currentPos -= (roller.row * roller.col); } let currentRoller = this.rollerMsg[rollerId]; if (currentRoller.isHorizontal) { // 横向滚轮直接返回列位置 return currentPos; } else { // 纵向滚轮返回行位置 return currentPos % currentRoller.row; } } // 获取第一个可以停止的滚轮id getFirstRollerIndex(): number { return 0; } // 获取下一个可以停止的滚轮id getNextRollerIndex(id: number): number { for (let lx = id + 1; lx < this.allRollers.length; lx++) { return lx; } return -1; } resetInfo() { this.allRollers.forEach(roller => { roller.resetInfo(); }) } getIsManualStop(): boolean { return this._isManualStop; } // 滚轮开始滚动 startScroll() { this.scatterPos = []; this._isManualStop = false; this.allRollers.forEach(roller => { roller.startScroll(); }) } // 滚轮停止滚动 stopScroll(data: GameData) { this._spinData = data; this._resultStopData = []; // 分割底盘数据 this._resultStopData = [data.PanColor.Top, ...this.splitArray(data.PanColor.Bottom, [5, 5, 5, 5, 5, 5])]; // 处理不对则icon this._crossSymbols = data.CrossSymbols; let processedCrossSymbols = this.processCrossSymbolsForRollers(); let stopSpeedData = this._isFastSpin ? [[0, 6000]] : [[0.1, 3500]]; if (this._isFastSpin) { // this.stopAllRollersImmediately(processedCrossSymbols); for (let i = 0; i < this.allRollers.length; i++) { let stopData = this._resultStopData[i]; let roller = this.allRollers[i]; let rollerCrossSymbols = processedCrossSymbols[i]; roller.setCrossSymbols(rollerCrossSymbols); roller.stopScroll(stopData, stopSpeedData, data.XnInfo) } } else { // this.stopRollersInSequence(processedCrossSymbols); let firstRollerCrossSymbols = processedCrossSymbols[0]; this.allRollers[0].setCrossSymbols(firstRollerCrossSymbols); this.allRollers[0].stopScroll(this._resultStopData[0], stopSpeedData, data.XnInfo); } } stopRollersInSequence(processedCrossSymbols: any[]) { let standardStopDuration = [[0.1, 3500]]; } manualStop(data: GameData) { this._isManualStop = true; this._resultStopData = []; let topData = data.PanColor.Top; this._resultStopData = [topData, ...this.splitArray(data.PanColor.Bottom, [5, 5, 5, 5, 5, 5])]; this._crossSymbols = data.CrossSymbols; let processedCrossSymbols = this.processCrossSymbolsForRollers(); for (let i = 0; i < this.allRollers.length; i++) { let stopData = this._resultStopData[i]; let roller = this.allRollers[i]; let rollerCrossSymbols = processedCrossSymbols[i]; roller.setCrossSymbols(rollerCrossSymbols); roller.manualStopScroll(stopData, data.XnInfo) } } // 对服务器下发的数据进行操作 splitArray(arr: T[], sizes: number[]): T[][] { let result: T[][] = []; let currentIndex = 0; for (let size of sizes) { let subArray = arr.slice(currentIndex, currentIndex + size); result.push(subArray); currentIndex += size; } return result; } // 获取滚轮的坐标 getRollerPosition(id: number): Vec3 { let col = 6; let hMiddle = Math.floor(col / 2); let x = -(col % 2 == 0 ? hMiddle - 0.5 : hMiddle) * (this.iconWidth + this.iconHMerge); let xdis = id * this.iconWidth + id * this.iconHMerge; return v3(x + xdis, 0, 0); } // 获取icon坐标 getIconWorldPosition(pos: number) { let lx = this.getLx(pos); let roller = this.allRollers[lx]; return roller.getIconWorldPosition(this.getLy(pos)); } getContentNode(pos: number): Node { let lx = this.getLx(pos); let roller = this.allRollers[lx]; return roller.getContentNode(); } showMultiMove(XnInfo) { for (let i = 0; i < this.allRollers.length; i++) { let roller = this.allRollers[i]; roller.showMultiMove(XnInfo) } } // 将图标移动到win层并处理删除和动画 handleWinIcons(winLayer: Node, deleteMsg: number[], aniData: number[]) { if (deleteMsg.length === 0 && aniData.length === 0) { return; // 没有需要处理的图标,直接返回 } // 激活win层 winLayer.active = true; // 1. 找出所有需要处理的唯一位置 let processedNodes = new Set(); let uniquePositions = []; // 合并并去重处理位置 [...deleteMsg, ...aniData].forEach(pos => { let iconNode = this.getIconNode(pos); if (iconNode && !processedNodes.has(iconNode)) { uniquePositions.push(pos); processedNodes.add(iconNode); } }); // 2. 缓存winLayer的UITransform以提高性能 let winLayerTransform = winLayer.getComponent(UITransform); // 3. 将所有需处理的图标移动到win层 uniquePositions.forEach(pos => { let iconNode = this.getIconNode(pos); if (iconNode) { // 保存原始父节点和位置信息到Map中 this.winIconNodeMap.set(pos, { node: iconNode, originalParent: iconNode.parent, originalPosition: iconNode.position.clone() }); // 计算并设置正确位置 let worldPos = this.getIconWorldPosition(pos); if (worldPos) { let localPos = winLayerTransform.convertToNodeSpaceAR(worldPos); iconNode.parent = winLayer; iconNode.setPosition(localPos); } } }); // 4. 准备删除操作的数据结构 let rollerDeletePositions = new Map(); let rollerAniPos = new Map(); // 5. 分类处理需要删除的位置 deleteMsg.forEach(pos => { let lx = this.getLx(pos); let ly = this.getLy(pos); if (!rollerDeletePositions.has(lx)) { rollerDeletePositions.set(lx, []); } rollerDeletePositions.get(lx).push(ly); }); // 6. 分类处理需要动画的位置 aniData.forEach(pos => { let lx = this.getLx(pos); let ly = this.getLy(pos); if (!rollerAniPos.has(lx)) { rollerAniPos.set(lx, []); } rollerAniPos.get(lx).push(ly); }); // 7. 执行删除操作 rollerDeletePositions.forEach((positions, lx) => { if (positions.length > 0) { this.allRollers[lx].deleteIconNode(positions); } }); AudioManager.instance.playSFX('Win_Frame_Sound'); // 8. 执行动画操作 rollerAniPos.forEach((positions, lx) => { if (positions.length > 0) { this.allRollers[lx].playFrameTypeChangeAni(positions); } }); // 保存一个引用以避免闭包中的引用问题 let positionsCopy = [...uniquePositions]; let winLayerRef = winLayer; // 9. 计算动画播放时间并处理没有删除图标的roller let animationTime = aniData.length > 0 ? 2.4 : 1.2; let rollersWithoutDeleteOps = []; for (let i = 0; i < this.allRollers.length; i++) { if (!rollerDeletePositions.has(i) || rollerDeletePositions.get(i).length === 0) { rollersWithoutDeleteOps.push(i); } } // 10. 使用单个计时器处理所有没有删除操作的roller if (rollersWithoutDeleteOps.length > 0) { this.scheduleOnce(() => { rollersWithoutDeleteOps.forEach(i => { this.allRollers[i].node.emit(ROLLER_EVENT.ICON_DELETED, this.allRollers[i]); }); }, animationTime); } // 11. 添加清理函数,根据需要在适当时机调用 this.scheduleOnce(() => { AudioManager.instance.playSFX('Win_Eliminate_Sound'); if (rollerAniPos.size > 0) { AudioManager.instance.playSFX('Symbol_Change_Sound'); } this.returnIconsFromWinLayer(winLayerRef, positionsCopy); }, 1.1); // 在动画结束前稍早将图标移回 } // 将图标从win层返回到原始层 private returnIconsFromWinLayer(winLayer: Node, positions: number[]) { if (!winLayer || !positions || positions.length === 0) { console.warn("Invalid arguments in returnIconsFromWinLayer"); if (winLayer) winLayer.active = false; return; } positions.forEach(pos => { let iconInfo = this.winIconNodeMap.get(pos); // 检查图标信息是否存在 if (!iconInfo) { console.warn(`No info found for icon at position ${pos}`); return; // 跳过当前图标 } let { node: iconNode, originalParent, originalPosition } = iconInfo; // 检查图标是否还存在(可能已被删除) if (iconNode && iconNode.isValid && originalParent && originalParent.isValid) { try { // 直接使用保存的原始父节点和位置信息 iconNode.parent = originalParent; iconNode.position = originalPosition; } catch (error) { console.error(`Error moving icon back at position ${pos}:`, error); } } else { console.warn(`Icon or original parent is invalid for position ${pos}`); } // 无论处理成功与否,都清理引用 this.winIconNodeMap.delete(pos); }); // 隐藏win层 winLayer.active = false; } // changeIconAndFrameType(panChanges: any[]) { // let rollerChangePositions: Map = new Map(); // panChanges.forEach(change => { // let lx = this.getLx(change.oldStartPos); // let ly = this.getLy(change.oldStartPos); // // 获取或创建该列的变化位置数组 // if (!rollerChangePositions.has(lx)) { // rollerChangePositions.set(lx, []); // } // // 将oldStartPos改为ly并添加到对应列的数组中 // change.oldStartPos = ly; // rollerChangePositions.get(lx).push(change); // }) // rollerChangePositions.forEach((changes, lx) => { // this.allRollers[lx].chanegeIconAndFrameType(changes); // }) // } createNewIconTop(createDatas: number[][], spinData: any) { this.allRollers.forEach((roller, index) => { let createData = createDatas[index]; roller.createNewIconTop(createData, spinData.XnInfo); }) } iconFallDown(data: GameData) { this._spinData = data; this._resultStopData = []; this._fallenRollerCount = 0; // 重置计数器 this._deletedRollerCount = 0; // 分割底盘数据 this._resultStopData = [data.PanColor.Top, ...this.splitArray(data.PanColor.Bottom, [5, 5, 5, 5, 5, 5])]; // 处理不对则icon this._crossSymbols = data.CrossSymbols; let processedCrossSymbols = this.processCrossSymbolsForRollers(); //从右到左掉落 this.allRollers.forEach((roller, index) => { let idx = this.allRollers.length - index - 1 let roll = this.allRollers[idx] this.scheduleOnce(() => { let stopData = this._resultStopData[idx]; let rollerCrossSymbols = processedCrossSymbols[idx]; roll.setCrossSymbols(rollerCrossSymbols); this.scheduleOnce(() => { roll.iconFallDown(stopData, rollerCrossSymbols) }, 0.01 * index) }, 0.06 * index) }) // 在第一个图标开始掉落时播放音效 this.scheduleOnce(() => { AudioManager.instance.playSFX('Win_Symbol_Fall'); }, 0.3); } onDestroy(): void { // 清理事件监听 for (let roller of this.allRollers) { roller.node.off(ROLLER_EVENT.ON_R_ICON_CREATE, this.onRollerRIconCreate, this); roller.node.off(ROLLER_EVENT.LAST_PAGE_CREATE, this.onRollerLastPageCreate, this); roller.node.off(ROLLER_EVENT.ROLLER_BOUNCE, this.onRollerBounce, this); roller.node.off(ROLLER_EVENT.ROLLER_DECELERATE, this.onRollerSlowDown, this); roller.node.off(ROLLER_EVENT.ROLLER_STOP, this.onRollerStop, this); roller.node.off(ROLLER_EVENT.ROLLER_UNIFORM, this.onRollerUniform, this); roller.node.off(ROLLER_EVENT.ICON_DELETED, this.onRollerIconDeleted, this); roller.node.off(ROLLER_EVENT.ICON_CREATE, this.onRollerIconCreate, this); roller.node.off(ROLLER_EVENT.ICON_FALLEN, this.onRollerIconFallen, this); } } // 修改winIconNodeMap的类型为存储更多信息 private winIconNodeMap: Map = new Map(); }