Circle Collision Detection and Animation: Exploring JavaScript and Canvas API

·

3 min read

Continuing from the previous article, in this article, we will focus on:

  1. Displaying an additional ball on the screen using the Point and Circle objects.

  2. Checking collisions between the objects on the screen.

  3. Moving the objects.

In the previous article, we had two balls moving on the screen, and when they reached the screen's boundaries, they would change direction.

Each Point object represents a point on the screen. In this case, we have two points: a(50, 50) and b(100, 100).

let a = new Point(50, 50);
let b = new Point(1000 , 100);

From these two points, we will initialize two circles: CircleA and CircleB.

constructor(point, radius, dx = 1, dy = 1)

Here, the point parameter represents the point a or b, radius is the radius of the ball, and dx and dy are the movement speeds, with a default value of 1. A higher value for dx or dy means the ball will move faster.

Inside the Circle class, we have the following methods: draw() to draw the ball, move() to determine the ball's movement, and changeDirection() to change the ball's direction upon collision.

Now, we have two circles: circleA and circleB.

let  circleA = new Circle(a, 50, 2);
let  circleB = new Circle(b, 100, 3);

To detect collisions between the two circles, we need to consider the distance between their centers and the sum of their radii.

If the sum of the radii is equal to the distance between the two points, the two balls will collide. When they collide, the balls will change direction and move in the opposite direction.

const distance = (A, B) => {
    let dx = (A.point.x  + circleA.radius) - (B.point.x  + circleB.radius)
    let dy = (A.point.y  + circleA.radius) - (B.point.y  + circleB.radius)
    console.log (Math.sqrt((dx * dx) + (dy * dy)))
    return (Math.sqrt((dx * dx) + (dy * dy)))
}

const checkCollision = (A, B) => {
    let distanceAB = distance(A, B)
    let totalRadius = A.radius + B.radius
    console.log (totalRadius <  distanceAB);
    return (totalRadius <  distanceAB);
}

Result below

const createCanvas = document.createElement("canvas");
createCanvas.id = "canvas";
document.body.appendChild(createCanvas);
const fullWidth = window.innerWidth;
const fullHeight = window.innerHeight;
const canvas = document.getElementById("canvas");
canvas.width = fullWidth;
canvas.height = fullHeight;
const context = canvas.getContext("2d");
class Point {
    constructor(x, y){
        this.x = x;
        this.y = y;
    }
}

class Circle {
    constructor(point, radius, dx = 1, dy = 1) {
        this.point = point
        this.radius = radius
        this.dx = dx
        this.dy = dy
    }
    draw() {
        context.beginPath();        
        context.ellipse(
        this.point.x + this.radius,
        this.point.y + this.radius,
        this.radius,
        this.radius,
        Math.PI / 4,
        0,
        2 * Math.PI
        );
        context.closePath();
        context.stroke();
    }
    move(){
        this.draw()
        this.point.x += this.dx
        this.point.y += this.dy
        if (this.point.x + 2*this.radius >= canvas.width || this.point.x < 0) {
            this.dx = -this.dx
        }
        if (this.point.y + 2*this.radius >= canvas.height || this.point.y < 0) {
            this.dy = -this.dy
        }
    }
    changeDirection(){
        this.dx = -this.dx
        this.dy = -this.dy
    }
}
let a = new Point(100, 100);
let b = new Point(1000 , 100);
let  circleA = new Circle(a, 50, 2);
let  circleB = new Circle(b, 100, 3);
const distance = (A, B) => {
    let dx = (A.point.x  + circleA.radius) - (B.point.x  + circleB.radius)
    let dy = (A.point.y  + circleA.radius) - (B.point.y  + circleB.radius)
    return (Math.sqrt((dx * dx) + (dy * dy)))
}
const checkCollision = (A, B) => {
    let distanceAB = distance(A, B)
    let totalRadius = A.radius + B.radius
    return (totalRadius <  distanceAB);
}
const animation = () => {
    context.clearRect(0, 0, canvas.width, canvas.height);
    circleA.move();
    circleB.move();
    if (!checkCollision(circleA, circleB)) {
        circleA.changeDirection()
        circleB.changeDirection()
   }
    requestAnimationFrame(animation)
}

animation()