Most collision tests come down to one question: how far apart are two things?
Along a line
The distance between two points and on a line is equal to the absolute value of the difference of their coordinates.
Try moving your cursor along this grid to interact with this example.
function distanceOnLine(x1: number, x2: number): number {
return Math.abs(x1 - x2);
}function distanceOnLine(x1, x2) {
return Math.abs(x1 - x2);
}def distance_on_line(x1: float, x2: float) -> float:
return abs(x1 - x2)distanceOnLine- time O(1) space O(1)
In the plane
The distance between two points and in the plane is the hypotenuse of the right triangle , where is level with and in line with : , . Pythagoras’ theorem says , so
type Point = { x: number; y: number };
function distance(a: Point, b: Point): number {
return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2);
}// A point is an object like { x: 4, y: 3 }.
function distance(a, b) {
return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2);
}import math
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
def distance(a: Point, b: Point) -> float:
return math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2)distance- time O(1) space O(1)
JavaScript’s Math.hypot and Python’s math.hypot do the squaring, adding and square root for you: pass them the two differences and they return the distance. They’re also careful with very large and very small numbers, where squaring them first could overflow or round down to zero.
function distance(a: Point, b: Point): number {
return Math.hypot(b.x - a.x, b.y - a.y);
}function distance(a, b) {
return Math.hypot(b.x - a.x, b.y - a.y);
}def distance(a: Point, b: Point) -> float:
return math.hypot(b.x - a.x, b.y - a.y)distance- time O(1) space O(1)
Skipping the square root
The square root is the slowest part of that function, and a collision test rarely needs the distance itself. It only needs to know whether the distance is smaller than something. Both sides of that comparison are never negative, so squaring them doesn’t change the answer:
Try it below. The point is inside the circle when its distance from the centre is at most the radius . The gauges on the right compare with , and with . grows much faster than , but it passes at exactly the moment passes , so both comparisons always agree, and only one of them needs a square root.
function distanceSquared(a: Point, b: Point): number {
return (b.x - a.x) ** 2 + (b.y - a.y) ** 2;
}function distanceSquared(a, b) {
return (b.x - a.x) ** 2 + (b.y - a.y) ** 2;
}def distance_squared(a: Point, b: Point) -> float:
return (b.x - a.x) ** 2 + (b.y - a.y) ** 2distanceSquared- time O(1) space O(1)
Every test in the following chapters compares squared distances with squared lengths, and never takes a root.
Comments
No comments yet. Questions and corrections are welcome.