MatchMaster/assets/gacha_bundle/script/GachaDrawAnime.ts
2026-07-30 12:22:02 +08:00

232 lines
6.4 KiB
TypeScript

import CatBounce from "../../Script/CatBounce";
import GachaBallDropSquash from "./GachaBallDropSquash";
import GachaManager from "./GachaManager";
const { ccclass, property } = cc._decorator;
@ccclass
export default class GachaDrawAnime extends cc.Component {
@property
autoPlay: boolean = true;
@property
fadeDuration: number = 2.55;
@property
spinDuration: number = 5.5;
@property
popDuration: number = 0.85;
@property
transitionRecoverDuration: number = 0.09;
@property
transitionSquashScaleY: number = 0.3;
private dropNode: cc.Node = null;
private fadeNode: cc.Node = null;
private spinNode: cc.Node = null;
private resultNode: cc.Node = null;
private fadeBaseY: number = 0;
private fadeBaseScaleX: number = 1;
private fadeBaseScaleY: number = 1;
private resultBaseY: number = 0;
private resultBaseScaleX: number = 1;
private resultBaseScaleY: number = 1;
onLoad() {
this.dropNode = this.node.getChildByName("1");
this.fadeNode = this.node.getChildByName("2");
this.spinNode = this.node.getChildByName("3");
this.resultNode = this.node.getChildByName("4");
if (this.fadeNode) {
this.fadeBaseY = this.fadeNode.y;
this.fadeBaseScaleX = this.fadeNode.scaleX;
this.fadeBaseScaleY = this.fadeNode.scaleY;
}
if (this.resultNode) {
this.resultBaseY = this.resultNode.y;
this.resultBaseScaleX = this.resultNode.scaleX;
this.resultBaseScaleY = this.resultNode.scaleY;
}
this.resetAnime();
}
onEnable() {
if (this.autoPlay) {
this.playAnime();
}
}
resetAnime() {
this.stopResultLoop();
if (this.dropNode) {
this.dropNode.active = true;
this.dropNode.opacity = 255;
}
if (this.fadeNode) {
this.fadeNode.active = false;
this.fadeNode.opacity = 255;
this.fadeNode.y = this.fadeBaseY;
this.fadeNode.scaleX = this.fadeBaseScaleX;
this.fadeNode.scaleY = this.fadeBaseScaleY;
}
if (this.spinNode) {
this.spinNode.active = false;
this.spinNode.opacity = 255;
this.spinNode.angle = 0;
}
if (this.resultNode) {
this.resultNode.active = false;
this.resultNode.opacity = 255;
this.resultNode.y = this.resultBaseY;
this.resultNode.scaleX = this.resultBaseScaleX;
this.resultNode.scaleY = this.resultBaseScaleY;
this.resultNode.angle = 0;
}
}
playAnime() {
this.resetAnime();
if (!this.dropNode) {
this.showResultStage();
return;
}
this.playGachaEffect("drop");
let dropAnime = this.dropNode.getComponent(GachaBallDropSquash);
if (dropAnime) {
dropAnime.playDropSquash(() => {
this.showResultStage();
});
return;
}
this.showResultStage();
}
showResultStage() {
if (this.dropNode) {
this.dropNode.active = false;
}
if (this.fadeNode) {
this.fadeNode.active = true;
this.fadeNode.opacity = 255;
this.fadeNode.y = this.fadeBaseY;
this.fadeNode.scaleX = this.fadeBaseScaleX;
this.fadeNode.scaleY = this.fadeBaseScaleY * this.transitionSquashScaleY;
cc.tween(this.fadeNode)
.call(() => {
this.fadeNode.scaleX = this.fadeBaseScaleX;
this.showResultNode();
})
.to(this.transitionRecoverDuration, {
scaleY: this.fadeBaseScaleY,
}, { easing: "linear" })
.to(this.fadeDuration, { opacity: 0 }, { easing: "sineOut" })
.start();
}
else {
this.showResultNode();
}
if (this.spinNode) {
this.spinNode.active = true;
this.spinNode.opacity = 255;
this.spinNode.angle = 0;
cc.tween(this.spinNode)
.repeatForever(
cc.tween()
.by(this.spinDuration, { angle: 360 })
)
.start();
}
}
showResultNode() {
if (!this.resultNode) {
return;
}
this.playGachaEffect("open");
this.resultNode.active = true;
this.resultNode.opacity = 255;
this.resultNode.y = this.resultBaseY;
this.resultNode.angle = 0;
this.resultNode.scaleX = 0;
this.resultNode.scaleY = 0;
cc.tween(this.resultNode)
.to(this.popDuration * 0.55, { scaleX: this.resultBaseScaleX, scaleY: this.resultBaseScaleY }, { easing: "sineOut" })
.to(this.popDuration * 0.2, { scaleX: this.resultBaseScaleX * 1.12, scaleY: this.resultBaseScaleY * 1.12 }, { easing: "sineInOut" })
.to(this.popDuration * 0.25, { scaleX: this.resultBaseScaleX, scaleY: this.resultBaseScaleY }, { easing: "sineInOut" })
.call(() => {
this.startResultBounce();
})
.start();
}
/** 音效资源统一由根节点 GachaManager 管理。 */
private playGachaEffect(type: string) {
let current = this.node;
while (current) {
const manager = current.getComponent(GachaManager);
if (manager) {
manager.playGachaEffect(type);
return;
}
current = current.parent;
}
}
startResultBounce() {
if (!this.resultNode) {
return;
}
const catBounce = this.resultNode.getComponent(CatBounce);
if (catBounce) {
catBounce.playBounce();
}
else {
this.resultNode.addComponent(CatBounce);
}
}
stopResultLoop() {
if (this.dropNode) {
this.dropNode.stopAllActions();
}
if (this.fadeNode) {
this.fadeNode.stopAllActions();
}
if (this.spinNode) {
this.spinNode.stopAllActions();
}
if (this.resultNode) {
this.resultNode.stopAllActions();
}
}
onDisable() {
this.stopResultLoop();
}
onDestroy() {
this.stopResultLoop();
}
}