Explorar el Código

按钮效果修复

181404010226 hace 4 meses
padre
commit
6b627bd26f

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 272 - 404
assets/Scenes/GameLevel.scene


+ 51 - 35
assets/scripts/Animations/BallAni.ts

@@ -76,10 +76,7 @@ export class BallAni extends Component {
             canFire: (canFire: boolean) => { 
                 hasActiveEnemies = canFire; 
             } 
-        });
-        
-        console.log('[BallAni] 开始播放方块撞击动画', blockNode.name, '有敌人:', hasActiveEnemies);
-        console.log('[BallAni] hasActiveEnemies 检查结果:', hasActiveEnemies);
+        });      
         
         // 立即执行动画
         this.executeBlockAnimation(blockNode, hasActiveEnemies);
@@ -113,42 +110,68 @@ export class BallAni extends Component {
         const nodeChild = blockNode.getChildByName('Node');
         const sprite = nodeChild ? nodeChild.getComponent(Sprite) : null;
         
-        // 保存原始材质和Sprite缩放
+        // 查找预制体根节点和Weapon节点
+        // 如果传入的是子节点(如"Node"),需要找到预制体根节点
+        let prefabRoot = blockNode;
+        if (blockNode.name === 'Node' && blockNode.parent) {
+            prefabRoot = blockNode.parent;
+        }
+        
+        const weaponNode = prefabRoot.getChildByName('Weapon');
+        
+
+        
+        // 保存原始材质和缩放
         // 优先保存customMaterial,如果没有则保存当前material
         const originalMaterial = sprite ? (sprite.customMaterial || sprite.material) : null;
-        const originalSpriteScale = sprite ? new Vec3(1, 1, 1) : new Vec3(1, 1, 1);
+        const originalBlockScale = new Vec3(blockNode.scale.x, blockNode.scale.y, blockNode.scale.z);
+        const originalWeaponScale = weaponNode ? new Vec3(weaponNode.scale.x, weaponNode.scale.y, weaponNode.scale.z) : null;
         
         
         if (hasActiveEnemies) {
-            // 有敌人时播放Sprite缩放动画(不影响碰撞体积)
-            const shrinkSpriteScale = new Vec3(0.7, 0.7, 1);
-            
-            // 应用白色描边材质
-            console.log('[BallAni] 检查材质状态:', {
-                hasSprite: !!sprite,
-                hasWhiteMaterial: !!BallAni.whiteMaterial,
-                currentMaterial: sprite ? sprite.material : null
-            });
+            // 有敌人时播放方块缩放动画(包括Node和Weapon子节点)
+            const shrinkBlockScale = new Vec3(0.7, 0.7, 1);
             
+            // 应用白色描边材质到Node子节点的Sprite组件
             if (sprite && BallAni.whiteMaterial) {
                 sprite.material = BallAni.whiteMaterial;
-                console.log('[BallAni] 应用白色描边材质成功');
-            } else if (sprite) {
-                console.log('[BallAni] 白色描边材质未加载,跳过材质应用');
             }
             
-            // 对Sprite节点进行缩放动画(不影响方块碰撞体积)
-            const animationTween = tween(sprite.node)
-                .to(0.2, { scale: shrinkSpriteScale })
-                .to(0.2, { scale: originalSpriteScale })
+            // 对方块预制体进行缩放动画
+            // Weapon节点需要在其原有0.4倍基础上再进行缩放动画
+            const weaponShrinkScale = originalWeaponScale ? new Vec3(
+                originalWeaponScale.x * 0.7, // 在0.4倍基础上再缩小到0.7倍
+                originalWeaponScale.y * 0.7,
+                originalWeaponScale.z
+            ) : null;
+            
+            const animationTween = tween(blockNode)
+                .to(0.2, { scale: shrinkBlockScale }, {
+                    onStart: () => {
+                        // 开始动画时,同时缩放Weapon节点
+                        if (weaponNode && weaponShrinkScale) {
+                            tween(weaponNode)
+                                .to(0.2, { scale: weaponShrinkScale })
+                                .start();
+                        }
+                    }
+                })
+                .to(0.2, { scale: originalBlockScale }, {
+                    onStart: () => {
+                        // 恢复动画时,同时恢复Weapon节点
+                        if (weaponNode && originalWeaponScale) {
+                            tween(weaponNode)
+                                .to(0.2, { scale: originalWeaponScale })
+                                .start();
+                        }
+                    }
+                })
                 .call(() => {
+                    // 确保Weapon节点恢复到原始缩放
+                    if (weaponNode && originalWeaponScale) {
+                        weaponNode.scale = originalWeaponScale;
+                    }
                     // 动画完成时恢复原始材质
-                    console.log('[BallAni] 恢复材质状态:', {
-                        hasSprite: !!sprite,
-                        hasOriginalMaterial: !!originalMaterial,
-                        currentMaterial: sprite ? sprite.material : null
-                    });
-                    
                     if (sprite && originalMaterial) {
                         // 如果原始材质是customMaterial,则恢复customMaterial
                         if (sprite.customMaterial === originalMaterial) {
@@ -156,20 +179,14 @@ export class BallAni extends Component {
                         } else {
                             sprite.material = originalMaterial;
                         }
-                        console.log('[BallAni] 恢复原始材质成功');
                     } else if (sprite) {
                         // 如果没有保存的原始材质,尝试恢复到customMaterial
                         if (sprite.customMaterial) {
                             sprite.material = sprite.customMaterial;
-                            console.log('[BallAni] 恢复到customMaterial');
                         } else {
                             sprite.material = null;
-                            console.log('[BallAni] 恢复到默认材质');
                         }
-                    } else {
-                        console.log('[BallAni] 无法恢复原始材质 - Sprite组件丢失');
                     }
-                    console.log('[BallAni] 方块动画完成,恢复原状');
                     // 动画完成,从活动列表中移除
                     this.activeBlockAnimations.delete(blockNode);
                 })
@@ -182,7 +199,6 @@ export class BallAni extends Component {
             const animationTween = tween({})
                 .delay(0.2)
                 .call(() => {
-                    console.log('[BallAni] 无敌人,直接恢复原状');
                     // 动画完成,从活动列表中移除
                     this.activeBlockAnimations.delete(blockNode);
                 })

+ 116 - 0
assets/scripts/Animations/ButtonManager.ts

@@ -0,0 +1,116 @@
+import { _decorator, Component, Node, Button, Tween, tween, Vec3 } from 'cc';
+const { ccclass, property } = _decorator;
+
+@ccclass('ButtonManager')
+export class ButtonManager extends Component {
+    private static _instance: ButtonManager = null;
+    
+    @property({ type: [Button], displayName: "按钮数组" })
+    public buttons: Button[] = [];
+    
+    // 动画参数
+    private readonly SCALE_DOWN = 0.85; // 缩小到原来的0.85倍(相当于缩小1.5倍的倒数)
+    private readonly ANIMATION_DURATION = 0.1; // 动画持续时间
+    
+    public static get instance(): ButtonManager {
+        return ButtonManager._instance;
+    }
+    
+    onLoad() {
+        // 设置单例
+        if (ButtonManager._instance === null) {
+            ButtonManager._instance = this;
+        } else {
+            this.destroy();
+            return;
+        }
+        
+        // 初始化按钮事件
+        this.initButtonEvents();
+    }
+    
+    onDestroy() {
+        if (ButtonManager._instance === this) {
+            ButtonManager._instance = null;
+        }
+    }
+    
+    private initButtonEvents() {
+        this.buttons.forEach((button, index) => {
+            if (button && button.node) {
+                // 添加点击事件监听
+                button.node.on(Button.EventType.CLICK, () => {
+                    this.playClickAnimation(button.node);
+                }, this);
+                
+                // 确保按钮初始缩放为1
+                button.node.setScale(Vec3.ONE);
+            }
+        });
+    }
+    
+    /**
+     * 播放按钮点击动画
+     * @param buttonNode 按钮节点
+     */
+    private playClickAnimation(buttonNode: Node) {
+        if (!buttonNode) return;
+        
+        // 停止之前的动画
+        Tween.stopAllByTarget(buttonNode);
+        
+        // 创建缩放动画:先缩小到0.85倍,然后回到原来大小
+        tween(buttonNode)
+            .to(this.ANIMATION_DURATION, { scale: new Vec3(this.SCALE_DOWN, this.SCALE_DOWN, 1) })
+            .to(this.ANIMATION_DURATION, { scale: Vec3.ONE })
+            .start();
+    }
+    
+    /**
+     * 手动添加按钮到管理器
+     * @param button 要添加的按钮
+     */
+    public addButton(button: Button) {
+        if (button && this.buttons.indexOf(button) === -1) {
+            this.buttons.push(button);
+            
+            // 为新添加的按钮设置事件
+            if (button.node) {
+                button.node.on(Button.EventType.CLICK, () => {
+                    this.playClickAnimation(button.node);
+                }, this);
+                
+                button.node.setScale(Vec3.ONE);
+            }
+        }
+    }
+    
+    /**
+     * 从管理器中移除按钮
+     * @param button 要移除的按钮
+     */
+    public removeButton(button: Button) {
+        const index = this.buttons.indexOf(button);
+        if (index !== -1) {
+            // 移除事件监听
+            if (button.node) {
+                button.node.off(Button.EventType.CLICK, this.playClickAnimation, this);
+            }
+            
+            this.buttons.splice(index, 1);
+        }
+    }
+    
+    /**
+     * 清空所有按钮
+     */
+    public clearAllButtons() {
+        this.buttons.forEach(button => {
+            if (button && button.node) {
+                button.node.off(Button.EventType.CLICK, this.playClickAnimation, this);
+            }
+        });
+        
+        this.buttons = [];
+    }
+}

+ 9 - 0
assets/scripts/Animations/ButtonManager.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "ba64bf99-bf95-4877-b1d2-7a612406dcb4",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 2 - 5
assets/scripts/Animations/ToastAni.ts

@@ -8,7 +8,7 @@ export class ToastAni extends Component {
     
     private originalPosition: Vec3 = new Vec3();
     private isAnimating: boolean = false;
-    private currentDuration: number = 2.0; // 默认显示时长(秒)
+    private currentDuration: number = 0; // 默认显示时长(秒)
     
     onLoad() {
         // 保存初始位置
@@ -31,9 +31,6 @@ export class ToastAni extends Component {
             return;
         }
         
-        // 设置显示时长
-        this.currentDuration = data.duration || 2.0;
-        
         // 设置Toast文本
         this.setToastMessage(data.message);
         
@@ -77,7 +74,7 @@ export class ToastAni extends Component {
         
         tween(this.node)
             .to(0.5, { position: targetPosition }, { easing: 'sineOut' })
-            .delay(this.currentDuration)
+            .delay(0.5)
             .call(() => {
                 this.playSlideOutAnimation();
             })

+ 7 - 9
assets/scripts/CombatSystem/BallController.ts

@@ -1097,9 +1097,7 @@ export class BallController extends Component {
      * 现在直接创建子弹实例并使用BulletController的实例方法
      * @param blockNode 激活的方块节点
      */
-    fireBullet(blockNode: Node) {
-        // Debug logs removed
-        
+    fireBullet(blockNode: Node) {     
         // 检查子弹预制体是否存在
         if (!this.bulletPrefab) {
             return;
@@ -1237,17 +1235,17 @@ export class BallController extends Component {
         }
         
         // 根据新的预制体结构,武器节点直接位于方块根节点下
+        // 首先检查当前节点是否有Weapon子节点
         const weaponNode = node.getChildByName('Weapon');
         if (weaponNode) {
             return weaponNode;
         }
         
-        // 兼容旧结构:如果直接查找失败,尝试B1/Weapon路径
-        const b1Node = node.getChildByName('B1');
-        if (b1Node) {
-            const b1WeaponNode = b1Node.getChildByName('Weapon');
-            if (b1WeaponNode) {
-                return b1WeaponNode;
+        // 如果当前节点没有Weapon子节点,检查父节点(可能传入的是Node子节点而不是预制体根节点)
+        if (node.parent) {
+            const parentWeaponNode = node.parent.getChildByName('Weapon');
+            if (parentWeaponNode) {
+                return parentWeaponNode;
             }
         }
         

+ 147 - 14
assets/scripts/FourUI/NavBarController.ts

@@ -1,23 +1,108 @@
-import { _decorator, Color, Component, Node, Sprite } from 'cc';
+import { _decorator, Color, Component, Node, Sprite, find, Vec3 } from 'cc';
 import EventBus, { GameEvents } from '../Core/EventBus';
+import { GameStartMove } from '../Animations/GameStartMove';
 const { ccclass, property } = _decorator;
 
 @ccclass('NavBarController')
 export class NavBarController extends Component {
     @property({ type: [Node] }) panels: Node[] = [];      // 依次给 Main、Shop、Upgrade、Skill
     @property({ type: [Node] }) buttons: Node[] = [];     // 依次给 Battle、Shop、Upgrade、Skill
+    @property({ type: [Node] }) buttonBorders: Node[] = []; // 按钮边框节点数组,需要手动配置
+    
     private normalColor = new Color(255, 255, 255, 255);
-    private activeColor = new Color(255, 0, 0, 255);      // 红色
     private lockedColor = new Color(128, 128, 128, 255);   // 灰色(锁定状态)
     
     // 按钮锁定状态数组 - 对应 Battle、Shop、Upgrade、Skill 四个按钮
     private buttonLockStates: boolean[] = [false, true, false, false];  // 默认只锁定Shop按钮
+    
+    // 存储按钮原始位置
+    private buttonOriginalPositions: Vec3[] = [];
+    
+    // 当前激活的按钮索引
+    private currentActiveButtonIndex: number = -1;
+    
+    // GameStartMove组件引用,用于重置镜头位置
+    private gameStartMoveComponent: GameStartMove = null;
 
     start () {
+        // 保存按钮原始位置
+        this.saveButtonOriginalPositions();
         // 默认打开 MainUI
         this.switchTo(0);
         // 初始化按钮状态,设置shop按钮为锁定状态
         this.updateButtonStates();
+        // 设置事件监听
+        this.setupEventListeners();
+    }
+    
+    onDestroy() {
+        // 移除事件监听
+        this.removeEventListeners();
+    }
+    
+    /**
+     * 设置事件监听器
+     */
+    private setupEventListeners() {
+        const eventBus = EventBus.getInstance();
+        
+        // 监听返回主菜单事件
+        eventBus.on(GameEvents.RETURN_TO_MAIN_MENU, this.onReturnToMainMenu, this);
+    }
+    
+    /**
+     * 移除事件监听器
+     */
+    private removeEventListeners() {
+        const eventBus = EventBus.getInstance();
+        
+        eventBus.off(GameEvents.RETURN_TO_MAIN_MENU, this.onReturnToMainMenu, this);
+    }
+    
+    /**
+     * 保存按钮原始位置
+     */
+    private saveButtonOriginalPositions() {
+        this.buttonOriginalPositions = [];
+        this.buttons.forEach(btn => {
+            this.buttonOriginalPositions.push(btn.position.clone());
+        });
+        console.log('[NavBarController] 已保存按钮原始位置');
+    }
+    
+    /**
+     * 处理返回主菜单事件
+     */
+    private onReturnToMainMenu() {
+        console.log('[NavBarController] 收到返回主菜单事件,切换到主界面');
+        
+        // 重置镜头位置到原始位置
+        this.resetCameraPosition();
+        
+        // 切换到主界面(Battle按钮对应的Main面板,索引0)
+        this.switchTo(0);
+    }
+    
+    /**
+     * 重置镜头位置到原始位置
+     * 确保从游戏中返回主界面时镜头位置正常
+     */
+    private resetCameraPosition() {
+        // 如果还没有获取GameStartMove组件,尝试获取
+        if (!this.gameStartMoveComponent) {
+            const cameraNode = find('Canvas/Main Camera');
+            if (cameraNode) {
+                this.gameStartMoveComponent = cameraNode.getComponent(GameStartMove);
+            }
+        }
+        
+        // 如果成功获取到组件,重置镜头位置
+        if (this.gameStartMoveComponent) {
+            console.log('[NavBarController] 重置镜头位置到原始位置');
+            this.gameStartMoveComponent.resetCameraToOriginalPosition(0.3);
+        } else {
+            console.warn('[NavBarController] 未找到GameStartMove组件,无法重置镜头位置');
+        }
     }
 
     onBattleClick ()  { 
@@ -84,39 +169,80 @@ export class NavBarController extends Component {
         // 实际映射: Battle->Main(0), Shop->Upgrade(2), Upgrade->Shop(1), Skill->Skill(3)
         const buttonToPanelMap = [0, 2, 1, 3]; // Battle->Main(0), Shop->Upgrade(2), Upgrade->Shop(1), Skill->Skill(3)
         
-        // 设置按钮颜色,考虑锁定状态
+        // 重置所有按钮到原始位置和状态
         this.buttons.forEach((btn, buttonIndex) => {
             const sp = btn.getComponent(Sprite);
             if (sp) {
-                // 检查按钮是否被锁定
+                // 重置按钮位置到原始位置
+                if (this.buttonOriginalPositions[buttonIndex]) {
+                    btn.position = this.buttonOriginalPositions[buttonIndex].clone();
+                }
+                
+                // 设置按钮颜色(只处理锁定状态)
                 if (this.buttonLockStates[buttonIndex]) {
                     sp.color = this.lockedColor;  // 锁定状态显示灰色
                 } else {
-                    // 检查当前按钮对应的面板是否是激活的面板
-                    const panelIndex = buttonToPanelMap[buttonIndex];
-                    sp.color = (panelIndex === index) ? this.activeColor : this.normalColor;
+                    sp.color = this.normalColor;  // 正常状态显示白色
                 }
             }
         });
+        
+        // 隐藏所有边框
+        this.buttonBorders.forEach(border => {
+            if (border) {
+                border.active = false;
+            }
+        });
+        
+        // 找到当前激活的按钮索引
+        let activeButtonIndex = -1;
+        for (let buttonIndex = 0; buttonIndex < buttonToPanelMap.length; buttonIndex++) {
+            if (buttonToPanelMap[buttonIndex] === index) {
+                activeButtonIndex = buttonIndex;
+                break;
+            }
+        }
+        
+        // 如果找到激活按钮且未被锁定,则应用激活效果
+        if (activeButtonIndex !== -1 && !this.buttonLockStates[activeButtonIndex]) {
+            const activeBtn = this.buttons[activeButtonIndex];
+            if (activeBtn && this.buttonOriginalPositions[activeButtonIndex]) {
+                // 向上移动20px
+                const newPos = this.buttonOriginalPositions[activeButtonIndex].clone();
+                newPos.y += 20;
+                activeBtn.position = newPos;
+                
+                // 显示对应的边框
+                if (this.buttonBorders[activeButtonIndex]) {
+                    this.buttonBorders[activeButtonIndex].active = true;
+                }
+                
+                this.currentActiveButtonIndex = activeButtonIndex;
+            }
+        } else {
+            this.currentActiveButtonIndex = -1;
+        }
     }
     
     /**
      * 更新按钮状态,主要用于设置锁定按钮的视觉效果
      */
     private updateButtonStates() {
-        // 按钮索引到面板索引的映射:根据实际的点击事件调用
-        const buttonToPanelMap = [0, 2, 1, 3]; // Battle->Main(0), Shop->Upgrade(2), Upgrade->Shop(1), Skill->Skill(3)
-        
         this.buttons.forEach((btn, buttonIndex) => {
             const sp = btn.getComponent(Sprite);
             if (sp) {
                 if (this.buttonLockStates[buttonIndex]) {
                     sp.color = this.lockedColor;  // 设置锁定按钮为锁定颜色
+                    // 确保锁定的按钮在原始位置
+                    if (this.buttonOriginalPositions[buttonIndex]) {
+                        btn.position = this.buttonOriginalPositions[buttonIndex].clone();
+                    }
+                    // 隐藏锁定按钮的边框
+                    if (this.buttonBorders[buttonIndex]) {
+                        this.buttonBorders[buttonIndex].active = false;
+                    }
                 } else {
-                    // 对于未锁定的按钮,设置为正常颜色(除非它是当前激活的)
-                    // 这里我们需要知道当前激活的面板,但为了简化,先设置为正常颜色
-                    // 实际的激活状态会在switchTo中正确设置
-                    sp.color = this.normalColor;
+                    sp.color = this.normalColor;  // 设置未锁定按钮为正常颜色
                 }
             }
         });
@@ -177,4 +303,11 @@ export class NavBarController extends Component {
     public getButtonLockStates(): boolean[] {
         return [...this.buttonLockStates];
     }
+    
+    /**
+     * 获取当前激活的按钮索引
+     */
+    public getCurrentActiveButtonIndex(): number {
+        return this.currentActiveButtonIndex;
+    }
 }

+ 65 - 0
assets/scripts/FourUI/UpgradeSystem/UpgradeAni.ts

@@ -13,6 +13,11 @@ export class UpgradeAni extends Component {
     @property(Node)
     weaponSpriteNode: Node = null;
     
+    @property(Node)
+    upgradeBtnNode: Node = null; // Canvas/UpgradePanel/UpgradeBtn/UP节点
+    
+    private blinkTween: Tween<Node> = null; // 闪烁动画的引用
+    
     /**
      * 植物升级成功动画
      * 播放植物图标的放大缩小动画,并在升级期间应用扫描效果材质,同时播放升级音效
@@ -178,5 +183,65 @@ export class UpgradeAni extends Component {
             panel.setScale(Vec3.ONE);
         }
     }
+    
+    /**
+     * 开始升级按钮闪烁动画
+     * 当钞票足够升级时调用此方法
+     */
+    public startUpgradeBtnBlink(): void {
+        if (!this.upgradeBtnNode) {
+            console.warn('[UpgradeAni] upgradeBtnNode为null,请在编辑器中设置Canvas/UpgradePanel/UpgradeBtn/UP节点');
+            return;
+        }
+        
+        // 停止之前的闪烁动画
+        this.stopUpgradeBtnBlink();
+        
+        // 重置到原始缩放状态
+        this.upgradeBtnNode.setScale(Vec3.ONE);
+        
+        // 创建循环闪烁动画:放大到1.5倍再缩小回原始大小,无限循环
+        this.blinkTween = tween(this.upgradeBtnNode)
+            .to(0.5, { scale: new Vec3(1.5, 1.5, 1) }, {
+                easing: 'sineInOut'
+            })
+            .to(0.5, { scale: Vec3.ONE }, {
+                easing: 'sineInOut'
+            })
+            .union() // 将上面的动画组合成一个整体
+            .repeatForever(); // 无限循环
+            
+        this.blinkTween.start();
+        
+        console.log('[UpgradeAni] 开始升级按钮闪烁动画');
+    }
+    
+    /**
+     * 停止升级按钮闪烁动画
+     * 当钞票不够升级时调用此方法
+     */
+    public stopUpgradeBtnBlink(): void {
+        if (this.blinkTween) {
+            this.blinkTween.stop();
+            this.blinkTween = null;
+        }
+        
+        if (this.upgradeBtnNode) {
+            // 停止节点上的所有动画
+            Tween.stopAllByTarget(this.upgradeBtnNode);
+            // 恢复到原始缩放状态
+            this.upgradeBtnNode.setScale(Vec3.ONE);
+        }
+        
+        console.log('[UpgradeAni] 停止升级按钮闪烁动画');
+    }
+    
+    /**
+     * 检查升级按钮是否正在闪烁
+     * @returns 是否正在闪烁
+     */
+    public isUpgradeBtnBlinking(): boolean {
+        return this.blinkTween !== null;
+    }
 
 }

+ 63 - 0
assets/scripts/FourUI/UpgradeSystem/UpgradeController.ts

@@ -120,6 +120,9 @@ export class UpgradeController extends Component {
         
         // 监听关卡完成事件,自动解锁武器
         EventBus.getInstance().on(GameEvents.GAME_SUCCESS, this.onLevelComplete, this);
+        
+        // 监听货币变化事件,更新升级按钮闪烁状态
+        EventBus.getInstance().on(GameEvents.CURRENCY_CHANGED, this.onCurrencyChanged, this);
     }
     
     /**
@@ -610,6 +613,9 @@ export class UpgradeController extends Component {
         
         // 升级按钮始终保持可点击状态,通过Toast显示各种提示
         console.log(`[UpgradeController] 升级按钮保持可交互状态`);
+        
+        // 检查并更新升级按钮闪烁状态
+        this.updateUpgradeBtnBlinkState();
     }
     
     /**
@@ -755,6 +761,9 @@ export class UpgradeController extends Component {
             // 使用新的状态切换方法更新武器节点
             this.switchWeaponNodeState(this.currentSelectedWeapon);
             
+            // 更新升级按钮闪烁状态(升级后钞票可能不足继续升级)
+            this.updateUpgradeBtnBlinkState();
+            
             // 保存数据
             this.saveDataManager.savePlayerData();
         } else {
@@ -1094,10 +1103,64 @@ export class UpgradeController extends Component {
         (window as any).upgradeController = this;
     }
     
+    /**
+     * 货币变化事件处理
+     */
+    private onCurrencyChanged() {
+        console.log('[UpgradeController] 货币发生变化,检查升级按钮闪烁状态');
+        // 如果升级面板打开,更新闪烁状态
+        if (this.upgradePanel && this.upgradePanel.active && this.currentSelectedWeapon) {
+            this.updateUpgradeBtnBlinkState();
+        }
+    }
+    
+    /**
+     * 更新升级按钮闪烁状态
+     */
+    private updateUpgradeBtnBlinkState() {
+        if (!this.weaponUpgradeAni || !this.currentSelectedWeapon) {
+            return;
+        }
+        
+        const weaponConfig = this.weaponsConfig.weapons.find(w => w.id === this.currentSelectedWeapon);
+        const weaponData = this.saveDataManager.getWeapon(this.currentSelectedWeapon);
+        
+        if (!weaponConfig || !weaponData) {
+            return;
+        }
+        
+        const maxLevel = weaponConfig.upgradeConfig?.maxLevel || 10;
+        
+        // 如果武器已达到最大等级,停止闪烁
+        if (weaponData.level >= maxLevel) {
+            this.weaponUpgradeAni.stopUpgradeBtnBlink();
+            console.log(`[UpgradeController] 武器已满级,停止闪烁: ${this.currentSelectedWeapon}`);
+            return;
+        }
+        
+        // 检查钞票是否足够升级
+        const canUpgrade = this.saveDataManager.canUpgradeWeapon(this.currentSelectedWeapon);
+        
+        if (canUpgrade) {
+            // 钞票足够,开始闪烁
+            if (!this.weaponUpgradeAni.isUpgradeBtnBlinking()) {
+                this.weaponUpgradeAni.startUpgradeBtnBlink();
+                console.log(`[UpgradeController] 钞票足够,开始闪烁: ${this.currentSelectedWeapon}`);
+            }
+        } else {
+            // 钞票不够,停止闪烁
+            if (this.weaponUpgradeAni.isUpgradeBtnBlinking()) {
+                this.weaponUpgradeAni.stopUpgradeBtnBlink();
+                console.log(`[UpgradeController] 钞票不足,停止闪烁: ${this.currentSelectedWeapon}`);
+            }
+        }
+    }
+    
     /**
      * 组件销毁时清理事件监听
      */
     onDestroy() {
         EventBus.getInstance().off(GameEvents.GAME_SUCCESS, this.onLevelComplete, this);
+        EventBus.getInstance().off(GameEvents.CURRENCY_CHANGED, this.onCurrencyChanged, this);
     }
 }

+ 2 - 2
settings/v2/packages/information.json

@@ -7,7 +7,7 @@
       "enable": true,
       "customSplash": {
         "complete": false,
-        "form": "https://creator-api.cocos.com/api/form/show?sid=eab532bed4bde2477c3fac47c379d78d"
+        "form": "https://creator-api.cocos.com/api/form/show?sid=f0e6e03f0114f158584a56be2a8c8e47"
       }
     },
     "removeSplash": {
@@ -16,7 +16,7 @@
       "enable": true,
       "removeSplash": {
         "complete": false,
-        "form": "https://creator-api.cocos.com/api/form/show?sid=eab532bed4bde2477c3fac47c379d78d"
+        "form": "https://creator-api.cocos.com/api/form/show?sid=f0e6e03f0114f158584a56be2a8c8e47"
       }
     }
   }

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio