# Space Game Canvas Collision Detection Algorithm: AABB Implementation in JavaScript

> Learn how the space game canvas collision detection algorithm works using AABB overlap tests in JavaScript. Detect intersections between game entities to trigger collision events.

- Repository: [Microsoft/Web-Dev-For-Beginners](https://github.com/microsoft/Web-Dev-For-Beginners)
- Tags: how-to-guide
- Published: 2026-02-27

---

**The space game canvas collision detection algorithm uses an axis-aligned bounding box (AABB) overlap test to determine when rectangular game entities intersect, checking geometric boundaries each frame to trigger collision events between heroes, enemies, and lasers.**

The collision detection system in Microsoft's Web-Dev-For-Beginners repository demonstrates a foundational approach to handling interactions in HTML5 canvas games. This space game canvas collision detection algorithm relies on pure geometric calculations rather than physics engines, comparing the rectangular bounds of sprites to detect overlaps and emit game state changes through an event-driven architecture.

## Understanding the Axis-Aligned Bounding Box Approach

The algorithm employs **axis-aligned bounding boxes (AABB)**, a standard technique in 2D game development where every game object is treated as a non-rotated rectangle defined by its top, left, right, and bottom edges. This simplification allows collision detection to use simple numerical comparisons rather than complex polygon intersection calculations, making it ideal for beginner-friendly canvas games where sprites remain parallel to the canvas edges.

## Core Components of the Collision System

### The intersectRect Function

The geometric heart of the system resides in the `intersectRect` function located at lines 126-128 in [`6-space-game/4-collision-detection/solution/app.js`](https://github.com/microsoft/Web-Dev-For-Beginners/blob/main/6-space-game/4-collision-detection/solution/app.js). This pure function implements the separating axis theorem for rectangles by checking if one rectangle's left edge is to the right of the other's right edge, or if one's top is below the other's bottom:

```javascript
function intersectRect(r1, r2) {
  return !(
    r2.left > r1.right ||
    r2.right < r1.left ||
    r2.top > r1.bottom ||
    r2.bottom < r1.top
  );
}

```

If any of these four separating conditions are true, the function returns `false` (no collision); otherwise, the rectangles overlap and it returns `true`.

### The rectFromGameObject Method

Every drawable entity in the game—`Hero`, `Enemy`, and `Laser`—inherits from the `GameObject` class, which provides the `rectFromGameObject` method at lines 36-43. This method converts an entity's position and dimensions into a rectangle object compatible with `intersectRect`:

```javascript
rectFromGameObject() {
  return {
    top: this.y,
    left: this.x,
    bottom: this.y + this.height,
    right: this.x + this.width,
  };
}

```

By centralizing this conversion, the system ensures consistent boundary calculations across all game object types, regardless of their specific sprite implementations.

### The updateGameObjects Function

The collision orchestration occurs within `updateGameObjects` at lines 206-229, which the game loop invokes every 100 milliseconds. This function filters the global `gameObjects` array into enemies and lasers, then executes pairwise collision checks:

1. **Hero-Enemy Collisions**: Each enemy rectangle is tested against the hero rectangle using `intersectRect`. On overlap, the system emits `Messages.COLLISION_ENEMY_HERO`.
2. **Laser-Enemy Collisions**: Nested loops check every laser against every enemy. Successful intersections emit `Messages.COLLISION_ENEMY_LASER`.
3. **Cleanup**: Objects marked as `dead` are filtered from the array, preventing them from being drawn or participating in later collisions.

## Step-by-Step Collision Detection Flow

The algorithm executes through a deterministic sequence each frame:

- **Bounding Box Extraction**: For every entity participating in collision, `rectFromGameObject()` generates current position data based on `x`, `y`, `width`, and `height` properties.
- **Separating Axis Test**: `intersectRect()` applies the AABB overlap logic, verifying that no edge of one rectangle exists completely outside the corresponding edge of the other.
- **Event Dispatch**: Upon detection, the `eventEmitter` broadcasts specific collision events without immediately modifying game state, maintaining separation between detection and response logic.
- **Object Lifecycle Management**: The system flags destroyed objects and purges them from the global pool, ensuring computational efficiency in subsequent frames.

## Practical Implementation Examples

### Basic AABB Intersection Test

You can reuse the core collision logic independently of the game framework:

```javascript
function intersectRect(r1, r2) {
  return !(
    r2.left > r1.right ||
    r2.right < r1.left ||
    r2.top > r1.bottom ||
    r2.bottom < r1.top
  );
}

// Example usage
const heroRect = { left: 50, top: 100, right: 149, bottom: 175 };
const enemyRect = { left: 120, top: 150, right: 218, bottom: 200 };
console.log(intersectRect(heroRect, enemyRect)); // true (overlap detected)

```

### Integrating Collision Detection into the Game Loop

The collision system hooks into the main animation cycle through `updateGameObjects`:

```javascript
function gameLoop() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  updateGameObjects();   // Collision detection executes here
  drawGameObjects(ctx);  // Render surviving entities
}

// Initialize 100ms interval
setInterval(gameLoop, 100);

```

### Extending the System for New Object Types

To add power-up collisions, extend the message enum and collision logic:

```javascript
// 1. Define new message type
const Messages = {
  COLLISION_ENEMY_HERO: 'COLLISION_ENEMY_HERO',
  COLLISION_ENEMY_LASER: 'COLLISION_ENEMY_LASER',
  COLLISION_HERO_POWERUP: 'COLLISION_HERO_POWERUP',
};

// 2. Add collision check in updateGameObjects
const powerUps = gameObjects.filter(go => go.type === 'PowerUp');
powerUps.forEach(pu => {
  if (intersectRect(pu.rectFromGameObject(), hero.rectFromGameObject())) {
    eventEmitter.emit(Messages.COLLISION_HERO_POWERUP, { powerUp: pu });
  }
});

// 3. Register handler in initGame()
eventEmitter.on(Messages.COLLISION_HERO_POWERUP, (_, { powerUp }) => {
  powerUp.dead = true;
  hero.points += 500;
});

```

## Summary

- The **space game canvas collision detection algorithm** relies on **axis-aligned bounding box (AABB)** intersection tests to detect overlaps between rectangular game entities.
- The **`intersectRect`** function at lines 126-128 implements the separating axis theorem through simple edge comparisons, returning `true` only when rectangles overlap on both X and Y axes.
- **`rectFromGameObject`** converts entity positions and dimensions into geometric bounds at lines 36-43, ensuring consistent rectangle representation across all sprite types.
- **`updateGameObjects`** orchestrates collision detection at lines 206-229 by filtering game entities, executing pairwise AABB tests, emitting collision events, and purging destroyed objects from the global pool.
- The **event-driven architecture** decouples collision detection from game logic, allowing developers to extend the system with new collision types without modifying the core geometric algorithms.

## Frequently Asked Questions

### What type of collision detection does the space game use?

The space game uses **axis-aligned bounding box (AABB)** collision detection, which treats every sprite as a non-rotated rectangle defined by its top, left, right, and bottom edges. This geometric approach uses the `intersectRect` function to check for overlaps by comparing the relative positions of these edges, making it computationally efficient for 2D canvas games where objects remain parallel to the screen boundaries.

### How does the intersectRect function determine if two objects collide?

The `intersectRect` function applies the **separating axis theorem** by checking four conditions: whether rectangle B's left edge is to the right of rectangle A's right edge, B's right edge is to the left of A's left edge, B's top is below A's bottom, or B's bottom is above A's top. If any of these separating conditions are true, the rectangles do not overlap and the function returns `false`; otherwise, it returns `true` indicating a collision has occurred.

### Can this collision algorithm handle rotated objects?

No, the AABB algorithm used in this space game cannot accurately detect collisions for rotated objects because it assumes all rectangles remain axis-aligned (parallel to the canvas edges). If sprites rotate, the bounding boxes would need to be recalculated as **oriented bounding boxes (OBB)** or use polygon collision detection, requiring replacement of the simple `intersectRect` logic with trigonometric calculations to account for rotation angles.

### How do I add new collision types to the space game?

To add new collision types, first define a new message constant in the `Messages` object (e.g., `COLLISION_HERO_POWERUP`), then add a collision check inside `updateGameObjects` that filters for the new object type and calls `intersectRect` against the hero or other entities. Finally, register an event handler using `eventEmitter.on()` to manage the game logic consequences, such as updating scores or marking objects as `dead`, without modifying the core geometric algorithm in `intersectRect`.