maze

Actually, her thread built the labyrinth.

Created by ge1doot on 2019/1/19
219
0

Log in to post a comment.

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

// Global code will be evaluated once.
const turtle = new Turtle();
turtle.up();
const linesDrawn = [];

class Line {
	constructor(x, y, a) {
		this.x1 = x;
		this.y1 = y;
		this.x2 = x;
		this.y2 = y;
		this.angle = a;
		this.x2 += Math.cos(a) * 0.1;
		this.y2 += Math.sin(a) * 0.1;
		this.collisionLines = new Set();
		for (let line of lines) {
			if (this.raytoline(line) && line.raytoline(this)) {
				this.collisionLines.add(line);
			}
		}
	}
	anim() {
		if (Math.random() > 0.94) {
			const a = this.angle + (Math.random() > 0.5 ? Math.PI / 2 : -Math.PI / 2);
			const line = new Line(
				this.x2 + Math.cos(a) * 0.1, 
				this.y2 + Math.sin(a) * 0.1, 
				a
			);
			lines.add(line);
			activeLines.add(line);
		}
		for (let line of this.collisionLines) {
			if (this !== line) {
				const collision = this.intersect(line);
				if (collision) {
					const x = collision.x;
					const y = collision.y;
					if (
						Math.abs(x - this.x2) < Math.abs(x - line.x2) && 
						Math.abs(y - this.y2) < Math.abs(y - line.y2)
					) {
						this.draw();
						activeLines.delete(this);
					}
					else {
						line.draw();
						activeLines.delete(line);
					}
				}
			}
		}
		this.x2 += Math.cos(this.angle) * 0.3;
		this.y2 += Math.sin(this.angle) * 0.3;
		if (Math.abs(this.x2) > 100 || Math.abs(this.y2) > 100) {
			this.draw();
			activeLines.delete(this);
		}
	}
	draw() {
		const line_hash =
			this.x1.toFixed(2) + "-" +
			this.y1.toFixed(2) + "-" +
			this.y2.toFixed(2) + "-" +
			this.y2.toFixed(2);
		if (!linesDrawn[line_hash]) {
			turtle.penup();
			turtle.goto(this.x1, this.y1);
			turtle.pendown();
			turtle.goto(this.x2, this.y2);
			linesDrawn[line_hash] = true;
		}
	}
	raytoline(line) {
		if (
			(this.y2 - this.y1) / (this.x2 - this.x1) !== (line.y2 - line.y1) / (line.x2 - line.x1)
		) {
			const d = (((this.x2 - this.x1) * (line.y2 - line.y1)) - (this.y2 - this.y1) * (line.x2 - line.x1));
			if (d !== 0) {
				const r = (((this.y1 - line.y1) * (line.x2 - line.x1)) - (this.x1 - line.x1) * (line.y2 - line.y1)) / d;
				if (r >= 0) return true;
			}
		}
		return false;
	}
	intersect(line) {
		const td = this.x1 * this.y2 - this.y1 * this.x2;
		const ld = line.x1 * line.y2 - line.y1 * line.x2;
		const x = (td * (line.x1 - line.x2) - (this.x1 - this.x2) * ld) / ((this.x1 - this.x2) * (line.y1 - line.y2) - (this.y1 - this.y2) * (line.x1 - line.x2));
		if (isNaN(x)) return false;
		const y = (td * (line.y1 - line.y2) - (this.y1 - this.y2) * ld) / ((this.x1 - this.x2) * (line.y1 - line.y2) - (this.y1 - this.y2) * (line.x1 - line.x2));
		if (isNaN(y)) return false;
		if (this.x1 >= this.x2) {
			if (!(this.x2 - 0.01 <= x && x <= this.x1 + 0.01)) return false;
		} else {
			if (!(this.x1 - 0.01 <= x && x <= this.x2 + 0.01)) return false;
		}
		if (this.y1 >= this.y2) {
			if (!(this.y2 - 0.01 <= y && y <= this.y1 + 0.01)) return false;
		} else {
			if (!(this.y1 - 0.01 <= y && y <= this.y2 + 0.01)) return false;
		}
		if (line.x1 >= line.x2) {
			if (!(line.x2 - 0.01 <= x && x <= line.x1 + 0.01)) return false;
		} else {
			if (!(line.x1 - 0.01 <= x && x <= line.x2 + 0.01)) return false;
		}
		if (line.y1 >= line.y2) {
			if (!(line.y2 - 0.01 <= y && y <= line.y1 + 0.01)) return false;
		} else {
			if (!(line.y1 - 0.01 <= y && y <= line.y2 + 0.01)) return false;
		}
		return {
			x: x,
			y: y
		};
	}
}
const lines = new Set();
const activeLines = new Set();
for (let j = 0; j < 3; j++) {
	const sx = Math.random() * 200 - 100;
	const sy = Math.random() * 200 - 100;
	for (let i = 0; i < 40; i++) {
		const a = Math.random() * 2 * Math.PI;
		const x = sx + (Math.random() - 0.5) * 200 * 0.05;
		const y = sy + (Math.random() - 0.5) * 200 * 0.05;
		let line = new Line(x, y, a, 90);
		lines.add(line);
		activeLines.add(line);
		line = new Line(x, y, a + Math.PI, 90);
		lines.add(line);
		activeLines.add(line);
	}
}

// The walk function will be called until it returns false.
function walk(i) {
    for (let line of activeLines) {
		line.anim();
	}
	return activeLines.size > 0;
}