Browse Source

29、32bug优化

181404010226 4 months ago
parent
commit
9340de68d7

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


+ 410 - 103
assets/assets/Prefabs/Enemy.prefab

@@ -20,28 +20,25 @@
     "_children": [
       {
         "__id__": 2
-      },
-      {
-        "__id__": 16
       }
     ],
     "_active": true,
     "_components": [
       {
-        "__id__": 22
+        "__id__": 38
       },
       {
-        "__id__": 24
+        "__id__": 40
       },
       {
-        "__id__": 26
+        "__id__": 42
       },
       {
-        "__id__": 28
+        "__id__": 44
       }
     ],
     "_prefab": {
-      "__id__": 30
+      "__id__": 46
     },
     "_lpos": {
       "__type__": "cc.Vec3",
@@ -83,22 +80,25 @@
     "_children": [
       {
         "__id__": 3
+      },
+      {
+        "__id__": 17
       }
     ],
     "_active": true,
     "_components": [
       {
-        "__id__": 9
+        "__id__": 31
       },
       {
-        "__id__": 11
+        "__id__": 33
       },
       {
-        "__id__": 13
+        "__id__": 35
       }
     ],
     "_prefab": {
-      "__id__": 15
+      "__id__": 37
     },
     "_lpos": {
       "__type__": "cc.Vec3",
@@ -131,28 +131,85 @@
   },
   {
     "__type__": "cc.Node",
-    "_name": "HPForeground",
+    "_name": "YellowBar",
     "_objFlags": 0,
     "__editorExtras__": {},
     "_parent": {
       "__id__": 2
     },
+    "_children": [
+      {
+        "__id__": 4
+      }
+    ],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 10
+      },
+      {
+        "__id__": 12
+      },
+      {
+        "__id__": 14
+      }
+    ],
+    "_prefab": {
+      "__id__": 16
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 1,
+      "y": 1,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 33554432,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "Bar",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 3
+    },
     "_children": [],
     "_active": true,
     "_components": [
       {
-        "__id__": 4
+        "__id__": 5
       },
       {
-        "__id__": 6
+        "__id__": 7
       }
     ],
     "_prefab": {
-      "__id__": 8
+      "__id__": 9
     },
     "_lpos": {
       "__type__": "cc.Vec3",
-      "x": -24.351,
+      "x": -26.901,
       "y": 0,
       "z": 0
     },
@@ -185,16 +242,16 @@
     "_objFlags": 0,
     "__editorExtras__": {},
     "node": {
-      "__id__": 3
+      "__id__": 4
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 5
+      "__id__": 6
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 20.400000000000002,
-      "height": 10
+      "width": 21.200000000000003,
+      "height": 15
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -205,7 +262,7 @@
   },
   {
     "__type__": "cc.CompPrefabInfo",
-    "fileId": "7b3f6pCChPY76EONQSIiZT"
+    "fileId": "d0YZ47XQNHL6oD9Bww8p5P"
   },
   {
     "__type__": "cc.Sprite",
@@ -213,27 +270,27 @@
     "_objFlags": 0,
     "__editorExtras__": {},
     "node": {
-      "__id__": 3
+      "__id__": 4
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 7
+      "__id__": 8
     },
     "_customMaterial": null,
     "_srcBlendFactor": 2,
     "_dstBlendFactor": 4,
     "_color": {
       "__type__": "cc.Color",
-      "r": 255,
-      "g": 255,
-      "b": 255,
+      "r": 240,
+      "g": 240,
+      "b": 240,
       "a": 255
     },
     "_spriteFrame": {
-      "__uuid__": "f5b3c771-0b73-4b9e-a778-932e7ee9d8fa@f9941",
+      "__uuid__": "45bd99da-8893-435b-8110-5da90043375b@f9941",
       "__expectedType__": "cc.SpriteFrame"
     },
-    "_type": 0,
+    "_type": 1,
     "_fillType": 0,
     "_sizeMode": 0,
     "_fillCenter": {
@@ -250,7 +307,7 @@
   },
   {
     "__type__": "cc.CompPrefabInfo",
-    "fileId": "d39xJhF0ZEuIGj/an3Cvis"
+    "fileId": "39yeth5LBNQLahadIDweIc"
   },
   {
     "__type__": "cc.PrefabInfo",
@@ -260,7 +317,7 @@
     "asset": {
       "__id__": 0
     },
-    "fileId": "c32+0H/CxFCYe7RovQQDgW",
+    "fileId": "9dE5SGjEhNIq04Oov7nlw5",
     "instance": null,
     "targetOverrides": null,
     "nestedPrefabInstanceRoots": null
@@ -271,11 +328,11 @@
     "_objFlags": 0,
     "__editorExtras__": {},
     "node": {
-      "__id__": 2
+      "__id__": 3
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 10
+      "__id__": 11
     },
     "_contentSize": {
       "__type__": "cc.Size",
@@ -291,7 +348,7 @@
   },
   {
     "__type__": "cc.CompPrefabInfo",
-    "fileId": "c0xBcPh6RJNq+0oHg/5T4W"
+    "fileId": "30ZGB8O3ZOGapZ6I2ggCj0"
   },
   {
     "__type__": "cc.Sprite",
@@ -299,29 +356,29 @@
     "_objFlags": 0,
     "__editorExtras__": {},
     "node": {
-      "__id__": 2
+      "__id__": 3
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 12
+      "__id__": 13
     },
     "_customMaterial": null,
     "_srcBlendFactor": 2,
     "_dstBlendFactor": 4,
     "_color": {
       "__type__": "cc.Color",
-      "r": 255,
-      "g": 255,
-      "b": 255,
+      "r": 0,
+      "g": 0,
+      "b": 0,
       "a": 255
     },
     "_spriteFrame": {
       "__uuid__": "45bd99da-8893-435b-8110-5da90043375b@f9941",
       "__expectedType__": "cc.SpriteFrame"
     },
-    "_type": 0,
+    "_type": 1,
     "_fillType": 0,
-    "_sizeMode": 1,
+    "_sizeMode": 0,
     "_fillCenter": {
       "__type__": "cc.Vec2",
       "x": 0,
@@ -336,7 +393,7 @@
   },
   {
     "__type__": "cc.CompPrefabInfo",
-    "fileId": "749I8dS7lParY+7HDeJxar"
+    "fileId": "afBV/7Tw1P7LcN8596AWqX"
   },
   {
     "__type__": "cc.ProgressBar",
@@ -344,24 +401,24 @@
     "_objFlags": 0,
     "__editorExtras__": {},
     "node": {
-      "__id__": 2
+      "__id__": 3
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 14
+      "__id__": 15
     },
     "_barSprite": {
-      "__id__": 6
+      "__id__": 7
     },
     "_mode": 0,
-    "_totalLength": 51,
+    "_totalLength": 53,
     "_progress": 0.4,
     "_reverse": false,
     "_id": ""
   },
   {
     "__type__": "cc.CompPrefabInfo",
-    "fileId": "04jIIwHABOua5t3rXGSuBe"
+    "fileId": "477xdalvxII5Oi+E4QFQh1"
   },
   {
     "__type__": "cc.PrefabInfo",
@@ -371,36 +428,93 @@
     "asset": {
       "__id__": 0
     },
-    "fileId": "45Lrr+eo5KiLJy5Ju4b9xG",
+    "fileId": "f7vhw+fZJIzK3K1cZysih2",
     "instance": null,
     "targetOverrides": null,
     "nestedPrefabInstanceRoots": null
   },
   {
     "__type__": "cc.Node",
-    "_name": "HPLabel",
+    "_name": "RedBar",
     "_objFlags": 0,
     "__editorExtras__": {},
     "_parent": {
-      "__id__": 1
+      "__id__": 2
     },
-    "_children": [],
+    "_children": [
+      {
+        "__id__": 18
+      }
+    ],
     "_active": true,
     "_components": [
       {
-        "__id__": 17
+        "__id__": 24
       },
       {
-        "__id__": 19
+        "__id__": 26
+      },
+      {
+        "__id__": 28
       }
     ],
     "_prefab": {
-      "__id__": 21
+      "__id__": 30
     },
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": 92.224,
+      "y": 0,
+      "z": 0
+    },
+    "_lrot": {
+      "__type__": "cc.Quat",
+      "x": 0,
+      "y": 0,
+      "z": 0,
+      "w": 1
+    },
+    "_lscale": {
+      "__type__": "cc.Vec3",
+      "x": 1,
+      "y": 1,
+      "z": 1
+    },
+    "_mobility": 0,
+    "_layer": 33554432,
+    "_euler": {
+      "__type__": "cc.Vec3",
+      "x": 0,
+      "y": 0,
+      "z": 0
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.Node",
+    "_name": "Bar",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "_parent": {
+      "__id__": 17
+    },
+    "_children": [],
+    "_active": true,
+    "_components": [
+      {
+        "__id__": 19
+      },
+      {
+        "__id__": 21
+      }
+    ],
+    "_prefab": {
+      "__id__": 23
+    },
+    "_lpos": {
+      "__type__": "cc.Vec3",
+      "x": -26.901,
+      "y": 0,
       "z": 0
     },
     "_lrot": {
@@ -432,39 +546,39 @@
     "_objFlags": 0,
     "__editorExtras__": {},
     "node": {
-      "__id__": 16
+      "__id__": 18
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 18
+      "__id__": 20
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 26.24609375,
-      "height": 54.4
+      "width": 53,
+      "height": 15
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
-      "x": 0.5,
+      "x": 0,
       "y": 0.5
     },
     "_id": ""
   },
   {
     "__type__": "cc.CompPrefabInfo",
-    "fileId": "dcJF6of+1JZ5oNezj7/gkm"
+    "fileId": "28Okm2nJRKZ7wubtHhrSj5"
   },
   {
-    "__type__": "cc.Label",
+    "__type__": "cc.Sprite",
     "_name": "",
     "_objFlags": 0,
     "__editorExtras__": {},
     "node": {
-      "__id__": 16
+      "__id__": 18
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 20
+      "__id__": 22
     },
     "_customMaterial": null,
     "_srcBlendFactor": 2,
@@ -476,51 +590,243 @@
       "b": 255,
       "a": 255
     },
-    "_string": "12",
-    "_horizontalAlign": 1,
-    "_verticalAlign": 1,
-    "_actualFontSize": 20,
-    "_fontSize": 20,
-    "_fontFamily": "Arial",
-    "_lineHeight": 40,
-    "_overflow": 0,
-    "_enableWrapText": true,
-    "_font": null,
-    "_isSystemFontUsed": true,
-    "_spacingX": 0,
-    "_isItalic": false,
-    "_isBold": false,
-    "_isUnderline": false,
-    "_underlineHeight": 2,
-    "_cacheMode": 0,
-    "_enableOutline": true,
-    "_outlineColor": {
+    "_spriteFrame": {
+      "__uuid__": "f5b3c771-0b73-4b9e-a778-932e7ee9d8fa@f9941",
+      "__expectedType__": "cc.SpriteFrame"
+    },
+    "_type": 1,
+    "_fillType": 0,
+    "_sizeMode": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_useGrayscale": false,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "f8/uX2gppPKZp15CvdbKAa"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "321igvQXtHC71l2sinZq0U",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 17
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 25
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 51,
+      "height": 13
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "85OsaD699IWqtLwvV+a6CE"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 17
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 27
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
       "__type__": "cc.Color",
-      "r": 0,
-      "g": 0,
-      "b": 0,
+      "r": 255,
+      "g": 255,
+      "b": 255,
       "a": 255
     },
-    "_outlineWidth": 2,
-    "_enableShadow": false,
-    "_shadowColor": {
+    "_spriteFrame": null,
+    "_type": 1,
+    "_fillType": 0,
+    "_sizeMode": 0,
+    "_fillCenter": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_useGrayscale": false,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "c5EZgvv4NIxo8d9lZkpLu+"
+  },
+  {
+    "__type__": "cc.ProgressBar",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 17
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 29
+    },
+    "_barSprite": {
+      "__id__": 21
+    },
+    "_mode": 0,
+    "_totalLength": 53,
+    "_progress": 1,
+    "_reverse": false,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "917k5QCVxFRai/rWLZYYAA"
+  },
+  {
+    "__type__": "cc.PrefabInfo",
+    "root": {
+      "__id__": 1
+    },
+    "asset": {
+      "__id__": 0
+    },
+    "fileId": "e7NJ39T0BEhYnJ4HIeKnh6",
+    "instance": null,
+    "targetOverrides": null,
+    "nestedPrefabInstanceRoots": null
+  },
+  {
+    "__type__": "cc.UITransform",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 32
+    },
+    "_contentSize": {
+      "__type__": "cc.Size",
+      "width": 51,
+      "height": 13
+    },
+    "_anchorPoint": {
+      "__type__": "cc.Vec2",
+      "x": 0.5,
+      "y": 0.5
+    },
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "c0xBcPh6RJNq+0oHg/5T4W"
+  },
+  {
+    "__type__": "cc.Sprite",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 34
+    },
+    "_customMaterial": null,
+    "_srcBlendFactor": 2,
+    "_dstBlendFactor": 4,
+    "_color": {
       "__type__": "cc.Color",
-      "r": 0,
-      "g": 0,
-      "b": 0,
+      "r": 255,
+      "g": 255,
+      "b": 255,
       "a": 255
     },
-    "_shadowOffset": {
+    "_spriteFrame": null,
+    "_type": 0,
+    "_fillType": 0,
+    "_sizeMode": 1,
+    "_fillCenter": {
       "__type__": "cc.Vec2",
-      "x": 2,
-      "y": 2
+      "x": 0,
+      "y": 0
+    },
+    "_fillStart": 0,
+    "_fillRange": 0,
+    "_isTrimmedMode": true,
+    "_useGrayscale": false,
+    "_atlas": null,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "749I8dS7lParY+7HDeJxar"
+  },
+  {
+    "__type__": "8c2b2vO4etNJpD2LS95veLN",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 36
+    },
+    "redBarNode": {
+      "__id__": 17
+    },
+    "yellowBarNode": {
+      "__id__": 3
     },
-    "_shadowBlur": 2,
     "_id": ""
   },
   {
     "__type__": "cc.CompPrefabInfo",
-    "fileId": "89bX9UyEVPJIrGJRdIoinn"
+    "fileId": "e0BPE1F8dP6rncsQI+aqhd"
   },
   {
     "__type__": "cc.PrefabInfo",
@@ -530,7 +836,7 @@
     "asset": {
       "__id__": 0
     },
-    "fileId": "67XE+pOTND3aI3f6ElNwf8",
+    "fileId": "45Lrr+eo5KiLJy5Ju4b9xG",
     "instance": null,
     "targetOverrides": null,
     "nestedPrefabInstanceRoots": null
@@ -545,7 +851,7 @@
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 23
+      "__id__": 39
     },
     "_contentSize": {
       "__type__": "cc.Size",
@@ -573,7 +879,7 @@
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 25
+      "__id__": 41
     },
     "_customMaterial": null,
     "_srcBlendFactor": 2,
@@ -618,7 +924,7 @@
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 27
+      "__id__": 43
     },
     "tag": 4,
     "_group": 16,
@@ -652,7 +958,7 @@
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 29
+      "__id__": 45
     },
     "enabledContactListener": false,
     "bullet": false,
@@ -685,6 +991,7 @@
       "__id__": 0
     },
     "fileId": "38hOg6AAZGVojOqsmsY5rA",
-    "instance": null
+    "instance": null,
+    "targetOverrides": null
   }
 ]

+ 45 - 36
assets/resources/data/weapons.json

@@ -53,10 +53,11 @@
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/001-1",
-          "1x2": "images/PlantsSprite/001-1",
-          "2x1": "images/PlantsSprite/001-1",
-          "2x2": "images/PlantsSprite/001-1"
+          "I": "images/PlantsSprite/001-1",
+          "H-I": "images/PlantsSprite/001-1",
+          "L": "images/PlantsSprite/001-1",
+          "S": "images/PlantsSprite/001-1",
+          "D-T": "images/PlantsSprite/001-1"
         },
         "fireSound": "audio/pea_shot"
       }
@@ -116,10 +117,11 @@
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/002",
-          "1x2": "images/PlantsSprite/002",
-          "2x1": "images/PlantsSprite/002",
-          "2x2": "images/PlantsSprite/002"
+          "I": "images/PlantsSprite/002",
+          "H-I": "images/PlantsSprite/002",
+          "L": "images/PlantsSprite/002",
+          "S": "images/PlantsSprite/002",
+          "D-T": "images/PlantsSprite/002"
         },
         "fireSound": "audio/carrot_shot"
       }
@@ -187,10 +189,11 @@
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/003",
-          "1x2": "images/PlantsSprite/003",
-          "2x1": "images/PlantsSprite/003",
-          "2x2": "images/PlantsSprite/003"
+          "I": "images/PlantsSprite/003",
+          "H-I": "images/PlantsSprite/003",
+          "L": "images/PlantsSprite/003",
+          "S": "images/PlantsSprite/003",
+          "D-T": "images/PlantsSprite/003"
         },
         "fireSound": "audio/saw_shot"
       }
@@ -250,10 +253,11 @@
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/007",
-          "1x2": "images/PlantsSprite/007",
-          "2x1": "images/PlantsSprite/007",
-          "2x2": "images/PlantsSprite/007"
+          "I": "images/PlantsSprite/007",
+          "H-I": "images/PlantsSprite/007",
+          "L": "images/PlantsSprite/007",
+          "S": "images/PlantsSprite/007",
+          "D-T": "images/PlantsSprite/007"
         },
         "fireSound": "audio/bomb_launch"
       }
@@ -312,10 +316,11 @@
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/004",
-          "1x2": "images/PlantsSprite/004",
-          "2x1": "images/PlantsSprite/004",
-          "2x2": "images/PlantsSprite/004"
+          "I": "images/PlantsSprite/004",
+          "H-I": "images/PlantsSprite/004",
+          "L": "images/PlantsSprite/004",
+          "S": "images/PlantsSprite/004",
+          "D-T": "images/PlantsSprite/004"
         },
         "fireSound": "audio/boomerang_throw"
       }
@@ -387,10 +392,11 @@
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/005",
-          "1x2": "images/PlantsSprite/005",
-          "2x1": "images/PlantsSprite/005",
-          "2x2": "images/PlantsSprite/005"
+          "I": "images/PlantsSprite/005",
+          "H-I": "images/PlantsSprite/005",
+          "L": "images/PlantsSprite/005",
+          "S": "images/PlantsSprite/005",
+          "D-T": "images/PlantsSprite/005"
         },
         "fireSound": "audio/pepper_launch"
       }
@@ -449,10 +455,11 @@
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/008",
-          "1x2": "images/PlantsSprite/008",
-          "2x1": "images/PlantsSprite/008",
-          "2x2": "images/PlantsSprite/008"
+          "I": "images/PlantsSprite/008",
+          "H-I": "images/PlantsSprite/008",
+          "L": "images/PlantsSprite/008",
+          "S": "images/PlantsSprite/008",
+          "D-T": "images/PlantsSprite/008"
         },
         "fireSound": "audio/cactus_shot"
       }
@@ -512,10 +519,11 @@
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/006",
-          "1x2": "images/PlantsSprite/006",
-          "2x1": "images/PlantsSprite/006",
-          "2x2": "images/PlantsSprite/006"
+          "I": "images/PlantsSprite/006",
+          "H-I": "images/PlantsSprite/006",
+          "L": "images/PlantsSprite/006",
+          "S": "images/PlantsSprite/006",
+          "D-T": "images/PlantsSprite/006"
         },
         "fireSound": "audio/missile_launch"
       }
@@ -573,10 +581,11 @@
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/009",
-          "1x2": "images/PlantsSprite/009",
-          "2x1": "images/PlantsSprite/009",
-          "2x2": "images/PlantsSprite/009"
+          "I": "images/PlantsSprite/009",
+          "H-I": "images/PlantsSprite/009",
+          "L": "images/PlantsSprite/009",
+          "S": "images/PlantsSprite/009",
+          "D-T": "images/PlantsSprite/009"
         },
         "fireSound": "audio/mace_shot"
       }

+ 79 - 33
assets/assets/Prefabs/TrailEffect.prefab → assets/resources/prefabs/DamageNumber.prefab

@@ -1,7 +1,7 @@
 [
   {
     "__type__": "cc.Prefab",
-    "_name": "TrailEffect",
+    "_name": "DamageNumber",
     "_objFlags": 0,
     "__editorExtras__": {},
     "_native": "",
@@ -13,7 +13,7 @@
   },
   {
     "__type__": "cc.Node",
-    "_name": "TrailEffect",
+    "_name": "DamageNumber",
     "_objFlags": 0,
     "__editorExtras__": {},
     "_parent": null,
@@ -25,23 +25,26 @@
       },
       {
         "__id__": 4
+      },
+      {
+        "__id__": 6
       }
     ],
     "_prefab": {
-      "__id__": 6
+      "__id__": 8
     },
     "_lpos": {
       "__type__": "cc.Vec3",
-      "x": 152.7896961479185,
-      "y": -206.03174942494672,
+      "x": 0,
+      "y": 92.224,
       "z": 0
     },
     "_lrot": {
       "__type__": "cc.Quat",
       "x": 0,
       "y": 0,
-      "z": 1,
-      "w": 6.123233995736766e-17
+      "z": 0,
+      "w": 1
     },
     "_lscale": {
       "__type__": "cc.Vec3",
@@ -50,12 +53,12 @@
       "z": 1
     },
     "_mobility": 0,
-    "_layer": 1073741824,
+    "_layer": 33554432,
     "_euler": {
       "__type__": "cc.Vec3",
       "x": 0,
       "y": 0,
-      "z": 180
+      "z": 0
     },
     "_id": ""
   },
@@ -73,22 +76,22 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 72.06999969482422,
-      "height": 175.0399932861328
+      "width": 26.24609375,
+      "height": 54.4
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
-      "x": 0.630914408397987,
-      "y": 0.5104547640610523
+      "x": 0.5,
+      "y": 0.5
     },
     "_id": ""
   },
   {
     "__type__": "cc.CompPrefabInfo",
-    "fileId": "b2ORjFD7NLPJnNCvtp+WHY"
+    "fileId": "dcJF6of+1JZ5oNezj7/gkm"
   },
   {
-    "__type__": "sp.Skeleton",
+    "__type__": "cc.Label",
     "_name": "",
     "_objFlags": 0,
     "__editorExtras__": {},
@@ -109,28 +112,70 @@
       "b": 255,
       "a": 255
     },
-    "_skeletonData": {
-      "__uuid__": "03e20616-4f08-4682-848d-7b9e8e27af35",
-      "__expectedType__": "sp.SkeletonData"
-    },
-    "defaultSkin": "default",
-    "defaultAnimation": "",
-    "_premultipliedAlpha": true,
-    "_timeScale": 1,
-    "_preCacheMode": 0,
+    "_string": "12",
+    "_horizontalAlign": 1,
+    "_verticalAlign": 1,
+    "_actualFontSize": 20,
+    "_fontSize": 20,
+    "_fontFamily": "Arial",
+    "_lineHeight": 40,
+    "_overflow": 0,
+    "_enableWrapText": true,
+    "_font": null,
+    "_isSystemFontUsed": true,
+    "_spacingX": 0,
+    "_isItalic": false,
+    "_isBold": false,
+    "_isUnderline": false,
+    "_underlineHeight": 2,
     "_cacheMode": 0,
-    "_sockets": [],
-    "_useTint": false,
-    "_debugMesh": false,
-    "_debugBones": false,
-    "_debugSlots": false,
-    "_enableBatch": false,
-    "loop": true,
+    "_enableOutline": true,
+    "_outlineColor": {
+      "__type__": "cc.Color",
+      "r": 0,
+      "g": 0,
+      "b": 0,
+      "a": 255
+    },
+    "_outlineWidth": 2,
+    "_enableShadow": false,
+    "_shadowColor": {
+      "__type__": "cc.Color",
+      "r": 0,
+      "g": 0,
+      "b": 0,
+      "a": 255
+    },
+    "_shadowOffset": {
+      "__type__": "cc.Vec2",
+      "x": 2,
+      "y": 2
+    },
+    "_shadowBlur": 2,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "89bX9UyEVPJIrGJRdIoinn"
+  },
+  {
+    "__type__": "cc.UIOpacity",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 1
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 7
+    },
+    "_opacity": 255,
     "_id": ""
   },
   {
     "__type__": "cc.CompPrefabInfo",
-    "fileId": "89GevWw75DH5vNWruxef6k"
+    "fileId": "fcJ/dhhHRGbpKzLGvHj/ou"
   },
   {
     "__type__": "cc.PrefabInfo",
@@ -140,7 +185,8 @@
     "asset": {
       "__id__": 0
     },
-    "fileId": "c0VG1uiDFIT7TYxrWYFB7q",
+    "fileId": "67XE+pOTND3aI3f6ElNwf8",
+    "instance": null,
     "targetOverrides": null
   }
 ]

+ 2 - 2
assets/assets/Prefabs/TrailEffect.prefab.meta → assets/resources/prefabs/DamageNumber.prefab.meta

@@ -2,12 +2,12 @@
   "ver": "1.1.50",
   "importer": "prefab",
   "imported": true,
-  "uuid": "94aece57-f0de-4383-bf9e-cdd8636a5ca3",
+  "uuid": "4548ec6f-ef3c-4d8c-84f0-ca4aa22521f9",
   "files": [
     ".json"
   ],
   "subMetas": {},
   "userData": {
-    "syncNodeName": "TrailEffect"
+    "syncNodeName": "DamageNumber"
   }
 }

+ 195 - 0
assets/scripts/Animations/DamageNumberAni.ts

@@ -0,0 +1,195 @@
+import { _decorator, Component, Node, Label, Vec3, tween, Tween, UITransform, UIOpacity, instantiate, resources, Prefab, Color, find } from 'cc';
+import { EnemyController } from '../CombatSystem/EnemyController';
+const { ccclass, property } = _decorator;
+
+/**
+ * 伤害数字动画组件
+ * 实现伤害数字从小变大再缩小消失的动画效果
+ * 可挂载到EnemyController节点上,通过装饰器获取EnemyController组件
+ */
+@ccclass('DamageNumberAni')
+export class DamageNumberAni extends Component {
+    
+    @property({ type: EnemyController, tooltip: 'EnemyController组件引用' })
+    private enemyController: EnemyController = null;
+    
+    @property({ type: Node, tooltip: 'GameArea节点引用' })
+    private gameArea: Node = null;
+    
+    @property({ type: Prefab, tooltip: 'DamageNumber预制体引用' })
+    private damageNumberPrefab: Prefab = null;
+    
+    onLoad() {
+        // 自动获取同节点上的EnemyController组件
+        if (!this.enemyController) {
+            this.enemyController = this.getComponent(EnemyController);
+        }
+        
+        // 只有在需要使用EnemyController功能时才报错
+        // 动态创建的伤害数字节点不需要EnemyController组件
+        if (!this.enemyController && this.damageNumberPrefab) {
+            console.warn('[DamageNumberAni] 未找到EnemyController组件,某些功能可能不可用');
+        }
+    }
+    
+    /**
+     * 创建并显示伤害数字
+     * @param damage 伤害值
+     * @param worldPosition 世界坐标位置(敌人头顶)
+     * @param isCritical 是否暴击
+     */
+    public showDamageNumber(damage: number, worldPosition: Vec3, isCritical: boolean = false) {
+        // 检查预制体引用
+        if (!this.damageNumberPrefab) {
+            console.error('[DamageNumberAni] DamageNumber预制体引用未设置');
+            return;
+        }
+        
+        // 实例化伤害数字节点
+        const damageNode = instantiate(this.damageNumberPrefab);
+            
+        // 使用装饰器引用的GameArea节点
+        if (!this.gameArea) {
+            console.error('[DamageNumberAni] GameArea节点引用未设置');
+            damageNode.destroy();
+            return;
+        }
+        
+        // 添加到GameArea
+        this.gameArea.addChild(damageNode);
+        
+        // 转换世界坐标到GameArea的本地坐标
+        const gameAreaTransform = this.gameArea.getComponent(UITransform);
+        if (gameAreaTransform) {
+            const localPos = gameAreaTransform.convertToNodeSpaceAR(worldPosition);
+            // 稍微向上偏移,显示在敌人头顶
+            localPos.y += 30;
+            damageNode.position = localPos;
+        }
+        
+        // 设置伤害数字文本
+        const label = damageNode.getComponent(Label);
+        if (label) {
+            label.string = Math.floor(damage).toString();
+            
+            // 暴击时使用不同颜色
+            if (isCritical) {
+                label.color = Color.YELLOW; // 暴击显示黄色
+                label.fontSize = 24; // 暴击字体更大
+            } else {
+                label.color = Color.WHITE; // 普通伤害白色
+                label.fontSize = 20;
+            }
+        }
+            
+            // 将DamageNumberAni组件添加到伤害数字节点
+        const aniComponent = damageNode.addComponent(DamageNumberAni);
+        aniComponent.playAnimation(isCritical);
+    }
+    
+    /**
+     * 静态方法保持兼容性,但推荐使用实例方法
+     * @param damage 伤害值
+     * @param worldPosition 世界坐标位置(敌人头顶)
+     * @param isCritical 是否暴击
+     */
+    public static showDamageNumber(damage: number, worldPosition: Vec3, isCritical: boolean = false) {
+        // 尝试找到EnemyController节点上的DamageNumberAni组件
+        const enemyControllerNode = find('Canvas/GameLevelUI/EnemyController');
+        if (enemyControllerNode) {
+            const damageAni = enemyControllerNode.getComponent(DamageNumberAni);
+            if (damageAni) {
+                damageAni.showDamageNumber(damage, worldPosition, isCritical);
+                return;
+            }
+        }
+        
+        console.warn('[DamageNumberAni] 未找到挂载的DamageNumberAni组件,请确保组件已挂载到EnemyController节点');
+    }
+    
+    /**
+     * 播放伤害数字动画
+     * @param isCritical 是否暴击
+     */
+    private playAnimation(isCritical: boolean = false) {
+        // 初始状态:缩放为0,透明度为1
+        this.node.setScale(0, 0, 1);
+        const uiTransform = this.node.getComponent(UITransform);
+        const uiOpacity = this.node.getComponent(UIOpacity);
+        if (uiOpacity) {
+            uiOpacity.opacity = 255;
+        }
+        
+        // 动画参数
+        const maxScale = isCritical ? 1.3 : 1.0; // 暴击时放大更多
+        const growDuration = 0.2; // 放大阶段持续时间
+        const stayDuration = 0.3; // 停留时间
+        const shrinkDuration = 0.4; // 缩小消失时间
+        const floatDistance = 50; // 向上漂浮距离
+        
+        // 第一阶段:从0放大到最大尺寸(从底部开始放大)
+        tween(this.node)
+            .to(growDuration, {
+                scale: new Vec3(maxScale, maxScale, 1)
+            }, {
+                easing: 'backOut' // 弹性效果
+            })
+            .call(() => {
+                // 第二阶段:保持大小,开始向上漂浮并逐渐缩小透明
+                const startPos = this.node.position.clone();
+                const endPos = startPos.clone();
+                endPos.y += floatDistance;
+                
+                // 位置动画
+                tween(this.node)
+                    .to(stayDuration + shrinkDuration, {
+                        position: endPos
+                    }, {
+                        easing: 'sineOut'
+                    })
+                    .start();
+                
+                // 延迟后开始缩小和淡出
+                tween(this.node)
+                    .delay(stayDuration)
+                    .to(shrinkDuration, {
+                        scale: new Vec3(0.3, 0.3, 1)
+                    }, {
+                        easing: 'sineIn'
+                    })
+                    .start();
+                
+                // 透明度动画
+                if (uiOpacity) {
+                    tween(uiOpacity)
+                        .delay(stayDuration)
+                        .to(shrinkDuration, {
+                            opacity: 0
+                        }, {
+                            easing: 'sineIn'
+                        })
+                        .call(() => {
+                            // 动画完成,销毁节点
+                            if (this.node && this.node.isValid) {
+                                this.node.destroy();
+                            }
+                        })
+                        .start();
+                }
+            })
+            .start();
+    }
+    
+    onDestroy() {
+        // 清理所有tween动画
+        Tween.stopAllByTarget(this.node);
+        const uiTransform = this.node.getComponent(UITransform);
+        const uiOpacity = this.node.getComponent(UIOpacity);
+        if (uiTransform) {
+            Tween.stopAllByTarget(uiTransform);
+        }
+        if (uiOpacity) {
+            Tween.stopAllByTarget(uiOpacity);
+        }
+    }
+}

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

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "1345a6f5-4309-470f-a924-1b1e963cac41",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 186 - 0
assets/scripts/Animations/HPBarAnimation.ts

@@ -0,0 +1,186 @@
+import { _decorator, Component, Node, ProgressBar,  tween } from 'cc';
+const { ccclass, property } = _decorator;
+
+/**
+ * 血条动画组件
+ * 使用两个重叠的血条实现黄色血皮滑动动画效果
+ * 红色血条显示当前血量,黄色血条用于滑动动画
+ */
+@ccclass('HPBarAnimation')
+export class HPBarAnimation extends Component {
+    
+    @property({
+        type: Node,
+        tooltip: '红色血条节点'
+    })
+    public redBarNode: Node = null;
+    
+    @property({
+        type: Node,
+        tooltip: '黄色血条节点'
+    })
+    public yellowBarNode: Node = null;
+    
+    private redProgressBar: ProgressBar = null;
+    private yellowProgressBar: ProgressBar = null;
+    private currentProgress: number = 1.0;
+    private targetProgress: number = 1.0;
+    
+    start() {
+        this.initializeComponents();
+    }
+    
+    /**
+     * 初始化组件
+     */
+    private initializeComponents() {
+        // 获取组件所属的敌人节点信息
+        const enemyNode = this.node;
+        const enemyName = enemyNode ? enemyNode.name : 'Unknown';
+     
+        // 获取红色血条组件
+        if (this.redBarNode) {
+            console.log(`[HPBarAnimation] [${enemyName}] 红色血条节点已设置:`, this.redBarNode.name);
+            this.redProgressBar = this.redBarNode.getComponent(ProgressBar);
+            if (this.redProgressBar) {
+                this.currentProgress = this.redProgressBar.progress;
+                this.targetProgress = this.currentProgress;
+                console.log(`[HPBarAnimation] [${enemyName}] 红色血条组件初始化成功,当前进度:`, this.currentProgress);
+            } else {
+                console.error(`[HPBarAnimation] [${enemyName}] 红色血条节点上未找到ProgressBar组件!`);
+            }
+        } else {
+            console.error(`[HPBarAnimation] [${enemyName}] 红色血条节点未设置!`);
+        }
+        
+        // 获取黄色血条组件
+        if (this.yellowBarNode) {
+            console.log(`[HPBarAnimation] [${enemyName}] 黄色血条节点已设置:`, this.yellowBarNode.name);
+            this.yellowProgressBar = this.yellowBarNode.getComponent(ProgressBar);
+            if (this.yellowProgressBar) {
+                // 黄色血条初始进度与红色血条同步
+                this.yellowProgressBar.progress = this.currentProgress;
+            } else {
+                console.error(`[HPBarAnimation] [${enemyName}] 黄色血条节点上未找到ProgressBar组件!`);
+            }
+        } else {
+            console.error(`[HPBarAnimation] [${enemyName}] 黄色血条节点未设置!`);
+        }
+    }
+    
+    /**
+     * 获取节点路径
+     */
+    private getNodePath(node: Node): string {
+        if (!node) return 'null';
+        let path = node.name;
+        let current = node;
+        
+        while (current.parent) {
+            current = current.parent;
+            path = current.name + '/' + path;
+        }
+        
+        return path;
+    }
+    
+
+    
+    /**
+     * 更新血条显示
+     */
+    private updateBarDisplay() {
+        if (!this.redProgressBar || !this.yellowProgressBar) {
+            return;
+        }
+        
+        // 红色血条显示当前血量
+        this.redProgressBar.progress = this.currentProgress;
+    }
+    
+    /**
+     * 更新血条进度并播放动画
+     * @param newProgress 新的血量百分比 (0-1)
+     */
+    public updateProgress(newProgress: number) {
+        const enemyName = this.node ? this.node.name : 'Unknown';
+        
+        if (!this.redProgressBar || !this.yellowProgressBar) {
+            console.warn(`[HPBarAnimation] [${enemyName}] 红色或黄色血条组件未初始化`);
+            return;
+        }
+        
+        // 限制进度范围
+        newProgress = Math.max(0, Math.min(1, newProgress));
+        
+        // 如果血量增加或没有变化,直接更新
+        if (newProgress >= this.currentProgress) {
+            this.currentProgress = newProgress;
+            this.targetProgress = newProgress;
+            // 同步更新两个血条
+            this.redProgressBar.progress = newProgress;
+            this.yellowProgressBar.progress = newProgress;
+            this.updateBarDisplay();
+            return;
+        }
+        
+        // 血量减少时播放黄色血皮滑动动画
+        this.playDamageAnimation(newProgress);
+    }
+    
+    /**
+     * 播放伤害动画
+     * @param newProgress 新的血量百分比
+     */
+    private playDamageAnimation(newProgress: number) {
+        console.log(`[HPBarAnimation] 开始播放伤害动画:${this.currentProgress} -> ${newProgress}`);
+        
+        this.targetProgress = newProgress;
+        
+        // 保存原始血量作为黄色血条起始位置
+        const originalProgress = this.currentProgress;
+        
+        // 1. 立即更新红色血条到新的血量值
+        this.currentProgress = newProgress;
+        this.redProgressBar.progress = newProgress;
+        
+        // 2. 黄色血条从原血量滑动到新血量位置        
+        // 黄色血条保持在原始位置
+        this.yellowProgressBar.progress = originalProgress;
+        this.updateBarDisplay();
+        
+        // 创建滑动动画,先暂停0.4秒再滑动
+        tween({ progress: originalProgress })
+            .delay(0.4) // 暂停0.4秒
+            .to(0.6, { progress: newProgress }, {
+                onUpdate: (target) => {
+                    // 动画过程中更新黄色血条进度
+                    this.yellowProgressBar.progress = target.progress;
+                    this.updateBarDisplay();
+                },
+                onComplete: () => {
+                    // 动画完成后黄色血条进度等于当前血量
+                    this.yellowProgressBar.progress = newProgress;
+                    this.updateBarDisplay();
+                }
+            })
+            .start();
+    }
+    
+    /**
+     * 获取当前血量百分比
+     */
+    public getCurrentProgress(): number {
+        return this.currentProgress;
+    }
+    
+    /**
+     * 重置血条到满血状态
+     */
+    public resetToFull() {
+        this.updateProgress(1.0);
+    }
+    
+    onDestroy() {
+    }
+}

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

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "8c2b2bce-e1eb-4d26-90f6-2d2f79bde2cd",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 130 - 28
assets/scripts/CombatSystem/BallController.ts

@@ -315,7 +315,10 @@ export class BallController extends Component {
         // 设置碰撞属性
         collider.radius = ball.getComponent(UITransform)?.width / 2 || 25;
         collider.group = 1; // 设置为球的碰撞组
+        collider.tag = 1; // 小球标签
         collider.sensor = false;
+        collider.friction = 0; // 无摩擦
+        collider.restitution = 1; // 完全弹性碰撞
         
         // 添加刚体组件
         let rigidBody = ball.getComponent(RigidBody2D);
@@ -327,14 +330,13 @@ export class BallController extends Component {
         rigidBody.type = 2; // 2 = 动态刚体
         rigidBody.allowSleep = false;
         rigidBody.gravityScale = 0;
-        rigidBody.linearDamping = 0;
-        rigidBody.angularDamping = 0;
+        rigidBody.linearDamping = 0; // 无线性阻尼,保持速度不衰减
+        rigidBody.angularDamping = 0; // 无角阻尼
         rigidBody.fixedRotation = true;
+        rigidBody.enabledContactListener = true; // 启用碰撞监听
         
-        // 添加碰撞回调
-        if (collider) {
-            collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
-        }
+        // 注意:不需要为每个小球单独添加碰撞回调,
+        // 因为我们使用的是全局物理系统回调
     }
 
     // 为额外小球初始化方向和速度
@@ -596,9 +598,14 @@ export class BallController extends Component {
         }
     }
 
-    // 碰撞回调 - 简化版本用于测试
+    // 碰撞回调 - 处理小球与方块以及小球之间的碰撞
     onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
-        // Debug logs removed
+        // 检查是否为小球之间的碰撞
+        if (selfCollider.group === 1 && otherCollider.group === 1) {
+            // 小球之间的碰撞 - 防止速度改变
+            this.handleBallToBallCollision(selfCollider, otherCollider, contact);
+            return;
+        }
         
         // 通过事件检查是否可以发射子弹
         const eventBus = EventBus.getInstance();
@@ -628,7 +635,6 @@ export class BallController extends Component {
         
         // 如果没有找到小球,跳过处理
         if (!ballNode || !blockNode) {
-            // Debug log removed
             return;
         }
         
@@ -666,6 +672,60 @@ export class BallController extends Component {
         }
     }
 
+    /**
+     * 处理小球之间的碰撞 - 保持恒定速度
+     */
+    private handleBallToBallCollision(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
+        const ball1 = selfCollider.node;
+        const ball2 = otherCollider.node;
+        
+        const rigidBody1 = ball1.getComponent(RigidBody2D);
+        const rigidBody2 = ball2.getComponent(RigidBody2D);
+        
+        if (!rigidBody1 || !rigidBody2) {
+            return;
+        }
+        
+        // 获取碰撞前的速度
+        const velocity1 = rigidBody1.linearVelocity.clone();
+        const velocity2 = rigidBody2.linearVelocity.clone();
+        
+        // 计算速度大小
+        const speed1 = Math.sqrt(velocity1.x * velocity1.x + velocity1.y * velocity1.y);
+        const speed2 = Math.sqrt(velocity2.x * velocity2.x + velocity2.y * velocity2.y);
+        
+        // 延迟一帧后恢复正确的速度,避免物理引擎的速度改变
+        this.scheduleOnce(() => {
+            if (ball1.isValid && rigidBody1.isValid) {
+                const currentVel1 = rigidBody1.linearVelocity;
+                const currentSpeed1 = Math.sqrt(currentVel1.x * currentVel1.x + currentVel1.y * currentVel1.y);
+                
+                // 如果速度发生了显著变化,恢复到目标速度
+                if (Math.abs(currentSpeed1 - this.currentSpeed) > 5) {
+                    const normalizedVel1 = currentVel1.clone().normalize();
+                    rigidBody1.linearVelocity = new Vec2(
+                        normalizedVel1.x * this.currentSpeed,
+                        normalizedVel1.y * this.currentSpeed
+                    );
+                }
+            }
+            
+            if (ball2.isValid && rigidBody2.isValid) {
+                const currentVel2 = rigidBody2.linearVelocity;
+                const currentSpeed2 = Math.sqrt(currentVel2.x * currentVel2.x + currentVel2.y * currentVel2.y);
+                
+                // 如果速度发生了显著变化,恢复到目标速度
+                if (Math.abs(currentSpeed2 - this.currentSpeed) > 5) {
+                    const normalizedVel2 = currentVel2.clone().normalize();
+                    rigidBody2.linearVelocity = new Vec2(
+                        normalizedVel2.x * this.currentSpeed,
+                        normalizedVel2.y * this.currentSpeed
+                    );
+                }
+            }
+        }, 0.016); // 约一帧的时间
+    }
+    
     // 碰撞结束事件 - 简化版本
     onEndContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
         // Debug log removed
@@ -879,33 +939,75 @@ export class BallController extends Component {
 
     update(dt: number) {
         // 只有当小球已启动时才执行运动逻辑
-        if (!this.ballStarted || !this.initialized || !this.activeBall || !this.activeBall.isValid) {
+        if (!this.ballStarted || !this.initialized) {
             return;
         }
         
-        // 使用刚体组件控制小球移动,而不是直接设置位置
-        const rigidBody = this.activeBall.getComponent(RigidBody2D);
-        if (rigidBody) {
-            // 获取当前速度并确保方向向量与实际速度方向一致
-            const currentVelocity = rigidBody.linearVelocity;
-            const speed = Math.sqrt(currentVelocity.x * currentVelocity.x + currentVelocity.y * currentVelocity.y);
+        // 维持所有小球的恒定速度
+        this.maintainAllBallsSpeed();
+        
+        // 定期检查小球是否接近方块但没有触发碰撞(调试用)
+        if (this.activeBall && this.activeBall.isValid) {
+            this.debugCheckNearBlocks();
+        }
+    }
+    
+    /**
+     * 维持所有小球的恒定速度
+     */
+    private maintainAllBallsSpeed() {
+        // 维持主小球速度
+        if (this.activeBall && this.activeBall.isValid) {
+            this.maintainBallSpeed(this.activeBall);
+        }
+        
+        // 维持额外小球的速度
+        const gameArea = find('Canvas/GameLevelUI/GameArea');
+        if (gameArea) {
+            const additionalBalls = gameArea.children.filter(child => 
+                child.name === 'AdditionalBall' && child.isValid
+            );
             
-            // 确保方向向量与实际速度方向一致
-            if (speed > 1.0) {
-                this.direction.x = currentVelocity.x / speed;
-                this.direction.y = currentVelocity.y / speed;
+            for (const ball of additionalBalls) {
+                this.maintainBallSpeed(ball);
             }
-            
-            // 如果速度过低,重新设置速度以维持恒定运动
-            if (speed < this.currentSpeed * 0.9) {
+        }
+    }
+    
+    /**
+     * 维持单个小球的恒定速度
+     */
+    private maintainBallSpeed(ball: Node) {
+        const rigidBody = ball.getComponent(RigidBody2D);
+        if (!rigidBody) return;
+        
+        // 获取当前速度
+        const currentVelocity = rigidBody.linearVelocity;
+        const speed = Math.sqrt(currentVelocity.x * currentVelocity.x + currentVelocity.y * currentVelocity.y);
+        
+        // 如果速度过低或过高,重新设置速度以维持恒定运动
+        if (speed < this.currentSpeed * 0.85 || speed > this.currentSpeed * 1.15) {
+            // 保持当前方向,但调整速度大小
+            if (speed > 0.1) {
+                const normalizedVelocity = currentVelocity.clone().normalize();
                 rigidBody.linearVelocity = new Vec2(
-                    this.direction.x * this.currentSpeed,
-                    this.direction.y * this.currentSpeed
+                    normalizedVelocity.x * this.currentSpeed,
+                    normalizedVelocity.y * this.currentSpeed
+                );
+            } else {
+                // 如果速度几乎为0,给一个随机方向
+                const angle = Math.random() * Math.PI * 2;
+                rigidBody.linearVelocity = new Vec2(
+                    Math.cos(angle) * this.currentSpeed,
+                    Math.sin(angle) * this.currentSpeed
                 );
             }
-            
-            // 定期检查小球是否接近方块但没有触发碰撞(调试用)
-            this.debugCheckNearBlocks();
+        }
+        
+        // 更新主小球的方向向量(用于其他逻辑)
+        if (ball === this.activeBall && speed > 1.0) {
+            this.direction.x = currentVelocity.x / speed;
+            this.direction.y = currentVelocity.y / speed;
         }
     }
     

+ 192 - 19
assets/scripts/CombatSystem/BlockManager.ts

@@ -1377,8 +1377,17 @@ export class BlockManager extends Component {
             return;
         }
         
-        // 选择合适的图片路径(这里默认使用1x1)
-        const spritePath = spriteConfig['1x1'] || spriteConfig['1x2'] || spriteConfig['2x1'] || spriteConfig['2x2'];
+        // 获取方块的形状ID
+        const blockShapeId = this.getBlockShape(block);
+        
+        // 根据方块形状选择合适的图片路径
+        let spritePath = null;
+        if (blockShapeId && spriteConfig[blockShapeId]) {
+            spritePath = spriteConfig[blockShapeId];
+        } else {
+            // 如果没有找到对应形状的图片,使用备用顺序
+            spritePath = spriteConfig['I'] || spriteConfig['H-I'] || spriteConfig['L'] || spriteConfig['S'] || spriteConfig['D-T'];
+        }
         if (!spritePath) {
             console.warn(`武器 ${weaponConfig.name} 没有可用的图片路径`);
             return;
@@ -1395,11 +1404,173 @@ export class BlockManager extends Component {
             }
             
             // Add comprehensive null safety checks before setting spriteFrame
-            if (weaponSprite && weaponSprite.isValid && 
-                weaponNode && weaponNode.isValid && 
-                block && block.isValid && 
-                spriteFrame && spriteFrame.isValid) {
-                weaponSprite.spriteFrame = spriteFrame;
+        if (weaponSprite && weaponSprite.isValid && 
+            weaponNode && weaponNode.isValid && 
+            block && block.isValid && 
+            spriteFrame && spriteFrame.isValid) {
+            weaponSprite.spriteFrame = spriteFrame;
+            
+            // 根据武器类型和方块形状旋转图片
+            this.rotateWeaponIconByShape(weaponNode, blockShapeId, weaponConfig.id);
+        }
+        });
+    }
+    
+    // 武器类型和方块形状组合的旋转角度配置
+    private readonly WEAPON_SHAPE_ROTATION_ANGLES: { [weaponId: string]: { [shapeId: string]: number } } = {
+        'pea_shooter': {
+            'I': 0,      // 毛豆射手竖条形状
+            'H-I': 90,   // 毛豆射手横条形状
+            'L': 0,      // 毛豆射手L型
+            'S': 0,      // 毛豆射手S型
+            'D-T': 0     // 毛豆射手倒T型
+        },
+        'sharp_carrot': {
+            'I': 0,      // 尖胡萝卜竖条形状
+            'H-I': 90,   // 尖胡萝卜横条形状,旋转适配水平方向
+            'L': -15,    // 尖胡萝卜L型,轻微调整
+            'S': 15,     // 尖胡萝卜S型,轻微调整
+            'D-T': 0     // 尖胡萝卜倒T型
+        },
+        'saw_grass': {
+            'I': 0,      // 锯齿草竖条形状
+            'H-I': 90,   // 锯齿草横条形状
+            'L': -45,    // 锯齿草L型,更大角度适配锯齿形状
+            'S': 30,     // 锯齿草S型,适配锯齿弯曲
+            'D-T': 0     // 锯齿草倒T型
+        },
+        'watermelon_bomb': {
+            'I': 0,      // 西瓜炸弹竖条形状
+            'H-I': 0,    // 西瓜炸弹横条形状,圆形炸弹不需要旋转
+            'L': 0,      // 西瓜炸弹L型
+            'S': 0,      // 西瓜炸弹S型
+            'D-T': 0     // 西瓜炸弹倒T型
+        },
+        'boomerang_plant': {
+            'I': 0,      // 回旋镖植物竖条形状
+            'H-I': 90,   // 回旋镖植物横条形状,旋转适配飞行方向
+            'L': -30,    // 回旋镖植物L型
+            'S': 45,     // 回旋镖植物S型,适配回旋轨迹
+            'D-T': 0     // 回旋镖植物倒T型
+        },
+        'hot_pepper': {
+            'I': 0,      // 辣椒竖条形状
+            'H-I': 90,   // 辣椒横条形状
+            'L': 0,      // 辣椒L型
+            'S': 0,      // 辣椒S型
+            'D-T': 0     // 辣椒倒T型
+        },
+        'cactus_shotgun': {
+            'I': 0,      // 仙人掌霰弹枪竖条形状
+            'H-I': 90,   // 仙人掌霰弹枪横条形状
+            'L': -20,    // 仙人掌霰弹枪L型
+            'S': 20,     // 仙人掌霰弹枪S型
+            'D-T': 0     // 仙人掌霰弹枪倒T型
+        },
+        'okra_missile': {
+            'I': 0,      // 秋葵导弹竖条形状
+            'H-I': 90,   // 秋葵导弹横条形状,旋转适配发射方向
+            'L': -10,    // 秋葵导弹L型
+            'S': 10,     // 秋葵导弹S型
+            'D-T': 0     // 秋葵导弹倒T型
+        },
+        'mace_club': {
+            'I': 0,      // 狼牙棒竖条形状
+            'H-I': 90,   // 狼牙棒横条形状
+            'L': -25,    // 狼牙棒L型,适配棒状武器
+            'S': 25,     // 狼牙棒S型
+            'D-T': 0     // 狼牙棒倒T型
+        }
+    };
+    
+    // 默认旋转角度配置(当武器类型未配置时使用)
+    private readonly DEFAULT_SHAPE_ROTATION_ANGLES: { [key: string]: number } = {
+        'I': 0,      // 竖条形状,保持原始方向
+        'H-I': 90,   // 横I型,旋转90度适配水平方向
+        'L': -15,    // L型,轻微左倾适配L形状的转角
+        'S': 15,     // S型,轻微右倾适配S形状的弯曲
+        'D-T': 0     // 倒T型,保持原始方向
+    };
+    
+    // 根据武器类型和方块形状旋转武器图标
+    private rotateWeaponIconByShape(weaponNode: Node, shapeId: string | null, weaponId?: string) {
+        if (!weaponNode || !shapeId) return;
+        
+        let rotationAngle = 0;
+        
+        // 如果提供了武器ID,尝试获取特定武器的旋转角度
+        if (weaponId && this.WEAPON_SHAPE_ROTATION_ANGLES[weaponId]) {
+            rotationAngle = this.WEAPON_SHAPE_ROTATION_ANGLES[weaponId][shapeId] || 0;
+            console.log(`为武器 ${weaponId} 形状 ${shapeId} 设置特定旋转角度: ${rotationAngle}度`);
+        } else {
+            // 使用默认旋转角度配置
+            rotationAngle = this.DEFAULT_SHAPE_ROTATION_ANGLES[shapeId] || 0;
+            console.log(`为形状 ${shapeId} 设置默认旋转角度: ${rotationAngle}度`);
+        }
+        
+        // 应用旋转
+        weaponNode.setRotationFromEuler(0, 0, rotationAngle);
+    }
+    
+    // 设置特定武器和形状的旋转角度
+    public setWeaponShapeRotationAngle(weaponId: string, shapeId: string, angle: number) {
+        if (!this.WEAPON_SHAPE_ROTATION_ANGLES[weaponId]) {
+            this.WEAPON_SHAPE_ROTATION_ANGLES[weaponId] = {};
+        }
+        this.WEAPON_SHAPE_ROTATION_ANGLES[weaponId][shapeId] = angle;
+        console.log(`已更新武器 ${weaponId} 形状 ${shapeId} 的旋转角度为: ${angle}度`);
+    }
+    
+    // 设置默认形状的旋转角度
+    public setDefaultShapeRotationAngle(shapeId: string, angle: number) {
+        this.DEFAULT_SHAPE_ROTATION_ANGLES[shapeId] = angle;
+        console.log(`已更新默认形状 ${shapeId} 的旋转角度为: ${angle}度`);
+    }
+    
+    // 获取特定武器和形状的旋转角度
+    public getWeaponShapeRotationAngle(weaponId: string, shapeId: string): number {
+        if (this.WEAPON_SHAPE_ROTATION_ANGLES[weaponId]) {
+            return this.WEAPON_SHAPE_ROTATION_ANGLES[weaponId][shapeId] || 0;
+        }
+        return 0;
+    }
+    
+    // 获取默认形状的旋转角度
+    public getDefaultShapeRotationAngle(shapeId: string): number {
+        return this.DEFAULT_SHAPE_ROTATION_ANGLES[shapeId] || 0;
+    }
+    
+    // 重新应用所有已放置方块的武器图标旋转
+    public refreshAllWeaponIconRotations() {
+        // 遍历所有已放置的方块
+        if (this.placedBlocksContainer) {
+            this.placedBlocksContainer.children.forEach(block => {
+                const weaponConfig = this.getBlockWeaponConfig(block);
+                if (weaponConfig) {
+                    const b1Node = block.getChildByName('B1');
+                    if (b1Node) {
+                        const weaponNode = b1Node.getChildByName('Weapon');
+                        if (weaponNode) {
+                            const shapeId = this.getBlockShape(block);
+                            this.rotateWeaponIconByShape(weaponNode, shapeId, weaponConfig.id);
+                        }
+                    }
+                }
+            });
+        }
+        
+        // 遍历kuang区域的方块
+        this.blocks.forEach(block => {
+            const weaponConfig = this.getBlockWeaponConfig(block);
+            if (weaponConfig) {
+                const b1Node = block.getChildByName('B1');
+                if (b1Node) {
+                    const weaponNode = b1Node.getChildByName('Weapon');
+                    if (weaponNode) {
+                        const shapeId = this.getBlockShape(block);
+                        this.rotateWeaponIconByShape(weaponNode, shapeId, weaponConfig.id);
+                    }
+                }
             }
         });
     }
@@ -1447,22 +1618,24 @@ export class BlockManager extends Component {
 
     // 从方块结构推断形状
     private inferBlockShapeFromStructure(block: Node): string {
-        const parts = this.getBlockParts(block);
-        if (parts.length === 0) return '1x1';
+        const actualShape = this.extractShapeFromBlock(block);
+        const blockShapes = this.configManager.getBlockShapes();
         
-        // 计算方块的边界
-        let minX = 0, maxX = 0, minY = 0, maxY = 0;
-        for (const part of parts) {
-            minX = Math.min(minX, part.x);
-            maxX = Math.max(maxX, part.x);
-            minY = Math.min(minY, part.y);
-            maxY = Math.max(maxY, part.y);
+        if (!blockShapes) {
+            console.warn('无法获取方块形状配置,使用默认形状');
+            return 'I';
         }
         
-        const width = maxX - minX + 1;
-        const height = maxY - minY + 1;
+        // 寻找匹配的形状配置
+        for (const shapeConfig of blockShapes) {
+            if (this.compareShapeMatrices(actualShape, shapeConfig.shape)) {
+                console.log(`[BlockManager] 识别方块形状: ${shapeConfig.id} (${shapeConfig.name})`);
+                return shapeConfig.id;
+            }
+        }
         
-        return `${width}x${height}`;
+        console.warn('[BlockManager] 未找到匹配的形状配置,使用默认形状I');
+        return 'I';
     }
     
     // 寻找与目标形状匹配的预制体

+ 16 - 16
assets/scripts/CombatSystem/BulletEffects/BulletHitEffect.ts

@@ -280,18 +280,18 @@ export class BulletHitEffect extends Component {
     private damageEnemy(enemyNode: Node, damage: number) {
         if (!this.isEnemyNode(enemyNode)) return;
         
-        // 计算暴击伤害
-        const finalDamage = this.calculateCriticalDamage(damage);
+        // 计算暴击伤害和暴击状态
+        const damageResult = this.calculateCriticalDamage(damage);
         
         // 尝试调用敌人的受伤方法
         const enemyInstance = enemyNode.getComponent('EnemyInstance') as any;
         if (enemyInstance) {
             if (typeof enemyInstance.takeDamage === 'function') {
-                enemyInstance.takeDamage(finalDamage);
+                enemyInstance.takeDamage(damageResult.damage, damageResult.isCritical);
                 return;
             }
             if (typeof enemyInstance.health === 'number') {
-                enemyInstance.health -= finalDamage;
+                enemyInstance.health -= damageResult.damage;
                 if (enemyInstance.health <= 0) {
                     enemyNode.destroy();
                 }
@@ -302,14 +302,14 @@ export class BulletHitEffect extends Component {
         // 备用方案:通过EnemyController
         const enemyController = find('Canvas/GameLevelUI/EnemyController')?.getComponent('EnemyController') as any;
         if (enemyController && typeof enemyController.damageEnemy === 'function') {
-            enemyController.damageEnemy(enemyNode, finalDamage);
+            enemyController.damageEnemy(enemyNode, damageResult.damage, damageResult.isCritical);
         }
     }
     
     /**
      * 计算暴击伤害
      */
-    private calculateCriticalDamage(baseDamage: number): number {
+    private calculateCriticalDamage(baseDamage: number): { damage: number, isCritical: boolean } {
         // 从WeaponBullet获取暴击相关数值
         const weaponBullet = this.getComponent('WeaponBullet') as any;
         if (!weaponBullet) {
@@ -321,9 +321,9 @@ export class BulletHitEffect extends Component {
                 const critDamage = baseDamage * 2; // 默认暴击倍数2倍
                 this.showCriticalHitEffect();
                 console.log(`[BulletHitEffect] 暴击!基础伤害: ${baseDamage}, 暴击伤害: ${critDamage}, 暴击率: ${(critChance * 100).toFixed(1)}%`);
-                return critDamage;
+                return { damage: critDamage, isCritical: true };
             }
-            return baseDamage;
+            return { damage: baseDamage, isCritical: false };
         }
         
         // 获取暴击率和暴击伤害
@@ -339,10 +339,10 @@ export class BulletHitEffect extends Component {
             
             console.log(`[BulletHitEffect] 暴击!基础伤害: ${baseDamage}, 暴击伤害: ${critDamage}, 暴击率: ${(critChance * 100).toFixed(1)}%`);
             
-            return critDamage;
+            return { damage: critDamage, isCritical: true };
         }
         
-        return baseDamage;
+        return { damage: baseDamage, isCritical: false };
     }
     
     /**
@@ -374,11 +374,11 @@ export class BulletHitEffect extends Component {
             const distance = Vec3.distance(center, enemy.worldPosition);
             if (distance <= radius) {
                 // 每个敌人独立计算暴击
-                const finalDamage = this.calculateCriticalDamage(baseDamage);
+                const damageResult = this.calculateCriticalDamage(baseDamage);
                 
                 // 直接处理伤害,避免重复计算暴击
-                this.applyDamageToEnemy(enemy, finalDamage);
-                totalDamage += finalDamage;
+                this.applyDamageToEnemy(enemy, damageResult.damage, damageResult.isCritical);
+                totalDamage += damageResult.damage;
             }
         }
         
@@ -388,14 +388,14 @@ export class BulletHitEffect extends Component {
     /**
      * 直接对敌人应用伤害(不进行暴击计算)
      */
-    private applyDamageToEnemy(enemyNode: Node, damage: number) {
+    private applyDamageToEnemy(enemyNode: Node, damage: number, isCritical: boolean = false) {
         if (!this.isEnemyNode(enemyNode)) return;
         
         // 尝试调用敌人的受伤方法
         const enemyInstance = enemyNode.getComponent('EnemyInstance') as any;
         if (enemyInstance) {
             if (typeof enemyInstance.takeDamage === 'function') {
-                enemyInstance.takeDamage(damage);
+                enemyInstance.takeDamage(damage, isCritical);
                 return;
             }
             if (typeof enemyInstance.health === 'number') {
@@ -410,7 +410,7 @@ export class BulletHitEffect extends Component {
         // 备用方案:通过EnemyController
         const enemyController = find('Canvas/GameLevelUI/EnemyController')?.getComponent('EnemyController') as any;
         if (enemyController && typeof enemyController.damageEnemy === 'function') {
-            enemyController.damageEnemy(enemyNode, damage);
+            enemyController.damageEnemy(enemyNode, damage, isCritical);
         }
     }
     

+ 2 - 2
assets/scripts/CombatSystem/EnemyController.ts

@@ -768,7 +768,7 @@ export class EnemyController extends BaseSingleton {
     }
 
     // 敌人受到伤害
-    damageEnemy(enemy: Node, damage: number) {
+    damageEnemy(enemy: Node, damage: number, isCritical: boolean = false) {
         if (!enemy || !enemy.isValid) return;
         
         // 游戏状态检查现在通过事件系统处理
@@ -778,7 +778,7 @@ export class EnemyController extends BaseSingleton {
         if (!enemyComp) return;
         
         // 减少敌人血量
-        enemyComp.takeDamage(damage);
+        enemyComp.takeDamage(damage, isCritical);
         
         // 检查敌人是否死亡
         if (enemyComp.health <= 0) {

+ 66 - 8
assets/scripts/CombatSystem/EnemyInstance.ts

@@ -1,5 +1,7 @@
 import { _decorator, Component, Node, ProgressBar, Label, Vec3, find, UITransform, Collider2D, Contact2DType, IPhysics2DContact, instantiate, resources, Prefab } from 'cc';
 import { sp } from 'cc';
+import { DamageNumberAni } from '../Animations/DamageNumberAni';
+import { HPBarAnimation } from '../Animations/HPBarAnimation';
 const { ccclass, property } = _decorator;
 
 // 前向声明EnemyController接口,避免循环引用
@@ -11,6 +13,7 @@ interface EnemyControllerType {
         bottom: number;
     };
     damageWall: (damage: number) => void;
+    getComponent: (componentType: any) => any;
 }
 
 // 敌人状态枚举
@@ -58,6 +61,9 @@ export class EnemyInstance extends Component {
 
     // 骨骼动画组件
     private skeleton: sp.Skeleton | null = null;
+    
+    // 血条动画组件
+    private hpBarAnimation: HPBarAnimation | null = null;
 
 
     start() {
@@ -74,6 +80,9 @@ export class EnemyInstance extends Component {
         this.attackInterval = 2.0; // 默认攻击间隔
         this.attackTimer = 0;
         
+        // 初始化血条动画组件
+        this.initializeHPBarAnimation();
+        
         // 获取骨骼动画组件
         this.skeleton = this.getComponent(sp.Skeleton);
         this.playWalkAnimation();
@@ -132,14 +141,48 @@ export class EnemyInstance extends Component {
         }
     }
 
-    // 更新血量显示
-    updateHealthDisplay() {
-        // 更新血条
+    /**
+     * 初始化血条动画组件
+     */
+    private initializeHPBarAnimation() {
         const hpBar = this.node.getChildByName('HPBar');
         if (hpBar) {
-            const progressBar = hpBar.getComponent(ProgressBar);
-            if (progressBar) {
-                progressBar.progress = this.health / this.maxHealth;
+            // 查找红色和黄色血条节点
+            const redBarNode = hpBar.getChildByName('RedBar');
+            const yellowBarNode = hpBar.getChildByName('YellowBar');
+            
+            if (redBarNode && yellowBarNode) {
+                // 添加血条动画组件
+                this.hpBarAnimation = this.node.addComponent(HPBarAnimation);
+                if (this.hpBarAnimation) {
+                    // 正确设置红色和黄色血条节点引用
+                    this.hpBarAnimation.redBarNode = redBarNode;
+                    this.hpBarAnimation.yellowBarNode = yellowBarNode;
+                    console.log(`[EnemyInstance] 血条动画组件已初始化`);
+                }
+            } else {
+                console.warn(`[EnemyInstance] HPBar下未找到RedBar或YellowBar节点,RedBar: ${!!redBarNode}, YellowBar: ${!!yellowBarNode}`);
+            }
+        } else {
+            console.warn(`[EnemyInstance] 未找到HPBar节点,无法初始化血条动画`);
+        }
+    }
+    
+    // 更新血量显示
+    updateHealthDisplay() {
+        const healthProgress = this.health / this.maxHealth;
+        
+        // 使用血条动画组件更新血条
+        if (this.hpBarAnimation) {
+            this.hpBarAnimation.updateProgress(healthProgress);
+        } else {
+            // 备用方案:直接更新血条
+            const hpBar = this.node.getChildByName('HPBar');
+            if (hpBar) {
+                const progressBar = hpBar.getComponent(ProgressBar);
+                if (progressBar) {
+                    progressBar.progress = healthProgress;
+                }
             }
         }
         
@@ -154,7 +197,7 @@ export class EnemyInstance extends Component {
     }
 
     // 受到伤害
-    takeDamage(damage: number) {
+    takeDamage(damage: number, isCritical: boolean = false) {
         // 如果已经死亡,不再处理伤害
         if (this.state === EnemyState.DEAD) {
             return;
@@ -163,7 +206,22 @@ export class EnemyInstance extends Component {
         this.health -= damage;
         console.log(`[EnemyInstance] 敌人受到伤害: ${damage}, 剩余血量: ${this.health}`);
         
-        // 更新血量显示
+        // 显示伤害数字动画(在敌人头顶)
+        // 优先使用EnemyController节点上的DamageNumberAni组件实例
+        if (this.controller) {
+            const damageAni = this.controller.getComponent(DamageNumberAni);
+            if (damageAni) {
+                damageAni.showDamageNumber(damage, this.node.worldPosition, isCritical);
+            } else {
+                // 如果没有找到组件实例,使用静态方法作为备用
+                DamageNumberAni.showDamageNumber(damage, this.node.worldPosition, isCritical);
+            }
+        } else {
+            // 如果没有controller引用,使用静态方法
+            DamageNumberAni.showDamageNumber(damage, this.node.worldPosition, isCritical);
+        }
+        
+        // 更新血量显示和动画
         this.updateHealthDisplay();
         
         // 如果血量低于等于0,销毁敌人

+ 2 - 2
assets/scripts/CombatSystem/WeaponBullet.ts

@@ -573,8 +573,8 @@ export class WeaponBullet extends Component {
             return;
         }
 
-        // 依次尝试常用尺寸键值
-        const spritePath = spriteConfig['1x1'] || spriteConfig['1x2'] || spriteConfig['2x1'] || spriteConfig['2x2'];
+        // 依次尝试新的形状ID键值
+        const spritePath = spriteConfig['I'] || spriteConfig['H-I'] || spriteConfig['L'] || spriteConfig['S'] || spriteConfig['D-T'];
         if (!spritePath) {
             return;
         }

+ 11 - 3
assets/scripts/Core/ConfigManager.ts

@@ -351,14 +351,22 @@ export class ConfigManager extends BaseSingleton {
         return this.enemiesConfig.enemies.filter(enemy => enemy.rarity === rarity);
     }
 
-    // 获取方块尺寸列表
+    // 获取方块尺寸列表(已更新为形状ID)
     public getBlockSizes(): string[] {
-        return this.weaponsConfig?.blockSizes || ['1x1', '1x2', '2x1', '2x2'];
+        if (!this.weaponsConfig || !this.weaponsConfig.blockSizes) {
+            return ['I', 'H-I', 'L', 'S', 'D-T'];
+        }
+        // 从blockSizes配置中提取形状ID
+        return this.weaponsConfig.blockSizes.map((shape: any) => shape.id);
     }
     
     // 获取方块形状配置列表
     public getBlockShapes(): any[] {
-        return this.weaponsConfig?.blockSizes || [];
+        if (!this.weaponsConfig || !this.weaponsConfig.blockSizes) {
+            console.warn('武器配置或方块形状配置未加载');
+            return [];
+        }
+        return this.weaponsConfig.blockSizes;
     }
 
     // 获取波次进展配置

+ 7 - 6
assets/scripts/FourUI/UpgradeSystem/UpgradeController.ts

@@ -22,10 +22,11 @@ interface WeaponConfig {
     };
     visualConfig: {
         weaponSprites: {
-            "1x1": string;
-            "1x2": string;
-            "2x1": string;
-            "2x2": string;
+            "I": string;
+            "H-I": string;
+            "L": string;
+            "S": string;
+            "D-T": string;
         };
     };
 }
@@ -372,7 +373,7 @@ export class UpgradeController extends Component {
         // 设置武器图标 - 查找专门的武器图标Sprite节点,避免影响背景
         const weaponSprite = spriteNode.getChildByName('WeaponSprite')?.getComponent(Sprite);
         if (weaponSprite && weaponConfig.visualConfig.weaponSprites) {
-            const spritePath = weaponConfig.visualConfig.weaponSprites['1x1'];
+            const spritePath = weaponConfig.visualConfig.weaponSprites['I'] || weaponConfig.visualConfig.weaponSprites['H-I'] || weaponConfig.visualConfig.weaponSprites['L'] || weaponConfig.visualConfig.weaponSprites['S'] || weaponConfig.visualConfig.weaponSprites['D-T'];
             this.loadWeaponSprite(weaponSprite, spritePath);
         }
         
@@ -571,7 +572,7 @@ export class UpgradeController extends Component {
         
         // 设置武器图标 - Canvas/UpgradeUI/UpgradePanel/WeaponSprite
         if (this.panelWeaponSprite && weaponConfig.visualConfig.weaponSprites) {
-            const spritePath = weaponConfig.visualConfig.weaponSprites['1x1'];
+            const spritePath = weaponConfig.visualConfig.weaponSprites['I'] || weaponConfig.visualConfig.weaponSprites['H-I'] || weaponConfig.visualConfig.weaponSprites['L'] || weaponConfig.visualConfig.weaponSprites['S'] || weaponConfig.visualConfig.weaponSprites['D-T'];
             this.loadWeaponSprite(this.panelWeaponSprite, spritePath);
         }
         

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