一些开箱即用碰撞检测!AABB

听说有群友已经不满足于,大V老师提供的简单检测方法了,那么让我们为自己的游戏增加更多有趣的碰撞检测罢!
全文采用AABB实现,包含矩矩,圆圆,矩圆,角度矩圆,椭圆,点矩,点环,点圆,点椭,等,必要情况下只要根据下文中的算法自行修改或嵌套使用即可!

在下文中,大家可能会发现,为什么没有旋转过的两个矩形的碰撞,那不是AABB了,未来在说。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// 定义一个结构体,表示二维空间中的点
struct Point_F {
double x; // 点的x坐标
double y; // 点的y坐标
};

// 定义一个结构体,表示矩形区域
struct RECT {
double left; // 矩形左边缘的x坐标
double top; // 矩形上边缘的y坐标
double right; // 矩形右边缘的x坐标
double bottom; // 矩形下边缘的y坐标
};

// 判断点是否在矩形区域内
bool AABBPointInside(const Point_F& V, const RECT& RECT) {
return (V.x > RECT.left && V.x < RECT.right && V.y > RECT.top && V.y < RECT.bottom);
}
// 判断一个矩形是否完全在另一个矩形内部
bool AABBRectInside(const RECT& rect1, const RECT& rect2) {
return (rect2.left >= rect1.left && rect2.right <= rect1.right && rect2.top >= rect1.top && rect2.bottom <= rect1.bottom);
}
// 判断两个矩形是否重叠
bool AABBRectOverlap(const RECT& rect1, const RECT& rect2) {
return (rect1.right < rect2.left || rect1.left > rect2.right || rect1.bottom < rect2.top || rect1.top > rect2.bottom) ? false : true;
}
// 判断矩形与圆形是否重叠,考虑矩形旋转的情况
bool AABBRectCircleOverlap(double rectCenterX, double rectCenterY, double rectWidth, double rectHeight, double angle, double circleX, double circleY, double circleRadius) {
// 计算旋转后的向量坐标
double vectorX = circleX - rectCenterX;
double vectorY = circleY - rectCenterY;
double radians = angle * M_PI / 180.0;
double x = vectorX * cos(radians) + vectorY * sin(radians);
double y = vectorY * cos(radians) - vectorX * sin(radians);
// 计算矩形的半宽和半高
double halfWidth = rectWidth * 0.5;
double halfHeight = rectHeight * 0.5;
if (x - circleRadius < halfWidth && x + circleRadius > -halfWidth) {
if (y - circleRadius < halfHeight && y + circleRadius > -halfHeight) {
if (x < -halfWidth && y < -halfHeight){
if (distance(x, y, -halfWidth, -halfHeight) >= circleRadius) { return true; }
}
else if (x < halfWidth && y < -halfHeight){
if (distance(x, y, halfWidth, -halfHeight) >= circleRadius) { return true; }
}
else if (x > halfWidth && y > halfHeight){
if (distance(x, y, halfWidth, halfHeight) >= circleRadius) { return true; }
}
else if (x < -halfWidth && y > halfHeight) {
if (distance(x, y, -halfWidth, halfHeight) >= circleRadius) { return true; }
}
}
return true;
}
return false;
}
// 判断点是否在圆内
bool AABBPointInCircle(double pointX, double pointY, double circleCenterX, double circleCenterY, double circleRadius) {
// 计算点到圆心的距离,判断是否小于等于半径
double dx = pointX - circleCenterX;
double dy = pointY - circleCenterY;
return sqrt(dx * dx + dy * dy) <= circleRadius;
}
// 判断两个圆是否相交
bool AABBCirclesIntersect(double circleCenterX1, double circleCenterY1, double circleRadius1, double circleCenterX2, double circleCenterY2, double circleRadius2) {
// 计算两个圆心之间的距离,判断是否小于等于两个圆的半径之和
double dx = circleCenterX1 - circleCenterX2;
double dy = circleCenterY1 - circleCenterY2;
return sqrt(dx * dx + dy * dy) <= circleRadius1 + circleRadius2;
}
// 判断点是否在圆环内
bool AABBPointInAnnulus(double x, double y, double circleCenterX, double circleCenterY, double circleRadius, double innerThickness, double outerThickness) {
// 计算点到圆心的距离
double dx = x - circleCenterX;
double dy = y - circleCenterY;
double dist = sqrt(dx * dx + dy * dy);
// 判断距离是否在内圆半径和外圆半径之间
return (dist <= circleRadius + outerThickness && dist >= circleRadius - innerThickness);
}
// 判断点是否在椭圆内
bool AABBPointInEllipse(double centerX, double centerY, double radiusA, double radiusB, double x, double y) {
// 计算点到椭圆中心的距离,并与椭圆的参数化方程比较
double dx = centerX - x;
double dy = centerY - y;
return (dx * dx / (radiusA * radiusA) + dy * dy / (radiusB * radiusB)) <= 1;
}
作者

VoidGameSpace

发布于

2024-05-28

更新于

2024-05-28

许可协议

评论