判断AABB是否重叠需检查x、y轴投影是否同时重叠;任一轴不重叠则无碰撞,仅当两轴均重叠才相交;因AABB轴对齐,仅需坐标比较,无需叉积或SAT。

判断两个 AABB 是否重叠只需检查投影分离
两个轴对齐矩形(AABB)是否碰撞,本质是看它们在 x 和 y 轴上的投影是否**同时重叠**。只要任一轴上投影不重叠,就无碰撞;只有两个轴都重叠,才算真正相交。
别被“矩形”误导——AABB 没有旋转,所以不需要叉积、点线关系或 SAT 复杂推导,纯坐标比较即可。
常见错误是写成 if (x1 这类边界逻辑混乱的条件,容易漏掉相等(刚好贴边)或搞反大小关系。
- 推荐统一用「最小-最大」表示法:每个 AABB 用
min_x、max_x、min_y、max_y描述,逻辑最清晰 - 若输入是左上角 + 宽高(如
left,top,width,height),先转成 min/max:例如max_x = left + width(注意:若 y 向下为正,max_y = top + height;若 y 向上为正,min_y = top - height) - 重叠判定公式固定为:
!(max_x1
C++ 实现时 float 比较要防 NaN 和精度抖动
如果 AABB 坐标是 float 类型,直接用 判定可能因浮点误差导致本该接触的两个矩形被误判为分离(尤其在动态移动后做连续帧检测时)。
但**不要**盲目加 std::abs(a - b) 到所有比较里——这会把「严格分离」也模糊成「疑似接触」,破坏 AABB 的确定性语义。
- 仅在你明确需要「容忍微小穿透」时,才对分离条件放宽:比如把
max_x1 改为max_x1 ,其中eps = 1e-5f - 更稳妥的做法是保持整数或定点运算(如用
int32_t存像素坐标),避免浮点不确定性 - 务必确保输入 AABB 自身合法:即
min_x 且min_y ,否则!(false || false || ...)可能返回意外结果
性能关键:分支预测友好写法比函数调用更重要
在游戏循环或物理更新中高频调用碰撞检测时,函数调用开销和分支预测失败代价远高于计算本身。别为了“封装”而写 bool intersects(const AABB& a, const AABB& b) 然后每次 new 对象传参。
- 直接内联比较,例如:
inline bool aabb_overlap(float min1x, float max1x, float min1y, float max1y, float min2x, float max2x, float min2y, float max2y) { return !(max1x - 若用结构体,确保成员顺序利于 CPU 缓存(如把 x 相关放一起:
struct AABB { float min_x, max_x, min_y, max_y; };) - 避免在循环内重复计算
max_x = left + width—— 提前算好存为 min/max 字段,别省那几个字节内存
OpenGL/DirectX 坐标系下 y 轴方向容易翻车
很多图形 API(如 OpenGL 默认 NDC)中 y 向上为正,但窗口坐标或纹理坐标常以左上为原点、y 向下为正。若把屏幕坐标直接当 AABB 输入而不调整,min_y 和 max_y 会颠倒,导致判定永远失败。
典型现象:鼠标拖拽选框在界面上看着明明盖住了物体,但 aabb_overlap() 返回 false。
- 统一做法:在进入碰撞系统前,将所有坐标归一到同一空间(例如全部转为「y 向上」世界坐标)
- 快速验证:打印两个 AABB 的
min_y和max_y,确认min_y 成立 - 若必须混用坐标系,至少加 assert:
assert(min_y
实际项目里最常出问题的不是算法本身,而是坐标系转换遗漏和浮点输入未校验。写完先拿「完全分离」「刚好贴边」「完全嵌套」三组手工数据测一遍,比跑单元测试更快定位问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











