rp_10012/assets/Game/scripts/game/BigWinUI.ts
TJH 097b967d78
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 43s
快速模式下spin按钮节奏调整,iconmsg数字间距调整,bigwin播放时停止bgm
2025-10-13 17:05:20 +08:00

565 lines
20 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, AudioClip, AudioSource, Component, easing, Label, Node, NodePool, ParticleSystem, Prefab, sp, Sprite, SpriteFrame, Tween, tween, UIOpacity, v3, Vec3 } from 'cc';
import { WIN_TYPE } from './Define';
import { NodePoolManager } from '../../../Loading/scripts/manager/NodePoolManager';
import { gold2cash } from '../../../Loading/scripts/comm';
import { I18nManager } from '../../../Loading/scripts/manager/I18nManager';
import { AudioManager } from '../../../Loading/scripts/manager/AudioManager';
const { ccclass, property } = _decorator;
@ccclass('BigWinUI')
export class BigWinUI extends Component {
@property(Prefab)
bigWinUiPre: Prefab = null;
@property(AudioSource)
bigWinAudio: AudioSource = null;
@property([AudioClip])
bigWinAudioClips: AudioClip[] = [];
bigWinUINode: Node = null;
winScore: number = 0; // 最终赢分
winType: WIN_TYPE = WIN_TYPE.BIG_WIN; // 最终赢分类型
endImageIndex: number = 0; // 最终的结果
currentScore: number = 0; // 初始赢分
isScrolling: boolean = true; // 分数是否在滚动
isAnimationFinished: boolean = false; // 动画和数字滚动是否完成
scoreLabel: Label | null = null; // 分数节点
endTime: number = 5; // 动画完成后回收的时间
scrollTime: number = 5; // 是否是自动旋转
multis: number[] = [35, 50]; // 倍数区间
betAmount: number = 100000;
dynamicTargets: number[] = [];
onCloseCallBack: (() => void) | null = null;
winMainSpine: sp.Skeleton | null = null;
bigwinLabelSprite: Sprite | null = null;
megawinLabelSprite: Sprite | null = null;
supermegawinLabelSprite: Sprite | null = null;
// 添加金币特效节点引用
// bwEffectNode: Node | null = null;
// mewEffectNode: Node | null = null;
// smwEffectNode: Node | null = null;
// currentEffectNode: Node | null = null;
currentWinType: WIN_TYPE = WIN_TYPE.BIG_WIN; // 当前播放的动画类型
// 添加一个标记来区分是否是点击跳过
isSkipByTouch: boolean = false;
isfree: boolean = false;//是否在小游戏内
protected onLoad(): void {
// this.show(600000, WIN_TYPE.SUPER_MEGA_WIN, 10000,false)
}
show(winScore: number, winType: WIN_TYPE, betAmount: number, isFreeSpin: boolean) {
this.bigWinUINode = NodePoolManager.instance.getNodeFromPoolStatic('bigWinUI', this.bigWinUiPre);
this.isfree = isFreeSpin
AudioManager.instance.stopBGM()
this.scoreLabel = this.bigWinUINode.getChildByName('score').getComponent(Label);
this.winMainSpine = this.bigWinUINode.getChildByName('winMain').getComponent(sp.Skeleton);
this.bigwinLabelSprite = this.bigWinUINode.getChildByName('bigwinLabel').getComponent(Sprite);
this.megawinLabelSprite = this.bigWinUINode.getChildByName('megawinLabel').getComponent(Sprite);
this.supermegawinLabelSprite = this.bigWinUINode.getChildByName('supermegawinLabel').getComponent(Sprite);
// let winGoldParticle = this.bigWinUINode.getChildByName('particle');
// 获取各个等级的特效节点
// this.bwEffectNode = winGoldParticle.getChildByName('BIGWIN');
// this.mewEffectNode = winGoldParticle.getChildByName('MEGAWIN');
// this.smwEffectNode = winGoldParticle.getChildByName('SUPERMEGAWIN');
// 初始时隐藏所有特效
// this.hideAllEffects();
this.resetState();
this.winScore = winScore;
this.winType = winType;
this.betAmount = betAmount;
this.endImageIndex = this.winType - 3;
this.currentWinType = WIN_TYPE.BIG_WIN;
// test
this.scoreLabel.string = '0';
this.calculateDynamicTargets();
this.bigWinUINode.on(Node.EventType.TOUCH_START, this.onTouch, this);
this.node.addChild(this.bigWinUINode);
this.playSpineByType(WIN_TYPE.BIG_WIN, 'in');
this.startScoreAni();
}
// 隐藏所有特效节点
// private hideAllEffects() {
// if (this.bwEffectNode) this.bwEffectNode.active = false;
// if (this.mewEffectNode) this.mewEffectNode.active = false;
// if (this.smwEffectNode) this.smwEffectNode.active = false;
// this.currentEffectNode = null;
// }
// 根据大奖类型显示对应特效
// private showEffectByType(winType: WIN_TYPE) {
// // 先隐藏当前显示的特效
// this.hideAllEffects();
// // 根据类型显示对应特效
// let targetNode: Node | null = null;
// switch (winType) {
// case WIN_TYPE.SUPER_MEGA_WIN:
// targetNode = this.smwEffectNode;
// break;
// case WIN_TYPE.MEGA_WIN:
// targetNode = this.mewEffectNode;
// break;
// case WIN_TYPE.BIG_WIN:
// targetNode = this.bwEffectNode;
// break;
// }
// if (targetNode) {
// targetNode.active = true;
// this.currentEffectNode = targetNode;
// // 播放该节点下的所有粒子系统
// const particles = targetNode.getComponentsInChildren(ParticleSystem);
// particles.forEach(particle => {
// particle.stop();
// particle.clear();
// particle.play();
// });
// }
// }
calculateDynamicTargets() {
this.dynamicTargets = [];
// 根据实际获得的 winType 来决定需要播放哪些阶段
switch (this.winType) {
case WIN_TYPE.SUPER_MEGA_WIN:
this.dynamicTargets.push(this.betAmount * 35); // BIG_WIN 阈值
this.dynamicTargets.push(this.betAmount * 50); // MEGA_WIN 阈值
this.dynamicTargets.push(this.winScore);
break;
case WIN_TYPE.MEGA_WIN:
this.dynamicTargets.push(this.betAmount * 35); // BIG_WIN 阈值
this.dynamicTargets.push(this.winScore);
break;
case WIN_TYPE.BIG_WIN:
this.dynamicTargets.push(this.winScore);
break;
}
}
resetState() {
this.currentScore = 0;
this.isScrolling = true;
this.isSkipByTouch = false;
this.isAnimationFinished = false;
this.imageIndex = 0;
this.currentWinType = WIN_TYPE.BIG_WIN;
this.scoreLabel.node.scale = v3(1, 1, 1);
Tween.stopAllByTarget(this.scoreLabel.node);
}
imageIndex: number = 0;
startScoreAni() {
if (this.dynamicTargets.length === 0) return;
let targetScore = this.dynamicTargets.shift()!;
// 修改这里的滚动逻辑
let startScore = this.currentScore;
let startTime = 0;
this.isScrolling = true;
let updateScore = function (dt: number) {
if (!this.isScrolling) return;
startTime += dt;
let progress = Math.min(startTime / this.scrollTime, 1);
// if (this.dynamicTargets.length == 0 && this.winType >= WIN_TYPE.SUPER_MEGA_WIN) {
// this.currentScore = targetScore;
// } else {
let easedProgress = this.easeOutQuad(progress);
this.currentScore = startScore + (targetScore - startScore) * easedProgress;
// }
this.checkAndPlaySpineAnim(this.currentScore);
this.updateScoreLabel();
if (progress >= 1) {
this.currentScore = targetScore; // 确保最终数值精确
this.updateScoreLabel();
this.unschedule(updateScore);
if (this.dynamicTargets.length > 0) {
this.imageIndex++;
this.startScoreAni();
} else {
this.endAni();
}
}
}.bind(this);
this.schedule(updateScore, 0.01);
}
// 添加缓动函数
easeOutQuad(t: number): number {
return t * (2 - t);
}
checkAndPlaySpineAnim(score: number) {
let newWinType = this.getWinTypeByScore(score);
if (newWinType !== this.currentWinType) {
this.currentWinType = newWinType;
this.playSpineByType(this.currentWinType, 'in');
}
}
async playSpineByType(winType: WIN_TYPE, state: 'in' | 'loop' | 'out') {
if (!this.winMainSpine) return;
if (!this.bigwinLabelSprite) return;
let prefix = '';
switch (winType) {
case WIN_TYPE.SUPER_MEGA_WIN:
prefix = 'super';
break;
case WIN_TYPE.MEGA_WIN:
prefix = 'mega';
break;
default:
prefix = 'big';
break;
}
const animName = `${prefix}_${state}`;
if (state === 'in') {
if (!this.isSkipByTouch) {
// 停止当前音效
this.bigWinAudio.stop();
// 根据类型切换音效
switch (winType) {
case WIN_TYPE.SUPER_MEGA_WIN:
this.bigWinAudio.clip = this.bigWinAudioClips[2];
break;
case WIN_TYPE.MEGA_WIN:
this.bigWinAudio.clip = this.bigWinAudioClips[1];
break;
case WIN_TYPE.BIG_WIN:
this.bigWinAudio.clip = this.bigWinAudioClips[0];
break;
}
// 播放新音效
if (!AudioManager.instance.getMuted()) {
this.bigWinAudio.play();
}
}
this.winMainSpine.setCompleteListener(() => {
this.playSpineByType(winType, 'loop');
});
this.winMainSpine.setAnimation(0, animName, false);
// this.winMainSpine.setCompleteListener(() => {
// this.playSpineByType(winType, 'loop');
// });
// this.winLabelSprite.setAnimation(0, animName, false);
this.playWinLabelAnimation(prefix, state)
// 显示对应类型的特效
// this.showEffectByType(winType);
} else if (state === 'loop') {
this.winMainSpine.setCompleteListener(null);
this.winMainSpine.setAnimation(0, animName, true);
// this.winLabelSprite.setCompleteListener(null);
// this.winLabelSprite.setAnimation(0, animName, true);
this.playWinLabelAnimation(prefix, state)
// 显示对应类型的特效
// this.showEffectByType(winType);
} else {
this.playWinLabelAnimation(prefix, state)
this.winMainSpine.setCompleteListener(null);
this.winMainSpine.setAnimation(0, animName, false);
// tween(this.winMainSpine.node.getComponent(UIOpacity))
// .to(0.5, { opacity: 0 })
// .call(() => {
// this.closeImmediately()
// })
// .start()
// this.winLabelSprite.setCompleteListener(null);
// this.winLabelSprite.setAnimation(0, animName, false);
// 停止并隐藏特效
// if (this.currentEffectNode) {
// const particles = this.currentEffectNode.getComponentsInChildren(ParticleSystem);
// particles.forEach(particle => {
// particle.stop();
// particle.clear();
// });
// }
// this.hideAllEffects();
}
}
getWinTypeByScore(score: number): WIN_TYPE {
// 根据分数判断属于哪个区间
if (score >= this.betAmount * 50) {
return WIN_TYPE.SUPER_MEGA_WIN;
} else if (score >= this.betAmount * 35) {
return WIN_TYPE.MEGA_WIN;
} else {
return WIN_TYPE.BIG_WIN;
}
}
playWinLabelAnimation(prefix, state: string) {
if (state == 'in') {
switch (prefix) {
case 'big':
Tween.stopAllByTag(100)
tween(this.bigwinLabelSprite.node)
.tag(100)
.to(0.5, { scale: v3(1.2, 1.2, 1) })
.to(0.2, { scale: v3(1, 1, 1) })
.start()
break
case 'mega':
Tween.stopAllByTag(100)
this.bigwinLabelSprite.node.setScale(0, 0, 1)
tween(this.megawinLabelSprite.node)
.tag(100)
.to(0.5, { scale: v3(1.2, 1.2, 1) })
.to(0.2, { scale: v3(1, 1, 1) })
.start()
break
case 'super':
Tween.stopAllByTag(100)
this.megawinLabelSprite.node.setScale(0, 0, 1)
this.bigwinLabelSprite.node.setScale(0, 0, 1)
tween(this.supermegawinLabelSprite.node)
.tag(100)
.to(0.5, { scale: v3(1.2, 1.2, 1) })
.to(0.2, { scale: v3(1, 1, 1) })
.start()
break
}
} else if (state == 'loop') {
switch (prefix) {
case 'big':
Tween.stopAllByTag(100)
let bigWinTween =
tween(this.bigwinLabelSprite.node)
.to(0.5, { scale: v3(1.1, 1.1, 1) })
.to(0.5, { scale: v3(1, 1, 1) })
tween(this.bigwinLabelSprite.node)
.tag(100)
.repeatForever(bigWinTween)
.start()
break
case 'mega':
Tween.stopAllByTag(100)
let megaWinTween =
tween(this.megawinLabelSprite.node)
.to(0.5, { scale: v3(1.1, 1.1, 1) })
.to(0.5, { scale: v3(1, 1, 1) })
tween(this.megawinLabelSprite.node)
.tag(100)
.repeatForever(megaWinTween)
.start()
break
case 'super':
Tween.stopAllByTag(100)
let superMegaWinTween =
tween(this.supermegawinLabelSprite.node)
.to(0.5, { scale: v3(1.1, 1.1, 1) })
.to(0.5, { scale: v3(1, 1, 1) })
tween(this.supermegawinLabelSprite.node)
.tag(100)
.repeatForever(superMegaWinTween)
.start()
break
}
} else {
switch (prefix) {
case 'big':
Tween.stopAllByTag(100)
tween(this.bigwinLabelSprite.node)
.tag(100)
.to(0.5, { scale: v3(1.3, 1.3, 1) })
.to(0.5, { scale: v3(0, 0, 1) })
.start()
break
case 'mega':
Tween.stopAllByTag(100)
tween(this.megawinLabelSprite.node)
.tag(100)
.to(0.5, { scale: v3(1.3, 1.3, 1) })
.to(0.5, { scale: v3(0, 0, 1) })
.start()
break
case 'super':
Tween.stopAllByTag(100)
tween(this.supermegawinLabelSprite.node)
.tag(100)
.to(0.5, { scale: v3(1.3, 1.3, 1) })
.to(0.5, { scale: v3(0, 0, 1) })
.start()
break
}
}
}
updateScoreLabel() {
if (this.scoreLabel) this.scoreLabel.string = gold2cash(this.currentScore);
}
async onTouch() {
if (!this.bigWinUINode) return; // 添加节点存在检查
if (this.isScrolling) {
this.isSkipByTouch = true;
// 如果当前index已经是最终index就不需要重复播放
if (this.imageIndex === this.endImageIndex) {
this.isScrolling = false;
this.unscheduleAllCallbacks();
this.currentScore = this.winScore;
this.updateScoreLabel();
this.endAni();
return;
}
// 立即完成当前动画
this.isScrolling = false;
this.unscheduleAllCallbacks();
// 直接设置为最终分数
this.currentScore = this.winScore;
this.updateScoreLabel();
// 直接播放最终类型的start动画完成后自动切换到loop
this.playSpineByType(this.winType, 'in');
// 直接切换到最终特效
// this.showEffectByType(this.winType);
this.bigWinAudio.stop();
this.bigWinAudio.clip = this.bigWinAudioClips[3];
if (!AudioManager.instance.getMuted()) {
this.bigWinAudio.play();
}
this.endAni();
} else if (this.isAnimationFinished) {
this.unscheduleAllCallbacks(); // 取消自动关闭定时器
this.autoClose(); // 复用自动关闭逻辑
}
}
endAni() {
this.isScrolling = false;
let scoreNode = this.scoreLabel.node;
// 只有在非点击跳过的情况下才播放结算音效
if (!this.isSkipByTouch && this.imageIndex === this.endImageIndex) {
this.bigWinAudio.stop();
this.bigWinAudio.clip = this.bigWinAudioClips[3];
if (!AudioManager.instance.getMuted()) {
this.bigWinAudio.play();
}
}
tween(scoreNode)
.to(0.25, { scale: v3(1.3, 1.3, 1.3) })
.to(0.25, { scale: v3(1, 1, 1) })
.call(() => {
this.isAnimationFinished = true;
// 在动画完成时启动5秒倒计时
this.scheduleOnce(this.autoClose.bind(this), 5);
})
.start();
}
private autoClose() {
if (this.isAnimationFinished) { // 确保还没被点击关闭
this.isAnimationFinished = false;
this.bigWinAudio.stop();
Tween.stopAllByTarget(this.scoreLabel.node);
tween(this.scoreLabel.node)
.to(0.2, { scale: v3(1.3, 1.3, 1.3) })
.to(0.3, { scale: v3(0, 0, 0) })
.start();
this.playSpineByType(this.winType, 'out');
this.winMainSpine.setCompleteListener(() => {
this.closeImmediately();
});
// this.winLabelSprite.setCompleteListener(() => {
// this.closeImmediately();
// });
}
}
closeImmediately() {
if (this.onCloseCallBack) {
this.onCloseCallBack();
}
// 停止所有特效
// if (this.currentEffectNode) {
// const particles = this.currentEffectNode.getComponentsInChildren(ParticleSystem);
// particles.forEach(particle => {
// particle.stop();
// particle.clear();
// });
// }
// this.hideAllEffects();
this.unscheduleAllCallbacks();
// 清理spine监听器
if (this.winMainSpine) {
this.winMainSpine.setCompleteListener(null);
}
// if (this.winLabelSprite) {
// this.winLabelSprite.setCompleteListener(null);
// }
this.bigWinUINode.off(Node.EventType.TOUCH_START, this.onTouch, this);
AudioManager.instance.playBGM(this.isfree ? 'Free_Mode_BGM' : 'Normal_Mode_BGM')
this.hide();
}
hide() {
NodePoolManager.instance.putNodeToPool('bigWinUI', this.bigWinUINode);
this.bigWinUINode = null;
}
public setCloseCallBack(call: () => void) {
this.onCloseCallBack = call;
}
}