-
-
Save christopher4lis/f9ccb589ee8ecf751481f05a8e59b1dc to your computer and use it in GitHub Desktop.
/** | |
* 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; | |
} | |
} |
Problem 1: collisIon resolving actually overlaps circles
Problem 2: when we set different masses for circles total energy in canvas is increased on several collisions (at least for my code )...
Problem 1:
// Prevent accidental overlap of particles
if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0)
i don't know why but this code gave bug in my code. if circles touched then they overlapped each other providing a centrifugal force(or centripetal i don't remember).
Later I changed it to if (xVelocityDiff * xDist + yVelocityDiff * yDist <= 0) it worked perfect
Problem 2:
there's something in comments above about this problem...refer to that
Thank you.
For those who wonder this line if (xVelocityDiff * xDist + yVelocityDiff * yDist >=0 )
This line is actually to detect if 2 overlapped circles are moving towards each other or not. If not, no need to perform a resolving process.
The actual inequality (if 2 circles are moving away) is (x + dx)^2 + (y + dy)^2 > x^2 + y^2
(velocity = dx / dy). After streamlined, you'll get the line.
Note that, in this example, velocityDiff & dist are inconsistently calculated upon.
u guys r awesome
Hi! Thanks for the nice utility. Unfortunately this will only work for particles with the same mass. There are two small mistakes in the calculations for the second velocity.
Line 52: const v2 = { x: u2.x * (m1 - m2) / (m1 + m2) + u1.x * 2 * m2 / (m1 + m2), y: u2.y };
Should be: const v2 = { x: u2.x * (m2 - m1) / (m1 + m2) + u1.x * 2 * m1 / (m1 + m2), y: u2.y };
There is actually a mistake in the formula that only shows up if the colliding circles have different masses. you have two swap the subscipts of the masses too. At least where there is subtraction and division.