How to code collision detection using Javascript a step-by-step guide.
Yash Solanki
Software Engineer | MLSA 2024 | Campus Ambassador at ADC | Co-founder at COL | MERN | NEXT.JS | NEST.JS
Understanding Collision Detection in HTML Canvas
When creating games or interactive animations, one of the key concepts you'll encounter is collision detection. Whether you're designing a simple ball bouncing game or a complex multiplayer experience, understanding how to detect and respond to collisions is crucial.
In this article, we'll delve into the principles of collision detection, particularly in the context of HTML canvas, and provide a practical example featuring a rectangle and a circle.
What is collisiion?
Collision is an event where two or more objects come into contact or intersect. In computer graphics and games, it involves detecting when shapes like circles or rectangles overlap, allowing for realistic interactions like bouncing, stopping, or triggering events.
The Principle of Collision Detection
There are various methods to detect collisions, depending on the shapes and the level of precision required. The most common techniques include:
In this article, we'll focus on a practical example using the bounding box and circle collision methods to detect interactions between a rectangle and a circle on the HTML canvas.
What we will achieve:
HTML and CSS Setup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Collision Detection</title>
<style>
body, html {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #000;
}
canvas {
display: block;
background-color: #111;
}
</style>
</head>
<body>
<canvas id="gameCanvas"></canvas>
<script src="collision.js"></script>
</body>
</html>
In this setup, we define a basic HTML structure with a canvas element, styled to occupy the full screen and have a dark background. The collision.js script will contain the main logic for our collision detection.
JavaScript: Rect Class
Rect is the class that we will use to create the rectangle object on our HTML canvas. This class will have a constructor, a draw() method and an update() method along with a getBounds() utility method. We will look into each of them one by one.
1. Constructor
class Rect {
constructor(x, y, width, height, color) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.velocity = {
x: random(-3, 3),
y: random(-3, 3)
};
}
}
Explanation:
2. draw() Method
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
Explanation:
The draw() method is responsible for rendering the rectangle on the canvas using its current properties.
3. update() Method
update() {
this.x += this.velocity.x;
this.y += this.velocity.y;
// Check for collision with canvas edges
if (this.x + this.width > canvas.width || this.x < 0) {
this.velocity.x = -this.velocity.x;
}
if (this.y + this.height > canvas.height || this.y < 0) {
this.velocity.y = -this.velocity.y;
}
this.draw();
}
Explanation:
How velocity works?
The velocity object controls the speed and direction of the rectangle's movement. It has two properties:
By updating the x and y positions with these velocity values in the update() method, the rectangle moves across the canvas. The collision detection with the canvas edges reverses the respective velocity, creating a bouncing effect.
4. getBounds() Method
getBounds() {
return {
left: this.x,
right: this.x + this.width,
top: this.y,
bottom: this.y + this.height
};
}
Really simple logic. The getBounds method returns an object with the pixel values of it's edges.
Thus moving ahead with the circle class it has similar logic as the rect class with only difference being the draw() method.
领英推荐
JavaScript: Circle Class
Circle is the class that we will use to create the circle object on our HTML canvas. This class will have a constructor, a draw() method and an update() method along with a getBounds() utility method. We will look into each of them one by one.
1. Constructor
class Circle {
constructor(x, y, radius, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.velocity = {
x: random(-3, 3),
y: random(-3, 3)
};
}
}
Explanation:
2. draw() Method
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
ctx.fillStyle = this.color;
ctx.fill();
ctx.closePath();
}
The draw() method is responsible for rendering the circle on the canvas using its current properties.
3. update() Method
update() {
this.x += this.velocity.x;
this.y += this.velocity.y;
// Check for collision with canvas edges
if (this.x + this.radius > canvas.width || this.x - this.radius < 0) {
this.velocity.x = -this.velocity.x;
}
if (this.y + this.radius > canvas.height || this.y - this.radius < 0) {
this.velocity.y = -this.velocity.y;
}
this.draw();
}
Explanation:
4. getBounds() Method
getBounds() {
return {
left: this.x - this.radius,
right: this.x + this.radius,
top: this.y - this.radius,
bottom: this.y + this.radius
};
}
Explanation
The getBounds() method calculates the edges of the circle based on its center coordinates (x, y) and its radius:
Starting the Animation engine
Now that we have coded our objects, It's time to look into coding our animation loop and create the instance of the Rect and Circle classes.
// Initialize rectangle and circle
const rect = new Rect(100, 100, 100, 100, 'red');
const circle = new Circle(300, 300, 50, 'blue');
// Animation loop
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
rect.update();
circle.update();
requestAnimationFrame(animate);
}
animate();
You must have noticed that we have still not checked the collision between the rectange and circle. So let's code a simple function that will check the collision in each animation frame.
The Collision detection function:
The checkCollision function checks if a rectangle and a circle collide on a canvas. It calculates the closest point on the rectangle to the circle's center, then determines if the distance from this point to the circle's center is less than the circle's radius. Here's a detailed explanation of each part:
Function definition and Setup
function checkCollision(rect, circle) {
const rectBounds = rect.getBounds();
const circleBounds = circle.getBounds();
Finding the Closest Point on the Rectangle to the Circle's Center
// Closest point on the rectangle to the circle
const closestX = Math.max(rectBounds.left, Math.min(circle.x, rectBounds.right));
const closestY = Math.max(rectBounds.top, Math.min(circle.y, rectBounds.bottom));
Calculating the Distance from the Closest Point to the Circle's Center
// Distance from closest point to the circle center
const distanceX = circle.x - closestX;
const distanceY = circle.y - closestY;
Collision Detection
return Math.sqrt(distanceX ** 2 + distanceY ** 2) < circle.radius;
Now that we have implemented the collision detection function. We will include it in our animation frame.
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
rect.update();
circle.update();
//Include collision detection
if (checkCollision(rect, circle)) {
rect.color = 'green';
circle.color = 'yellow';
} else {
rect.color = 'red';
circle.color = 'blue';
}
requestAnimationFrame(animate);
}
AND THAT'S IT!!
That is all you need in order to implement a simple collision detection.
Thanks for reading this article. This was my first ever article on LinkedIn. I would greatly appreciate your feedback. Peace.
Pursuing a dual degree: BSc Data Science and AI at IIT Madras + Bachelor of Engineering at New LJ Institute. Passionate about AI and engineering, exploring innovative intersections in tech. Let’s connect!
7 个月Insightful!
Student at New L.J institute of engineering and technology
7 个月Superb??
Data Science Intern at RESOLUTE CORP BHARAT PRIVATE LIMITED | Data Science | Azure Machine Learning | Deep Learning | GenAI | Computer vision | Python Developer | Flutter Android Development |
7 个月Excellent!!
Intern at Infopercept
7 个月Great work!!