rp_10012/assets/Game/scripts/game/Icon.ts
TJH 4124b6821f
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 1m25s
添加音效
2025-10-09 10:50:55 +08:00

798 lines
27 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { _decorator, Component, Node, Prefab, sp, Sprite, UITransform, Vec3, v3, EventTarget, Label, tween, UIOpacity, instantiate, SpriteFrame, Tween } from 'cc';
import { ICON_STATE, ICON_WIDTH } from './Define';
import { GameDataManager } from 'db://assets/Loading/scripts/manager/GameDataManager';
import { NodePoolManager } from 'db://assets/Loading/scripts/manager/NodePoolManager';
import { SlotGame } from '../SlotGame';
import { AudioManager } from 'db://assets/Loading/scripts/manager/AudioManager';
const { ccclass, property } = _decorator;
// 声明一个全局事件总线
export const IconEventBus = new EventTarget();
// 高度映射表 - 减少重复计算
let HEIGHT_MAP = {
1: 174,
2: 174 * 2,
3: 174 * 3,
4: 174 * 4
};
let BTN_HEIGHT_MAP = {
1: 180,
2: 180 * 2,
3: 180 * 3,
4: 180 * 4
};
// 静态共享的Vec3对象 - 减少GC压力
let SHARED_VEC3 = v3(0, 0, 0);
@ccclass('Icon')
export class Icon extends Component {
// /** Icon的资源 */
@property(sp.Skeleton)
iconSpine: sp.Skeleton = null;
@property(Node)
bgNode: Node = null;
// 倍数图片
@property([SpriteFrame])
multiSprite: Array<SpriteFrame> = new Array<SpriteFrame>
// 模糊倍数图片
@property([SpriteFrame])
multiBlurSprite: Array<SpriteFrame> = new Array<SpriteFrame>
//倍数框
@property([SpriteFrame])
multiFrameSprite: Array<SpriteFrame> = new Array<SpriteFrame>
//模糊倍数框
@property([SpriteFrame])
multiBlurFrameSprite: Array<SpriteFrame> = new Array<SpriteFrame>
// @property(Sprite)
// blurFrame: Sprite = null;
@property(Prefab)
winSpinePrefab: Prefab = null;
// 节点引用
private _normalNode: Node = null;
private _fastNode: Node = null;
private _btn: Node = null;
// private _frameNode: Node = null;
// private _fastFrameNode: Node = null;
private _normalSpriteNode: Node = null;
private _fastSpriteNode: Node = null;
// 组件缓存 - 提高性能
private _transform: UITransform = null;
// private _frameTransform: UITransform = null;
private _bgTransform: UITransform = null;
// private _fastFrameTransform: UITransform = null;
private _btnTransform: UITransform = null;
// 基础属性
private _iconId: number = 99;
private _lheight: number = 1; // 图标的高度倍数默认1*1
private _state = ICON_STATE.ACTIVATE;
private _iconKey: string = '';
// private _frameType: number = 0;
private _rollerIndex: number = 0;
private _multi: number = 0;
// 缓存的向量对象,避免重复创建
private readonly _position = new Vec3();
// 组件状态标志
private _isInitialized: boolean = false;
private _isFastMode: boolean = false;
private _isWildOrScatter: boolean = false;
private _isMulti: boolean = false;
// 动画相关
private _iconChangeCallback: Function = null;
private _changeSprite: Sprite = null; // 用于切换动画的新Sprite
// getter/setter
set index(id: number) {
this._iconId = id;
this._isWildOrScatter = id === 0 || id === 1;
this._isMulti = id == 2;
}
get index(): number {
return this._iconId;
}
set lHeight(height: number) {
this._lheight = height;
}
get lHeight(): number {
return this._lheight;
}
set iconKey(key: string) {
this._iconKey = key;
}
get iconKey(): string {
return this._iconKey;
}
set rollerIndex(index: number) {
this._rollerIndex = index;
}
get rollerIndex(): number {
return this._rollerIndex;
}
get startPos(): number {
// 检查是否有有效的图标key
if (!this._iconKey || this._iconKey.length === 0) {
return 0;
}
const parts = this._iconKey.split('_');
return parseInt(parts[1]);
}
// set frameType(type: number) {
// if (this._frameType === type) return; // 避免重复设置
// this._frameType = type;
// this.updateFrames();
// }
/**
* 获取icon框类型
* @returns 0:普通框 1:银框 2:金框 3:百搭框
*/
// get frameType(): number {
// return this._frameType;
// }
// 生命周期:组件加载时
onLoad() {
// 缓存常用组件引用
this._transform = this.node.getComponent(UITransform) || this.node.addComponent(UITransform);
this.initializeComponents();
}
onIconClick() {
IconEventBus.emit('ICON_CLICKED', this);
}
/**
* 获取图标的世界坐标
* @returns 图标在世界空间中的位置
*/
getWorldPosition(): Vec3 {
// 获取当前图标的世界坐标
if (this._transform) {
// 使用缓存的向量对象来减少内存分配
return this._transform.convertToWorldSpaceAR(v3(0, 0, 0));
}
return null;
}
// 生命周期:组件启用时
onEnable() {
if (!this._isInitialized) {
this.initializeComponents();
}
}
// 更新框架精灵
// updateFrames() {
// if (!this.Frame || !this.blurFrame) return;
// const manager = GameDataManager.instance;
// let frameName, blurFrameName;
// switch (this._frameType) {
// case 0:
// frameName = 'fr01_IronFrame';
// blurFrameName = 'fr01_IronFrame_blur';
// break;
// case 1:
// frameName = 'fr02_SilverFrame';
// blurFrameName = 'fr02_SilverFrame_blur';
// break;
// case 2:
// frameName = 'fr03_GoldFrame';
// blurFrameName = 'fr03_GoldFrame_blur';
// break;
// default:
// frameName = 'fr01_IronFrame';
// blurFrameName = 'fr01_IronFrame_blur';
// }
// this.Frame.spriteFrame = manager.getFrameTypeCache(frameName);
// this.blurFrame.spriteFrame = manager.getFrameTypeCache(blurFrameName);
// }
// 初始化所有组件引用
private initializeComponents() {
if (this._isInitialized) return;
// 获取节点引用
this._normalNode = this.node.getChildByName('normal');
if (this._normalNode) {
this._normalSpriteNode = this._normalNode.getChildByName('sprite');
// this._frameNode = this._normalNode.getChildByName('frame');
// 缓存组件
// if (this._frameNode) {
// this._frameTransform = this._frameNode.getComponent(UITransform);
// }
}
//适配
// this._normalSpriteNode.setScale(0.9, 0.9, 1)
// this._normalNode.getComponent(UITransform).setContentSize(170, 174)
this._btn = this.node.getChildByName('btn');
if (this._btn) {
this._btnTransform = this._btn.getComponent(UITransform);
this._btn.on(Node.EventType.TOUCH_END, this.onIconClick, this);
}
this._fastNode = this.node.getChildByName('fast');
this._fastSpriteNode = this._fastNode.getChildByName('sp_fast');
// if (this._fastNode) {
// this._fastFrameNode = this._fastNode.getChildByName('frame');
// // 缓存组件
// if (this._fastFrameNode) {
// this._fastFrameTransform = this._fastFrameNode.getComponent(UITransform);
// }
// }
// 缓存背景节点组件
if (this.bgNode) {
this._bgTransform = this.bgNode.getComponent(UITransform);
}
// 设置初始状态
if (this._normalNode) this._normalNode.active = true;
// if (this._frameNode) this._frameNode.active = true;
if (this._normalSpriteNode) this._normalSpriteNode.active = true;
if (this._fastNode) this._fastNode.active = false;
// if (this._fastFrameNode) this._fastFrameNode.active = false;
this._isInitialized = true;
}
// 初始化图标
initIcon(id: number, lHeight: number = 1, IconKey: string = '', frameType: number = 0, rollerIndex: number = 0, multi: number = 0) {
// 确保组件已初始化
if (!this._isInitialized) {
this.initializeComponents();
}
// 设置基本属性
this.index = id;
this.lHeight = lHeight;
this.iconKey = IconKey;
// this.frameType = frameType;
this.rollerIndex = rollerIndex;
// 设置尺寸
if (this._transform) {
this._transform.width = ICON_WIDTH;
this._transform.height = HEIGHT_MAP[lHeight] || HEIGHT_MAP[1];
} else {
this.node.getComponent(UITransform).width = ICON_WIDTH;
this.updateHeightForLheight(lHeight, this.node);
}
// 批量更新子节点尺寸
let height = HEIGHT_MAP[lHeight] || HEIGHT_MAP[1];
// 使用缓存的UITransform组件
if (this._bgTransform) this._bgTransform.height = height;
else this.updateHeightForLheight(lHeight, this.bgNode);
// if (this._frameTransform) this._frameTransform.height = height;
// else this.updateHeightForLheight(lHeight, this._frameNode);
// if (this._fastFrameTransform) this._fastFrameTransform.height = height;
// else this.updateHeightForLheight(lHeight, this._fastFrameNode);
if (this._btnTransform) {
this._btnTransform.height = BTN_HEIGHT_MAP[lHeight] || BTN_HEIGHT_MAP[1];
this._btnTransform.width = ICON_WIDTH;
} else {
if (!this._btn) return;
let transform = this._btn.getComponent(UITransform);
if (!transform) return;
// 使用映射表而不是多个if判断
transform.height = BTN_HEIGHT_MAP[lHeight] || BTN_HEIGHT_MAP[1];
transform.width = ICON_WIDTH;
}
if (id == 2 && multi > 1) {
this._multi = multi
this._normalSpriteNode.getComponent(Sprite).spriteFrame = this.multiSprite[multi]
this._fastSpriteNode.getComponent(Sprite).spriteFrame = this.multiBlurSprite[multi]
Tween.stopAllByTarget(this._normalSpriteNode)
let loopTween =
tween(this._normalSpriteNode)
.to(0.5, { scale: new Vec3(1.1, 1.1, 1) })
.to(0.5, { scale: new Vec3(1, 1, 1) })
tween(this._normalSpriteNode)
.repeatForever(loopTween)
.start()
switch (true) {
case multi < 4:
this._normalNode.children[0].active = true
this._normalNode.children[1].active = false
this._normalNode.children[2].active = false
break
case multi >= 7:
this._normalNode.children[0].active = false
this._normalNode.children[1].active = false
this._normalNode.children[2].active = true
break
default:
this._normalNode.children[0].active = false
this._normalNode.children[1].active = true
this._normalNode.children[2].active = false
break
}
}
// 重置状态
this.resetState();
}
// 重置状态
private resetState() {
this._isFastMode = false;
this.node.active = true;
// 批量设置节点状态
if (this._normalNode) this._normalNode.active = true;
if (this._fastNode) this._fastNode.active = false;
// 根据图标类型设置显示
if (this._isWildOrScatter) {
if (this.iconSpine && this.iconSpine.node) this.iconSpine.node.active = true;
if (this._normalSpriteNode) this._normalSpriteNode.active = false;
} else {
if (this.iconSpine && this.iconSpine.node) this.iconSpine.node.active = false;
if (this._normalSpriteNode) this._normalSpriteNode.active = true;
}
if (this._isMulti) {
if (this.iconSpine && this.iconSpine.node) this.iconSpine.node.active = true;
if (this._normalSpriteNode) this._normalSpriteNode.active = true;
}
this._state = ICON_STATE.IDLE;
if (!this._isMulti) return
this._normalSpriteNode.getComponent(UIOpacity).opacity = 255
}
updateHeightForLheight(lheight: number, node: Node) {
if (!node) return;
let transform = node.getComponent(UITransform);
if (!transform) return;
// 使用映射表而不是多个if判断
transform.height = HEIGHT_MAP[lheight] || HEIGHT_MAP[1];
}
// 更新位置
setPosition(x: number, y: number, z: number = 0) {
this._position.set(x, y, z);
this.node.setPosition(this._position);
}
// 更新缩放
setScale(x: number, y: number, z: number = 1) {
this.node.setScale(x, y, z);
}
// 改变图标状态
changeIconState(iconState: ICON_STATE) {
if (this._state === iconState) return; // 避免重复设置状态
switch (iconState) {
case ICON_STATE.ACTIVATE:
this.node.active = true;
break;
case ICON_STATE.IDLE:
this.showFastIcon(false);
break;
case ICON_STATE.ROTATE:
// 可以添加旋转相关逻辑
break;
case ICON_STATE.FAST:
this.showFastIcon(true);
break;
case ICON_STATE.WIN:
this.showFastIcon(false);
if (this._isMulti) {
break
}
if (this._isWildOrScatter) {
if (this.iconSpine && this.iconSpine.node) {
this.iconSpine.node.active = true;
this._normalSpriteNode && (this._normalSpriteNode.active = false);
this.iconSpine.clearTracks();
this.iconSpine.setCompleteListener(null);
if (this._iconId == 0) {
this.iconSpine.setAnimation(0, 'win', false);
} else if (this._iconId == 1) {
this.iconSpine.setAnimation(0, 'win_1', false);
}
}
} else if (this.iconSpine && this.iconSpine.node) {
// this.iconSpine.node.active = true;
// this._normalSpriteNode && (this._normalSpriteNode.active = false);
// this.iconSpine.clearTracks();
// this.iconSpine.setCompleteListener(null);
// this.iconSpine.setAnimation(0, 'win', false);
}
if (this.iconSpine) {
this.iconSpine.setCompleteListener(() => {
this.iconSpine.setCompleteListener(null);
if (this._isWildOrScatter) {
if (this._iconId == 0) {
this.iconSpine.setAnimation(0, 'idle', true);
} else if (this._iconId == 1) {
this.iconSpine.setAnimation(0, 'idle_1', true);
}
} else {
this.iconSpine.clearTracks();
this.iconSpine.node.active = false;
this._normalSpriteNode && (this._normalSpriteNode.active = true);
}
});
}
break;
case ICON_STATE.HIDE:
this.node.active = false;
break;
}
this._state = iconState;
}
playSpawnAni() {
if (!this.iconSpine || !this.iconSpine.node || this._isMulti) return;
if (this._isWildOrScatter) {
this.iconSpine.node.active = true;
this._normalSpriteNode && (this._normalSpriteNode.active = false);
} else if (this._isMulti) {
this.iconSpine.node.active = true;
this._normalSpriteNode && (this._normalSpriteNode.active = true);
} else {
this.iconSpine.node.active = false;
this._normalSpriteNode && (this._normalSpriteNode.active = true);
}
this.iconSpine.clearTracks();
// 使用计时器回调而不是匿名函数,减少闭包
this.playSpawnAnimation()
}
playNormalMultiMove(XnInfo) {
if (this._iconId != 2) return
if (XnInfo.AddN == 0) {
return
}
let slotGame = this.node.parent.parent.parent.parent.parent.parent
this._normalSpriteNode.getComponent(UIOpacity).opacity = 150
Tween.stopAllByTarget(this._normalSpriteNode)
let multiMoveNode = instantiate(slotGame.getChildByName('multiMove'))
let bigMultiNode = slotGame.parent.getChildByName('showMulti')
let bigMultiLabel = bigMultiNode.getChildByName('multi')
let isFreeSpin = slotGame.getComponent(SlotGame).isInfreeSpin
let isHasScore = XnInfo.Win != ""
let multiMovePos = -550
if (isFreeSpin && !isHasScore) {
multiMovePos = -400
}
multiMoveNode.parent = slotGame
multiMoveNode.setWorldPosition(this.node.getWorldPosition())
multiMoveNode.getComponent(Sprite).spriteFrame = this.multiSprite[this._multi]
AudioManager.instance.playSFX('Multi_show');
tween(multiMoveNode)
.delay(0.3)
.to(1, { scale: new Vec3(1.2, 1.2, 1) })
.start()
tween(multiMoveNode.getComponent(UIOpacity))
.delay(0.3)
.to(1, { opacity: 80 })
.start()
tween(multiMoveNode)
.to(0.3, { scale: new Vec3(1.5, 1.5, 1) })
.to(1, { position: new Vec3(0, 200, 0) })
.call(() => {
multiMoveNode.destroy()
AudioManager.instance.playSFX('Multi_merge');
if (bigMultiNode.active) return
bigMultiLabel.getComponent(Label).string = 'x' + XnInfo.NowN
bigMultiNode.active = true
bigMultiNode.getComponent(sp.Skeleton).setAnimation(0, 'animation', false)
tween(bigMultiLabel.getComponent(UIOpacity))
.to(0.3, { opacity: 255 })
.delay(0.7)
.to(0.2, { opacity: 0 })
.start()
tween(bigMultiLabel)
.to(0.3, { scale: new Vec3(0.24, 0.24, 1) })
.to(0.3, { scale: new Vec3(0.2, 0.2, 1) })
.to(0.4, { position: new Vec3(0, multiMovePos, 0) })
.to(0.2, { scale: new Vec3(0.3, 0.3, 1) })
.call(() => {
bigMultiLabel.setPosition(0, 100, 0)
bigMultiLabel.setScale(0.2, 0.2, 1)
bigMultiNode.active = false
})
.start()
})
.start()
}
hideNormalSprite() {
if (this._normalSpriteNode) this._normalSpriteNode.active = false;
if (this._fastNode) this._fastNode.active = false;
}
hideNormalSpine() {
if (this.iconSpine) this.iconSpine.node.active = false;
}
private playSpawnAnimation() {
if (!this.iconSpine) return;
if (this._isWildOrScatter) {
// this.iconSpine.setAnimation(0, 'spawn_1', false);
// this.iconSpine.setCompleteListener(() => {
// this.iconSpine.node.active = true;
if (!this.iconSpine) return;
if (this._iconId == 0) {
this.iconSpine.setAnimation(0, 'idle', true);
} else if (this._iconId == 1) {
this.iconSpine.setAnimation(0, 'idle_1', true);
}
this.iconSpine.setCompleteListener(null);
// });
} else {
// this.iconSpine.setAnimation(0, "spawn", false);
}
}
// 显示/隐藏快速图标
showFastIcon(show: boolean) {
if (this._isFastMode === show) return; // 避免重复设置
this._isFastMode = show;
// 批量设置节点状态
if (this._normalNode) this._normalNode.active = !show;
if (this._fastNode) this._fastNode.active = show;
if (!show && !this._isWildOrScatter) {
if (this._isWildOrScatter && this.iconSpine) {
this.iconSpine.node.active = true;
this._normalSpriteNode && (this._normalSpriteNode.active = false);
this.iconSpine.clearTracks();
this.iconSpine.setCompleteListener(null);
if (this._iconId == 0) {
this.iconSpine.setAnimation(0, 'idle', false);
} else if (this._iconId == 1) {
this.iconSpine.setAnimation(0, 'idle_1', false);
}
} else if (this.iconSpine) {
this.iconSpine.node.active = false;
this.iconSpine.clearTracks();
this.iconSpine.setCompleteListener(null);
this._normalSpriteNode && (this._normalSpriteNode.active = true);
}
}
}
// 播放获胜动画
playWinAni(show: boolean) {
this.changeIconState(show ? ICON_STATE.WIN : ICON_STATE.IDLE);
}
// 1.2s
playDeleteAni() {
// 从对象池获取或重用winSpine节点
// let winSpine = NodePoolManager.instance.getNodeFromPoolStatic('winSpine', this.winSpinePrefab);
let winSpine = instantiate(this.winSpinePrefab)
winSpine.setParent(this.node);
winSpine.setPosition(0, 0, 0);
winSpine.setScale(1, 1, 1);
let ascendWin = winSpine.getChildByName('ascend_win');
ascendWin.active = true;
let skeleton = ascendWin.getComponent(sp.Skeleton);
skeleton.setAnimation(0, `anim${this.lHeight}`, false);
this.schedule(() => {
skeleton.setCompleteListener(null);
skeleton.clearTracks()
ascendWin.active = false;
// 隐藏所有子节点
let children = winSpine.children;
for (let i = 0; i < children.length; i++) {
children[i].active = false;
}
winSpine.removeFromParent();
// NodePoolManager.instance.putNodeToPool('winSpine', winSpine);
}, 1.2)
// skeleton.setCompleteListener(() => {
// skeleton.setCompleteListener(null);
// skeleton.clearTracks()
// ascendWin.active = false;
// // 隐藏所有子节点
// let children = winSpine.children;
// for (let i = 0; i < children.length; i++) {
// children[i].active = false;
// }
// winSpine.removeFromParent();
// // NodePoolManager.instance.putNodeToPool('winSpine', winSpine);
// })
}
// playChangeAni(isChange: boolean) {
// if (isChange) {
// let winSpine = NodePoolManager.instance.getNodeFromPoolStatic('winSpine', this.winSpinePrefab);
// winSpine.setParent(this.node);
// winSpine.setPosition(0, 0, 0);
// winSpine.setScale(1, 1, 1);
// let ascendWin = winSpine.getChildByName('ascend_win');
// let skeleton = ascendWin.getComponent(sp.Skeleton);
// ascendWin.active = true;
// skeleton.setAnimation(0, `anim${this.lHeight}`, false);
// skeleton.setCompleteListener(() => {
// skeleton.setCompleteListener(null);
// skeleton.clearTracks()
// ascendWin.active = false;
// this.playChangeSprite(true);
// })
// } else {
// // 清理winSpine节点
// let winSpine = this.node.getChildByName('winSpine');
// if (winSpine) {
// // 停用所有子节点
// let children = winSpine.children;
// for (let i = 0; i < children.length; i++) {
// children[i].active = false;
// }
// // 回收节点
// winSpine.removeFromParent();
// NodePoolManager.instance.putNodeToPool('winSpine', winSpine);
// }
// // 停止精灵切换动画
// this.playChangeSprite(false);
// }
// }
// playChangeSprite(isChange: boolean) {
// // 先清理之前的回调
// if (this._iconChangeCallback) {
// this.unschedule(this._iconChangeCallback);
// this._iconChangeCallback = null;
// }
// if (isChange) {
// // 隐藏原始节点
// if (this._normalSpriteNode) {
// this._normalSpriteNode.active = false;
// }
// // 复用现有changeNode或创建新的
// let changeNode = this.node.getChildByName('ChangeSprite');
// if (!changeNode) {
// changeNode = new Node('ChangeSprite');
// changeNode.setParent(this.node);
// }
// if (this._normalSpriteNode) {
// changeNode.setPosition(this._normalSpriteNode.position);
// changeNode.setScale(this._normalSpriteNode.scale);
// }
// // 获取或添加Sprite组件
// this._changeSprite = changeNode.getComponent(Sprite) || changeNode.addComponent(Sprite);
// // 复制原始Sprite的属性
// if (this._normalSpriteNode) {
// let originalSprite = this._normalSpriteNode.getComponent(Sprite);
// if (originalSprite && originalSprite.spriteFrame) {
// this._changeSprite.spriteFrame = originalSprite.spriteFrame;
// this._changeSprite.sizeMode = originalSprite.sizeMode;
// this._changeSprite.trim = originalSprite.trim;
// }
// }
// this._iconChangeCallback = this.updateChangeSpriteFrame;
// this.schedule(this._iconChangeCallback, 0.1);
// } else {
// // 停止动画并清理
// if (this._iconChangeCallback) {
// this.unschedule(this._iconChangeCallback);
// this._iconChangeCallback = null;
// }
// // 移除切换动画节点
// if (this._changeSprite && this._changeSprite.node) {
// this._changeSprite.node.destroy();
// this._changeSprite = null;
// }
// }
// }
// updateChangeSpriteFrame = () => {
// if (this._changeSprite) {
// this._changeSprite.spriteFrame = GameDataManager.instance.getRandomSymbol();
// }
// }
// 获取精灵帧
getSkeData(): sp.SkeletonData {
return this.iconSpine ? this.iconSpine.skeletonData : null;
}
// 生命周期:组件禁用时
onDisable() {
// 移除切换动画节点
if (this._changeSprite && this._changeSprite.node) {
this._changeSprite.node.destroy();
this._changeSprite = null;
}
}
protected onDestroy(): void {
this.node.off(Node.EventType.TOUCH_END, this.onIconClick, this);
}
}