181404010226 il y a 4 mois
Parent
commit
291eb33bf4

+ 33 - 11
assets/Scenes/GameLevel.scene

@@ -26,7 +26,7 @@
     "_active": true,
     "_components": [],
     "_prefab": {
-      "__id__": 930
+      "__id__": 931
     },
     "_lpos": {
       "__type__": "cc.Vec3",
@@ -57,7 +57,7 @@
     },
     "autoReleaseAssets": false,
     "_globals": {
-      "__id__": 931
+      "__id__": 932
     },
     "_id": "29694223-a59c-44b3-acb0-80ab92d103f5"
   },
@@ -135,6 +135,9 @@
       },
       {
         "__id__": 929
+      },
+      {
+        "__id__": 930
       }
     ],
     "_prefab": null,
@@ -17979,7 +17982,9 @@
     "_disabledSprite": null,
     "_duration": 0.1,
     "_zoomScale": 1.2,
-    "_target": null,
+    "_target": {
+      "__id__": 466
+    },
     "_id": "66Sa3k3iBGNL2wi27hFSKi"
   },
   {
@@ -34866,6 +34871,23 @@
     "debugDraw": true,
     "_id": "ffMig9DF9DQLd2SVeZA893"
   },
+  {
+    "__type__": "28dc4qNYC5JVYhnfXE7Wy75",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "__prefab": null,
+    "pressScale": 0.9,
+    "pressDuration": 0.1,
+    "releaseDuration": 0.1,
+    "autoFindButtons": true,
+    "manualButtons": [],
+    "_id": "e4nnYkkPBEFqJC83fdCrzh"
+  },
   {
     "__type__": "cc.PrefabInfo",
     "root": null,
@@ -34877,28 +34899,28 @@
   {
     "__type__": "cc.SceneGlobals",
     "ambient": {
-      "__id__": 932
+      "__id__": 933
     },
     "shadows": {
-      "__id__": 933
+      "__id__": 934
     },
     "_skybox": {
-      "__id__": 934
+      "__id__": 935
     },
     "fog": {
-      "__id__": 935
+      "__id__": 936
     },
     "octree": {
-      "__id__": 936
+      "__id__": 937
     },
     "skin": {
-      "__id__": 937
+      "__id__": 938
     },
     "lightProbeInfo": {
-      "__id__": 938
+      "__id__": 939
     },
     "postSettings": {
-      "__id__": 939
+      "__id__": 940
     },
     "bakedWithStationaryMainLight": false,
     "bakedWithHighpLightmap": false

+ 198 - 0
assets/scripts/Animations/ButtonAni.ts

@@ -0,0 +1,198 @@
+import { _decorator, Component, Node, Button, Vec3, tween, find } from 'cc';
+const { ccclass, property } = _decorator;
+
+/**
+ * ButtonAni - 通用按钮按压效果管理器
+ * 自动为场景中所有按钮添加按压缩放效果
+ * 挂载在场景的根节点或UI管理节点上
+ */
+@ccclass('ButtonAni')
+export class ButtonAni extends Component {
+    
+    @property({ tooltip: '按压时的缩放比例' })
+    public pressScale: number = 0.9;
+    
+    @property({ tooltip: '按压动画时长(秒)' })
+    public pressDuration: number = 0.1;
+    
+    @property({ tooltip: '释放动画时长(秒)' })
+    public releaseDuration: number = 0.1;
+    
+    @property({ tooltip: '是否自动查找所有按钮' })
+    public autoFindButtons: boolean = true;
+    
+    @property({ type: [Node], tooltip: '手动指定的按钮节点列表(如果不自动查找)' })
+    public manualButtons: Node[] = [];
+    
+    // 存储按钮的原始缩放值
+    private originalScales: Map<Node, Vec3> = new Map();
+    
+    // 存储正在播放动画的按钮
+    private animatingButtons: Set<Node> = new Set();
+    
+    start() {
+        this.initializeButtonEffects();
+    }
+    
+    /**
+     * 初始化所有按钮的按压效果
+     */
+    private initializeButtonEffects() {
+        const buttons = this.getAllButtons();
+        console.log(`[ButtonAni] 找到 ${buttons.length} 个按钮,开始添加按压效果`);
+        
+        buttons.forEach(buttonNode => {
+            this.addButtonPressEffect(buttonNode);
+        });
+    }
+    
+    /**
+     * 获取所有需要添加效果的按钮
+     */
+    private getAllButtons(): Node[] {
+        if (!this.autoFindButtons) {
+            return this.manualButtons.filter(btn => btn && btn.isValid);
+        }
+        
+        const allButtons: Node[] = [];
+        
+        // 从Canvas开始递归查找所有按钮
+        const canvas = find('Canvas');
+        if (canvas) {
+            this.findButtonsRecursively(canvas, allButtons);
+        }
+        
+        // 也查找Canvas-001(如果存在)
+        const canvas001 = find('Canvas-001');
+        if (canvas001) {
+            this.findButtonsRecursively(canvas001, allButtons);
+        }
+        
+        return allButtons;
+    }
+    
+    /**
+     * 递归查找节点下的所有按钮组件
+     */
+    private findButtonsRecursively(node: Node, buttons: Node[]) {
+        if (!node || !node.isValid) return;
+        
+        // 检查当前节点是否有Button组件
+        const button = node.getComponent(Button);
+        if (button && button.enabled) {
+            buttons.push(node);
+        }
+        
+        // 递归检查子节点
+        node.children.forEach(child => {
+            this.findButtonsRecursively(child, buttons);
+        });
+    }
+    
+    /**
+     * 为单个按钮添加按压效果
+     */
+    private addButtonPressEffect(buttonNode: Node) {
+        if (!buttonNode || !buttonNode.isValid) return;
+        
+        const button = buttonNode.getComponent(Button);
+        if (!button) return;
+        
+        // 保存原始缩放值
+        this.originalScales.set(buttonNode, buttonNode.scale.clone());
+        
+        // 添加按下事件监听
+        buttonNode.on(Node.EventType.TOUCH_START, this.onButtonPress.bind(this, buttonNode), this);
+        buttonNode.on(Node.EventType.TOUCH_END, this.onButtonRelease.bind(this, buttonNode), this);
+        buttonNode.on(Node.EventType.TOUCH_CANCEL, this.onButtonRelease.bind(this, buttonNode), this);
+        
+        console.log(`[ButtonAni] 已为按钮 ${buttonNode.name} 添加按压效果`);
+    }
+    
+    /**
+     * 按钮按下事件处理
+     */
+    private onButtonPress(buttonNode: Node) {
+        if (!buttonNode || !buttonNode.isValid || this.animatingButtons.has(buttonNode)) {
+            return;
+        }
+        
+        this.animatingButtons.add(buttonNode);
+        
+        const originalScale = this.originalScales.get(buttonNode) || Vec3.ONE;
+        const pressedScale = originalScale.clone().multiplyScalar(this.pressScale);
+        
+        // 停止之前的动画
+        tween(buttonNode).stop();
+        
+        // 播放按压动画
+        tween(buttonNode)
+            .to(this.pressDuration, { scale: pressedScale }, { easing: 'quadOut' })
+            .call(() => {
+                // 动画完成后从集合中移除
+                this.animatingButtons.delete(buttonNode);
+            })
+            .start();
+    }
+    
+    /**
+     * 按钮释放事件处理
+     */
+    private onButtonRelease(buttonNode: Node) {
+        if (!buttonNode || !buttonNode.isValid) {
+            return;
+        }
+        
+        this.animatingButtons.add(buttonNode);
+        
+        const originalScale = this.originalScales.get(buttonNode) || Vec3.ONE;
+        
+        // 停止之前的动画
+        tween(buttonNode).stop();
+        
+        // 播放释放动画
+        tween(buttonNode)
+            .to(this.releaseDuration, { scale: originalScale }, { easing: 'backOut' })
+            .call(() => {
+                // 动画完成后从集合中移除
+                this.animatingButtons.delete(buttonNode);
+            })
+            .start();
+    }
+    
+    /**
+     * 手动刷新按钮效果(当有新按钮动态创建时调用)
+     */
+    public refreshButtonEffects() {
+        // 清理之前的监听
+        this.cleanup();
+        
+        // 重新初始化
+        this.initializeButtonEffects();
+    }
+    
+    /**
+     * 清理所有按钮监听和动画
+     */
+    private cleanup() {
+        this.originalScales.forEach((scale, buttonNode) => {
+            if (buttonNode && buttonNode.isValid) {
+                // 移除事件监听
+                buttonNode.off(Node.EventType.TOUCH_START, this.onButtonPress, this);
+                buttonNode.off(Node.EventType.TOUCH_END, this.onButtonRelease, this);
+                buttonNode.off(Node.EventType.TOUCH_CANCEL, this.onButtonRelease, this);
+                
+                // 停止动画并恢复原始缩放
+                tween(buttonNode).stop();
+                buttonNode.setScale(scale);
+            }
+        });
+        
+        this.originalScales.clear();
+        this.animatingButtons.clear();
+    }
+    
+    onDestroy() {
+        this.cleanup();
+    }
+}

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

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "28dc4a8d-602e-4955-8867-7d713b5b2ef9",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}