Master 2D Collision Detection: From Bounding Boxes to SAT
This article explains common 2D collision‑detection techniques—including axis‑aligned bounding boxes, circle checks, grid partitioning, pixel‑level tests, ray casting, and the Separating Axis Theorem—detailing their concepts, algorithms, code examples, advantages, drawbacks, and typical use cases for game development.
Axis-Aligned Bounding Box (AABB)
Concept: Detect collision between two non‑rotated rectangles by testing whether their edges overlap.
rect1.x < rect2.x + rect2.width &&
rect1.x + rect1.width > rect2.x &&
rect1.y < rect2.y + rect2.height &&
rect1.y + rect1.height > rect2.yDrawbacks:
Only works for axis‑aligned rectangles; rotation is not supported.
Precision suffers when the rectangle contains transparent or patterned regions.
Fast‑moving objects may tunnel between frames and miss collisions.
Typical use case: Collision between rectangular game objects.
Circle Collision
Concept: Two circles collide when the distance between their centers is less than the sum of their radii.
Math.sqrt(Math.pow(circleA.x - circleB.x, 2) +
Math.pow(circleA.y - circleB.y, 2)) <
circleA.radius + circleB.radiusDrawbacks: Similar limitations to AABB when circles are approximated by bounding boxes.
Typical use case: Collision of spherical objects such as balls.
Map Grid Partitioning
Concept: Divide the game world into a grid; each object records the cell it occupies. Collision is checked only between objects in the same or neighboring cells. All colliding objects must fit within a cell or an integer multiple of a cell.
map = [
[0,0,1,1,1,0,0,0,0],
[0,1,1,0,0,1,0,0,0],
[0,1,0,0,0,0,1,0,0],
[0,1,0,0,0,0,1,0,0],
[0,1,1,1,1,1,1,0,0]
];
player = { left: 2, top: 2 };
// movement logic checks the next cell before movingDrawbacks: Limited to scenarios where object size matches grid granularity.
Typical use case: Tile‑based games such as Sokoban or Minesweeper.
Pixel‑Level Detection
Concept: Determine overlap by examining each pixel of two objects on an off‑screen canvas.
Render both objects to separate off‑screen canvases and compare pixel opacity at identical coordinates.
Use globalCompositeOperation = 'destination-in' to keep only overlapping pixels; non‑transparent pixels indicate a collision.
Note: The first method requires two off‑screen canvases, the second only one.
Drawbacks: High computational cost because every pixel must be examined.
Typical use case: Precise collision checks where visual fidelity matters.
Ray Casting
Concept: Cast a line along an object's velocity vector and another line from a second object; if the intersection lies within the target area, a collision is reported.
Example: Throwing a ball into a bucket – draw line #1 along the ball’s velocity, draw line #2 from the bucket edge, and test the intersection point.
Advantages: Works well for fast‑moving objects.
Drawbacks: Applicable only to limited scenarios.
Typical use case: Projectile‑into‑target checks.
Separating Axis Theorem (SAT)
Concept: For any two convex polygons, project them onto each potential separating axis (normals of edges). If a gap exists on any axis, the polygons do not intersect; otherwise they collide.
function polygonsCollide(polygon1, polygon2) {
var axes = polygon1.getAxes();
axes.push.apply(axes, polygon2.getAxes());
for (var i = 0; i < axes.length; i++) {
var axis = axes[i];
var projection1 = polygon1.project(axis);
var projection2 = polygon2.project(axis);
if (!projection1.overlaps(projection2)) {
return false;
}
}
return true;
}Key steps:
Determine edge vectors for each polygon.
Compute a perpendicular (normal) vector for each edge and normalize it to obtain the projection axis.
Project all vertices onto the axis, recording the minimum and maximum scalar values.
Check whether the intervals overlap; a non‑overlap on any axis means no collision.
Supporting classes:
// Vector class
function Vector(x, y) {
this.x = x;
this.y = y;
}
Vector.prototype = {
getMagnitude: function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
},
dotProduct: function(v) {
return this.x * v.x + this.y * v.y;
},
subtract: function(v) {
return new Vector(this.x - v.x, this.y - v.y);
},
edge: function(v) {
return this.subtract(v);
},
perpendicular: function() {
return new Vector(this.y, -this.x);
},
normalize: function() {
var m = this.getMagnitude();
return m !== 0 ? new Vector(this.x / m, this.y / m) : new Vector(0, 0);
},
normal: function() {
return this.perpendicular().normalize();
}
};
// Projection class
function Projection(min, max) {
this.min = min;
this.max = max;
}
Projection.prototype = {
overlaps: function(p) {
return this.max > p.min && p.max > this.min;
}
};
// Project a polygon onto an axis
function project(polygon, axis) {
var scalars = [];
polygon.points.forEach(function(point) {
var v = new Vector(point.x, point.y);
scalars.push(v.dotProduct(axis));
});
return new Projection(Math.min.apply(Math, scalars), Math.max.apply(Math, scalars));
}Advantages: Precise detection for any convex polygon and circles (by treating a circle as a polygon with many edges).
Drawbacks: Not suitable for concave polygons.
Typical use case: Collision between arbitrary convex shapes and circles.
Collision Performance Optimisation
Testing every pair of objects each frame is wasteful. Most engines split collision handling into two phases:
Broad Phase
Provides a shortlist of potentially colliding entities using spatial data structures such as Quad‑Trees, R‑Trees, or spatial hash maps.
Narrow Phase
Applies precise algorithms (AABB, circle, SAT, pixel, etc.) to the shortlist to confirm actual collisions.
Minimum Translation Vector (MTV)
When two objects remain intersecting after a collision, the Minimum Translation Vector separates them by the smallest possible displacement.
References
https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection
https://example.com/html5-canvas-core-techniques
Aotu Lab
Aotu Lab, founded in October 2015, is a front-end engineering team serving multi-platform products. The articles in this public account are intended to share and discuss technology, reflecting only the personal views of Aotu Lab members and not the official stance of JD.com Technology.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
