DEV Community

hifijohn
hifijohn

Posted on

bouncing ball in html

click any where on the screen and watch the balls bounce off of each other

<!DOCTYPE html>



Bouncing Balls by XAWPHAD html, body { margin: 0; padding: 0; background: black; overflow: hidden; } canvas { display: block; }

const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
resizeCanvas();

window.addEventListener("resize", resizeCanvas);
canvas.addEventListener("click", createBall);

let balls = [];
const MAX_SPEED = 28; // Disappear threshold
const SPEED_INCREASE = 1.07; // Gentler acceleration on collision

function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}

class Ball {
constructor(x, y, radius, color, dx, dy) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.dx = dx;
this.dy = dy;
}

draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
}

update() {
this.x += this.dx;
this.y += this.dy;

// Bounce off left/right edges
if (this.x - this.radius &lt; 0) {
  this.x = this.radius; // reposition inside
  this.dx *= -1;
} else if (this.x + this.radius &gt; canvas.width) {
  this.x = canvas.width - this.radius;
  this.dx *= -1;
}

// Bounce off top/bottom edges
if (this.y - this.radius &lt; 0) {
  this.y = this.radius;
  this.dy *= -1;
} else if (this.y + this.radius &gt; canvas.height) {
  this.y = canvas.height - this.radius;
  this.dy *= -1;
}
Enter fullscreen mode Exit fullscreen mode

}

getSpeed() {
return Math.sqrt(this.dx * this.dx + this.dy * this.dy);
}
}

function createBall(event) {
const x = event.clientX;
const y = event.clientY;

// Smaller overall balls
const radius = Math.random() * 15 + 8;
const color = hsl(${Math.random() * 360}, 80%, 60%);
const speed = Math.random() * 4 + 1;
const angle = Math.random() * Math.PI * 2;
const dx = Math.cos(angle) * speed;
const dy = Math.sin(angle) * speed;

balls.push(new Ball(x, y, radius, color, dx, dy));
}

function handleCollisions() {
for (let i = 0; i < balls.length; i++) {
for (let j = i + 1; j < balls.length; j++) {
const b1 = balls[i];
const b2 = balls[j];
const dx = b2.x - b1.x;
const dy = b2.y - b1.y;
const distance = Math.sqrt(dx * dx + dy * dy);

  if (distance &lt; b1.radius + b2.radius) {
    // Swap velocities
    const tempDx = b1.dx;
    const tempDy = b1.dy;
    b1.dx = b2.dx;
    b1.dy = b2.dy;
    b2.dx = tempDx;
    b2.dy = tempDy;

    // Slight speed increase
    b1.dx *= SPEED_INCREASE;
    b1.dy *= SPEED_INCREASE;
    b2.dx *= SPEED_INCREASE;
    b2.dy *= SPEED_INCREASE;

    // Separate to avoid overlap sticking
    const overlap = (b1.radius + b2.radius - distance) / 2;
    const nx = dx / distance;
    const ny = dy / distance;
    b1.x -= nx * overlap;
    b1.y -= ny * overlap;
    b2.x += nx * overlap;
    b2.y += ny * overlap;
  }
}
Enter fullscreen mode Exit fullscreen mode

}

// Remove balls going too fast
balls = balls.filter(b => b.getSpeed() <= MAX_SPEED);
}

function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
balls.forEach(ball => {
ball.update();
ball.draw();
});
handleCollisions();
requestAnimationFrame(animate);
}

animate();

Top comments (0)