import { _decorator, Color, Component, Enum, Node, Sprite, tween, Vec3, UITransform, view, sp, Game, UIOpacity } from 'cc'; import { CupHeight, WaterColorHex, WaterColors } from '../TakeGobletGlobalInstance'; import { Water } from './Water'; import { EventDispatcher } from 'db://assets/core_tgx/easy_ui_framework/EventDispatcher'; import { GameEvent } from '../Enum/GameEvent'; import { OutArea } from './OutArea'; import { GameUtil } from '../GameUtil'; import { TakeGobletAudioMgr } from '../Manager/TakeGobletAudioMgr'; const { ccclass, property, executeInEditMode } = _decorator; //调酒杯状态 默认 接水 export enum CocktailCupState { Default, GetWater, Move, Full } /** 调酒杯组件脚本*/ @ccclass('CocktailCup') // @executeInEditMode export class CocktailCup extends Component { @property(Node) waters: Node = null! //水流节点 @property(sp.Skeleton) colorB: sp.Skeleton = null! //水流颜色骨骼 @property(Node) good: Node = null!; @property({ type: Enum(CupHeight), displayName: '杯高度' }) cupHeight: CupHeight = CupHeight.Two @property({ type: Enum(WaterColors) }) private _cupColor: WaterColors = WaterColors.Blue @property({ type: Enum(WaterColors) }) get cupColor() { return this._cupColor } set cupColor(value) { this._cupColor = value this.changeColor() } currentLayers: number = 0; onLoad() { this.playAnimationByState(CocktailCupState.Default); } changeColor() { const color = new Color(WaterColorHex[this.cupColor]); this.waters.children.forEach((water, index) => { water.getComponent(sp.Skeleton)!.color = color; }) this.colorB.color = color; } /** 添加图层 接水动画*/ async addLayer() { this.currentLayers++; this.playAnimationByState(CocktailCupState.GetWater); await GameUtil.delay(0.4); await this.checkAndDestroy(); } //补满水 public async fillUp() { if (!this.node) return; TakeGobletAudioMgr.playOneShot(TakeGobletAudioMgr.getMusicIdName(5), 1.0); this.playAnimationByState(CocktailCupState.Full); this.fadeOut(); await GameUtil.delay(0.5); // 补满后执行移动销毁动画 const uiTransform = this.node.getComponent(UITransform)!; const screenWidth = view.getVisibleSize().width; const targetX = screenWidth + uiTransform.width * 1.5; await new Promise(resolve => { tween(this.node) .to(0.5, { position: new Vec3(targetX, 0, 0) }, { easing: 'sineIn' }) .call(async () => { const outArea = this.node.parent?.parent?.getComponent(OutArea); if (outArea) { this.node.removeFromParent(); // 先从父节点移除 this.node.destroy(); await outArea.arrangeCups(); // 等待排列完成 } resolve(); }) .start(); }); } //渐隐效果 fadeOut() { if (!this.good) return; const uiOpacity = this.good.getComponent(UIOpacity)!; this.good.active = true; uiOpacity.opacity = 255; tween(uiOpacity) .to(0.5, { opacity: 0 }, { easing: 'sineIn' }) .call(() => { this.good.active = false; }) .start(); } //播放动画 playAnimationByState(state: CocktailCupState) { const waters = this.waters.children; const siblingNodes = this.node.children.filter(child => child.name !== 'waters' && child.name !== 'good'); const allNodes = [...waters, ...siblingNodes]; switch (state) { case CocktailCupState.GetWater: this.setSpineTimeScale(1.5); allNodes.forEach(child => child.getComponent(sp.Skeleton)!.setAnimation(0, `pour_0${this.currentLayers}`, false)); break; case CocktailCupState.Move: allNodes.forEach(child => child.getComponent(sp.Skeleton)!.setAnimation(0, 'move', false)); break; case CocktailCupState.Full: allNodes.forEach(child => child.getComponent(sp.Skeleton)!.setAnimation(0, 'full', false)); break; default: allNodes.forEach(child => child.getComponent(sp.Skeleton)!.setAnimation(0, 'idle', false)); break; } } //设置spine 时间缩放率 setSpineTimeScale(timeScale: number = 1) { if (!this.node) return; const spineComponents = this.node.getComponentsInChildren(sp.Skeleton); spineComponents.forEach(spine => { spine.timeScale = timeScale; }); } protected onDestroy(): void { EventDispatcher.instance.emit(GameEvent.EVENT_REFRESH_REMAIN_CUP); } // 清空水层(消除时调用) reset() { this.currentLayers = 0; } get isFull(): boolean { return this.currentLayers >= this.cupHeight; } private async checkAndDestroy() { if (this.isFull) { await this.fillUp(); } } public get currentColor(): WaterColors { return this.cupColor; } public get remainingCapacity(): number { return this.cupHeight - this.currentLayers; } }