So I have this code that creates a number of balls and they get random x, y, and velocities, and they kind of just bounce around the screen, this part works great, but I want more. I have been trying to figure out how to get them to collide and bounce off in opposite directions. I've been trying to figure out what I've done wrong but I have not been able to figure it out for about 30 minutes, any suggestions?
var canvas = document.getElementById('gamecanvas');
var c = canvas.getContext('2d');
var ma = Math.random;
var mo = Math.round;
var ballcount = 5;
var balls = [];
function setup() {
//canvas
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
for (i = 0; i < ballcount; i++) {
//ball setup
r = mo(ma() * 40) + 10;
y = mo(ma() * (canvas.height - r));
x = mo(ma() * (canvas.width - r));
vx = mo(ma() * 20) - 10;
vy = mo(ma() * 20) - 10;
balls[i] = { x, y, vx, vy, r };
}
}
function gameloop() {
//clear
c.clearRect(0, 0, canvas.width, canvas.height);
c.strokeStyle = 'white';
//move
for (i = 0; i < ballcount; i++) {
balls[i].x += balls[i].vx;
balls[i].y += balls[i].vy;
//wall collision
if (balls[i].x <= balls[i].r) {
balls[i].x = balls[i].r;
balls[i].vx *= -1;
}
if (balls[i].y <= balls[i].r) {
balls[i].y = balls[i].r;
balls[i].vy *= -1;
}
if (balls[i].x >= canvas.width - balls[i].r) {
balls[i].x = canvas.width - balls[i].r;
balls[i].vx *= -1;
}
if (balls[i].y >= canvas.height - balls[i].r) {
balls[i].y = canvas.height - balls[i].r;
balls[i].vy *= -1;
}
//ball collision
for (j = 0; j < ballcount; j++) {
if(i != j) {
dx = balls[j].x - balls[i].x;
dy = balls[j].y - balls[i].y;
rs = balls[j].r + balls[i].r;
if(Math.sqrt((dx * dx) - (dy * dy)) < rs) {
balls[i].vx *= -1;
balls[j].vx *= -1;
}
}
}
}
//draw
c.beginPath();
for (i = 0; i < ballcount; i++) {
c.moveTo(balls[i].x + balls[i].r, balls[i].y);
c.arc(balls[i].x, balls[i].y, balls[i].r, 0, 7);
}
c.stroke();
}
setup();
setInterval(gameloop, 1000 / 60);
body {
background-color: black;
overflow: hidden;
margin: 0;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="index.css">
<title>Bslls</title>
</head>
<body id="body">
<canvas id="gamecanvas"></canvas>
<script src="index.js"></script>
</body>
</html>
Hints:
There are two subproblems: finding the collision point and reflecting the trajectories.
To find the collision point, you can reason as follows:
inflate one ball by the radius of the other and let the other reduce to a point;
consider the relative speeds of the ball and the point (i.e. vector difference), and move the ball to the origin.
Now you have a fixed circle and a point moving along a straight line. You can find the first intersection point between the circle and the line by solving a quadratic equation. The most convenient is to use the parametric equation of the point motion vs. the implicit equation of the circle. For the same price, you get the meeting time.
To reflect the trajectories, consider that the normal to the circle at the intersection point is the bisector of the incident and reflected directions. In case of a perfect elastic shock, the speed after reflection is the same as before.
Now by undoing the initial transformations, you can find the meeting point and the new directions of the two balls.
Just a bit of vector calculus :-)