Back

HTML5 Canvas: Advanced Physics and Collision (Hitbox)

12 min read

HTML5 Canvas: Advanced Physics and Hitbox Collision

Drawing a player and applying gravity is fantastic, but a game isn't a game until objects interact. When a player's foot hits a ball, the ball needs to fly! When the ball hits the ground, it shouldn't just stick—it needs to bounce and roll to a stop.

This module will teach you Hitbox Collision Detection and Advanced Projectile Physics (Bounciness and Friction) in a simple, understandable way.

1. The Hitbox: AABB Collision Detection

In 2D games, we usually don't calculate collisions pixel-by-pixel—it's too slow. Instead, we draw an invisible rectangular box around our sprite called a Hitbox (or Bounding Box).

The industry standard algorithm for checking if two rectangles overlap is called AABB (Axis-Aligned Bounding Box). The math is surprisingly simple! We check four absolute limits:

// Function returns TRUE if Box1 and Box2 overlap 
function checkAABBCollision(box1, box2) {
  // We check if it's IMPOSSIBLE for them to collide first.
  // Example: Is Box1's right edge further left than Box2's left edge?
  return (
    box1.x < box2.x + box2.width &&   // Box1 Left is past Box2 Right
    box1.x + box1.width > box2.x &&   // Box1 Right is past Box2 Left
    box1.y < box2.y + box2.height &&  // Box1 Top is past Box2 Bottom
    box1.y + box1.height > box2.y     // Box1 Bottom is past Box2 Top
  );
}

If ALL those conditions are true, the two objects are currently crashing into each other!

2. Advanced Game Physics: The Ball

If you are making a sports or platformer game, your ball needs to feel realistic. A true physics ball requires two new concepts:

  1. Bounce / Restitution: When it hits the floor, it reverses direction (-dy), but it loses some energy so it doesn't bounce forever.
  2. Friction / Drag: When rolling left or right, the grass slows it down until it completely stops.
class Ball {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.width = 50;  // Standardizing hitbox
    this.height = 50;
    
    // Physics properties
    this.dx = 0; // Horizontal speed
    this.dy = 0; // Vertical falling speed
    this.gravity = 0.5;
    
    // THE SECRET INGREDIENTS
    this.bounce = -0.7; // Loses 30% of energy every bounce
    this.friction = 0.98; // Multiplies dx to slow it down 2% every frame
  }

  update(groundLevel) {
    // 1. Apply Gravity
    this.dy += this.gravity;
    
    // 2. Apply Friction to slow rolling
    this.dx *= this.friction; 

    // Stop completely if the speed is incredibly slow (micro-movements)
    if (Math.abs(this.dx) < 0.1) this.dx = 0;

    // 3. Move the Ball
    this.x += this.dx;
    this.y += this.dy;

    // 4. Floor Collision & Bouncing Logic
    if (this.y + this.height >= groundLevel) {
      this.y = groundLevel - this.height; // Prevent sinking
      
      // Only bounce if falling fast enough (prevents infinite micro-jitters)
      if (this.dy > 1) {
        this.dy *= this.bounce; // Reverse direction and lose energy!
      } else {
        this.dy = 0; // Settle on the ground completely
      }
    }
  }
}

3. Creating the Impact (Transferring Momentum)

How do we put everything together? Inside your Game Loop, you use your AABB math to check if the Player touches the Ball. If they touch, AND the player is currently in the "Kick" animation state, we instantly inject explosive velocity (dx and dy) into the ball!

// Inside your requestAnimationFrame Loop...

// 1. Update entities
player.update();
ball.update(canvas.height - 90);

// 2. Check Hitbox Collision
if (checkAABBCollision(player, ball)) {
  
  // Did the player hit the kick button just now?
  if (player.state === "Kick") {
    
    // BOOM! Transfer huge momentum to the ball
    // Shoot it upwards and forwards!
    ball.dy = -15; 
    
    // Shoot left or right depending on player's side
    if (player.position === "left") {
      ball.dx = 20; // Blast to the right
    } else {
      ball.dx = -20; // Blast to the left
    }
  } else {
    // If just walking into it normally, nudge the ball slightly
    ball.dx = player.dx * 1.2; 
  }
}

With these three steps, your characters no longer pass through objects like ghosts! You have successfully implemented a professional Physics Engine logic within HTML5 Canvas.