Forked from christopher4lis/util-elastic-collision.js
Last active
November 8, 2019 20:48
-
-
Save gyopiazza/c924f83087288fe429539b808bcbf94d to your computer and use it in GitHub Desktop.
A set of utility functions used to reproduce the effect of elastic collision within HTML5 canvas. Used in the Chris Courses tutorial video on collision detection: https://www.youtube.com/watch?v=789weryntzM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment