All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 1m13s
846 lines
28 KiB
TypeScript
846 lines
28 KiB
TypeScript
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';
|
||
let { ccclass, property, executeInEditMode } = _decorator;
|
||
|
||
// 帧到启动ID映射(按帧序)
|
||
let frameOrder = [
|
||
{ frame: 1, ids: [5] },
|
||
{ frame: 3, ids: [0] },
|
||
{ frame: 9, ids: [1, 6] },
|
||
{ frame: 14, ids: [2, 7] },
|
||
{ frame: 20, ids: [3] },
|
||
{ frame: 22, ids: [8] },
|
||
{ frame: 27, ids: [4] },
|
||
];
|
||
|
||
let fps = 60;
|
||
|
||
@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;
|
||
|
||
rollerMsg: any[] = [
|
||
{ row: 5, col: 1 },
|
||
{ row: 5, col: 1 },
|
||
{ row: 5, col: 1 },
|
||
{ row: 5, col: 1 },
|
||
{ row: 5, col: 1 },
|
||
{ row: 5, col: 1 },
|
||
];
|
||
// 竖向滚轮数组
|
||
vRollers: Roller[] = [];
|
||
// 滚轮数组
|
||
allRollers: Roller[] = [];
|
||
// 是否快速旋转
|
||
_isFastSpin: boolean = false;
|
||
// 是否手动停止
|
||
_isManualStop: boolean = false;
|
||
// spinData
|
||
_spinData: GameData = null;
|
||
/** 分割过的数据,一位数组改为二维数组, 每个元素代表一个滚轮 */
|
||
_resultStopData: number[][] = [];
|
||
// 是否是免费游戏
|
||
_isFreeSpin: boolean = false;
|
||
// 不规则图标信息
|
||
_CroSymbols: any = null;
|
||
// 处理过的不规则icon信息
|
||
_processedCroSymbols: any = 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.vRollers = [];
|
||
|
||
this.vMaskNode = this.createMaskNode('VMask');
|
||
|
||
this.node.addChild(this.vMaskNode);
|
||
|
||
let rollerLength = this.rollerMsg.length;
|
||
for (let i = 0; i < rollerLength; i++) {
|
||
let rollerMsg = this.rollerMsg[i];
|
||
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);
|
||
roller.node.setPosition(rollerPosition);
|
||
this.vRollers.push(roller);
|
||
this.allRollers.push(roller);
|
||
// }
|
||
}
|
||
}
|
||
|
||
private createMaskNode(name: string): Node {
|
||
let maskNode = new Node();
|
||
|
||
maskNode.name = name;
|
||
|
||
let comp = maskNode.addComponent(Mask);
|
||
let UIComponent = maskNode.addComponent(UITransform);
|
||
comp.type = Mask.Type.GRAPHICS_RECT;
|
||
|
||
UIComponent.setContentSize(1040, 830)
|
||
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 nextStopRollerCroSymbols = this._processedCroSymbols[nextStopRollerId];
|
||
this.allRollers[nextStopRollerId].setCroSymbols(nextStopRollerCroSymbols);
|
||
this.allRollers[nextStopRollerId].stopScroll(this._resultStopData[nextStopRollerId], stopSpeedData);
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
scatterPos: number[] = [];
|
||
checkNextRollerExpect(rollerId: number, needScatterCount: number = 3) {
|
||
let curScatterCount = 0;
|
||
this.scatterPos = [];
|
||
|
||
// 检查所有已经停止的垂直滚轮(包括当前滚轮)
|
||
for (let i = 0; i <= rollerId; i++) {
|
||
const rollerData = this._resultStopData[i];
|
||
if (!rollerData) continue;
|
||
|
||
// 检查每个位置
|
||
for (let j = 0; j < rollerData.length; j++) {
|
||
// 检查是否有交叉符号覆盖该位置
|
||
if (this._processedCroSymbols &&
|
||
this._processedCroSymbols[i] &&
|
||
this._processedCroSymbols[i][j]) {
|
||
|
||
const symbolInfo = this._processedCroSymbols[i][j];
|
||
|
||
// 只计算开始位置,避免重复计数
|
||
if (symbolInfo.isStart && symbolInfo.iconIndex === 1) {
|
||
curScatterCount++;
|
||
this.scatterPos.push(i * 5 + symbolInfo.startPos);
|
||
}
|
||
}
|
||
// 如果位置没有被交叉符号覆盖,且是scatter
|
||
else if (rollerData[j] === 1) {
|
||
curScatterCount++;
|
||
this.scatterPos.push(i * 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 && this._isFastSpin) {
|
||
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_StopQuick_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 bottomData = data.Symbol.Middle;
|
||
this._CroSymbols = data.CroSymbols;
|
||
|
||
// 分割数据
|
||
this._resultStopData = [...this.splitArray(bottomData, [5, 5, 5, 5, 5, 5])];
|
||
// 处理n*1符号
|
||
let processedCroSymbols = this.processCroSymbolsForRollers();
|
||
for (let i = 0; i < this.allRollers.length; i++) {
|
||
let roller = this.allRollers[i];
|
||
let rollerCroSymbols = processedCroSymbols[i];
|
||
roller.initRollerWithIcon(i, this._resultStopData[i], rollerCroSymbols);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 只处理竖向滚轮
|
||
* 处理n*1符号数据,为每个滚轮准备对应的n*1符号信息
|
||
* @returns 处理后的n*1符号数据数组,每个元素对应一个滚轮
|
||
*/
|
||
private processCroSymbolsForRollers(): any[] {
|
||
this._processedCroSymbols = [];
|
||
let row = 5;
|
||
let col = 6;
|
||
// 如果没有交叉符号数据,返回空对象数组
|
||
if (!this._CroSymbols) {
|
||
return new Array(col).fill({});
|
||
}
|
||
|
||
// 为每个滚轮创建一个空对象
|
||
let rollerSymbols: any[] = [];
|
||
for (let i = 0; i < col; i++) {
|
||
rollerSymbols.push({});
|
||
}
|
||
|
||
// 遍历所有交叉符号
|
||
for (let symbolId in this._CroSymbols) {
|
||
let symbol = this._CroSymbols[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,
|
||
Type: symbol.Type,
|
||
iconIndex: symbol.Symbol
|
||
};
|
||
}
|
||
}
|
||
this._processedCroSymbols = [...rollerSymbols];
|
||
return this._processedCroSymbols;
|
||
}
|
||
|
||
// 滚轮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._isManualStop = false;
|
||
this.unscheduleAllCallbacks();
|
||
if (this._isFastSpin) {
|
||
for (let i = 0; i < this.allRollers.length; i++) {
|
||
let roller = this.allRollers[i];
|
||
if (roller) {
|
||
if (this._isManualStop) return;
|
||
roller.startScroll();
|
||
}
|
||
}
|
||
} else {
|
||
this.allRollers.forEach(roller => {
|
||
roller.startScroll();
|
||
})
|
||
}
|
||
}
|
||
|
||
// 滚轮停止滚动
|
||
stopScroll(data: GameData) {
|
||
this._spinData = data;
|
||
|
||
this._resultStopData = [];
|
||
// 分割底盘数据
|
||
this._resultStopData = [...this.splitArray(data.Symbol.Middle, [5, 5, 5, 5, 5, 5])];
|
||
// 处理不对则icon
|
||
this._CroSymbols = data.CroSymbols;
|
||
let processedCroSymbols = this.processCroSymbolsForRollers();
|
||
let stopSpeedData = this._isFastSpin ? [[0, 6000]] : [[0.1, 3500]];
|
||
if (this._isFastSpin) {
|
||
// this.stopAllRollersImmediately(processedCroSymbols);
|
||
for (let i = 0; i < this.allRollers.length; i++) {
|
||
let stopData = this._resultStopData[i];
|
||
let roller = this.allRollers[i];
|
||
|
||
let rollerCroSymbols = processedCroSymbols[i];
|
||
roller.setCroSymbols(rollerCroSymbols);
|
||
roller.stopScroll(stopData, stopSpeedData)
|
||
}
|
||
} else {
|
||
// this.stopRollersInSequence(processedCroSymbols);
|
||
let firstRollerCroSymbols = processedCroSymbols[0];
|
||
this.allRollers[0].setCroSymbols(firstRollerCroSymbols);
|
||
this.allRollers[0].stopScroll(this._resultStopData[0], stopSpeedData);
|
||
}
|
||
}
|
||
|
||
stopRollersInSequence(processedCroSymbols: any[]) {
|
||
let standardStopDuration = [[0.1, 3500]];
|
||
}
|
||
|
||
manualStop(data: GameData) {
|
||
this._isManualStop = true;
|
||
this._resultStopData = [];
|
||
this._resultStopData = [...this.splitArray(data.Symbol.Middle, [5, 5, 5, 5, 5, 5])];
|
||
this._CroSymbols = data.CroSymbols;
|
||
let processedCroSymbols = this.processCroSymbolsForRollers();
|
||
for (let i = 0; i < this.allRollers.length; i++) {
|
||
let stopData = this._resultStopData[i];
|
||
let roller = this.allRollers[i];
|
||
let rollerCroSymbols = processedCroSymbols[i];
|
||
roller.setCroSymbols(rollerCroSymbols);
|
||
roller.manualStopScroll(stopData)
|
||
}
|
||
}
|
||
|
||
// 对服务器下发的数据进行操作
|
||
splitArray<T>(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();
|
||
}
|
||
|
||
|
||
// 将图标移动到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<number, number[]>();
|
||
let rollerAniPos = new Map<number, number[]>();
|
||
|
||
// 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 ? 1.1 : 1.1;
|
||
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);
|
||
}, 0.8); // 在动画结束前稍早将图标移回
|
||
}
|
||
|
||
// 将图标从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<number, any[]> = 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[][][], CroSymbols: any) {
|
||
this.allRollers.forEach((roller, index) => {
|
||
let rollerData = createDatas[index];
|
||
roller.createNewIconTop(rollerData, CroSymbols);
|
||
})
|
||
}
|
||
|
||
iconFallDown(data: GameData, inPan: boolean) {
|
||
this._spinData = data;
|
||
this._resultStopData = [];
|
||
this._fallenRollerCount = 0; // 重置计数器
|
||
this._deletedRollerCount = 0;
|
||
// 分割底盘数据
|
||
this._resultStopData = [...this.splitArray(data.Symbol.Middle, [5, 5, 5, 5, 5, 5])];
|
||
// 处理不对则icon
|
||
this._CroSymbols = data.CroSymbols;
|
||
let processedCroSymbols = this.processCroSymbolsForRollers();
|
||
|
||
this.allRollers.forEach((roller, index) => {
|
||
let stopData = this._resultStopData[index];
|
||
let rollerCroSymbols = processedCroSymbols[index];
|
||
roller.setCroSymbols(rollerCroSymbols);
|
||
this.scheduleOnce(() => {
|
||
roller.iconFallDown(stopData, rollerCroSymbols, inPan)
|
||
}, 0.03 * index)
|
||
})
|
||
|
||
// 在第一个图标开始掉落时播放音效
|
||
this.scheduleOnce(() => {
|
||
AudioManager.instance.playSFX('Win_Symbol_Fall');
|
||
}, 0.1);
|
||
}
|
||
|
||
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<number, {
|
||
node: Node,
|
||
originalParent: Node,
|
||
originalPosition: Vec3
|
||
}> = new Map();
|
||
|
||
|
||
}
|
||
|