AABB轴对齐矩形是指矩形的四条边分别平行于x轴和y轴的矩形,在2D游戏开发、图形碰撞检测等场景中,判断两个AABB矩形是否碰撞是非常常见的需求,其核心逻辑是通过坐标投影重叠判定来实现。

AABB矩形碰撞检测原理
AABB矩形的边界可以用四个坐标值来表示,分别是矩形左边界的x坐标x_min、右边界的x坐标x_max、下边界的y坐标y_min、上边界的y坐标y_max。对于两个矩形A和B,当且仅当两个矩形在x轴上的投影有重叠,并且在y轴上的投影也有重叠时,两个矩形才会发生碰撞。
两个矩形在x轴上的投影区间分别是[A.x_min, A.x_max]和[B.x_min, B.x_max],投影重叠的条件是A.x_min < B.x_max 且 B.x_min < A.x_max。同理,y轴上的投影重叠条件是A.y_min < B.y_max 且 B.y_min < A.y_max。只有两个条件同时满足,才说明两个矩形发生碰撞。
C++代码实现
首先定义AABB矩形的结构体,存储矩形的四个边界坐标:
#include <iostream>
#include <algorithm>
// 定义AABB矩形结构体
struct AABBRect {
float x_min; // 左边界x坐标
float x_max; // 右边界x坐标
float y_min; // 下边界y坐标
float y_max; // 上边界y坐标
// 构造函数,传入左上角坐标和宽高初始化
AABBRect(float left, float top, float width, float height) {
x_min = left;
x_max = left + width;
y_min = top;
y_max = top + height;
}
// 构造函数,直接传入四个边界坐标初始化
AABBRect(float x1, float x2, float y1, float y2) {
x_min = std::min(x1, x2);
x_max = std::max(x1, x2);
y_min = std::min(y1, y2);
y_max = std::max(y1, y2);
}
};
接下来实现碰撞检测的函数,判断两个AABB矩形是否发生碰撞:
// 判断两个AABB矩形是否碰撞
bool isAABBCollision(const AABBRect& rect1, const AABBRect& rect2) {
// 判断x轴投影是否重叠
bool x_overlap = rect1.x_min < rect2.x_max && rect2.x_min < rect1.x_max;
// 判断y轴投影是否重叠
bool y_overlap = rect1.y_min < rect2.y_max && rect2.y_min < rect1.y_max;
// 两个轴都重叠才发生碰撞
return x_overlap && y_overlap;
}
测试代码示例
编写测试代码验证碰撞检测逻辑的正确性:
int main() {
// 创建第一个矩形,左上角(0,0),宽高100
AABBRect rect1(0.0f, 0.0f, 100.0f, 100.0f);
// 创建第二个矩形,左上角(50,50),宽高100
AABBRect rect2(50.0f, 50.0f, 100.0f, 100.0f);
// 创建第三个矩形,左上角(200,200),宽高100
AABBRect rect3(200.0f, 200.0f, 100.0f, 100.0f);
std::cout << "rect1和rect2是否碰撞: " << (isAABBCollision(rect1, rect2) ? "是" : "否") << std::endl;
std::cout << "rect1和rect3是否碰撞: " << (isAABBCollision(rect1, rect3) ? "是" : "否") << std::endl;
// 测试边界相切的情况,两个矩形刚好相邻没有重叠
AABBRect rect4(0.0f, 0.0f, 100.0f, 100.0f);
AABBRect rect5(100.0f, 0.0f, 100.0f, 100.0f);
std::cout << "rect4和rect5是否碰撞: " << (isAABBCollision(rect4, rect5) ? "是" : "否") << std::endl;
return 0;
}
边界情况说明
上述代码使用的是严格小于的判断,当两个矩形的边界刚好相切时,比如一个矩形的右边界等于另一个矩形的左边界,此时rect1.x_min < rect2.x_max和rect2.x_min < rect1.x_max的条件不成立,会判定为不碰撞。如果需要将边界相切的情况也判定为碰撞,只需要把判断条件中的小于号改成小于等于号即可:
// 边界相切也判定为碰撞的版本
bool isAABBCollisionIncludeEdge(const AABBRect& rect1, const AABBRect& rect2) {
bool x_overlap = rect1.x_min <= rect2.x_max && rect2.x_min <= rect1.x_max;
bool y_overlap = rect1.y_min <= rect2.y_max && rect2.y_min <= rect1.y_max;
return x_overlap && y_overlap;
}
开发者可以根据实际场景的需求选择合适的判定逻辑,以上就是C++中判断两个AABB轴对齐矩形是否碰撞的完整实现方法。