/** * 负责单个滚轮的创建、滚动、停止等逻辑 */ import { _decorator, Node, UITransform, Vec2, v2, Vec3, v3, tween, Tween, } from 'cc'; import { IconFactory } from './IconFactory'; import { Icon } from './Icon'; import { BaseRoller, ROLLER_STATE } from './BaseRoller'; import { ICON_STATE, ROLLER_COMBINE_EVENT, ROLLER_EVENT } from './Define'; import { AudioManager } from 'db://assets/Loading/scripts/manager/AudioManager'; let { ccclass, property, executeInEditMode } = _decorator; /** * 滚轮组件类 */ @ccclass('Roller') @executeInEditMode export class Roller extends BaseRoller { // 编辑器属性 @property({ tooltip: '行数' }) row: number = 3; // 本地格式化相关 @property private _format = false; @property({ tooltip: '本地格式化' }) get format(): boolean { return this._format; } set format(b: boolean) { this._format = b; this.resizeContentSize(); if (!this.iconFactory) { console.error('IconFactory没有设置'); return; } // 重新创建图标 this._content.removeAllChildren(); this._info.icons = []; this._allIcons.clear(); this._posToIconKey.clear(); // 清除位置缓存 - 添加这一行 this._positionCache.clear(); for (let i = 0; i < this.row; i++) { let randomIndex = Math.floor(Math.random() * this.iconFactory.getIconNum()); this.createNormalIcon(i, randomIndex); } } _cachedContentHeight: number = 0; _cachedAnchorY: number = 0; /** * 创建滚轮实例 * @param id 滚轮ID * @param row 行数 * @param iconWidth 图标宽度 * @param iconHeight 图标高度 * @param iconFactory 图标工厂实例 * @param anchor 锚点位置 * @returns 新创建的滚轮实例 */ static create( id: number, row: number, iconWidth: number, iconHeight: number, iconFactory: IconFactory, anchor: Vec2 = v2(0.5, 0.5) ): Roller { let rollerNode = new Node(`Roller${id}`); rollerNode.addComponent(UITransform); let roller = rollerNode.addComponent(Roller); roller._rollerId = id; roller.row = row; roller.iconWidth = iconWidth; roller.iconHeight = iconHeight; roller.iconFactory = iconFactory; rollerNode.getComponent(UITransform).setAnchorPoint(anchor); roller.resizeContentSize(); roller.initRoller(id); return roller; } /** * 设置节点尺寸和位置 */ setupNodesSizeAndPosition() { let totalHeight = this.iconHeight * this.row; let anchorPoint = this.node.getComponent(UITransform).anchorPoint; // 设置主节点尺寸 this.node.getComponent(UITransform).setContentSize(this.iconWidth, totalHeight); // 设置view节点 this._view.setPosition(0, 0); this._view.getComponent(UITransform).setContentSize(this.iconWidth, totalHeight); this._view.getComponent(UITransform).setAnchorPoint(anchorPoint); this._view.getComponent(UITransform).width *= 2; // 设置content节点 this._content.setPosition(0, 0); this._content.getComponent(UITransform).setContentSize(this.iconWidth, totalHeight); this._content.getComponent(UITransform).setAnchorPoint(anchorPoint); this._content.removeAllChildren(); } /** * 获取图标的实际坐标 * @param pos 图标位置索引 * @param size 图标大小 * @returns 图标的世界坐标 */ getIconPosition(pos: number, size: number = 1): Vec3 { // 创建缓存键 let cacheKey = size > 1 ? (pos + 1) * 1000 + size : pos; if (this._positionCache.has(cacheKey)) { return this._positionCache.get(cacheKey).clone(); } // 确保缓存数据已初始化 if (!this._cachedContentHeight) { this._cachedContentHeight = this._content.getComponent(UITransform).height; this._cachedAnchorY = this._content.getComponent(UITransform).anchorY; } // 计算基准位置 let contentHeight = this._cachedContentHeight; let anchorY = this._cachedAnchorY; // 计算顶部位置 let topY = contentHeight * (1 - anchorY); // 计算第一个位置的中心Y坐标 let firstCenterY = topY - this.iconHeight / 2; // 计算当前位置的中心Y坐标 let centerY = firstCenterY - pos * this.iconHeight; // 对于大图标,需要调整位置 let finalY = centerY; if (size > 1) { // 大图标的中心点应该下移,使其顶部对齐格子 // 对于高度为3的图标,中心点应该下移1个格子高度 finalY = centerY - (size - 1) * this.iconHeight / 2; } // 创建最终位置 let position = v3(0, finalY, 0); // 缓存结果 this._positionCache.set(cacheKey, position.clone()); return position; } /** * 初始化性能优化相关的缓存 */ initCache() { this._cachedUITransform = this._content.getComponent(UITransform); this._cachedContentHeight = this._cachedUITransform.height; this._cachedAnchorY = this._cachedUITransform.anchorY; } /** * 收集现有图标 */ collectExistingIcons() { for (let i = 0; i < this.row; i++) { let icon = this._allIcons.get(this._posToIconKey.get(i)); if (icon) { this._allIcons.delete(this._posToIconKey.get(i)); this._posToIconKey.delete(i); this._info.icons.push(icon); } } } startScroll() { if (this._info.state != ROLLER_STATE.STOP) return; this.collectExistingIcons(); let speedData = this.getInitialSpeedData(); this.changeState(ROLLER_STATE.ACCELERATE); this.tweenSpeed(speedData, () => { let uniformSpeedData = this._info.isFastSpin ? [[0]] : [[0.6]]; this.changeState(ROLLER_STATE.UNIFORM); if (this._info.isManualStop) { this._info.speedDataComplete = true; let stopSpeedData = this._info.isFastSpin ? [[0, 15000]] : [[0.3, 15000]]; if (this._info.receiveStopData) { this.stopScrollWork(stopSpeedData); } return; } this.tweenSpeed(uniformSpeedData, () => { this._info.speedDataComplete = true; let rollerSpeed = this.row * this.iconHeight / 0.1 * 175; let stopSpeedData = this._info.isFastSpin ? [[0, rollerSpeed]] : [[0.4, 5500]]; if (this._info.receiveStopData) { this.stopScrollWork(stopSpeedData); } }); }); } stopScroll(panData: number[], stopSpeedDataExpect?: number[][]) { this._stopData = panData; let stopSpeedData = []; if (stopSpeedDataExpect) { stopSpeedData = stopSpeedDataExpect; } else { let rollerSpeed = this.row * this.iconHeight / 0.1 * 175; stopSpeedData = this._info.isFastSpin ? [[0, rollerSpeed]] : [[0.4, 5500]]; } this._info.receiveStopData = true; if (this._info.speedDataComplete) { this.stopScrollWork(stopSpeedData); } } stopScrollWork(stopSpeedData: number[][]) { this._info.hasStopScrollWork = true; this.changeState(ROLLER_STATE.DECELERATE); this._info.stopSpeedData = stopSpeedData; this.tweenSpeed(this._info.stopSpeedData, () => { this.changeState(ROLLER_STATE.LAST_PAGE_CREATE); }); } /** * 手动停止滚动 * @param data 停止时的图标数据 */ async manualStopScroll(data: number[]) { this.resetInfo(); this._stopData = data; this._info.isManualStop = true; Tween.stopAllByTarget(this._info.speedNode); // 回收所有动态图标 while (this._info.icons.length > 0) { let icon = this._info.icons.pop(); this.iconFactory.recycleIcon(icon); } // 回收固定位置图标 for (let i = 0; i < this.row; i++) { let icon = this._allIcons.get(this._posToIconKey.get(i)); if (icon) { this._allIcons.delete(this._posToIconKey.get(i)); this._posToIconKey.delete(i); this.iconFactory.recycleIcon(icon); } } this.createInitIcons(data); this.changeState(ROLLER_STATE.STOP); } /** * 创建最后一页图标 */ createLastPage() { let data = this._stopData; if (!data) return; // 计算顶部基准位置 let topY = this.getIconPosition(0).y; let icons = this._info.icons; if (icons.length > 0) { topY = Math.max(topY, this.findHighestIconXorY(icons)); } // 清除已有的位置映射,准备重新创建 this._allIcons.clear(); this._posToIconKey.clear(); // 从上到下依次创建图标(从位置0开始) for (let i = 0; i < data.length; i++) { // 检查当前位置是否需要创建特殊图标(n*1图标) if (this._CroSymbols && this._CroSymbols[i]) { let iconSpecialMsg = this._CroSymbols[i]; // 检查这个特殊图标是否已经被处理过 let isProcessed = false; for (let j = 0; j < i; j++) { if (this._CroSymbols[j] && this._CroSymbols[j].id === iconSpecialMsg.id) { isProcessed = true; break; } } // 如果这个特殊图标还没有被处理,创建它 if (!isProcessed) { let startPos = iconSpecialMsg.startPos; let endPos = iconSpecialMsg.endPos; let height = iconSpecialMsg.lHeight; let iconIndex = iconSpecialMsg.iconIndex; let frameType = iconSpecialMsg.Type; // 生成图标ID let iconKey = this.generateIconKey(startPos, height, endPos); // 创建图标节点 let icon = this.iconFactory.icfactoryCreateIcon(iconIndex); icon.getComponent(Icon).initIcon(iconIndex, height, iconKey, frameType, this._rollerId); // 计算位置 // 计算该位置普通图标应该在的Y坐标 let normalIconY = topY + (this.row - startPos) * this.iconHeight; // 对于大图标,需要考虑其锚点在中心,向下偏移(height-1)/2个格子高度 let offsetY = (height - 1) * this.iconHeight / 2; // 最终位置 let y = normalIconY - offsetY; icon.setPosition(0, y, 0); this._content.addChild(icon); icon.getComponent(Icon).changeIconState(ICON_STATE.IDLE); // 存储图标节点 this._allIcons.set(iconKey, icon); // 设置位置映射 for (let i = 0; i < height; i++) { this._posToIconKey.set(startPos + i, iconKey); } } } // 如果当前位置已被特殊图标占用,跳过 if (this._posToIconKey.has(i)) continue; // 生成图标ID let pos = i; let iconIndex = data[i]; let iconKey = this.generateIconKey(pos, 1, pos); // 创建图标节点 let icon = this.iconFactory.icfactoryCreateIcon(iconIndex); icon.getComponent(Icon).initIcon(iconIndex, 1, iconKey, 0, this._rollerId); // 计算位置 let y = topY + (this.row - pos) * this.iconHeight; icon.setPosition(0, y, 0); this._content.addChild(icon); icon.getComponent(Icon).changeIconState(ICON_STATE.IDLE); // 存储图标节点 this._allIcons.set(iconKey, icon); this._posToIconKey.set(pos, iconKey); } this.node.emit(ROLLER_EVENT.LAST_PAGE_CREATE, this._rollerId); } /** * 检查图标是否超出显示范围 */ checkDeadLine(icon: Node): boolean { if (!this._cachedContentHeight) { this._cachedContentHeight = this._content.getComponent(UITransform).height; this._cachedAnchorY = this._content.getComponent(UITransform).anchorY; } let iconComponent = icon.getComponent(Icon); let lheight = iconComponent.lHeight; let iconBody = (lheight - 1) * this.iconHeight + this.iconHeight / 2; let deadLine = -(this._cachedContentHeight * this._cachedAnchorY) - iconBody; return icon.position.y <= deadLine; } /** * 补充新的图标 */ suppleIcon() { let bornLine = this.getIconPosition(0, 1).y; let icons = this._info.icons; // 找到最高的图标Y坐标 let topY = this.findHighestIconXorY(icons); // 如果最高的图标低于出生线,创建新图标 if (topY < bornLine) { this.createRandomIcon(); } } /** * 创建随机图标 */ createRandomIcon() { let iconIndex = this.getRandomIconIndex(); let newY = this.computeNewIconXorY(); let icon = this.iconFactory.icfactoryCreateIcon(iconIndex); // 设置快速图标效果 if (this.shouldShowFastIcon()) { icon.getComponent(Icon).showFastIcon(true); } icon.setPosition(0, newY, 0); this._content.addChild(icon); icon.getComponent(Icon).changeIconState(ICON_STATE.IDLE); this._info.icons.push(icon); this.node.emit(ROLLER_EVENT.ON_R_ICON_CREATE, this._rollerId, icon); } /** * 找到最高的图标Y坐标 * @param icons 图标数组 * @returns 最高的Y坐标 */ findHighestIconXorY(icons: Node[]): number { return icons.reduce((maxY, icon) => { if (!icon || !icon.active) return maxY; let iconComponent = icon.getComponent(Icon); if (!iconComponent) return maxY; let lHeight = iconComponent.lHeight || 1; let iconY = icon.position.y; // 对于高度大于1的图标,考虑其顶部位置 if (lHeight > 1) { // 计算图标顶部位置:当前位置 + 高度差 * 图标高度 / 2 return Math.max(maxY, iconY + (lHeight - 1) * this.iconHeight / 2); } else { return Math.max(maxY, iconY); } }, -999); } /** * 计算新图标的Y坐标 */ computeNewIconXorY(): number { let icons = this._info.icons; // 如果没有图标,使用初始位置 if (!icons.length) { return this.getIconPosition(0).y + this.iconHeight; } // 找到最高的图标Y坐标 let highestY = this.findHighestIconXorY(icons); // 新图标位置 = 最高图标位置 + 图标高度 return highestY + this.iconHeight; } /** * 清理资源 */ onDestroy() { this._cachedUITransform = null; this._cachedContentHeight = 0; this._cachedAnchorY = 0; this._positionCache.clear(); } /** * 滚轮移动 * @param dt 时间增量 */ rollerMove(dt: number) { // 计算移动向量 let speed = this._info.speed; let move = speed * dt; let moveVec = v3(0, move, 0); // 更新动态图标位置 this._info.icons.forEach(icon => { if (!icon || !icon.isValid) return; if (icon.active) { let newPosition = icon.position.clone().subtract(moveVec); icon.setPosition(newPosition); } }); // 获取所有图标 let allIcons = Array.from(this._allIcons.values()); allIcons.forEach(icon => { if (!icon || !icon.isValid) return; let newPosition = icon.position.clone().subtract(moveVec); icon.setPosition(newPosition); }); } /** * 回收滚轮图标 */ recycleRollerIcon() { // 回收动态图标 let icons = this._info.icons; for (let i = icons.length - 1; i >= 0; i--) { let icon = icons[i]; if (!icon || !icon.isValid) { icons.splice(i, 1); continue; } if (this.checkDeadLine(icon)) { // 从数组中移除 icons.splice(i, 1); // 回收图标 this.iconFactory.recycleIcon(icon); } } // 回收固定位置图标(非最后一页创建状态) if (this._info.state !== ROLLER_STATE.LAST_PAGE_CREATE) { for (let i = 0; i < this.row; i++) { let iconKey = this._posToIconKey.get(i); if (!iconKey) continue; let icon = this._allIcons.get(iconKey); if (!icon || !icon.isValid) { this._posToIconKey.delete(i); this._allIcons.delete(iconKey); continue; } if (this.checkDeadLine(icon)) { // 从映射中移除 this._allIcons.delete(iconKey); this._posToIconKey.delete(i); // 回收图标 this.iconFactory.recycleIcon(icon); } } } // 处理特殊图标(n*1图标) if (this._info.state !== ROLLER_STATE.LAST_PAGE_CREATE) { // 获取所有特殊图标的key let specialIconKeys = Array.from(this._allIcons.keys()) .filter(key => key.startsWith('large_')); for (let iconKey of specialIconKeys) { let icon = this._allIcons.get(iconKey); if (!icon || !icon.isValid) { this._allIcons.delete(iconKey); continue; } if (this.checkDeadLine(icon)) { // 从映射中移除 this._allIcons.delete(iconKey); // 移除所有关联的位置映射 for (let [pos, key] of this._posToIconKey.entries()) { if (key === iconKey) { this._posToIconKey.delete(pos); } } // 回收图标 this.iconFactory.recycleIcon(icon); } } } } /** * 停止处理 */ stopProcess() { let upIcon = this.getIconPosition(0); let stopline = upIcon.y - 100; // 偏移量100 let topY = this.findHighestIconXorY(Array.from(this._allIcons.values())); if (topY <= stopline) { this.changeState(ROLLER_STATE.BOUNCE); this.playBounceAnimation(); } } /** * 播放回弹动画 */ playBounceAnimation() { let time = 0.1; let offset = 50; // 获取所有图标 let allIcons = Array.from(this._allIcons.values()); allIcons.forEach(icon => { if (!icon || !icon.isValid) return; let iconComponent = icon.getComponent(Icon); if (!iconComponent) return; // 获取图标的起始位置和高度 let startPos = iconComponent.startPos; let lHeight = iconComponent.lHeight || 1; // 获取图标应该在的位置 let position = this.getIconPosition(startPos, lHeight); // 设置初始位置(向下偏移) // icon.setPosition(position.add(v3(0, -offset, 0))); icon.setPosition(position); iconComponent.playSpawnAni(); // // 创建回弹动画 // tween(icon) // .by(time, { position: v3(0, offset, 0) }) // .start(); }); // 延迟切换到停止状态 this.scheduleOnce(() => { this.changeState(ROLLER_STATE.STOP); }, time); } // 添加一个集合来追踪已删除的位置 private _deletedPositions = new Set(); /** * 消除逻辑 * 一定是在静止状态消除的 * @param deleteMsg 删除信息 * */ deleteIconNode(positions: number[]) { // 记录被处理过的图标键 let processedPos = new Set(); // 处理每个位置 for (let pos of positions) { // 如果此图标已处理过,跳过 if (processedPos.has(pos)) { continue; } let iconKey = this._posToIconKey.get(pos); // if (!iconKey) { // console.error('deleteIconNode iconKey is null', pos); // continue; // } let iconNode = this._allIcons.get(iconKey); // if (!iconNode || !iconNode.isValid) { // console.error('deleteIconNode iconNode is null', pos); // continue; // } let iconComponent = iconNode.getComponent(Icon); // if (!iconComponent) { // console.error('deleteIconNode iconComponent is null', pos); // continue; // } let startPos = iconComponent.startPos; // 从allIcons中删除图标 this._allIcons.delete(iconKey); let height = iconComponent.lHeight || 1; // 移除所有关联的位置映射 if (height > 1) { // 对于n*1图标,需要清除所有占用的位置 for (let i = 0; i < height; i++) { this._posToIconKey.delete(startPos + i); // 标记此图标已处理 processedPos.add(startPos + i); } } else { this._posToIconKey.delete(pos); // 标记此图标已处理 processedPos.add(pos); } iconComponent.playWinAni(true); iconComponent.playDeleteAni(); this.scheduleOnce(() => { this.iconFactory.recycleIcon(iconNode); }, 0.9) } this.scheduleOnce(() => { this.node.emit(ROLLER_EVENT.ICON_DELETED, this._rollerId); }, 0.9) } // 播放动画 playFrameTypeChangeAni(positions: number[]) { // 记录被处理过的图标键 let processedPos = new Set(); for (let pos of positions) { // 如果此图标已处理过,跳过 if (processedPos.has(pos)) { continue; } let iconKey = this._posToIconKey.get(pos); if (!iconKey) continue; let iconNode = this._allIcons.get(iconKey); if (!iconNode || !iconNode.isValid) continue; let iconComponent = iconNode.getComponent(Icon); if (!iconComponent) continue; let startPos = iconComponent.startPos; let height = iconComponent.lHeight || 1; if (height > 1) { for (let i = 0; i < height; i++) { processedPos.add(startPos + i); } } else { processedPos.add(startPos); } iconComponent.playWinAni(true); iconComponent.playChangeAni(true); } } chanegeIconAndFrameType(data: any[]) { for (let i = 0; i < data.length; i++) { let oldStartPos = data[i].oldStartPos; let newIndex = data[i].newIndex; let newFrameType = data[i].newFrameType; let lheight = data[i].lheight || 1; // 获取该位置对应的iconKey const iconKey = this._posToIconKey.get(oldStartPos); if (!iconKey) { console.error('changeIconAndFrameType: iconKey is null for position', oldStartPos); return; } // 获取对应的图标节点 const iconNode = this._allIcons.get(iconKey); if (!iconNode || !iconNode.isValid) { console.error('changeIconAndFrameType: iconNode is null or invalid for position', oldStartPos); return; } // 获取Icon组件 const iconComponent = iconNode.getComponent(Icon); if (!iconComponent) { console.error('changeIconAndFrameType: iconComponent is null for position', oldStartPos); return; } iconComponent.playChangeAni(false); // 1. 从数据结构中删除旧图标 this._allIcons.delete(iconKey); // 回收旧图标节点 this.iconFactory.recycleIcon(iconNode); // 创建新图标 // 创建新的图标节点 const newIcon = this.iconFactory.icfactoryCreateIcon(newIndex); // 初始化新的Icon组件 newIcon.getComponent(Icon).initIcon(newIndex, lheight, iconKey, newFrameType, this._rollerId); // 设置新图标的位置 const newPos = this.getIconPosition(oldStartPos, lheight); newIcon.setPosition(newPos); // 添加到场景 this._content.addChild(newIcon); newIcon.getComponent(Icon).changeIconState(ICON_STATE.IDLE); // 3. 更新Roller的数据结构 // 将新图标添加到_allIcons中 this._allIcons.set(iconKey, newIcon); } } /** * 创建新icon * @param createMsg 信息 */ createNewIconTop(createDatas: number[][], CroSymbols: any) { // 获取所有图标 let topY = this.getIconPosition(0, 1); //总共掉落了多少格 let fallDownNum = 0 //3 //已经计算的格数 let nowDownNum = 0 for (let i = 0; i < createDatas.length; i++) { fallDownNum += createDatas[i].length } for (let i = 0; i < createDatas.length; i++) { let iconHeight = createDatas[i].length let startPos = nowDownNum - fallDownNum; let iconIndex = createDatas[i][0]; let iconKey = this.generateIconKey(startPos, iconHeight, startPos - iconHeight + 1); let icon = this.iconFactory.icfactoryCreateIcon(iconIndex); let iconFramType = 0 if (CroSymbols) { for (let key in CroSymbols) { if (Math.floor(CroSymbols[key].PosFirst / 5) == this._rollerId) { if (CroSymbols[key].PosFirst % 5 == i) { iconFramType = CroSymbols[key].Type } } } } icon.getComponent(Icon).initIcon(iconIndex, iconHeight, iconKey, iconFramType, this._rollerId); let y = topY.y + (((fallDownNum - nowDownNum) - 0.5 * (iconHeight - iconHeight > 1 ? 1 : 0)) * this.iconHeight); icon.setPosition(0, y, 0); this._content.addChild(icon); icon.getComponent(Icon).changeIconState(ICON_STATE.IDLE); this._allIcons.set(iconKey, icon); this._posToIconKey.set(startPos, iconKey); nowDownNum += iconHeight } this.node.emit(ROLLER_EVENT.ICON_CREATE, this._rollerId); } /** icon进行掉落移动 */ iconFallDown(data: number[], CroSymbols: any, inPan: boolean) { let updates = []; let sortNewIconStartPos = this.getNewIconsStartPos(data, CroSymbols); let sortIcons = this.getSortIcons(); for (let i = 0; i < sortNewIconStartPos.length; i++) { let newStartPos = sortNewIconStartPos[i]; let oldIcon = sortIcons[i]; let oldIconStartPos = oldIcon.startPos; if (inPan) { if (oldIconStartPos < 0) { continue } } // else { // if (oldIconStartPos >= 0) { // continue // } // } if (oldIconStartPos === newStartPos) { continue; } let oldIconNode = oldIcon.icon; let oldIconComponent = oldIcon.component; let oldIconkey = oldIconComponent.iconKey; let lHeight = oldIconComponent.lHeight || 1; let newIconkey = this.generateIconKey(newStartPos, 1, newStartPos); let newY = this.getIconPosition(newStartPos, lHeight).y; let oldY = oldIconNode.position.y; updates.push({ node: oldIconNode, component: oldIconComponent, oldKey: oldIconkey, oldStartPos: oldIconStartPos, newStartPos: newStartPos, newKey: newIconkey, height: lHeight, newY: newY, }) } let delayBetweenIcons = 0.05; // 每个图标之间的掉落延迟 // 添加依次掉落效果 for (let update of updates) { let fallDelay = update.index * delayBetweenIcons; // 根据索引计算延迟 let fallTime = 0.2; // 掉落动画时间 // 清除可能存在的动画 tween(update.node).stop(); // 添加延迟和掉落动画 tween(update.node) .delay(fallDelay) // 添加延迟 .to(fallTime, { position: v3(0, update.newY, 0) }, { easing: 'quadIn' // 下落加速 }) .start(); } for (let update of updates) { this._allIcons.delete(update.oldKey); for (let i = 0; i < update.height; i++) { this._posToIconKey.delete(update.oldStartPos + i); } } // 再添加所有新映射 for (let update of updates) { // 添加新的映射 update.component.iconKey = update.newKey; this._allIcons.set(update.newKey, update.node); for (let i = 0; i < update.height; i++) { this._posToIconKey.set(update.newStartPos + i, update.newKey); } } // 根据最长的动画时间调整音效和事件触发时间 let totalFallTime = updates.length > 0 ? (updates.length - 1) * delayBetweenIcons + 0.1 : 0.1; // 在所有图标都完成掉落后触发事件 this.scheduleOnce(() => { if (!inPan) { this.node.emit(ROLLER_EVENT.ICON_FALLEN, this._rollerId); } }, totalFallTime + 0.1); // 添加一点额外时间确保所有动画完成 } getSortIcons() { let iconInfos: { icon: Node, component: Icon, startPos: number }[] = []; // 收集所有图标信息 for (let [iconKey, iconNode] of this._allIcons.entries()) { if (!iconNode || !iconNode.isValid) continue; let iconComponent = iconNode.getComponent(Icon); if (!iconComponent) continue; // 记录图标信息 iconInfos.push({ icon: iconNode, component: iconComponent, startPos: iconComponent.startPos }); } // 按startPos从小到大排序 iconInfos.sort((a, b) => a.startPos - b.startPos); return iconInfos; } getNewIconsStartPos(data: number[], CroSymbols: any) { // 存储所有图标的startPos let startPositions: number[] = []; // 记录已处理的位置 let processedPositions = new Set(); // 记录已经处理的pos let processedPos = new Set(); // 首先处理不规则图标(n*1图标) if (CroSymbols) { for (let pos in CroSymbols) { let id = CroSymbols[pos].id; if (processedPos.has(id)) continue; processedPos.add(id); let iconSpecialMsg = CroSymbols[pos]; let startPos = iconSpecialMsg.startPos; let endPos = iconSpecialMsg.endPos; // 添加不规则图标的startPos startPositions.push(startPos); // 标记所有被占用的位置 for (let i = startPos; i <= endPos; i++) { processedPositions.add(i); } } } // 然后处理常规图标 for (let i = 0; i < data.length; i++) { // 如果该位置未被处理(不是不规则图标的一部分) if (!processedPositions.has(i)) { startPositions.push(i); } } // 从小到大排序 startPositions.sort((a, b) => a - b); return startPositions; } }