console
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
class Ball {
constructor(x, y, radius) {
this.x = x
this.y = y
this.radius = radius
this.dx = Math.random() * 5
this.dy = Math.random() * 5
this.flag = false
}
draw(ctx) {
ctx.beginPath()
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI)
ctx.closePath()
ctx.fillStyle = 'blue'
ctx.fill()
}
collide(ball) {
const dx = this.x - ball.x
const dy = this.y - ball.y
const dl = Math.sqrt(dx * dx + dy * dy)
return dl <= this.radius + ball.radius
}
redirect(ball) {
if (!this.flag) {
const dx = ball.dx; ball.dx = this.dx; this.dx = dx;
const dy = ball.dy; ball.dy = this.dy; this.dy = dy;
this.flag = true
ball.flag = true
}
}
}
const balls = []
while (balls.length < 5) {
const radius = Math.random() * 20 + 10
const x = Math.random() * (canvas.width - radius - radius) + radius
const y = Math.random() * (canvas.height - radius - radius) + radius
const newBall = {x, y, radius}
if (balls.every( x => !x.collide(newBall))) {
balls.push(new Ball(x, y, radius))
}
}
function drawFrame () {
window.requestAnimationFrame(drawFrame, canvas)
canvas.height = canvas.height
ctx.strokeRect(0, 0, canvas.width, canvas.height)
for (let ball of balls) {
ball.x += ball.dx
ball.y -= ball.dy
ball.draw(ctx)
ball.flag = false
}
for (let i = 0; i < balls.length; i++) {
const ball = balls[i]
if (!ball.flag) {
if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
ball.dx = -ball.dx
ball.flag = true
}
if (ball.y - ball.radius < 0 || ball.y + ball.radius > canvas.height) {
ball.dy = -ball.dy
ball.flag = true
}
}
for (let j = i + 1; j < balls.length; j++) {
if (ball.collide(balls[j])) {
ball.redirect(balls[j])
}
}
}
}
drawFrame()
<canvas id="canvas" width="300" height="300"></canvas>