181404010226 6 месяцев назад
Родитель
Сommit
cf39da06e7

Разница между файлами не показана из-за своего большого размера
+ 384 - 136
assets/Scenes/GameLevel.scene


+ 1 - 1
assets/assets/Prefabs/Ball.prefab

@@ -187,7 +187,7 @@
       "__uuid__": "bf1d1e67-5bab-4c32-b912-5fadfb93974a",
       "__expectedType__": "cc.Prefab"
     },
-    "speed": 300,
+    "speed": 50,
     "_id": ""
   },
   {

+ 40 - 32
assets/assets/Prefabs/Shooter.prefab → assets/assets/Prefabs/Bullet.prefab

@@ -1,7 +1,7 @@
 [
   {
     "__type__": "cc.Prefab",
-    "_name": "Shooter",
+    "_name": "Bullet",
     "_objFlags": 0,
     "__editorExtras__": {},
     "_native": "",
@@ -13,7 +13,7 @@
   },
   {
     "__type__": "cc.Node",
-    "_name": "Shooter",
+    "_name": "Bullet",
     "_objFlags": 0,
     "__editorExtras__": {},
     "_parent": null,
@@ -24,9 +24,6 @@
     ],
     "_active": true,
     "_components": [
-      {
-        "__id__": 8
-      },
       {
         "__id__": 10
       },
@@ -82,10 +79,13 @@
       },
       {
         "__id__": 5
+      },
+      {
+        "__id__": 7
       }
     ],
     "_prefab": {
-      "__id__": 7
+      "__id__": 9
     },
     "_lpos": {
       "__type__": "cc.Vec3",
@@ -189,6 +189,36 @@
     "__type__": "cc.CompPrefabInfo",
     "fileId": "d1qLZLV3NElaBQ9sZgaBiw"
   },
+  {
+    "__type__": "cc.CircleCollider2D",
+    "_name": "",
+    "_objFlags": 0,
+    "__editorExtras__": {},
+    "node": {
+      "__id__": 2
+    },
+    "_enabled": true,
+    "__prefab": {
+      "__id__": 8
+    },
+    "tag": 0,
+    "_group": 1,
+    "_density": 1,
+    "_sensor": false,
+    "_friction": 0.2,
+    "_restitution": 0,
+    "_offset": {
+      "__type__": "cc.Vec2",
+      "x": 0,
+      "y": 0
+    },
+    "_radius": 28.5,
+    "_id": ""
+  },
+  {
+    "__type__": "cc.CompPrefabInfo",
+    "fileId": "a2t8cuTdhLd5+xBu2uCHFe"
+  },
   {
     "__type__": "cc.PrefabInfo",
     "root": {
@@ -212,7 +242,7 @@
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 9
+      "__id__": 11
     },
     "_contentSize": {
       "__type__": "cc.Size",
@@ -240,7 +270,7 @@
     },
     "_enabled": true,
     "__prefab": {
-      "__id__": 11
+      "__id__": 13
     },
     "_customMaterial": null,
     "_srcBlendFactor": 2,
@@ -252,10 +282,7 @@
       "b": 255,
       "a": 255
     },
-    "_spriteFrame": {
-      "__uuid__": "7efa8afb-730c-43f8-9d0a-5cbf71082a54@f9941",
-      "__expectedType__": "cc.SpriteFrame"
-    },
+    "_spriteFrame": null,
     "_type": 0,
     "_fillType": 0,
     "_sizeMode": 1,
@@ -275,24 +302,6 @@
     "__type__": "cc.CompPrefabInfo",
     "fileId": "f41qNq5FNE96SOtUcEBjOb"
   },
-  {
-    "__type__": "febae4X34pEoomu+tZr4ags",
-    "_name": "",
-    "_objFlags": 0,
-    "__editorExtras__": {},
-    "node": {
-      "__id__": 1
-    },
-    "_enabled": true,
-    "__prefab": {
-      "__id__": 13
-    },
-    "_id": ""
-  },
-  {
-    "__type__": "cc.CompPrefabInfo",
-    "fileId": "5eN5F2CvZBr6kTCLCWUCHP"
-  },
   {
     "__type__": "cc.PrefabInfo",
     "root": {
@@ -302,7 +311,6 @@
       "__id__": 0
     },
     "fileId": "3549ek5TVKYYngJeAEZalg",
-    "instance": null,
-    "targetOverrides": null
+    "instance": null
   }
 ]

+ 1 - 1
assets/assets/Prefabs/Shooter.prefab.meta → assets/assets/Prefabs/Bullet.prefab.meta

@@ -8,6 +8,6 @@
   ],
   "subMetas": {},
   "userData": {
-    "syncNodeName": "Shooter"
+    "syncNodeName": "Bullet"
   }
 }

+ 129 - 53
assets/scripts/BallController.ts

@@ -1,4 +1,4 @@
-import { _decorator, Component, Node, Vec2, Vec3, UITransform, Collider2D, Contact2DType, IPhysics2DContact, director, CircleCollider2D, RigidBody2D, Prefab, instantiate, find, js } from 'cc';
+import { _decorator, Component, Node, Vec2, Vec3, UITransform, Collider2D, Contact2DType, IPhysics2DContact, RigidBody2D, Prefab, instantiate, find, CircleCollider2D } from 'cc';
 const { ccclass, property } = _decorator;
 
 @ccclass('BallController')
@@ -20,7 +20,7 @@ export class BallController extends Component {
     // 球的方向向量
     private direction: Vec2 = new Vec2();
     
-    // 游戏区域边界
+    // GameArea区域边界
     private gameBounds = {
         left: 0,
         right: 0,
@@ -34,40 +34,51 @@ export class BallController extends Component {
     // 是否已初始化
     private initialized: boolean = false;
 
+    // 子弹预制体
+    @property({
+        type: Prefab,
+        tooltip: '拖拽子弹预制体到这里'
+    })
+    public bulletPrefab: Prefab = null;
+
+    // 子弹速度
+    @property
+    public bulletSpeed: number = 50;
+
     start() {
         // 计算游戏边界
         this.calculateGameBounds();
     }
 
-    // 计算游戏边界(使用整个屏幕)
+    // 计算游戏边界(使用GameArea节点
     calculateGameBounds() {
-        // 获取屏幕尺寸
-        const canvas = find('Canvas');
-        if (!canvas) {
-            console.error('找不到Canvas节点');
+        // 获取GameArea节点
+        const gameArea = find('Canvas/GameArea');
+        if (!gameArea) {
+            console.error('找不到GameArea节点');
             return;
         }
 
-        const canvasUI = canvas.getComponent(UITransform);
-        if (!canvasUI) {
-            console.error('Canvas节点没有UITransform组件');
+        const gameAreaUI = gameArea.getComponent(UITransform);
+        if (!gameAreaUI) {
+            console.error('GameArea节点没有UITransform组件');
             return;
         }
 
-        // 获取屏幕的尺寸
-        const screenWidth = canvasUI.width;
-        const screenHeight = canvasUI.height;
+        // 获取GameArea的尺寸
+        const areaWidth = gameAreaUI.width;
+        const areaHeight = gameAreaUI.height;
         
-        // 获取屏幕的世界坐标位置
-        const worldPos = canvas.worldPosition;
+        // 获取GameArea的世界坐标位置
+        const worldPos = gameArea.worldPosition;
 
-        // 计算屏幕的世界坐标边界
-        this.gameBounds.left = worldPos.x - screenWidth / 2;
-        this.gameBounds.right = worldPos.x + screenWidth / 2;
-        this.gameBounds.bottom = worldPos.y - screenHeight / 2;
-        this.gameBounds.top = worldPos.y + screenHeight / 2;
+        // 计算GameArea的世界坐标边界
+        this.gameBounds.left = worldPos.x - areaWidth / 2;
+        this.gameBounds.right = worldPos.x + areaWidth / 2;
+        this.gameBounds.bottom = worldPos.y - areaHeight / 2;
+        this.gameBounds.top = worldPos.y + areaHeight / 2;
 
-        console.log('Screen Bounds:', this.gameBounds);
+        console.log('GameArea Bounds:', this.gameBounds);
     }
 
     // 创建小球
@@ -84,10 +95,16 @@ export class BallController extends Component {
 
         // 实例化小球
         this.activeBall = instantiate(this.ballPrefab);
-        this.node.addChild(this.activeBall);
-
+        
+        // 将小球添加到GameArea中
+        const gameArea = find('Canvas/GameArea');
+        if (gameArea) {
+            gameArea.addChild(this.activeBall);
+        } else {
+            this.node.addChild(this.activeBall);
+        }
 
-        // 随机位置(在屏幕范围内)
+        // 随机位置(在GameArea范围内)
         this.positionBallRandomly();
 
         // 设置球的半径
@@ -105,7 +122,6 @@ export class BallController extends Component {
         this.initialized = true;
     }
 
-
     // 随机位置小球
     positionBallRandomly() {
         if (!this.activeBall) return;
@@ -114,19 +130,19 @@ export class BallController extends Component {
         const ballRadius = transform ? transform.width / 2 : 25;
         
         // 计算可生成的范围(考虑小球半径,避免生成在边缘)
-        const minX = this.gameBounds.left + ballRadius;
-        const maxX = this.gameBounds.right - ballRadius;
-        const minY = this.gameBounds.bottom + ballRadius;
-        const maxY = this.gameBounds.top - ballRadius;
+        const minX = this.gameBounds.left + ballRadius + 20; // 额外偏移,避免生成在边缘
+        const maxX = this.gameBounds.right - ballRadius - 20;
+        const minY = this.gameBounds.bottom + ballRadius + 20;
+        const maxY = this.gameBounds.top - ballRadius - 20;
 
         // 随机生成位置
         const randomX = Math.random() * (maxX - minX) + minX;
         const randomY = Math.random() * (maxY - minY) + minY;
 
-        // 将世界坐标转换为相对于节点的本地坐标
-        const canvas = find('Canvas');
-        if (canvas) {
-            const localPos = canvas.getComponent(UITransform).convertToNodeSpaceAR(new Vec3(randomX, randomY, 0));
+        // 将世界坐标转换为相对于GameArea的本地坐标
+        const gameArea = find('Canvas/GameArea');
+        if (gameArea) {
+            const localPos = gameArea.getComponent(UITransform).convertToNodeSpaceAR(new Vec3(randomX, randomY, 0));
             this.activeBall.position = localPos;
         } else {
             // 直接设置位置(不太准确,但作为后备)
@@ -138,22 +154,20 @@ export class BallController extends Component {
     setupCollider() {
         if (!this.activeBall) return;
 
-        let collider = this.activeBall.getComponent(CircleCollider2D);
-        if (!collider) {
-            collider = this.activeBall.addComponent(CircleCollider2D);
-            collider.radius = this.radius;
-            collider.tag = 0;
-            collider.group = 1;
-            collider.sensor = false;
-            collider.friction = 0;
-            collider.restitution = 1; // 完全弹性碰撞
-        } else {
-            // 设置碰撞组件的属性
-            collider.restitution = 1; // 确保完全弹性碰撞
+        // 确保小球有刚体组件
+        let rigidBody = this.activeBall.getComponent(RigidBody2D);
+        if (!rigidBody) {
+            rigidBody = this.activeBall.addComponent(RigidBody2D);
+            rigidBody.type = 2; // Dynamic
+            rigidBody.gravityScale = 0; // 不受重力影响
+            rigidBody.enabledContactListener = true; // 启用碰撞监听
+            rigidBody.bullet = true; // 高精度碰撞检测
+            rigidBody.fixedRotation = false; // 允许旋转
+            rigidBody.allowSleep = true;
         }
 
         // 注册碰撞事件
-        collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
+        this.activeBall.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
     }
 
     // 初始化方向
@@ -186,11 +200,6 @@ export class BallController extends Component {
                 this.direction.y * this.speed
             );
         }
-        
-        // 不再需要这些代码,因为物理引擎会处理碰撞和位置更新
-        // const newPos = new Vec3(...);
-        // this.checkBoundaryCollision(newPos);
-        // this.activeBall.position = newPos;
     }
 
     // 碰撞回调中,只需要更新方向向量,物理引擎会处理实际的反弹
@@ -229,7 +238,74 @@ export class BallController extends Component {
     // 发射子弹
     fireBullet(blockNode: Node) {
         console.log('发射子弹!击中方块:', blockNode.name);
-        // 这里只是模拟发射子弹,实际的子弹逻辑和动画将在后续添加
+        
+        // 检查是否有子弹预制体
+        if (!this.bulletPrefab) {
+            console.error('未设置子弹预制体');
+            return;
+        }
+        
+        // 查找Weapon节点
+        const weaponNode = blockNode.getChildByName('Weapon');
+        if (!weaponNode) {
+            console.warn(`方块 ${blockNode.name} 没有Weapon子节点`);
+            return;
+        }
+        
+        // 实例化子弹
+        const bullet = instantiate(this.bulletPrefab);
+        
+        // 将子弹添加到GameArea中
+        const gameArea = find('Canvas/GameArea');
+        if (gameArea) {
+            gameArea.addChild(bullet);
+            
+            // 设置子弹初始位置为Weapon节点的位置
+            const weaponWorldPos = weaponNode.worldPosition;
+            bullet.worldPosition = weaponWorldPos;
+            
+            // 计算子弹方向 - 从Weapon指向小球
+            const ballPos = this.activeBall.worldPosition;
+            const direction = new Vec2(
+                ballPos.x - weaponWorldPos.x,
+                ballPos.y - weaponWorldPos.y
+            );
+            direction.normalize();
+            
+            // 添加刚体组件控制子弹移动
+            let rigidBody = bullet.getComponent(RigidBody2D);
+            if (!rigidBody) {
+                rigidBody = bullet.addComponent(RigidBody2D);
+                rigidBody.type = 2; // Dynamic
+                rigidBody.gravityScale = 0; // 不受重力影响
+                rigidBody.fixedRotation = true; // 固定旋转
+                rigidBody.allowSleep = false; // 不允许休眠
+            }
+            
+            // 设置子弹速度
+            rigidBody.linearVelocity = new Vec2(
+                direction.x * this.bulletSpeed,
+                direction.y * this.bulletSpeed
+            );
+            
+            // 确保子弹有碰撞体
+            let collider = bullet.getComponent(CircleCollider2D);
+            if (!collider) {
+                collider = bullet.addComponent(CircleCollider2D);
+                collider.radius = 5; // 设置适当的半径
+                collider.tag = 3; // 子弹标签
+                collider.group = 1; // 与其他物体同组
+                collider.sensor = false;
+                collider.friction = 0;
+                collider.restitution = 1;
+            }
+            
+            // 添加自动销毁逻辑
+            this.scheduleOnce(() => {
+                if (bullet && bullet.isValid) {
+                    bullet.destroy();
+                }
+            }, 5); // 5秒后销毁子弹
+        }
     }
-
 } 

Некоторые файлы не были показаны из-за большого количества измененных файлов