/** * Check if 2 circles collide * * Takes velocities and alters them as if the coordinate system they're on was rotated * * @param Number | p1x | x coordinate of the first particle * @param Number | p1y | y coordinate of the first particle * @param Number | r1 | radius of the first particle * @param Number | p2x | x coordinate of the second particle * @param Number | p2y | y coordinate of the second particle * @param Number | r2 | radius of the second particle * @return Boolean | true if particles are in collision */ const checkCollision = (p1x, p1y, r1, p2x, p2y, r2) => ((r1 + r2) ** 2 > (p1x - p2x) ** 2 + (p1y - p2y) ** 2) /** * Rotates coordinate system for velocities * * Takes velocities and alters them as if the coordinate system they're on was rotated * * @param Object | velocity | The velocity of an individual particle * @param Float | angle | The angle of collision between two objects in radians * @return Object | The altered x and y velocities after the coordinate system has been rotated */ function rotate(velocity, angle) { const rotatedVelocities = { x: velocity.x * Math.cos(angle) - velocity.y * Math.sin(angle), y: velocity.x * Math.sin(angle) + velocity.y * Math.cos(angle) }; return rotatedVelocities; } /** * Swaps out two colliding particles' x and y velocities after running through * an elastic collision reaction equation * * @param Object | particle | A particle object with x and y coordinates, plus velocity * @param Object | otherParticle | A particle object with x and y coordinates, plus velocity * @return Null | Does not return a value */ function resolveCollision(particle, otherParticle) { const xVelocityDiff = particle.velocity.x - otherParticle.velocity.x; const yVelocityDiff = particle.velocity.y - otherParticle.velocity.y; const xDist = otherParticle.x - particle.x; const yDist = otherParticle.y - particle.y; // Prevent accidental overlap of particles if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0) { // Grab angle between the two colliding particles const angle = -Math.atan2(otherParticle.y - particle.y, otherParticle.x - particle.x); // Store mass in var for better readability in collision equation const m1 = particle.mass; const m2 = otherParticle.mass; // Velocity before equation const u1 = rotate(particle.velocity, angle); const u2 = rotate(otherParticle.velocity, angle); // Velocity after 1d collision equation const v1 = { x: u1.x * (m1 - m2) / (m1 + m2) + u2.x * 2 * m2 / (m1 + m2), y: u1.y }; const v2 = { x: u2.x * (m1 - m2) / (m1 + m2) + u1.x * 2 * m2 / (m1 + m2), y: u2.y }; // Final velocity after rotating axis back to original location const vFinal1 = rotate(v1, -angle); const vFinal2 = rotate(v2, -angle); // Swap particle velocities for realistic bounce effect particle.velocity.x = vFinal1.x; particle.velocity.y = vFinal1.y; otherParticle.velocity.x = vFinal2.x; otherParticle.velocity.y = vFinal2.y; } }