The Separating Axis Theorem (SAT) is the gold standard for detecting collisions between convex polygons. It not only tells you if they collide but also provides the Minimum Translation Vector (MTV)—the shortest path to move the shapes so they are no longer overlapping.
Two convex shapes are not colliding if there exists an axis on which their projections do not overlap.
Imagine shining a flashlight from different angles: if you can find just one angle where the shadows of the two shapes don’t touch, the shapes are separate.
For 2D polygons, you only need to check the normals of every edge of both shapes.
false.struct Projection {
float min, max;
bool Overlaps(Projection other) {
return !(this->max < other.min || other.max < this->min);
}
float GetOverlap(Projection other) {
return std::min(this->max, other.max) - std::max(this->min, other.min);
}
};
bool CheckCollision(Polygon polyA, Polygon polyB, Vector2& outMTV) {
float minOverlap = std::numeric_limits<float>::max();
Vector2 shortestAxis;
auto axes = polyA.GetNormals();
axes.insert(axes.end(), polyB.GetNormals().begin(), polyB.GetNormals().end());
for (Vector2 axis : axes) {
Projection pA = polyA.Project(axis);
Projection pB = polyB.Project(axis);
if (!pA.Overlaps(pB)) return false; // Gap found!
float overlap = pA.GetOverlap(pB);
if (overlap < minOverlap) {
minOverlap = overlap;
shortestAxis = axis;
}
}
outMTV = shortestAxis * minOverlap;
return true;
}