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

碰撞检测-物体不相交:Java 2D方块碰撞无穿透功能实现咨询

2D轴对齐方块(AABB)碰撞防穿透实现方案

你已经完成的碰撞检测属于AABB(轴对齐包围盒)碰撞判定的第一步,防穿透的核心逻辑是计算碰撞后的重叠深度,沿最短重叠轴向对两个方块的位置做修正,步骤如下:

1 计算碰撞重叠深度

两个轴对齐方块发生碰撞时,分别计算水平、垂直两个方向的重叠长度:

  • 水平重叠深度:Math.min(boxA.x + boxA.width, boxB.x + boxB.width) - Math.max(boxA.x, boxB.x)
  • 垂直重叠深度:Math.min(boxA.y + boxA.height, boxB.y + boxB.height) - Math.max(boxA.y, boxB.y)
    碰撞后优先沿重叠量更小的轴向做位置修正,避免出现方块被横向碰撞后诡异弹跳的问题。

2 位置修正逻辑

根据碰撞的轴向和方块的相对位置,把重叠部分的距离分配给两个方块做位移:

  • 如果两个方块都是可移动的,各自承担一半重叠深度的位移量
  • 如果其中一个是静态物体(比如墙面、地面,不会被撞动),所有位移量由动态物体承担
    如果需要实现碰撞反弹效果,同步把对应轴向的速度反向,乘以弹性系数即可,弹性系数取值0-1,1为完全弹性碰撞无能量损失,0为碰撞后完全不反弹。

3 核心实现代码示例

// 自定义方块实体类
class Box {
    // 方块左上角坐标
    float x;
    float y;
    // 方块尺寸
    float width;
    float height;
    // 方块移动速度
    float velX;
    float velY;
    // 标记是否为静态物体(墙面、地面等固定不动的元素)
    boolean isStatic;
}

// 碰撞修正方法,在检测到两个方块碰撞后调用
void resolveCollision(Box boxA, Box boxB) {
    // 计算两个方向的重叠深度
    float overlapX = Math.min(boxA.x + boxA.width, boxB.x + boxB.width) - Math.max(boxA.x, boxB.x);
    float overlapY = Math.min(boxA.y + boxA.height, boxB.y + boxB.height) - Math.max(boxA.y, boxB.y);

    // 沿重叠更小的轴向修正位置
    if (overlapX < overlapY) {
        // 水平方向碰撞修正
        if (boxA.x < boxB.x) {
            // boxA在boxB左侧,boxA左移,boxB右移
            float correction = overlapX / (boxA.isStatic || boxB.isStatic ? 1 : 2);
            if (!boxA.isStatic) boxA.x -= correction;
            if (!boxB.isStatic) boxB.x += correction;
            // 反弹逻辑,不需要可以删除
            if (!boxA.isStatic) boxA.velX *= -0.8f;
            if (!boxB.isStatic) boxB.velX *= -0.8f;
        } else {
            // boxA在boxB右侧,boxA右移,boxB左移
            float correction = overlapX / (boxA.isStatic || boxB.isStatic ? 1 : 2);
            if (!boxA.isStatic) boxA.x += correction;
            if (!boxB.isStatic) boxB.x -= correction;
            // 反弹逻辑,不需要可以删除
            if (!boxA.isStatic) boxA.velX *= -0.8f;
            if (!boxB.isStatic) boxB.velX *= -0.8f;
        }
    } else {
        // 垂直方向碰撞修正
        if (boxA.y < boxB.y) {
            // boxA在boxB上方,boxA上移,boxB下移
            float correction = overlapY / (boxA.isStatic || boxB.isStatic ? 1 : 2);
            if (!boxA.isStatic) boxA.y -= correction;
            if (!boxB.isStatic) boxB.y += correction;
            // 反弹逻辑,不需要可以删除
            if (!boxA.isStatic) boxA.velY *= -0.8f;
            if (!boxB.isStatic) boxB.velY *= -0.8f;
        } else {
            // boxA在boxB下方,boxA下移,boxB上移
            float correction = overlapY / (boxA.isStatic || boxB.isStatic ? 1 : 2);
            if (!boxA.isStatic) boxA.y += correction;
            if (!boxB.isStatic) boxB.y -= correction;
            // 反弹逻辑,不需要可以删除
            if (!boxA.isStatic) boxA.velY *= -0.8f;
            if (!boxB.isStatic) boxB.velY *= -0.8f;
        }
    }
}

4 高速移动场景优化

如果你的方块单帧移动距离超过自身边长,会出现帧末检测时已经完全穿过另一个方块的漏检问题,这种情况可以把单帧的移动路径拆分为多个小步,每移动一小步就检测一次碰撞,碰到障碍物就终止移动即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 00:15:03