You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

子弹消失或玩家被击中时玩家均受伤害的原因排查

问题分析与修复方案

你的核心问题出在碰撞检测的逻辑缺陷上:

  • 碰撞判断用的是子弹创建瞬间的玩家位置,没有实时获取玩家移动后的最新位置,导致玩家移动后,旧位置和子弹位置可能误判碰撞,甚至子弹出界时触发掉血。
  • 仅用子弹左上角的单点位置判断是否在玩家范围内,没有考虑子弹的整体矩形,精度极低,容易出现误触发。

修复步骤

  1. 实时获取玩家位置:将玩家位置的获取移到moveBullet函数内部,确保每次碰撞判断都用玩家当前的最新位置。
  2. 改用矩形碰撞检测:获取子弹的完整边界矩形,通过判断两个矩形是否重叠来确认碰撞,这是更准确的碰撞判断方式。

修改后的完整代码

function shootPlayer() {
    if (!document.body.contains(enemy)) return;  // Stop if the enemy is removed

    const enemyRect = enemy.getBoundingClientRect();
    const enemyCenterX = enemyRect.left + enemyRect.width / 2;
    const enemyCenterY = enemyRect.top + enemyRect.height / 2;

    const playerRectInitial = player.getBoundingClientRect();
    const playerCenterX = playerRectInitial.left + playerRectInitial.width / 2;
    const playerCenterY = playerRectInitial.top + playerRectInitial.height / 2;

    const angle = Math.atan2(playerCenterY - enemyCenterY, playerCenterX - enemyCenterX);

    const bullet = document.createElement('div');
    bullet.className = 'bullet';
    bullet.style.position = 'absolute';
    bullet.style.top = `${enemyCenterY}px`;
    bullet.style.left = `${enemyCenterX}px`;
    document.body.appendChild(bullet);

    const bulletSpeed = 5;
    const bulletDamage = 5;

    function moveBullet() {
        // 实时获取玩家和子弹的最新边界
        const playerRect = player.getBoundingClientRect();
        const bulletRect = bullet.getBoundingClientRect();
        
        let bulletTop = parseFloat(bullet.style.top);
        let bulletLeft = parseFloat(bullet.style.left);

        bulletTop += bulletSpeed * Math.sin(angle);
        bulletLeft += bulletSpeed * Math.cos(angle);

        bullet.style.top = `${bulletTop}px`;
        bullet.style.left = `${bulletLeft}px`;

        console.log(`Bullet Position: (${bulletLeft}, ${bulletTop})`);

        // 准确的矩形碰撞判定逻辑
        if (
            bulletRect.right >= playerRect.left &&
            bulletRect.left <= playerRect.right &&
            bulletRect.bottom >= playerRect.top &&
            bulletRect.top <= playerRect.bottom
        ) {
            decreasePlayerHealth(bulletDamage);
            bullet.remove();
            console.log('Bullet hit the player.');
            return;
        }

        // 检查子弹是否出界并移除
        if (bulletTop < 0 || bulletTop > window.innerHeight || bulletLeft < 0 || bulletLeft > window.innerWidth) {
            bullet.remove();
            console.log('Bullet despawned.');
            return;
        }

        // 继续移动子弹
        requestAnimationFrame(moveBullet);
    }

    requestAnimationFrame(moveBullet);
}

额外测试建议

暂时关闭被动伤害逻辑,单独测试子弹碰撞功能,确认只有子弹实际击中玩家时才会触发decreasePlayerHealth。如果子弹有超时销毁逻辑,要确保超时分支不会调用掉血函数。

内容的提问来源于stack exchange,提问作者Lachie Dwyer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 18:15:10