181404010226 5 ماه پیش
والد
کامیت
46e3f1cfac

+ 42 - 42
assets/resources/data/weapons.json

@@ -247,17 +247,17 @@
         },
         "visual": {
           "bulletPrefab": "bullets/WatermelonBomb",
-          "hitEffect": "Animation/WeaponTx/tx0004/tx0004",
-          "trailEffect": "Animation/WeaponTx/tx0004/tx0004",
-          "muzzleFlash": "Animation/WeaponTx/tx0004/tx0004"
+          "hitEffect": "Animation/WeaponTx/tx0007/tx0007",
+          "trailEffect": "Animation/WeaponTx/tx0007/tx0007",
+          "muzzleFlash": "Animation/WeaponTx/tx0007/tx0007"
         }
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/004",
-          "1x2": "images/PlantsSprite/004",
-          "2x1": "images/PlantsSprite/004",
-          "2x2": "images/PlantsSprite/004"
+          "1x1": "images/PlantsSprite/007",
+          "1x2": "images/PlantsSprite/007",
+          "2x1": "images/PlantsSprite/007",
+          "2x2": "images/PlantsSprite/007"
         },
         "fireSound": "audio/bomb_launch"
       }
@@ -284,11 +284,11 @@
           "burstDelay": 0
         },
         "trajectory": {
-          "type": "arc",
+          "type": "homing_arc",
           "speed": 150,
-          "gravity": 0,
+          "gravity": 0.3,
           "arcHeight": 50,
-          "homingStrength": 0,
+          "homingStrength": 0.8,
           "homingDelay": 0
         },
         "hitEffects": [
@@ -312,17 +312,17 @@
         },
         "visual": {
           "bulletPrefab": "bullets/BoomerangBullet",
-          "hitEffect": "Animation/WeaponTx/tx0005/tx0005",
-          "trailEffect": "Animation/WeaponTx/tx0005/tx0005",
-          "muzzleFlash": "Animation/WeaponTx/tx0005/tx0005"
+          "hitEffect": "Animation/WeaponTx/tx0004/tx0004",
+          "trailEffect": "Animation/WeaponTx/tx0004/tx0004",
+          "muzzleFlash": "Animation/WeaponTx/tx0004/tx0004"
         }
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/005",
-          "1x2": "images/PlantsSprite/005",
-          "2x1": "images/PlantsSprite/005",
-          "2x2": "images/PlantsSprite/005"
+          "1x1": "images/PlantsSprite/004",
+          "1x2": "images/PlantsSprite/004",
+          "2x1": "images/PlantsSprite/004",
+          "2x2": "images/PlantsSprite/004"
         },
         "fireSound": "audio/boomerang_throw"
       }
@@ -349,10 +349,10 @@
           "burstDelay": 0
         },
         "trajectory": {
-          "type": "parabolic",
+          "type": "straight",
           "speed": 100,
-          "gravity": 0.6,
-          "arcHeight": 80,
+          "gravity": 0,
+          "arcHeight": 0,
           "homingStrength": 0,
           "homingDelay": 0
         },
@@ -387,18 +387,18 @@
         },
         "visual": {
           "bulletPrefab": "bullets/PepperBomb",
-          "hitEffect": "Animation/WeaponTx/tx0006/tx0006",
-          "trailEffect": "Animation/WeaponTx/tx0006/tx0006",
-          "burnEffect": "Animation/WeaponTx/tx0006/tx0006",
-          "muzzleFlash": "Animation/WeaponTx/tx0006/tx0006"
+          "hitEffect": "Animation/WeaponTx/tx0005/tx0005",
+          "trailEffect": "Animation/WeaponTx/tx0005/tx0005",
+          "burnEffect": "Animation/WeaponTx/tx0005/tx0005",
+          "muzzleFlash": "Animation/WeaponTx/tx0005/tx0005"
         }
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/006",
-          "1x2": "images/PlantsSprite/006",
-          "2x1": "images/PlantsSprite/006",
-          "2x2": "images/PlantsSprite/006"
+          "1x1": "images/PlantsSprite/005",
+          "1x2": "images/PlantsSprite/005",
+          "2x1": "images/PlantsSprite/005",
+          "2x2": "images/PlantsSprite/005"
         },
         "fireSound": "audio/pepper_launch"
       }
@@ -451,17 +451,17 @@
         },
         "visual": {
           "bulletPrefab": "bullets/CactusBullet",
-          "hitEffect": "Animation/WeaponTx/tx0007/tx0007",
-          "trailEffect": "Animation/WeaponTx/tx0007/tx0007",
-          "muzzleFlash": "Animation/WeaponTx/tx0007/tx0007"
+          "hitEffect": "Animation/WeaponTx/tx0008/tx0008",
+          "trailEffect": "Animation/WeaponTx/tx0008/tx0008",
+          "muzzleFlash": "Animation/WeaponTx/tx0008/tx0008"
         }
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/007",
-          "1x2": "images/PlantsSprite/007",
-          "2x1": "images/PlantsSprite/007",
-          "2x2": "images/PlantsSprite/007"
+          "1x1": "images/PlantsSprite/008",
+          "1x2": "images/PlantsSprite/008",
+          "2x1": "images/PlantsSprite/008",
+          "2x2": "images/PlantsSprite/008"
         },
         "fireSound": "audio/cactus_shot"
       }
@@ -515,17 +515,17 @@
         },
         "visual": {
           "bulletPrefab": "bullets/OkraMissile",
-          "hitEffect": "Animation/WeaponTx/tx0004/tx0004",
-          "trailEffect": "Animation/WeaponTx/tx0007/tx0007",
-          "muzzleFlash": "Animation/WeaponTx/tx0004/tx0004"
+          "hitEffect": "Animation/WeaponTx/tx0006/tx0006",
+          "trailEffect": "Animation/WeaponTx/tx0006/tx0006",
+          "muzzleFlash": "Animation/WeaponTx/tx0006/tx0006"
         }
       },
       "visualConfig": {
         "weaponSprites": {
-          "1x1": "images/PlantsSprite/008",
-          "1x2": "images/PlantsSprite/008-1",
-          "2x1": "images/PlantsSprite/008-1",
-          "2x2": "images/PlantsSprite/008-1"
+          "1x1": "images/PlantsSprite/006",
+          "1x2": "images/PlantsSprite/006",
+          "2x1": "images/PlantsSprite/006",
+          "2x2": "images/PlantsSprite/006"
         },
         "fireSound": "audio/missile_launch"
       }

+ 7 - 24
assets/scripts/CombatSystem/BallController.ts

@@ -868,16 +868,7 @@ export class BallController extends Component {
                 console.log('方块碰撞体是否启用:', blockCollider.enabled);
             }
             
-            // 检查碰撞矩阵
-            console.log('=== 碰撞矩阵检查 ===');
-            if (ballCollider && blockCollider) {
-                console.log(`小球组${ballCollider.group} 是否能与方块组${blockCollider.group} 碰撞: ${this.checkCollisionMatrix(ballCollider.group, blockCollider.group)}`);
-            }
-            
-            // 检查物理引擎状态
-            console.log('=== 物理引擎状态检查 ===');
-            console.log('物理引擎是否启用:', PhysicsManager.getInstance()?.getSystem().enable);
-            console.log('物理引擎重力:', PhysicsManager.getInstance()?.getSystem().gravity);
+            // (已移除碰撞矩阵与物理引擎状态的冗余调试输出)
         }
     }
     
@@ -897,16 +888,14 @@ export class BallController extends Component {
         const mask1 = collisionMatrix[group1.toString()];
         const mask2 = collisionMatrix[group2.toString()];
         
-        console.log(`组${group1}的碰撞掩码: ${mask1} (二进制: ${mask1?.toString(2)})`);
-        console.log(`组${group2}的碰撞掩码: ${mask2} (二进制: ${mask2?.toString(2)})`);
+        // (调试输出移除)
         
         // 检查group1是否能与group2碰撞
         const canCollide1to2 = mask1 && (mask1 & (1 << group2)) !== 0;
         // 检查group2是否能与group1碰撞
         const canCollide2to1 = mask2 && (mask2 & (1 << group1)) !== 0;
         
-        console.log(`组${group1}->组${group2}: ${canCollide1to2}`);
-        console.log(`组${group2}->组${group1}: ${canCollide2to1}`);
+        // (调试输出移除)
         
         return canCollide1to2 && canCollide2to1;
     }
@@ -994,11 +983,7 @@ export class BallController extends Component {
             "5": 18
         };
         
-        console.log('🔍 === 碰撞矩阵配置 ===');
-        for (const group in collisionMatrix) {
-            const mask = collisionMatrix[group];
-            console.log(`组 ${group}: 掩码 ${mask} (二进制: ${mask?.toString(2)})`);
-        }
+        // (调试输出移除)
         
         // 测试Ball组(1)和Block组(2)是否能碰撞
         const ballMask = collisionMatrix["1"]; // 39
@@ -1007,11 +992,9 @@ export class BallController extends Component {
         const ballCanCollideWithBlock = (ballMask & (1 << 2)) !== 0; // 检查Ball能否与组2碰撞
         const blockCanCollideWithBall = (blockMask & (1 << 1)) !== 0; // 检查Block能否与组1碰撞
         
-        console.log('🎯 碰撞测试结果:');
-        console.log(`Ball组(1) -> Block组(2): ${ballCanCollideWithBlock}`);
-        console.log(`Block组(2) -> Ball组(1): ${blockCanCollideWithBall}`);
-        console.log(`双向碰撞可用: ${ballCanCollideWithBlock && blockCanCollideWithBall}`);
-        console.log('🔍 === 碰撞矩阵分析完成 ===');
+        // (调试输出移除)
+        
+        // (调试输出移除)
     }
 
     /**

+ 0 - 1
assets/scripts/CombatSystem/BlockManager.ts

@@ -1136,7 +1136,6 @@ export class BlockManager extends Component {
             
             if (weaponSprite && spriteFrame) {
                 weaponSprite.spriteFrame = spriteFrame;
-                console.log(`✅ 武器图片加载成功: ${weaponConfig.name} -> ${spriteFramePath}`);
             }
         });
     }

+ 31 - 20
assets/scripts/CombatSystem/BulletEffects/BulletLifecycle.ts

@@ -338,27 +338,38 @@ export class BulletLifecycle extends Component {
      * 检查越界
      */
     private checkOutOfBounds(): boolean {
-        const canvas = find('Canvas');
-        if (!canvas) return false;
-        
-        const uiTransform = canvas.getComponent(UITransform);
-        if (!uiTransform) return false;
-        
-        const halfWidth = uiTransform.width / 2;
-        const halfHeight = uiTransform.height / 2;
-        const center = canvas.worldPosition;
-        
-        const left = center.x - halfWidth;
-        const right = center.x + halfWidth;
-        const bottom = center.y - halfHeight;
-        const top = center.y + halfHeight;
-        
-        // 允许一定的越界容差
-        const margin = 200;
-        
+        // 优先使用 GameArea 的可视区域(若存在)
+        const gameArea = find('Canvas/GameLevelUI/GameArea');
+        let bounding = null;
+        if (gameArea) {
+            const tr = gameArea.getComponent(UITransform);
+            if (tr) {
+                bounding = tr.getBoundingBoxToWorld();
+            }
+        }
+
+        // fallback => Canvas 整体区域
+        if (!bounding) {
+            const canvas = find('Canvas');
+            if (canvas) {
+                const tr = canvas.getComponent(UITransform);
+                if (tr) {
+                    bounding = tr.getBoundingBoxToWorld();
+                }
+            }
+        }
+
+        // 若无法获取区域,则不做越界销毁
+        if (!bounding) return false;
+
+        // 允许一定的 margin
+        const margin = 300; // 扩大容差,防止大速度时瞬移出界
         const pos = this.node.worldPosition;
-        return pos.x < left - margin || pos.x > right + margin || 
-               pos.y < bottom - margin || pos.y > top + margin;
+
+        return pos.x < bounding.xMin - margin ||
+               pos.x > bounding.xMax + margin ||
+               pos.y < bounding.yMin - margin ||
+               pos.y > bounding.yMax + margin;
     }
     
     /**

+ 60 - 28
assets/scripts/CombatSystem/BulletEffects/BulletTrajectory.ts

@@ -93,21 +93,38 @@ export class BulletTrajectory extends Component {
      * 计算抛物线初始速度
      */
     private calculateParabolicVelocity(): Vec2 {
-        const direction = this.state.initialVelocity.clone().normalize();
+        // NOTE:
+        // 1. 当目标位于子弹正上/下方时, 原 direction 的 x 分量可能非常小甚至为 0, 导致 vx≈0, 子弹会几乎垂直运动, 看起来像"钢球"直落。
+        // 2. 对于抛物线/弧线弹道, 我们总是希望子弹具备一个最小的水平速度, 并且保证初速度向上( vy>0 ),
+        //    这样才能形成明显的抛物或弧线效果并最终击中目标。
+
+        const rawDir = this.state.initialVelocity.clone().normalize();
+
+        // 单独提取水平方向, 忽略原始 y 分量, 以保证抛物线始终向前飞行
+        const horizontalDir = new Vec3(rawDir.x, 0, 0);
+
+        // 若水平方向过小, 取发射者面朝方向 (rawDir.x 的符号) 作为水平单位向量
+        if (Math.abs(horizontalDir.x) < 0.01) {
+            horizontalDir.x = rawDir.x >= 0 ? 1 : -1;
+        }
+        horizontalDir.normalize();
+
         const speed = this.config.speed;
-        
-        // 基础抛物线速度
-        let vx = direction.x * speed;
-        let vy = direction.y * speed;
-        
-        // 如果有弧线高度,调整y轴速度
-        if (this.config.arcHeight > 0) {
-            // 计算到达弧线顶点需要的额外速度
-            const timeToApex = Math.abs(vx) / speed; // 简化计算
-            const extraVy = Math.sqrt(2 * Math.abs(this.config.gravity * 9.8) * this.config.arcHeight);
-            vy += extraVy;
+
+        // 基础水平速度 (保持恒定, 不受重力影响)
+        const vx = horizontalDir.x * speed;
+
+        // 计算纵向初速度, 使得理论最高点接近 arcHeight
+        // vy = sqrt(2 * g * h)
+        const g = Math.max(0.1, Math.abs(this.config.gravity * 9.8)); // 避免 g=0 导致除0或 vy=0
+        const desiredHeight = Math.max(1, this.config.arcHeight); // 至少 1 避免 0 导致 vy=0
+        let vy = Math.sqrt(2 * g * desiredHeight);
+
+        // 如果原始方向有明显的向上分量, 为了兼容旧配置, 适当叠加
+        if (rawDir.y > 0.1) {
+            vy += rawDir.y * speed * 0.5; // 50% 叠加, 防止过高
         }
-        
+
         return new Vec2(vx, vy);
     }
     
@@ -211,16 +228,16 @@ export class BulletTrajectory extends Component {
      * 更新弧线弹道
      */
     private updateArcTrajectory(dt: number) {
-        // 弧线弹道结合了直线和抛物线特性
+        // 先应用基础的抛物线逻辑 (受重力影响)
+        this.updateParabolicTrajectory(dt);
+
+        // 再在垂直方向叠加一个小幅度的正弦扰动, 让轨迹更加圆润。
         const t = this.state.elapsedTime;
-        const arcPeriod = 2.0; // 弧线周期
-        const arcFactor = Math.sin(t * Math.PI / arcPeriod) * this.config.arcHeight * 0.1;
-        
-        const currentVel = this.rigidBody.linearVelocity;
-        this.rigidBody.linearVelocity = new Vec2(
-            currentVel.x,
-            currentVel.y + arcFactor * dt
-        );
+        const sinus = Math.sin(t * Math.PI); // [-1,1]
+        const extraVy = sinus * this.config.arcHeight * 0.05; // 0.05 系数保证不至于过大
+
+        const curVel = this.rigidBody.linearVelocity;
+        this.rigidBody.linearVelocity = new Vec2(curVel.x, curVel.y + extraVy);
     }
     
     /**
@@ -229,21 +246,36 @@ export class BulletTrajectory extends Component {
     private updateHomingTrajectory(dt: number) {
         // 先按抛物线运动
         this.updateParabolicTrajectory(dt);
-        
+
         // 追踪延迟后开始追踪
         if (this.homingTimer > 0) {
             this.homingTimer -= dt;
             return;
         }
-        
-        if (!this.targetNode || !this.targetNode.isValid) {
-            this.findTarget(); // 重新寻找目标
+
+        // 确定追踪目标位置(敌人节点 or 返回点)
+        let targetPos: Vec3 = null;
+
+        if (this.state.phase === 'return' && this.state.targetPosition) {
+            // 回程阶段,使用存储的返回坐标
+            targetPos = this.state.targetPosition;
+        } else {
+            // 主动追踪敌人
+            if (!this.targetNode || !this.targetNode.isValid) {
+                this.findTarget();
+            }
+            if (this.targetNode && this.targetNode.isValid) {
+                targetPos = this.targetNode.worldPosition;
+            }
+        }
+
+        // 若依旧没有目标,直接退出
+        if (!targetPos) {
             return;
         }
-        
+
         // 计算追踪力
         const currentPos = this.node.worldPosition;
-        const targetPos = this.targetNode.worldPosition;
         const direction = targetPos.clone().subtract(currentPos).normalize();
         
         // 获取当前速度

+ 12 - 0
assets/scripts/CombatSystem/WeaponBullet.ts

@@ -215,6 +215,16 @@ export class WeaponBullet extends Component {
             initData.firePosition
         );
         
+        // --- 额外偏移 ---
+        // 若子弹在生成时与发射方块碰撞(位置重叠), 会立刻触发碰撞事件导致被销毁。
+        // 因此在初始化完弹道后, 将子弹沿发射方向平移一小段距离(默认 30 像素左右)。
+        const dir = (initData.direction || this.calculateDirection(initData.autoTarget)).clone().normalize();
+        const spawnOffset = 30; // 可根据子弹半径或方块大小调整
+        if (!Number.isNaN(dir.x) && !Number.isNaN(dir.y)) {
+            const newLocalPos = this.node.position.clone().add(new Vec3(dir.x * spawnOffset, dir.y * spawnOffset, 0));
+            this.node.setPosition(newLocalPos);
+        }
+        
         // 初始化命中效果组件
         this.bulletHitEffect = this.getComponent(BulletHitEffect) || this.addComponent(BulletHitEffect);
         this.bulletHitEffect.init(config.hitEffects);
@@ -228,6 +238,8 @@ export class WeaponBullet extends Component {
         this.bulletLifecycle = this.getComponent(BulletLifecycle) || this.addComponent(BulletLifecycle);
         this.bulletLifecycle.init(config.lifecycle, initData.firePosition);
         
+        console.log('生命周期穿透值 =', config.lifecycle.penetration);
+        
         // 设置碰撞监听
         this.setupCollisionListener();