ソースを参照

锯齿草弹射优化

181404010226 3 ヶ月 前
コミット
c32b2d4914

+ 125 - 88
assets/scripts/CombatSystem/BulletEffects/BulletHitEffect.ts

@@ -35,6 +35,10 @@ export class BulletHitEffect extends Component {
     private detectionCollider: CircleCollider2D | null = null;
     private detectedEnemies: Set<Node> = new Set();
     
+    // 锯齿草子弹状态管理
+    private hasFirstHit: boolean = false;  // 是否已经首次击中敌人
+    private currentTargetEnemy: Node | null = null;  // 当前击中的目标敌人
+    
     // 默认特效路径(从WeaponBullet传入)
     private defaultHitEffectPath: string = '';
     private defaultTrailEffectPath: string = '';
@@ -53,6 +57,9 @@ export class BulletHitEffect extends Component {
         // 按优先级排序
         this.hitEffects = [...effects].sort((a, b) => a.priority - b.priority);
         
+        // 重置锯齿草状态
+        this.resetSawGrassState();
+        
         // 检查是否有手动添加的检测范围碰撞器
         this.setupDetectionColliderEvents();
     }
@@ -64,8 +71,16 @@ export class BulletHitEffect extends Component {
         // 检查是否是弹射后的命中
         const isRicochetHit = this.ricochetCount > 0;
         const hitType = isRicochetHit ? '弹射命中' : '直接命中';
+                
+        // 锯齿草子弹首次击中逻辑
+        const weaponBullet = this.getComponent(WeaponBullet);
+        const weaponInfo = weaponBullet ? weaponBullet.getWeaponInfo() : null;
+        const weaponId = weaponInfo ? weaponInfo.getWeaponId() : null;
         
-        console.log(`💥 [${hitType}] 处理命中 - 目标: ${hitNode.name}, 位置: (${contactPos.x.toFixed(1)}, ${contactPos.y.toFixed(1)}), 弹射次数: ${this.ricochetCount}, 效果数量: ${this.hitEffects.length}`);
+        if (weaponId === 'saw_grass' && !this.hasFirstHit && this.isEnemyNode(hitNode)) {
+            this.hasFirstHit = true;
+            this.currentTargetEnemy = hitNode;
+        }
         
         this.hitCount++;
         
@@ -96,12 +111,7 @@ export class BulletHitEffect extends Component {
         } else if (result.shouldRicochet) {
             result.shouldContinue = false;
         }
-        
-        // 输出命中结果
-        if (isRicochetHit) {
-            console.log(`✅ [弹射成功] 弹射子弹成功击中敌人: ${hitNode.name}, 造成伤害: ${result.damageDealt.toFixed(1)}, 是否继续弹射: ${result.shouldRicochet}`);
-        }
-        
+
         return result;
     }
     
@@ -132,7 +142,6 @@ export class BulletHitEffect extends Component {
                 break;
                 
             case 'ground_burn':
-                console.log(`[BulletHitEffect] 触发灼烧效果处理`);
                 this.processGroundBurn(effect, hitNode);
                 break;
                 
@@ -154,9 +163,7 @@ export class BulletHitEffect extends Component {
         // 使用WeaponBullet的最终伤害值而不是配置中的基础伤害
         const weaponBullet = this.getComponent(WeaponBullet);
         const damage = weaponBullet ? weaponBullet.getFinalDamage() : (effect.damage || 0);
-        
-        console.log(`[BulletHitEffect] 普通伤害处理 - 配置伤害: ${effect.damage || 0}, 最终伤害: ${damage}`);
-        
+                
         this.damageEnemy(hitNode, damage);
         this.spawnHitEffect(hitNode.worldPosition);
         return damage;
@@ -169,9 +176,7 @@ export class BulletHitEffect extends Component {
         // 使用WeaponBullet的最终伤害值而不是配置中的基础伤害
         const weaponBullet = this.getComponent(WeaponBullet);
         const damage = weaponBullet ? weaponBullet.getFinalDamage() : (effect.damage || 0);
-        
-        console.log(`[BulletHitEffect] 穿透伤害处理 - 配置伤害: ${effect.damage || 0}, 最终伤害: ${damage}`);
-        
+                
         this.damageEnemy(hitNode, damage);
         this.spawnHitEffect(hitNode.worldPosition);
         this.pierceCount++;
@@ -185,9 +190,7 @@ export class BulletHitEffect extends Component {
         // 使用WeaponBullet的最终伤害值而不是配置中的基础伤害
         const weaponBullet = this.getComponent(WeaponBullet);
         const explosionDamage = weaponBullet ? weaponBullet.getFinalDamage() : (effect.damage || 0);
-        
-        console.log(`[BulletHitEffect] 爆炸伤害处理 - 配置伤害: ${effect.damage || 0}, 最终伤害: ${explosionDamage}`);
-        
+                
         const scheduleExplosion = () => {
             // 播放爆炸音效
             this.playAttackSound();
@@ -211,9 +214,7 @@ export class BulletHitEffect extends Component {
     /**
      * 处理地面燃烧区域效果
      */
-    private processGroundBurn(effect: HitEffectConfig, hitNode: Node) {
-        console.log(`[BulletHitEffect] processGroundBurn 被调用 - 创建地面燃烧区域`);
-        
+    private processGroundBurn(effect: HitEffectConfig, hitNode: Node) {        
         // 获取地面燃烧区域管理器
         const burnAreaManager = GroundBurnAreaManager.getInstance();
         if (!burnAreaManager) {
@@ -228,9 +229,7 @@ export class BulletHitEffect extends Component {
         if (this.isEnemyNode(hitNode)) {
             burnPosition.set(hitNode.worldPosition);
         }
-        
-        console.log(`[BulletHitEffect] 在位置 (${burnPosition.x.toFixed(1)}, ${burnPosition.y.toFixed(1)}) 创建地面燃烧区域 - 持续时间: ${effect.duration}秒, 伤害: ${effect.damage}, 间隔: ${effect.tickInterval}秒`);
-        
+                
         try {
             // 获取武器子弹组件
             const weaponBullet = this.getComponent(WeaponBullet);
@@ -246,9 +245,7 @@ export class BulletHitEffect extends Component {
             if (burnAreaNode) {
                 // 将燃烧区域添加到活跃列表中
                 this.activeBurnAreas.push(burnAreaNode);
-                console.log(`[BulletHitEffect] 地面燃烧区域已通过管理器创建`);
-            }
-            
+            }        
         } catch (error) {
             console.error('[BulletHitEffect] 通过管理器创建地面燃烧区域失败:', error);
         }
@@ -263,9 +260,7 @@ export class BulletHitEffect extends Component {
         // 使用WeaponBullet的最终伤害值而不是配置中的基础伤害
         const weaponBullet = this.getComponent(WeaponBullet);
         const damage = weaponBullet ? weaponBullet.getFinalDamage() : (effect.damage || 0);
-        
-        console.log(`[BulletHitEffect] 弹射伤害处理 - 当前弹射次数: ${this.ricochetCount}, 最大弹射次数: ${effect.ricochetCount}, 配置伤害: ${effect.damage || 0}, 最终伤害: ${damage}`);
-        
+                
         this.damageEnemy(hitNode, damage);
         
         // 检查是否还能继续弹射
@@ -273,10 +268,9 @@ export class BulletHitEffect extends Component {
             this.ricochetCount++;
             
             // 计算弹射方向
-            console.log(`[BulletHitEffect] 执行弹射 - 弹射次数: ${this.ricochetCount}/${effect.ricochetCount}, 弹射角度: ${effect.ricochetAngle}`);
             this.calculateRicochetDirection(effect.ricochetAngle);
         } else {
-            console.log(`[BulletHitEffect] 弹射次数已达上限,不再弹射`);
+            //console.log(`[BulletHitEffect] 弹射次数已达上限,不再弹射`);
         }
         
         return damage;
@@ -295,8 +289,15 @@ export class BulletHitEffect extends Component {
         const weaponId = weaponInfo ? weaponInfo.getWeaponId() : null;
         const detectionRange = weaponId ? this.getDetectionRange(weaponId) : 500;
         
-        // 寻找最近的敌人作为弹射目标(在指定范围内)
-        const nearestEnemy = this.findNearestEnemy(detectionRange);
+        let nearestEnemy: Node | null = null;
+        
+        // 锯齿草武器使用专门的CircleCollider2D实时追踪逻辑
+        if (weaponId === 'saw_grass') {
+            nearestEnemy = this.findNearestEnemyForSawGrass(detectionRange);
+        } else {
+            // 其他武器使用原有的实时计算方法
+            nearestEnemy = this.findNearestEnemy(detectionRange);
+        }
         
         let newDirection: Vec3;
         
@@ -320,7 +321,7 @@ export class BulletHitEffect extends Component {
                 0
             ).normalize();
             
-            console.log(`🚀 [弹射执行] 智能弹射追踪敌人: ${nearestEnemy.name}, 距离: ${Vec3.distance(bulletPos, enemyPos).toFixed(1)}, 检测范围: ${detectionRange}, 偏移角度: ${(angleRad * 180 / Math.PI).toFixed(1)}°`);
+            const weaponType = weaponId === 'saw_grass' ? '锯齿草CircleCollider2D' : '实时计算';
         } else {
             // 如果没有找到敌人,使用随机方向(保持原有逻辑)
             const currentVel = trajectory.getCurrentVelocity();
@@ -334,7 +335,7 @@ export class BulletHitEffect extends Component {
                 0
             ).normalize();
             
-            console.log(`🎲 [弹射执行] 检测范围${detectionRange}内未找到敌人,使用随机弹射方向`);
+            const weaponType = weaponId === 'saw_grass' ? '锯齿草CircleCollider2D' : '实时计算';
         }
         
         // 使用弹道组件的changeDirection方法
@@ -372,7 +373,6 @@ export class BulletHitEffect extends Component {
                 // 暴击伤害 = 基础伤害 × (1 + 暴击伤害倍率),默认暴击倍率100%
                 const critDamage = Math.ceil((baseDamage * (1 + 1.0)) * 10) / 10; // 向上取整到一位小数
                 this.showCriticalHitEffect();
-                console.log(`[BulletHitEffect] 暴击!基础伤害: ${baseDamage}, 暴击伤害: ${critDamage}, 暴击率: ${(critChance * 100).toFixed(1)}%`);
                 return { damage: critDamage, isCritical: true };
             }
             return { damage: baseDamage, isCritical: false };
@@ -393,9 +393,7 @@ export class BulletHitEffect extends Component {
             
             // 显示暴击特效
             this.showCriticalHitEffect();
-            
-            console.log(`[BulletHitEffect] 暴击!基础伤害: ${baseDamage}, 暴击倍率: ${(critDamageMultiplier * 100).toFixed(1)}%, 暴击伤害: ${critDamage}, 暴击率: ${(critChance * 100).toFixed(1)}%`);
-            
+                        
             return { damage: critDamage, isCritical: true };
         }
         
@@ -440,7 +438,6 @@ export class BulletHitEffect extends Component {
             
             // 播放攻击音效
             const attackSoundPath = weaponConfig.visualConfig.attackSound;
-            console.log(`[BulletHitEffect] 播放攻击音效: ${attackSoundPath}`);
             Audio.playWeaponSound(attackSoundPath);
             
         } catch (error) {
@@ -524,7 +521,6 @@ export class BulletHitEffect extends Component {
             return false;
         }
         const name = node.name.toLowerCase();
-        console.log("敌人名字",name);
         return name.includes('enemy') || 
                name.includes('敌人');
     }
@@ -547,49 +543,70 @@ export class BulletHitEffect extends Component {
     /**
      * 寻找最近的敌人(在指定范围内)
      */
-    private findNearestEnemy(maxRange: number = 500): Node | null {
-        const weaponBullet = this.getComponent(WeaponBullet);
-        const weaponInfo = weaponBullet ? weaponBullet.getWeaponInfo() : null;
-        const weaponId = weaponInfo ? weaponInfo.getWeaponId() : null;
+    /**
+     * 锯齿草武器专用的敌人查找方法 - 基于CircleCollider2D检测并实时追踪
+     */
+    private findNearestEnemyForSawGrass(maxRange: number = 500): Node | null {        
+        // 如果还没有首次击中敌人,不使用CircleCollider检测到的敌人
+        if (!this.hasFirstHit) {
+            console.log(`⏳ [锯齿草弹射] 尚未首次击中敌人,暂不启用CircleCollider追踪`);
+            return null;
+        }
         
-        // 对于锯齿草武器,优先使用CircleCollider2D检测到的敌人
-        if (weaponId === 'saw_grass') {
-            console.log(`🔍 [调试] 锯齿草武器弹射检测 - detectedEnemies数量: ${this.detectedEnemies.size}, detectionCollider存在: ${!!this.detectionCollider}`);
-            console.log(`🔍 [调试] 锯齿草武器弹射检测 - detectedEnemies数量: ${this.detectedEnemies.size}, detectionCollider存在: ${this.detectionCollider.node.name}`);
-            
-            if (this.detectedEnemies.size > 0) {
-                console.log(`[BulletHitEffect] 锯齿草武器使用CircleCollider2D检测到的敌人 - 数量: ${this.detectedEnemies.size}`);
-                
-                const currentPos = this.node.worldPosition;
-                let nearestEnemy: Node | null = null;
-                let nearestDistance = Infinity;
-                
-                // 从检测到的敌人中找最近的
-                for (const enemy of this.detectedEnemies) {
-                    if (enemy && enemy.isValid && enemy.active) {
-                        const distance = Vec3.distance(currentPos, enemy.worldPosition);
-                        console.log(`🔍 [调试] 检查检测到的敌人: ${enemy.name}, 距离: ${distance.toFixed(1)}, 有效: ${enemy.isValid}, 激活: ${enemy.active}`);
-                        if (distance < nearestDistance && distance <= maxRange) {
-                            nearestDistance = distance;
-                            nearestEnemy = enemy;
-                        }
-                    } else {
-                        console.log(`⚠️ [调试] 检测到的敌人无效: ${enemy ? enemy.name : 'null'}, 有效: ${enemy ? enemy.isValid : 'N/A'}, 激活: ${enemy ? enemy.active : 'N/A'}`);
-                    }
+        // 清理无效的敌人节点
+        const invalidEnemies = new Set<Node>();
+        for (const enemy of this.detectedEnemies) {
+            if (!enemy || !enemy.isValid || !enemy.active) {
+                invalidEnemies.add(enemy);
+            }
+        }
+        
+        // 移除无效敌人
+        for (const invalidEnemy of invalidEnemies) {
+            this.detectedEnemies.delete(invalidEnemy);
+        }
+        
+        if (this.detectedEnemies.size === 0) {
+            return null;
+        }
+        
+        const currentPos = this.node.worldPosition;
+        let nearestEnemy: Node | null = null;
+        let nearestDistance = Infinity;
+        
+        // 实时计算每个检测到敌人的当前位置,排除当前目标敌人
+        for (const enemy of this.detectedEnemies) {
+            if (enemy && enemy.isValid && enemy.active) {
+                // 排除当前击中的目标敌人
+                if (this.currentTargetEnemy && enemy === this.currentTargetEnemy) {
+                    continue;
                 }
                 
-                if (nearestEnemy) {
-                    console.log(`🎯 [弹射追踪] 通过CircleCollider2D找到最近敌人 - 检测范围: ${maxRange}, 找到敌人: ${nearestEnemy.name}, 距离: ${nearestDistance.toFixed(1)}`);
-                    return nearestEnemy;
-                } else {
-                    console.log(`⚠️ [调试] CircleCollider2D检测到敌人但都不在范围内或无效`);
+                // 获取敌人的实时位置
+                const enemyCurrentPos = enemy.worldPosition;
+                const distance = Vec3.distance(currentPos, enemyCurrentPos);
+                                
+                // 检查是否在范围内且是最近的
+                if (distance <= maxRange && distance < nearestDistance) {
+                    nearestDistance = distance;
+                    nearestEnemy = enemy;
                 }
-            } else {
-                console.log(`⚠️ [调试] 锯齿草武器但detectedEnemies为空,将使用实时计算`);
             }
         }
         
-        // 回退到原有的实时计算方法(用于非锯齿草武器或检测范围内无敌人的情况)
+        if (nearestEnemy) {
+        } else {
+            console.log(`❌ [锯齿草弹射] 检测到的敌人都超出范围或无效,或都是当前目标敌人`);
+        }
+        
+        return nearestEnemy;
+    }
+    
+    /**
+     * 通用的敌人查找方法 - 用于非锯齿草武器
+     */
+    private findNearestEnemy(maxRange: number = 500): Node | null {
+        // 回退到原有的实时计算方法(用于非锯齿草武器)
         const enemyContainer = find('Canvas/GameLevelUI/enemyContainer');
         if (!enemyContainer) return null;
 
@@ -615,9 +632,7 @@ export class BulletHitEffect extends Component {
                 nearest = enemy;
             }
         }
-        
-        console.log(`⚡ [实时计算] 通过实时计算找到最近敌人 - 检测范围: ${maxRange}, 找到敌人: ${nearest ? nearest.name : '无'}, 距离: ${nearest ? nearestDist.toFixed(1) : 'N/A'}`);
-        
+                
         return nearest;
     }
     
@@ -714,9 +729,7 @@ export class BulletHitEffect extends Component {
      */
     onDestroy() {
         // 不再强制销毁燃烧区域,让它们按照自己的持续时间自然销毁
-        // 燃烧区域现在由GroundBurnAreaManager统一管理,有自己的生命周期
-        console.log(`[BulletHitEffect] 子弹销毁,但不会影响已创建的${this.activeBurnAreas.length}个燃烧区域`);
-        
+        // 燃烧区域现在由GroundBurnAreaManager统一管理,有自己的生命周期        
         // 只清空引用,不销毁燃烧区域节点
         this.activeBurnAreas = [];
         
@@ -729,6 +742,9 @@ export class BulletHitEffect extends Component {
         
         // 清理检测到的敌人集合
         this.detectedEnemies.clear();
+        
+        // 重置锯齿草状态
+        this.resetSawGrassState();
     }
     
     /**
@@ -751,8 +767,6 @@ export class BulletHitEffect extends Component {
                 // 启用碰撞监听 - Cocos Creator 3.8.6正确的事件类型
                 this.detectionCollider.on(Contact2DType.BEGIN_CONTACT, this.onDetectionEnter, this);
                 this.detectionCollider.on(Contact2DType.END_CONTACT, this.onDetectionExit, this);
-                
-                console.log(`[BulletHitEffect] 找到手动添加的检测范围碰撞器,位置: ${collider.node.name}, 半径: ${this.detectionCollider.radius}, tag: ${this.detectionCollider.tag}`);
                 break;
             }
         }
@@ -767,11 +781,19 @@ export class BulletHitEffect extends Component {
      */
     private onDetectionEnter(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
         const otherNode = otherCollider.node;
-        console.log("🎯 [CircleCollider2D检测]");
 
         if (this.isEnemyNode(otherNode)) {
+            // 获取武器信息,确认是否为锯齿草武器
+            const weaponBullet = this.getComponent(WeaponBullet);
+            const weaponInfo = weaponBullet ? weaponBullet.getWeaponInfo() : null;
+            const weaponId = weaponInfo ? weaponInfo.getWeaponId() : null;
+            
+            // 对于锯齿草武器,记录所有检测到的敌人,但在弹射时会根据hasFirstHit状态进行过滤
             this.detectedEnemies.add(otherNode);
-            console.log(`🎯 [CircleCollider2D检测] 敌人进入检测范围: ${otherNode.name}, 当前检测到敌人数量: ${this.detectedEnemies.size}`);
+            
+            if (weaponId === 'saw_grass') {
+                const hitStatus = this.hasFirstHit ? '已首次击中' : '尚未首次击中';
+            }
         }
     }
     
@@ -782,7 +804,15 @@ export class BulletHitEffect extends Component {
         const otherNode = otherCollider.node;
         if (this.isEnemyNode(otherNode)) {
             this.detectedEnemies.delete(otherNode);
-            console.log(`🚫 [CircleCollider2D检测] 敌人离开检测范围: ${otherNode.name}, 当前检测到敌人数量: ${this.detectedEnemies.size}`);
+            
+            // 获取武器信息,确认是否为锯齿草武器
+            const weaponBullet = this.getComponent(WeaponBullet);
+            const weaponInfo = weaponBullet ? weaponBullet.getWeaponInfo() : null;
+            const weaponId = weaponInfo ? weaponInfo.getWeaponId() : null;
+            
+            if (weaponId === 'saw_grass') {
+                console.log(`🌿 [锯齿草检测] 锯齿草武器敌人离开: ${otherNode.name}`);
+            }
         }
     }
     
@@ -818,5 +848,12 @@ export class BulletHitEffect extends Component {
         }
     }
     
+    /**
+     * 重置锯齿草状态
+     */
+    private resetSawGrassState() {
+        this.hasFirstHit = false;
+        this.currentTargetEnemy = null;
+    }
 
 }

+ 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;
     }
 
     /**