两个AABB不碰撞当且仅当在x轴或y轴上完全分离;反之,x轴重叠且y轴重叠即判定碰撞,因AABB轴对齐,分离轴定理简化为两轴投影全重叠才相交,比求交集更高效、无浮点误差。

两个AABB(Axis-Aligned Bounding Box)矩形不发生碰撞,当且仅当它们在x轴或y轴上完全分离;反之,只要x轴重叠 且 y轴也重叠,就判定为碰撞。
为什么用“分离轴”逻辑而不是“求交集”
AABB是轴对齐的,没有旋转,所以只需检查两个方向:x和y。如果任一方向上两个矩形的投影区间不重叠,整个矩形就不可能相交——这是分离轴定理(SAT)在2D轴对齐情形下的简化版本。比计算交集区域、判断点是否在内部等方法更轻量、无分支误差、无浮点除法。
常见错误是写成:if (left1 left2 && top1 top2),但坐标系定义混乱(比如top是小值还是大值)会导致逻辑翻转。
- 统一约定:y轴向下增长(如屏幕坐标),则
top ;若y向上增长(如数学坐标),则<code>top > bottom,必须前后一致 - 推荐用中心+半宽高表示,避免左右/上下命名歧义:
struct AABB { float cx, cy, hx, hy; }; - 实际比较时,用
abs(cx1 - cx2) 判断x重叠,同理y,更直观且抗坐标系干扰
标准实现:基于左/右/上/下边界的判断
假设所有坐标按屏幕惯例(y向下),每个矩形由left、right、top、bottom定义,且满足left 、<code>top :
立即学习“C++免费学习笔记(深入)”;
bool intersect(const AABB& a, const AABB& b) {
return !(a.right <= b.left || // a在b左边
b.right <= a.left || // b在a左边
a.bottom <= b.top || // a在b上方
b.bottom <= a.top); // b在a上方
}注意:用<=而非<,确保边刚好接触时也判为相交(多数物理/碰撞场景需要“接触即碰撞”)。
- 若需严格内部重叠(排除边缘接触),把
<=全换成< - 若输入可能乱序(如
top > bottom),先做归一化:float t = min(a.top, a.bottom); float b = max(a.top, a.bottom); - 该函数无浮点异常风险,不依赖
std::abs或sqrt,适合高频调用(如每帧上千次检测)
性能与边界情况提醒
这个判断是纯比较运算,现代CPU下通常2–4个周期,比调用std::minmax或构造临时std::pair快一个数量级。但有三个容易被忽略的点:
- 空矩形(
left == right或top == bottom)会被判为永不相交——如果你的业务允许退化矩形,需提前检查并按需处理 - 涉及浮点数时,若坐标来自变换或累加,可能有微小误差;必要时加epsilon容差,但不要直接加在边界比较里(会破坏AABB语义),应在输入归一化阶段处理
- 若矩形带z坐标(如3D AABB),只需扩展为三组比较:
!(a.maxz ,逻辑完全一致
真正麻烦的从来不是写对这四行比较,而是确保所有上游模块输出的left/right等字段符合同一套方向约定——坐标系混用比算法写错更难调试。


















