Most impractical window wipers

(because they keep missing spots)

Log in to post a comment.

const opacity = 0.008; // min=0.001, max=0.1, step=0.001
const numWipers = 3; // min=1, max=20, step=1
const numSegments = 32; // min=1, max=200, step=1
const maxStartVelocity = 0.4; // min=0, max=5, step=0.01
const maxStartAngle = 360; // min=0, max=360, step=1
const damping = 0.999; // min=0.98, max=1.0, step=0.001
const springStrength = 0.0; // min=0.0, max=1.0, step=0.001
const baseLength = 10.0; // min=1.0, max=50.0, step=1
const maxSteps = 1000;

const springs = [];
const stopThreshold = 0.001;

Canvas.setpenopacity(opacity);

function createSpring(x, y) {
	const spring = new Turtle();

	spring.segments = []

	for (let i = 0; i < numSegments; i++) {
		spring.segments.push({
			v: (Math.random() - 0.5) * maxStartVelocity * 2,
			a: 0,
			t: (Math.random() - 0.5) * maxStartAngle * 2,
			c: (Math.random() - 0.5) * maxStartAngle * 2,
			length: baseLength + 10 * (i / numSegments),

			update: function () {
				let d = this.t - this.c;
				this.a = d * springStrength;
				this.v += this.a;
				this.c += this.v;

				this.v *= damping;

				return Math.abs(this.v) > stopThreshold || Math.abs(this.a) > stopThreshold;
			}
		});
	}

	spring.draw = function () {
		this.jump(x, y);
		let h = 0;

		return this.segments.reduce((p, s) => {
			let active = s.update();
			h += s.c;

			this.setheading(h);
			this.forward(s.length);

			return p || active;
		}, true);
	}

	return spring;
}

for (let w = 0.0; w < numWipers; w++) {
	let t = w / (numWipers-1);
	let x = -50 + (100 * t);
	springs.push(createSpring(x, 0));
}

// The walk function will be called until it returns false.
function walk(i) {
	return i < maxSteps && springs.reduce((p, c) => p && c.draw(), true);
}