import { _decorator, Component, Node, Vec3, instantiate, UITransform, resources, sp, find, JsonAsset } from 'cc'; const { ccclass, property } = _decorator; /** * 小球撞击动画管理器 * 负责在小球撞击时播放特效动画 */ @ccclass('BallAni') export class BallAni extends Component { // 撞击特效预制体缓存 private static impactEffectSkeleton: sp.SkeletonData = null; private static isLoading: boolean = false; // 当前播放中的特效节点列表 private activeEffects: Node[] = []; start() { // 预加载撞击特效资源 this.preloadImpactEffect(); } /** * 预加载撞击特效资源 */ private preloadImpactEffect() { if (BallAni.impactEffectSkeleton || BallAni.isLoading) { return; } BallAni.isLoading = true; const path = 'Animation/WeaponTx/tx0005/tx0005'; resources.load(path, sp.SkeletonData, (err, sData: sp.SkeletonData) => { BallAni.isLoading = false; if (err || !sData) { console.warn('[BallAni] 加载撞击特效失败:', err); return; } BallAni.impactEffectSkeleton = sData; console.log('[BallAni] 撞击特效资源加载成功'); }); } /** * 在指定位置播放撞击特效 * @param worldPosition 世界坐标位置 */ public playImpactEffect(worldPosition: Vec3) { // 如果资源未加载,直接加载并播放 if (!BallAni.impactEffectSkeleton) { const path = 'Animation/WeaponTx/tx0005/tx0005'; resources.load(path, sp.SkeletonData, (err, sData: sp.SkeletonData) => { if (err || !sData) { console.warn('[BallAni] 加载撞击特效失败:', err); return; } BallAni.impactEffectSkeleton = sData; this.createAndPlayEffect(worldPosition, sData); }); return; } this.createAndPlayEffect(worldPosition, BallAni.impactEffectSkeleton); } /** * 创建并播放特效 */ private createAndPlayEffect(worldPosition: Vec3, skeletonData: sp.SkeletonData) { const effectNode = new Node('ImpactEffect'); const skeleton = effectNode.addComponent(sp.Skeleton); skeleton.skeletonData = skeletonData; skeleton.premultipliedAlpha = false; skeleton.setAnimation(0, 'animation', false); skeleton.setCompleteListener(() => { this.removeEffect(effectNode); }); const canvas = find('Canvas'); if (canvas) { canvas.addChild(effectNode); effectNode.setWorldPosition(worldPosition); // 设置特效缩放 effectNode.setScale(0.8, 0.8, 1); // 添加到活动特效列表 this.activeEffects.push(effectNode); } else { effectNode.destroy(); } } /** * 移除特效节点 * @param effectNode 要移除的特效节点 */ private removeEffect(effectNode: Node) { // 从活动特效列表中移除 const index = this.activeEffects.indexOf(effectNode); if (index !== -1) { this.activeEffects.splice(index, 1); } // 销毁节点 if (effectNode && effectNode.isValid) { effectNode.destroy(); } } /** * 清理所有活动的特效 */ public clearAllEffects() { for (const effect of this.activeEffects) { if (effect && effect.isValid) { effect.destroy(); } } this.activeEffects = []; } onDestroy() { // 组件销毁时清理所有特效 this.clearAllEffects(); } /** * 获取单例实例(如果需要全局访问) */ public static getInstance(): BallAni | null { const gameArea = find('Canvas/GameLevelUI/GameArea'); if (!gameArea) { return null; } let ballAni = gameArea.getComponent(BallAni); if (!ballAni) { ballAni = gameArea.addComponent(BallAni); } return ballAni; } }