Browse Source

方块收缩特效

181404010226 4 months ago
parent
commit
66fcdf19cd

File diff suppressed because it is too large
+ 167 - 152
assets/Scenes/GameLevel.scene


+ 12 - 0
assets/resources/shaders.meta

@@ -0,0 +1,12 @@
+{
+  "ver": "1.2.0",
+  "importer": "directory",
+  "imported": true,
+  "uuid": "c3d4e5f6-g7h8-9012-cdef-345678901234",
+  "files": [],
+  "subMetas": {},
+  "userData": {
+    "compressionType": {},
+    "isRemoteBundle": {}
+  }
+}

+ 137 - 5
assets/scripts/Animations/BallAni.ts

@@ -1,4 +1,5 @@
-import { _decorator, Component, Node, Vec3, instantiate, UITransform, resources, sp, find, JsonAsset } from 'cc';
+import { _decorator, Component, Node, Vec3, tween, Color, Sprite, resources, sp, find } from 'cc';
+import EventBus, { GameEvents } from '../Core/EventBus';
 const { ccclass, property } = _decorator;
 
 /**
@@ -15,11 +16,102 @@ export class BallAni extends Component {
     // 当前播放中的特效节点列表
     private activeEffects: Node[] = [];
     
+    // 当前播放中的方块动画列表
+    private activeBlockAnimations: Map<Node, any> = new Map();
+    
     start() {
         // 预加载撞击特效资源
         this.preloadImpactEffect();
     }
     
+    /**
+     * 播放方块被撞击动画
+     * @param blockNode 方块节点
+     */
+    public playBlockHitAnimation(blockNode: Node) {
+        if (!blockNode || !blockNode.isValid) {
+            console.warn('[BallAni] 方块节点无效');
+            return;
+        }
+        
+        // 如果该方块已经在播放动画,跳过
+        if (this.activeBlockAnimations.has(blockNode)) {
+            console.log('[BallAni] 方块动画已在播放中,跳过');
+            return;
+        }
+        
+        // 检查是否有活跃敌人,只有有敌人时才播放缩放动画
+        const eventBus = EventBus.getInstance();
+        let hasActiveEnemies = false;
+        
+        // 通过事件系统检查是否有活跃敌人
+        eventBus.emit(GameEvents.BALL_FIRE_BULLET, { 
+            canFire: (canFire: boolean) => { 
+                hasActiveEnemies = canFire; 
+            } 
+        });
+        
+        console.log('[BallAni] 开始播放方块撞击动画', blockNode.name, '有敌人:', hasActiveEnemies);
+        
+        const sprite = blockNode.getComponent(Sprite);
+        const originalScale = blockNode.scale.clone();
+        const originalColor = sprite ? sprite.color.clone() : Color.WHITE.clone();
+        
+        console.log('[BallAni] 原始缩放:', originalScale, '原始颜色:', originalColor);
+        
+        if (hasActiveEnemies) {
+            // 有敌人时播放完整动画:收缩到0.5倍 -> 变白发亮 -> 恢复正常
+            const shrinkScale = originalScale.clone().multiplyScalar(0.5);
+            const animationTween = tween(blockNode)
+                .to(0.2, { scale: shrinkScale })
+                .call(() => {
+                    console.log('[BallAni] 方块收缩完成,开始变白');
+                    // 变白发光效果
+                    if (sprite) {
+                        sprite.color = Color.WHITE;
+                    }
+                })
+                .to(0.2, { scale: originalScale })
+                .call(() => {
+                    console.log('[BallAni] 方块动画完成,恢复原状');
+                    // 恢复原始颜色
+                    if (sprite) {
+                        sprite.color = originalColor;
+                    }
+                    // 动画完成,从活动列表中移除
+                    this.activeBlockAnimations.delete(blockNode);
+                })
+                .start();
+            
+            // 添加到活动动画列表
+            this.activeBlockAnimations.set(blockNode, animationTween);
+        } else {
+            // 没有敌人时只播放白光效果,不缩放
+            const animationTween = tween({})
+                .call(() => {
+                    console.log('[BallAni] 无敌人,仅播放白光效果');
+                    // 变白发光效果
+                    if (sprite) {
+                        sprite.color = Color.WHITE;
+                    }
+                })
+                .delay(0.2) // 保持白光一段时间
+                .call(() => {
+                    console.log('[BallAni] 白光效果完成,恢复原状');
+                    // 恢复原始颜色
+                    if (sprite) {
+                        sprite.color = originalColor;
+                    }
+                    // 动画完成,从活动列表中移除
+                    this.activeBlockAnimations.delete(blockNode);
+                })
+                .start();
+            
+            // 添加到活动动画列表
+            this.activeBlockAnimations.set(blockNode, animationTween);
+        }
+    }
+    
     /**
      * 预加载撞击特效资源
      */
@@ -106,6 +198,24 @@ export class BallAni extends Component {
         }
     }
     
+    /**
+     * 停止指定方块的动画
+     * @param blockNode 方块节点
+     */
+    public stopBlockAnimation(blockNode: Node) {
+        const animation = this.activeBlockAnimations.get(blockNode);
+        if (animation) {
+            animation.stop();
+            this.activeBlockAnimations.delete(blockNode);
+            
+            // 恢复原始状态
+            const sprite = blockNode.getComponent(Sprite);
+            if (sprite) {
+                sprite.color = Color.WHITE;
+            }
+        }
+    }
+    
     /**
      * 清理所有活动的特效
      */
@@ -118,23 +228,45 @@ export class BallAni extends Component {
         this.activeEffects = [];
     }
     
+    /**
+     * 清除所有方块动画
+     */
+    public clearAllBlockAnimations() {
+        // 停止所有方块动画
+        for (const [blockNode, animation] of this.activeBlockAnimations) {
+            if (animation) {
+                animation.stop();
+            }
+            // 恢复方块状态
+            const sprite = blockNode.getComponent(Sprite);
+            if (sprite) {
+                sprite.color = Color.WHITE;
+            }
+        }
+        this.activeBlockAnimations.clear();
+    }
+    
     onDestroy() {
-        // 组件销毁时清理所有特效
+        // 组件销毁时清理所有特效和动画
         this.clearAllEffects();
+        this.clearAllBlockAnimations();
     }
     
     /**
-     * 获取单例实例(如果需要全局访问)
+     * 获取BallAni实例
+     * @returns BallAni实例
      */
     public static getInstance(): BallAni | null {
         const gameArea = find('Canvas/GameLevelUI/GameArea');
         if (!gameArea) {
+            console.warn('[BallAni] 未找到GameArea节点');
             return null;
         }
         
-        let ballAni = gameArea.getComponent(BallAni);
+        const ballAni = gameArea.getComponent(BallAni);
         if (!ballAni) {
-            ballAni = gameArea.addComponent(BallAni);
+            console.warn('[BallAni] GameArea节点上未找到BallAni组件');
+            return null;
         }
         
         return ballAni;

+ 23 - 9
assets/scripts/Animations/HPBarAnimation.ts

@@ -95,7 +95,9 @@ export class HPBarAnimation extends Component {
         }
         
         // 红色血条显示当前血量
-        this.redProgressBar.progress = this.currentProgress;
+        if (this.redProgressBar && this.redProgressBar.isValid) {
+            this.redProgressBar.progress = this.currentProgress;
+        }
     }
     
     /**
@@ -118,8 +120,12 @@ export class HPBarAnimation extends Component {
             this.currentProgress = newProgress;
             this.targetProgress = newProgress;
             // 同步更新两个血条
-            this.redProgressBar.progress = newProgress;
-            this.yellowProgressBar.progress = newProgress;
+            if (this.redProgressBar && this.redProgressBar.isValid) {
+                this.redProgressBar.progress = newProgress;
+            }
+            if (this.yellowProgressBar && this.yellowProgressBar.isValid) {
+                this.yellowProgressBar.progress = newProgress;
+            }
             this.updateBarDisplay();
             return;
         }
@@ -142,11 +148,15 @@ export class HPBarAnimation extends Component {
         
         // 1. 立即更新红色血条到新的血量值
         this.currentProgress = newProgress;
-        this.redProgressBar.progress = newProgress;
+        if (this.redProgressBar && this.redProgressBar.isValid) {
+            this.redProgressBar.progress = newProgress;
+        }
         
         // 2. 黄色血条从原血量滑动到新血量位置        
         // 黄色血条保持在原始位置
-        this.yellowProgressBar.progress = originalProgress;
+        if (this.yellowProgressBar && this.yellowProgressBar.isValid) {
+            this.yellowProgressBar.progress = originalProgress;
+        }
         this.updateBarDisplay();
         
         // 创建滑动动画,先暂停0.4秒再滑动
@@ -155,13 +165,17 @@ export class HPBarAnimation extends Component {
             .to(0.6, { progress: newProgress }, {
                 onUpdate: (target) => {
                     // 动画过程中更新黄色血条进度
-                    this.yellowProgressBar.progress = target.progress;
-                    this.updateBarDisplay();
+                    if (this.yellowProgressBar && this.yellowProgressBar.isValid) {
+                        this.yellowProgressBar.progress = target.progress;
+                        this.updateBarDisplay();
+                    }
                 },
                 onComplete: () => {
                     // 动画完成后黄色血条进度等于当前血量
-                    this.yellowProgressBar.progress = newProgress;
-                    this.updateBarDisplay();
+                    if (this.yellowProgressBar && this.yellowProgressBar.isValid) {
+                        this.yellowProgressBar.progress = newProgress;
+                        this.updateBarDisplay();
+                    }
                 }
             })
             .start();

+ 4 - 0
assets/scripts/CombatSystem/BallController.ts

@@ -658,6 +658,10 @@ export class BallController extends Component {
             hasWeaponChild;
             
         if (isBlock) {
+            // 播放方块撞击动画
+            if (ballAni) {
+                ballAni.playBlockHitAnimation(otherNode);
+            }
             // 通过事件检查是否可以发射子弹
             const eventBus = EventBus.getInstance();
             let canFire = true;

+ 1 - 3
assets/scripts/CombatSystem/EnemyController.ts

@@ -302,9 +302,7 @@ export class EnemyController extends BaseSingleton {
     private onBallFireBulletEvent(data: { canFire: (value: boolean) => void }) {
         // 检查是否有活跃敌人
         const hasActiveEnemies = this.hasActiveEnemies();
-        if (!hasActiveEnemies) {
-            data.canFire(false);
-        }
+        data.canFire(hasActiveEnemies);
     }
 
     /**

Some files were not shown because too many files changed in this diff