两个AABB碰撞当且仅当x方向重叠且y方向重叠,即A.left B.left && A.bottom B.bottom;浮点场景需引入epsilon容差避免精度误判。

用分离轴定理快速判断AABB碰撞
两个AABB不碰撞,当且仅当它们在x轴或y轴(2D)上完全分离。反过来,只要x方向有重叠 且 y方向也有重叠,就一定碰撞——这是最直接、最高效的判定逻辑,不用开方、不用叉积,纯比较运算。
常见错误是写成「任一方向重叠即碰撞」,这会导致误判;或者用中心距+半宽比较,多算两次减法和绝对值,没必要。
- 设矩形A的左、右、下、上边界为
A.left、A.right、A.bottom、A.top,B同理 - 正确条件:
A.left B.left && A.bottom B.bottom - 注意:边界是否包含取决于你的坐标约定。若用「左闭右开」(如像素坐标),则应改为
A.left B.left(无需等号);若用闭区间(如浮点物理模拟),且允许边接触视为碰撞,则用和 <code>>=
避免浮点精度导致的误判
当坐标是 float 或 double 时,直接用 == 或裸比较 /<code>> 在边界对齐场景下可能因累积误差失效,比如两个矩形本该刚好贴合,却因计算路径不同产生微小偏差而被判定为“未碰撞”。
- 若需容忍微小间隙(例如UI拖拽吸附),可引入 epsilon 偏移:
A.right > B.left - 1e-6f - 更稳妥的做法是统一使用整数坐标(如SDL2的
SDL_Rect),或封装为带 epsilon 的内联函数:bool overlaps(const AABB& a, const AABB& b, float eps = 1e-5f) - 不要对原始坐标做
std::abs(a.x - b.x) 这类中心距判断——它无法区分“远距离错开”和“紧邻但未重叠”
与 std::pair<:pair>, std::pair> 等嵌套结构配合时的坑
有人用 std::pair<:pair>, std::pair<int>></int></:pair> 表示AABB(左下+右上),读写易错,且无法自解释字段含义。
- 解包时容易把
rect.first.first(左)和rect.second.first(右)搞反,导致条件恒假 - 推荐定义结构体:
struct AABB { int left, right, bottom, top; };,哪怕只用两行,也能杜绝字段顺序混淆 - 若必须用
std::tuple或std::array,至少加static constexpr索引常量:enum { LEFT=0, RIGHT=1, BOTTOM=2, TOP=3 };
性能敏感场景下的内联与分支预测
在每帧调用数百次的渲染剔除或物理预检中,一次AABB碰撞检测应控制在4次整数比较+2次短路逻辑跳转内。编译器通常能自动内联简单函数,但要注意人为阻断:
- 避免将判断逻辑写在虚函数里(破坏内联)
- 避免传入
const AABB&却在函数体内又取地址做额外操作(可能抑制优化) - 条件顺序影响分支预测:把最可能为假的条件放前面(例如大量物体在屏幕外),可减少误预测惩罚;但实践中x轴分离概率通常≈y轴,保持默认顺序即可
- Clang/GCC 下加
[[likely]]对单个条件无意义,整个表达式也无法标注,别硬加
真正容易被忽略的是坐标系一致性:Y轴朝上还是朝下?top 是否一定大于 bottom?一旦混用(比如OpenGL纹理坐标 vs SDL窗口坐标),A.top > B.bottom 就会变成永远为真或永远为假。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











