Browse Source

敌人攻击墙体尝试优化

181404010226 2 months ago
parent
commit
3a0eec77c4

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


+ 53 - 16
assets/scripts/CombatSystem/EnemyController.ts

@@ -58,6 +58,18 @@ export class EnemyController extends BaseSingleton {
     @property({ type: Node, tooltip: '拖拽 BottomFence 节点到这里' })
     public bottomFenceNode: Node = null;
 
+    @property({ 
+        type: Node, 
+        tooltip: '拖拽 Line5 节点到这里 (Canvas/GameLevelUI/enemyContainer/Line5)' 
+    })
+    public line5Node: Node = null;
+
+    @property({ 
+        type: Node, 
+        tooltip: '拖拽 Line6 节点到这里 (Canvas/GameLevelUI/enemyContainer/Line6)' 
+    })
+    public line6Node: Node = null;
+
     // 关卡配置管理器节点
     @property({
         type: Node,
@@ -667,22 +679,47 @@ export class EnemyController extends BaseSingleton {
         let driftWorldX = spawnWorldX;
         let driftWorldY = spawnWorldY;
         
-        // 获取屏幕边界(Canvas边界)
-        const canvas = find('Canvas');
-        if (canvas) {
-            const canvasUI = canvas.getComponent(UITransform);
-            if (canvasUI) {
-                const screenHeight = canvasUI.height;
-                const canvasWorldPos = canvas.worldPosition;
-                
-                if (fromTop) {
-                    // 从Line1生成,漂移到屏幕上边界位置-30px
-                    const screenTop = canvasWorldPos.y + screenHeight / 2;
-                    driftWorldY = screenTop - 30;
-                } else {
-                    // 从Line2生成,漂移到屏幕下边界位置+30px
-                    const screenBottom = canvasWorldPos.y - screenHeight / 2;
-                    driftWorldY = screenBottom + 30;
+        // 获取漂移目标线节点
+        let targetLineNode: Node = null;
+        if (fromTop) {
+            // 从Line1生成,漂移到Line5
+            targetLineNode = this.line5Node || enemyContainer.getChildByName('Line5');
+            console.log(`[EnemyController] 从Line1生成敌人,查找Line5节点: this.line5Node=${!!this.line5Node}, 通过名称查找=${!!enemyContainer.getChildByName('Line5')}`);
+        } else {
+            // 从Line2生成,漂移到Line6
+            targetLineNode = this.line6Node || enemyContainer.getChildByName('Line6');
+            console.log(`[EnemyController] 从Line2生成敌人,查找Line6节点: this.line6Node=${!!this.line6Node}, 通过名称查找=${!!enemyContainer.getChildByName('Line6')}`);
+        }
+        
+        if (targetLineNode && targetLineNode.isValid) {
+            // 使用目标线的Y坐标作为漂移目标
+            driftWorldY = targetLineNode.worldPosition.y;
+            console.log(`[EnemyController] 使用新逻辑:目标线节点找到`);
+            console.log(`[EnemyController] 节点名称: ${targetLineNode.name}`);
+            console.log(`[EnemyController] 本地坐标Y: ${targetLineNode.position.y}`);
+            console.log(`[EnemyController] 世界坐标Y: ${targetLineNode.worldPosition.y}`);
+            console.log(`[EnemyController] 漂移目标Y坐标: ${driftWorldY}`);
+        } else {
+            console.log(`[EnemyController] 目标线节点未找到或无效,使用旧逻辑(屏幕边界)`);
+            // 如果找不到目标线节点,回退到原来的屏幕边界逻辑
+            const canvas = find('Canvas');
+            if (canvas) {
+                const canvasUI = canvas.getComponent(UITransform);
+                if (canvasUI) {
+                    const screenHeight = canvasUI.height;
+                    const canvasWorldPos = canvas.worldPosition;
+                    
+                    if (fromTop) {
+                        // 从Line1生成,漂移到屏幕上边界位置-30px
+                        const screenTop = canvasWorldPos.y + screenHeight / 2;
+                        driftWorldY = screenTop - 30;
+                        console.log(`[EnemyController] 旧逻辑:从Line1漂移到屏幕上边界,Y坐标: ${driftWorldY}`);
+                    } else {
+                        // 从Line2生成,漂移到屏幕下边界位置+30px
+                        const screenBottom = canvasWorldPos.y - screenHeight / 2;
+                        driftWorldY = screenBottom + 30;
+                        console.log(`[EnemyController] 旧逻辑:从Line2漂移到屏幕下边界,Y坐标: ${driftWorldY}`);
+                    }
                 }
             }
         }

+ 29 - 10
assets/scripts/CombatSystem/EnemyInstance.ts

@@ -351,16 +351,41 @@ export class EnemyInstance extends Component {
     onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
         const nodeName = otherCollider.node.name;
         
-        // 如果碰到墙体,停止移动并开始攻击
-        if (nodeName.includes('Wall') || nodeName.includes('wall') || nodeName.includes('Fence') || nodeName.includes('Jiguang')) {
+        console.log(`[EnemyInstance] 敌人 ${this.getEnemyName()} 碰撞检测 - 碰撞对象: ${nodeName}, 当前状态: ${EnemyState[this.state]}`);
+        
+        // 只有在移动状态下才能切换到攻击状态,避免重复触发
+        if (this.state !== EnemyState.MOVING) {
+            return;
+        }
+        
+        // 检查是否碰到墙体(更严格的墙体识别)
+        const isWall = this.isWallNode(otherCollider.node);
+        if (isWall) {
+            console.log(`[EnemyInstance] 敌人 ${this.getEnemyName()} 碰撞到墙体 ${nodeName},切换到攻击状态`);
+            
             this.state = EnemyState.ATTACKING;
             this.attackTimer = 0; // 立即开始攻击
+            this.collidedWall = otherCollider.node; // 记录碰撞的墙体
             
             // 切换攻击动画
             this.playAttackAnimation();
         }
     }
     
+    // 检查节点是否为墙体
+    private isWallNode(node: Node): boolean {
+        const nodeName = node.name.toLowerCase();
+        
+        // 检查节点名称是否包含墙体关键词
+        const wallKeywords = ['wall', 'fence', 'jiguang', '墙', '围栏'];
+        const isWallByName = wallKeywords.some(keyword => nodeName.includes(keyword));
+        
+        // 检查节点是否有Wall组件
+        const hasWallComponent = node.getComponent('Wall') !== null;
+        
+        return isWallByName || hasWallComponent;
+    }
+    
     // 获取节点路径
     getNodePath(node: Node): string {
         let path = node.name;
@@ -608,14 +633,8 @@ export class EnemyInstance extends Component {
         const dir = targetWorldPos.subtract(currentWorldPos);
         const distanceToTarget = dir.length();
         
-        // 如果距离目标很近,停止移动并切换到攻击状态
-        const stopDistance = 30; // 停止距离,可以根据需要调整
-        if (distanceToTarget <= stopDistance) {
-            this.state = EnemyState.ATTACKING;
-            this.attackTimer = 0; // 立即开始攻击
-            this.playAttackAnimation();
-            return;
-        }
+        // 移除基于距离的攻击触发逻辑,只通过碰撞回调触发攻击
+        // 这样可以确保攻击触发的准确性,避免位置计算误差
         
         if (distanceToTarget === 0) return;
         dir.normalize();

+ 38 - 1
assets/scripts/CombatSystem/Wall.ts

@@ -1,4 +1,4 @@
-import { _decorator, Component, Node, Label, find, JsonAsset } from 'cc';
+import { _decorator, Component, Node, Label, find, JsonAsset, Collider2D, RigidBody2D, ERigidBody2DType, BoxCollider2D } from 'cc';
 import { SaveDataManager } from '../LevelSystem/SaveDataManager';
 import EventBus, { GameEvents } from '../Core/EventBus';
 import { JsonConfigLoader } from '../Core/JsonConfigLoader';
@@ -75,6 +75,40 @@ export class Wall extends Component {
         };
     }
 
+    /**
+     * 设置墙体碰撞器
+     * 确保墙体能够与敌人发生碰撞
+     */
+    private setupWallCollider(): void {
+        // 检查是否已有碰撞器组件
+        let collider = this.node.getComponent(Collider2D);
+        if (!collider) {
+            // 添加BoxCollider2D组件
+            collider = this.node.addComponent(BoxCollider2D);
+            console.log(`[Wall] 为墙体节点 ${this.node.name} 添加碰撞器组件`);
+        }
+
+        // 确保有RigidBody2D组件
+        let rigidBody = this.node.getComponent(RigidBody2D);
+        if (!rigidBody) {
+            rigidBody = this.node.addComponent(RigidBody2D);
+            console.log(`[Wall] 为墙体节点 ${this.node.name} 添加刚体组件`);
+        }
+
+        // 设置刚体属性
+        if (rigidBody) {
+            rigidBody.type = ERigidBody2DType.Static; // 静态刚体
+            rigidBody.enabledContactListener = true; // 启用碰撞监听
+        }
+
+        // 设置碰撞器属性
+        if (collider) {
+            collider.sensor = false; // 不是传感器,会产生物理碰撞
+        }
+
+        console.log(`[Wall] 墙体 ${this.node.name} 碰撞器设置完成,碰撞器启用: ${collider?.enabled}, 刚体启用: ${rigidBody?.enabled}`);
+    }
+
     /**
      * 初始化墙体
      */
@@ -98,6 +132,9 @@ export class Wall extends Component {
         // 初始化血量显示
         this.updateHealthDisplay();
         
+        // 设置墙体碰撞器
+        this.setupWallCollider();
+        
         // 监听治疗技能变化
         this.setupSkillListeners();
         

+ 8 - 8
assets/scripts/Core/PhysicsManager.ts

@@ -22,14 +22,14 @@ export class PhysicsManager extends BaseSingleton {
         // 设置物理系统的重力为零(因为是2D平面游戏)
         PhysicsSystem2D.instance.gravity = new Vec2(0, 0);
         
-        // // 调试绘制
-        // PhysicsSystem2D.instance.debugDrawFlags = this.debugDraw ?
-        //     (EPhysics2DDrawFlags.Aabb |
-        //      EPhysics2DDrawFlags.Pair |
-        //      EPhysics2DDrawFlags.CenterOfMass |
-        //      EPhysics2DDrawFlags.Joint |
-        //      EPhysics2DDrawFlags.Shape) :
-        //     EPhysics2DDrawFlags.None;
+        // 调试绘制
+        PhysicsSystem2D.instance.debugDrawFlags = this.debugDraw ?
+            (EPhysics2DDrawFlags.Aabb |
+             EPhysics2DDrawFlags.Pair |
+             EPhysics2DDrawFlags.CenterOfMass |
+             EPhysics2DDrawFlags.Joint |
+             EPhysics2DDrawFlags.Shape) :
+            EPhysics2DDrawFlags.None;
     }
 
     /**

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