Intervals on a line
Back on a single number axis. A segment from to is the interval . Two intervals and overlap unless one ends before the other begins, so they overlap exactly when
function overlap(a1: number, a2: number, b1: number, b2: number): boolean {
return a1 <= b2 && b1 <= a2;
}function overlap(a1, a2, b1, b2) {
return a1 <= b2 && b1 <= a2;
}def overlap(a1: float, a2: float, b1: float, b2: float) -> bool:
return a1 <= b2 and b1 <= a2overlap- time O(1) space O(1)
Rectangle vs rectangle
A rectangle whose sides run along the axes is called an axis-aligned bounding box, or AABB. With its corner at , width and height , it’s nothing more than two intervals: on the -axis and on the -axis.
Two AABBs collide when their intervals overlap on the -axis and on the -axis. If there’s a gap on either axis, you can slide a straight line between them.
type Rect = { x: number; y: number; w: number; h: number };
function rectsCollide(a: Rect, b: Rect): boolean {
return (
overlap(a.x, a.x + a.w, b.x, b.x + b.w) &&
overlap(a.y, a.y + a.h, b.y, b.y + b.h)
);
}// A rectangle is an object like { x: 20, y: 40, w: 120, h: 80 }.
function rectsCollide(a, b) {
return (
overlap(a.x, a.x + a.w, b.x, b.x + b.w) &&
overlap(a.y, a.y + a.h, b.y, b.y + b.h)
);
}@dataclass
class Rect:
x: float
y: float
w: float
h: float
def rects_collide(a: Rect, b: Rect) -> bool:
return (
overlap(a.x, a.x + a.w, b.x, b.x + b.w)
and overlap(a.y, a.y + a.h, b.y, b.y + b.h)
)rectsCollide- time O(1) space O(1)
AABBs are so cheap that games often wrap complicated shapes in one, and only run the exact test when the boxes overlap.
Circle vs rectangle
Find the point of the rectangle that is closest to the circle’s centre , and it’s a point-in-circle test again. Finding takes no geometry at all: clamp each coordinate of into the rectangle’s interval on that axis.
When the centre is inside the rectangle, is the centre itself, the distance is , and the test rightly says they collide.
function clamp(value: number, min: number, max: number): number {
return Math.max(min, Math.min(max, value));
}
function circleRectCollide(c: Circle, rect: Rect): boolean {
const closest = {
x: clamp(c.x, rect.x, rect.x + rect.w),
y: clamp(c.y, rect.y, rect.y + rect.h)
};
return pointInCircle(closest, c);
}function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
function circleRectCollide(c, rect) {
const closest = {
x: clamp(c.x, rect.x, rect.x + rect.w),
y: clamp(c.y, rect.y, rect.y + rect.h)
};
return pointInCircle(closest, c);
}def clamp(value: float, low: float, high: float) -> float:
return max(low, min(high, value))
def circle_rect_collide(c: Circle, rect: Rect) -> bool:
closest = Point(
clamp(c.x, rect.x, rect.x + rect.w),
clamp(c.y, rect.y, rect.y + rect.h),
)
return point_in_circle(closest, c)clamp- time O(1) space O(1)
circleRectCollide- time O(1) space O(1)
Comments
No comments yet. Questions and corrections are welcome.