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;
}