AABB重叠判断只需检查x、y轴投影是否同时重叠;正确条件是max1 > min2 && max2 > min1,常见错误是将分离条件误作重叠条件。

用分离轴定理快速判断AABB重叠
AABB(Axis-Aligned Bounding Box)之间是否重叠,根本不需要做几何计算——只要任一坐标轴上两个矩形投影不重叠,整体就不重叠;只有所有轴都重叠,才真正发生碰撞。C++里最直接的方式就是检查x和y方向是否**同时重叠**。
常见错误是写成 if (overlapX && overlapY) 却把重叠条件写反,比如用 min1 > max2 当作“重叠”,实际那是“分离”条件。
- 假设每个AABB由左上角
tl和右下角br表示(y向下增长),则x方向重叠条件是:rect1.tl.x - y方向同理:
rect1.tl.y - 若使用中心+半宽高(
center,halfExtents),更简洁:abs(c1.x - c2.x)
注意坐标系和顶点顺序导致的逻辑翻转
很多bug源于默认假设了某种坐标系。比如SDL或OpenGL中y向上,而Windows GDI或Canvas中y向下——这会直接影响 tl/br 的y值大小关系。
若你用 top, bottom, left, right 字段存储,务必确认:top 是否成立。不成立时,y方向重叠判断就得改成 <code>rect1.bottom > rect2.top && rect2.bottom > rect1.top,否则结果恒为假。
- 用顶点数组(如
vec4 min, max)最安全:始终保证min.x ,然后统一用 <code>max1.x > min2.x && max2.x > min1.x - 别依赖结构体字段名推断大小关系,运行时加个
assert(min.x 能早发现问题
避免浮点精度导致的误判
当矩形由浮点数定义且边缘几乎贴合(比如 rect1.right == rect2.left),直接比较可能因计算误差被判为“不重叠”。这不是理论问题,而是真实出现在动画帧间微位移、缩放后坐标还原等场景。
解决方案不是加 epsilon 模糊判断(那会扩大碰撞体),而是**统一用“非分离”定义**:只要没明确分离,就认为潜在接触——这对物理响应或UI反馈更鲁棒。
- 推荐写法:
! (max1.x - 这个形式天然规避了“等于即分离”的歧义,且短路求值效率不差
- 如果真要支持“接触即触发”,可把
改成 <code>,但必须全改,不能混用
性能关键:内联函数 + 成员变量直取
碰撞检测常在每帧调用数百甚至上千次,函数调用开销和内存访问模式会影响性能。别封装成 bool intersects(const AABB& other) const 就完事——编译器不一定内联,尤其跨编译单元时。
更实际的做法是把判定逻辑写成 constexpr 函数,并确保所有字段是public POD成员,让编译器能彻底展开。
- 示例:
struct AABB { float x0, y0, x1, y1; }; constexpr bool overlaps(const AABB& a, const AABB& b) { return !(a.x1 - 避免 getter 函数(如
a.getXMin()),它们阻碍优化 - 若用类封装,至少给
[[nodiscard]] constexpr+inline,并把字段设为public
最容易被忽略的是:AABB本身是否真的“轴对齐”——如果你在变换后直接拿世界坐标顶点算 min/max,那得到的是OBB的包围盒,不是原AABB。每次用前确认数据来源,比优化判定逻辑更重要。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











