xxxxxxxxxx
// Not finished
const N = 8, B = 3;
let root = new Int8Array(N).fill(-1);
function find(i){
if(root[i] < 0) return i;
return root[i] = find(root[i]);
}
function same(a, b){
return find(a) == find(b);
}
let adj = new Array(N);
for(let i=0; i<N; ++i) adj[i] = new Uint8Array(N).fill(0);
let comp = N, full = 0, hit = new Uint8Array(N).fill(0);
function merge(a, b){
if(adj[a][b]) return;
adj[a][b] = 1; adj[b][a] = 1;
if(++hit[a] == 2) ++full;
if(++hit[b] == 2) ++full;
if(same(a, b)) return;
--comp;
a = find(a); b = find(b);
if(root[a] < root[b]){
root[a] += root[b];
root[b] = a;
}else{
root[b] += root[a];
root[a] = b;
}
}
let pos = new Array(N), lpos = new Array(N), vel = new Array(N);
for(let i=0; i<N; ++i){
pos[i] = [25 + 350*Math.random(), 25 + 350*Math.random()];
lpos[i] = [200, 200];
vel[i] = [0, 0];
}
function setup(){
while(comp > 1 || full < N){
let opt = new Set();
while(opt.size < B)
opt.add(Math.floor(Math.random()*N));
merge( (Array.from(opt)
.sort((x, y) => hit[x] - hit[y])
.slice(0, 2)));
}
createCanvas(400, 400);
}
function draw(){
for(let s=0; s<100; ++s)
for(let i=0; i<N; ++i)
for(let j=0; j<N; ++j)
if(i != j){
let v = [pos[j][0] - pos[i][0], pos[j][1] - pos[i][1]],
d = Math.sqrt(v[0]*v[0] + v[1]*v[1]);
if(adj[i][j]) d = d-100;
else d = -Math.max(0, 80-d)*3;
const dt = 0.0000001;
d *= Math.abs(d)*dt;
v = [v[0]*d, v[1]*d];
vel[i][0] += v[0]; vel[i][1] += v[1];
}
let d = [0, 0];
for(let i=0; i<N; ++i)
for(let j=0; j<2; ++j)
d[j] += (200 - pos[i][j])/N;
let ease = Math.max(0.02, Math.min(1, Math.pow(frameCount/40, 2) - 0.2));
for(let i=0; i<N; ++i){
let v = Math.sqrt(vel[i][0]*vel[i][0] + vel[i][1]*vel[i][1]),
r = Math.min(v, 1)/v;
for(let j=0; j<2; ++j){
pos[i][j] += (vel[i][j]*r + d[j]/10) * ease;
lpos[i][j] = lpos[i][j]*(1 - 0.1*ease) + pos[i][j]*0.1*ease;
vel[i][j] = 0;
}
}
background(30);
noStroke(); fill(60);
for(let i=0; i<N; ++i)
circle(pos[i], 20);
stroke(120); strokeWeight(2);
for(let i=0; i<N; ++i)
for(let j=0; j<i; ++j)
if(adj[i][j]) line(lpos[i], lpos[j]);
noStroke(); fill(200);
for(let i=0; i<N; ++i)
circle(lpos[i], 30);
fill(0); textAlign(CENTER, CENTER);
for(let i=0; i<N; ++i)
text(i.toString(), lpos[i]);
}