N particles

codepen.io/ge1doot/pen/vOMMxE?editors=0010

Created by ge1doot on 2019/1/31
57
0

Log in to post a comment.

// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(1);

// Global code will be evaluated once.
const turtle = new Turtle();
turtle.penup();
// N particles
// Adapted from an Oliver Knill's script
// http://www.dynamical-systems.org
// January 1, 2000
//////////////////////////
const numParticles = 10;
const g = 0.7;
const v = 0.02;
const f = 0.995;
const p = 50;
class Particle {
    constructor () {
		this.y  = 5 * Math.random() - 2.5;
		this.x  = 5 * Math.random() - 2.5;
		this.vx = 0;
		this.vy = 0;
	}
}
const particles = [];
for (let i = 0; i < numParticles; i++) {
	particles.push(new Particle());
}

const step = () => {
    for (let i = 0; i < numParticles; i++) {
	    const oi = particles[i];
		let dx = 0;
		let dy = 0;
		for (let j = 1; j < numParticles; j++) {
			const k = (i + j) % numParticles;
			const ok = particles[k];
			let h  = g / (Math.pow(oi.y - ok.y, 2) + Math.pow(oi.x - ok.x, 2) + 0.01);
			if (k === 0) h *= (p * Math.random());
			dx += (oi.y - ok.y) * h;
			dy += (oi.x - ok.x) * h;
		}
		if (i === 0) {
			oi.y = 0;
			oi.x = 0;
		} else {
			oi.y += v * oi.vx;
			oi.x += v * oi.vy;
			oi.vx = f * oi.vx - v * dx;
			oi.vy = f * oi.vy - v * dy;
		    steps.push([oi.x * 20 - 5, oi.y * 20, 5]);
		}
	}
};
const steps = [];
for (let i = 0; i < 400; i++) step();
steps.reverse();
// The walk function will be called until it returns false.
function walk(i) {
    const d = steps[i];
    if (d) disk(d[0], d[1], d[2]);
	return d;
}
/////////////////////// disks occlusion //////////////////////////
const disks = [];
const disk = (x, y, r, s = 36) => new Disk(x, y, r, s);
const Disk = class {
    constructor (x, y, r, s) {
        this.x = x;
        this.y = y;
        this.r = r;
        this.s = Math.PI / (0.5 * s);
        const visible = this.draw();
        if (visible) disks.push(this);
    }
    draw() {
        turtle.goto(this.x + this.r, this.y);
        turtle.down();
        let down = true;
        let visible = false;
        for (let i = this.s; i <= Math.PI * 2 + this.s; i += this.s) {
            const x = this.x + this.r * Math.cos(i);
            const y = this.y + this.r * Math.sin(i);
            if (this.visible(x, y) === true) {
                // visible
                visible = true;
                turtle.goto(x, y);
                if (down === false) {
                    turtle.down();
                    down = true;
                }
            } else {
                // hidden
                if (down === true) {
                    turtle.up();
                    down = false;
                }
            }
        }
        turtle.up();
        return visible;
    }
    visible (x, y) {
        for (let i = 0, len = disks.length; i < len; i++) {
            const d = disks[i];
            if (((x - d.x) ** 2 + (y - d.y) ** 2) < d.r * d.r) return false;
        }
        return true;
    }
}