Collision Detection
What happens when the player touches an enemy? Or picks up a coin? Collision detection is how we know when game objects interact.
AABB Collision
AABB stands for "Axis-Aligned Bounding Box". It's the simplest and most common collision detection method. We treat every object as a rectangle and check if they overlap.
The Logic
Two rectangles are colliding if all four of these conditions are true:
- Left edge of A is to the left of Right edge of B
- Right edge of A is to the right of Left edge of B
- Top edge of A is above Bottom edge of B
- Bottom edge of A is below Top edge of B
function isColliding(rect1, rect2) {
return rect1.x < rect2.x + rect2.width &&
rect1.x + rect1.width > rect2.x &&
rect1.y < rect2.y + rect2.height &&
rect1.y + rect1.height > rect2.y;
}
// Usage
const player = { x: 100, y: 100, width: 40, height: 40 };
const enemy = { x: 120, y: 110, width: 30, height: 30 };
if (isColliding(player, enemy)) {
console.log('💥 Collision detected!');
}
Circle Collision
For circular objects (balls, coins, characters), we check if the distance between centers is less than the sum of their radii.
function isCircleColliding(circle1, circle2) {
const dx = circle1.x - circle2.x;
const dy = circle1.y - circle2.y;
const distance = Math.sqrt(dx * dx + dy * dy);
return distance < circle1.radius + circle2.radius;
}
// Usage
const ball = { x: 200, y: 150, radius: 20 };
const coin = { x: 210, y: 160, radius: 15 };
if (isCircleColliding(ball, coin)) {
console.log('🪙 Coin collected!');
}
Point in Rectangle
Useful for detecting mouse clicks on buttons or objects:
function isPointInRect(px, py, rect) {
return px >= rect.x &&
px <= rect.x + rect.width &&
py >= rect.y &&
py <= rect.y + rect.height;
}
// Usage with mouse click
canvas.addEventListener('click', (e) => {
const mouseX = e.offsetX;
const mouseY = e.offsetY;
if (isPointInRect(mouseX, mouseY, button)) {
console.log('Button clicked!');
}
});
Complete Example: Collectible Coins
Here's a mini-game where you move a player to collect coins:
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const player = { x: 50, y: 50, width: 30, height: 30 };
let coins = [
{ x: 200, y: 100, width: 20, height: 20 },
{ x: 350, y: 250, width: 20, height: 20 },
{ x: 500, y: 150, width: 20, height: 20 }
];
let score = 0;
const keys = {};
window.addEventListener('keydown', e => keys[e.key] = true);
window.addEventListener('keyup', e => keys[e.key] = false);
function isColliding(a, b) {
return a.x < b.x + b.width &&
a.x + a.width > b.x &&
a.y < b.y + b.height &&
a.y + a.height > b.y;
}
function gameLoop() {
// UPDATE
if (keys['ArrowUp']) player.y -= 4;
if (keys['ArrowDown']) player.y += 4;
if (keys['ArrowLeft']) player.x -= 4;
if (keys['ArrowRight']) player.x += 4;
// Check coin collisions
coins = coins.filter(coin => {
if (isColliding(player, coin)) {
score++;
return false; // Remove coin
}
return true;
});
// CLEAR
ctx.fillStyle = '#111';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// DRAW coins
ctx.fillStyle = '#ffd700';
coins.forEach(c => ctx.fillRect(c.x, c.y, c.width, c.height));
// DRAW player
ctx.fillStyle = '#4ade80';
ctx.fillRect(player.x, player.y, player.width, player.height);
// DRAW score
ctx.fillStyle = '#fff';
ctx.font = '20px Arial';
ctx.fillText('Score: ' + score, 10, 30);
requestAnimationFrame(gameLoop);
}
gameLoop();
Grab the Code
Copy ready-to-use collision functions from our Resources library!
View Collision SnippetsWhat's Next?
You've completed the "Getting Started" path! Here's where you can go from here:
- Build Snake — Apply everything you learned in a classic game.
- Explore Resources — Copy-paste utility functions and AI algorithms.
- Read Advanced Topics — Game AI, physics engines, and more.