Circle Collision Detection and Animation: Exploring JavaScript and Canvas API
Photo by jyothi kumar on Unsplash
Continuing from the previous article, in this article, we will focus on:
Displaying an additional ball on the screen using the Point and Circle objects.
Checking collisions between the objects on the screen.
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()