const intendedDT = speedMult;
const dt = intendedDT / (substeps);
function mouseClicked() {
particles.push(new Particle(mouseX, mouseY, cursorBonds, particles.length, cursorBonds))
for(let i = 0; i < cursorBonds; i++) {
let ang = random(-PI, PI)
particles.push(new Particle(mouseX + sin(ang) * 10, mouseY + cos(ang) * 10, 1, particles.length, 1));
createCanvas(windowWidth, windowHeight);
for (let i = 0; i < numEach; i++) {
let x = random(0, width/2);
let y = random(0, height-10);
particles.push(new Particle(x, y-10, 1, i));
particles.push(new Particle(x, y, bonds, i, 2));
particles.push(new Particle(x, y+10, 1, i));
for (let i = numEach; i < numEach + numEach; i++) {
let x = random(width/2, width);
let y = random(0, height-10);
particles.push(new Particle(x, y, bonds, i, 4));
particles.push(new Particle(x, y+10, 1, i));
particles.push(new Particle(x, y-10, 1, i));
particles.push(new Particle(x+5, y, 1, i));
particles.push(new Particle(x-5, y, 1, i));
let l = particles.length;
for (let i = 0; i < substeps; i++) {
for (let i = 0; i < particles.length; i++) {
for (let bond = 0; bond < particles[i].bonded.length; bond++) {
let avgX = 0.5 * (x + particles[i].bonded[bond].x);
let avgY = 0.5 * (y + particles[i].bonded[bond].y);
if (particles[i].bondStrengths[bond] > 1) {
if (particles[i].bondStrengths[bond] > 1 && i > particles[i].bonded[bond].id) {
line(x, y, particles[i].bonded[bond].x, particles[i].bonded[bond].y);
for (let i = 0; i < particles.length; i++) {
fill(colors[particles[i].bonds - 1])
circle(particles[i].x, particles[i].y, 5 + particles[i].bonds);
for (let i = 0; i < particles.length; i++) {
particles[i].addForce(random(heating / dt, -heating / dt), random(heating / dt, -heating / dt));
for (let j = 0; j < particles.length; j++) {
let dist = sqrt((particles[i].x - particles[j].x) ** 2 + (particles[i].y - particles[j].y) ** 2);
if (dist > 120) continue;
let normalX = (particles[i].x - particles[j].x) / dist;
let normalY = (particles[i].y - particles[j].y) / dist;
let avgX = 0.5 * (particles[i].x + particles[j].x);
let avgY = 0.5 * (particles[i].y + particles[j].y);
let center = createVector(avgX, avgY);
let angle = atan2(normalY, normalX);
let potentialSingleStrength = particles[i].bondStrength(particles[i], 1);
let potentialDoubleStrength = particles[i].bondStrength(particles[i], 1);
0.5 * (particles[i].bonds + particles[j].bonds) *
((particles[i].vx - particles[j].vx) ** 2 + (particles[i].vy - particles[j].vy) ** 2);
if (dist < 14 && particles[i].availableBonds >= 1 && (particles[i].primeAmt > 0 || collisionEnergy * 0.25 > potentialSingleStrength**2)) {
if (particles[j].availableBonds >= 1) {
if (particles[j].availableBonds >= 2 && collisionEnergy * 0.25 > potentialDoubleStrength**2 ) {
particles[i].bond(particles[j], 2, center);
particles[i].bond(particles[j], 1, center);
particles[j].collapse(particles[i], center);
if (particles[i].bondedTo(j)) {
let strength = particles[i].bondStrengths[particles[i].bondedId.indexOf(particles[j].id)];
let bondLength = particles[i].bondLength(particles[j], strength);
particles[i].nx = avgX + normalX * (1 + (particles[i].bonds + particles[j].bonds) * 0.5);
particles[i].ny = avgY + normalY * (1 + (particles[i].bonds + particles[j].bonds) * 0.5);
particles[j].nx = avgX - normalX * (1 + (particles[i].bonds + particles[j].bonds) * 0.5);
particles[j].ny = avgY - normalY * (1 + (particles[i].bonds + particles[j].bonds) * 0.5);
particles[i].addForce(0.5 * (particles[i].nx - particles[i].x), 0.5 * (particles[i].ny - particles[i].y))
particles[j].addForce(0.5 * (particles[j].nx - particles[j].x), 0.5 * (particles[j].ny - particles[j].y))
if (particles[i].ax ** 2 + particles[i].ay ** 2 > (6 + particles[i].bondStrength(particles[j], particles[i].bondedId.indexOf(particles[j].id))) / dt) {
particles[i].debond(particles[j])
particles[i].updateBondCenter(particles[j].id, center);
550 * normalX / (dist ** 3),
550 * normalY / (dist ** 3)
-550 * normalX / (dist ** 3),
-550 * normalY / (dist ** 3)
if (isNaN(particles[i].ax + particles[i].ay)) {
console.log(particles[i])
for(let i = 0; i < particles.length; i++) {
for(let a = 0; a < particles[i].bondCenters.length; a++) {
for(let b = 0; b < particles[i].bondCenters.length; b++) {
let aDist = Math.hypot((particles[i].bondCenters[a].x - particles[i].x), (particles[i].bondCenters[a].y - particles[i].y));
let ax = (particles[i].bondCenters[a].x - particles[i].x) / aDist;
let ay = (particles[i].bondCenters[a].y - particles[i].y) / aDist;
let bDist = Math.hypot((particles[i].bondCenters[b].x - particles[i].x), (particles[i].bondCenters[b].y - particles[i].y));
let bx = (particles[i].bondCenters[b].x - particles[i].x) / aDist;
let by = (particles[i].bondCenters[b].y - particles[i].y) / aDist;
let dist = Math.hypot (ax - bx, ay - by);
let normX = (ax - bx) / dist;
let normY = (ay - by) / dist;
dist = Math.max(dist, 3);
forceX += normX * (1000/dist**3);
forceY += normY * (1000/dist**3);
let other = particles[i].bonded[a]
let dist = Math.hypot (particles[i].x - other.x, particles[i].y - other.y);
dist = Math.max(dist, 3);
let normX = (particles[i].x - other.x) / dist;
let normY = (particles[i].y - other.y) / dist;
let dot = normX * forceX + normY * forceY;
other.addForce(forceX - normX * dot, forceY - normY * dot);
for (let i = 0; i < particles.length; i++) {
particles[i].updatePos();