Massy particles with weird interactions.
Log in to post a comment.
Canvas.setpenopacity(-0.1); const nObjects = 4; const massSize = 5; const spawnArea = 30; const startAngle = 15+Math.random()*15; const iters = 10000; const gravity = 0.08; const minVel = 0.01; const maxVel = 0.05; const lightspeed = 1.5; const minMass = 0.4; const maxMass = 1; const crashMassLoss = 0.7; const crashVelocityLoss = 0.1; const turnVelocityLoss = 0.1; const edge = 100; const seed = Math.random()*360; let newTurtles = []; let turtles = [...Array(nObjects*nObjects)].map((_, i) => { const turtle = new Turtle(); turtle.velocity = minVel + (maxVel-minVel)*Math.random(); turtle.mass = minMass + (maxMass-minMass)*Math.random(); turtle.seth(seed+i*startAngle); turtle.penup(); turtle.goto( -spawnArea+spawnArea/nObjects+2*spawnArea/nObjects*(i%nObjects), -spawnArea+spawnArea/nObjects+2*spawnArea/nObjects*Math.floor(i/nObjects), ); turtle.pendown(); return turtle; }); function angleBetween(a, b) { return Math.min((360+a-b)%360, (360+b-a)%360); } function walk(i) { newTurtles = []; for (let index = 0; index < turtles.length; index++) { const turtle = turtles[index]; const tx = turtle.x(); const ty = turtle.y(); const otherTurtles = turtles.filter((t, oi) => !t.crashed && oi != index); for (let oti = 0; oti < otherTurtles.length; oti++) { const ot = otherTurtles[oti]; const th = turtle.h(); const ox = ot.x(); const oy = ot.y(); const oh = ot.h(); const dx = ox-tx; const dy = oy-ty; const angle = angleBetween(th, Math.atan2(dx, dy)*180/Math.PI); const dist = Math.sqrt(dx*dx+dy*dy); const distFactor = 1/(dist*dist); if (dist < (turtle.mass*massSize+ot.mass*massSize)/2) { turtle.crashed = true; ot.crashed = true; const nt = turtle.clone(); const angleDiff = angleBetween(oh, th); nt.mass = ot.mass+turtle.mass*crashMassLoss; nt.velocity = (ot.velocity*ot.mass/turtle.velocity*turtle.mass)*crashVelocityLoss; nt.goto(ox-dx, oy-dy); nt.seth((oh+angleDiff*(ot.mass/turtle.mass))%360); newTurtles.push(nt); } else { const turnFactor = ((dx>=0 && dy>0) || (dx<0 && dy>=0) ? 1 : -1)*(distFactor*((ot.mass*ot.mass)/(turtle.mass*turtle.mass))*angle*gravity); turtle.velocity *= 1 + distFactor * (turtle.mass/ot.mass) * turnVelocityLoss; turtle.right(turtle.mass * turnFactor); } } turtle.forward(turtle.velocity - (turtle.velocity/turtle.mass)*(turtle.velocity/lightspeed)); const size = turtle.mass*massSize; turtle.penup(); turtle.left(90); turtle.forward(size/2); turtle.right(90); turtle.pendown(); turtle.circle(size, 360, Math.round(10*turtle.mass)); turtle.penup(); turtle.left(90); turtle.backward(size/2); turtle.right(90); if (tx > edge+size || tx < -edge-size || ty >= edge+size || ty < -edge-size) turtle.crashed = true;; } turtles = turtles.concat(newTurtles).filter(turtle => !turtle.crashed); return turtles.length > 0 && i < iters; }