Star Treet
再起というテクニックを使った木を生成するプログラムです。
木の枝は木の性質上、同じ繰り返し処理を適応すると作ることができるので、再起を使うと非常に簡潔なコードで実装できます。
1、枝(最初は幹でしょうか)作る
2、生やした枝の先端からまた枝を生やす
3、2を繰り返す

画面上でクリックすると、新しい木が生成されます。
		var treeNum = 4;
		var rootNum = 30;
		var sum = treeNum + rootNum;
		var tree = [];
		var turn = [];

		function setup() {
			createCanvas(windowWidth, windowHeight);
			noiseSeed(655);
			for (var i = 0; i < sum; i++) {
				if (i < rootNum) tree.push(new Tree(true));
				else tree.push(new Tree(false));
			}
			for (var i = 0; i < sum; i++) {
				tree[i].initBranch();
			}
			shuffleNumber();
		}

		function draw() {
			background(50);
			for (var i = 0; i < sum; i++) {
				tree[turn[i]].run();
			}
		}

		function shuffleNumber() {
			var temp;
			for (var i = 0; i < sum; i++) {turn.push(i);}

			for (var i = turn.length-1; i >= 0; i--) {
				var m = int(random(0, i+1));
				temp = turn[i];
				turn[i] = turn[m];
				turn[m] = temp;
			}
		}

		function mousePressed() {
			loop();
			noiseSeed(655);
			for (var i = 0; i < sum; i++) {
				tree[i].initBranch();
			}
			loop(); //I do not know why second loop() is necessary for loop.
		}

		function keyPressed() {
			if (key =='s') saveFrame("####tree.png");
		}


		var Branch = function(_origin, _angle, _maxLen, _weight, _id) {
			this.origin = _origin;
			this.angle = _angle;
			this.maxLen = _maxLen;
			this.len = 0;
			this.weight = _weight;
			this.isGenerated = false;
			this.id = _id;
			this.brightness = 1.4;
			this.upColor = 50;
			this.col =color(205*noise(this.id/100.0)*this.brightness+this.upColor, 255*noise(this.id/100.0)*this.brightness+this.upColor, 255*noise(this.id/100.0)*this.brightness+this.upColor);
		};

		Branch.prototype.generate = function(id){
			var nextOrigin = createVector(0, -this.maxLen);
			nextOrigin.rotate(this.angle);
			nextOrigin.add(this.origin);
			var rGauss = randomGaussian();
			var range = 0.2;
			var mean = 0.6;
			var nextmaxLen = this.maxLen*(mean + rGauss*range) ;
			var nextAngle = this.angle + random(-PI/3, PI/3);
			var nextWeight = this.weight*random(0.5, 0.8);
			return new Branch(nextOrigin, nextAngle, nextmaxLen, nextWeight, id);
		};

		Branch.prototype.update = function() {
			if (this.len < this.maxLen) {
				this.len += this.maxLen;
			} else {
				this.len = this.maxLen;
			}
		};

		Branch.prototype.display = function() {
			push();
			translate(this.origin.x, this.origin.y);
			rotate(this.angle);
			strokeWeight(this.weight);
			stroke(this.col);
			line(0, 0, 0, -this.len);
			fill("#0DE0FA");
			ellipse(0, -this.len, this.len*0.1, this.len*0.1);
			pop();
		};

		Branch.prototype.isDone = function() {
			if (this.len == this.maxLen) return true;
			else return false;
		};

		var Root = function(_origin, _angle, _maxLen, _weight, _id) {
			this.origin = _origin;
			this.angle = _angle;
			this.maxLen = _maxLen;
			this.len = 0;
			this.weight = _weight;
			this.isGenerated = false;
			this.id = _id;
			this.brightness = 1.3;
			this.upColor = 50;
			this.col =color(205*noise(this.id/100.0)*this.brightness+this.upColor, 255*noise(this.id/100.0)*this.brightness+this.upColor, 255*noise(this.id/100.0)*this.brightness+this.upColor);
		};

		Root.prototype.generate = function(id){
			var nextOrigin = createVector(0, this.maxLen);
			nextOrigin.rotate(this.angle);
			nextOrigin.add(this.origin);
			var rGauss = randomGaussian();
			var range = 0.3;
			var mean = 0.6;
			var nextmaxLen = this.maxLen*(mean + rGauss*range) ;
			var nextAngle = this.angle + random(-PI/5, PI/5);
			var nextWeight = this.weight*random(0.4, 0.7);
			return new Root(nextOrigin, nextAngle, nextmaxLen, nextWeight, id);
		};

		Root.prototype.update = function() {
			if (this.len < this.maxLen) {
				this.len += this.maxLen;
			} else {
				this.len = this.maxLen;
			}
		};

		Root.prototype.display = function() {
			push();
			translate(this.origin.x, this.origin.y);
			rotate(this.angle);
			strokeWeight(this.weight);
			stroke(this.col);
			line(0, 0, 0, this.len);
			pop();
		};

		Root.prototype.isDone = function() {
			if (this.len == this.maxLen) return true;
			else return false;
		};

		var Tree = function(_isRoot) {
			this.branches = [];
			this.branchId = 0;
			this.origin;
			this.isRoot = _isRoot;
			this.x, this.y;
			this.initBranch();
			this.history = 0;
			this.lastLen = 0;
			this.len = 0;
		};

		Tree.prototype.initBranch = function() {
			this.branches = [];
			this.history = 0;
			this.lastLen = 0;
			this.len = 0;
			if (!this.isRoot) {
				this.x = width/2 + random(-13, 13);
				this.y = height*0.95;
			} else {
				this.x = width/2;
				this.y = height*0.95 + random(-20,20) + 0;
			}
			this.origin = createVector(this.x, this.y);
			this.branchId = 0;
			if (!this.isRoot) {
				this.branches.push(new Branch(this.origin, random(-PI/50, PI/50), random(80, 150), random(5, 30), this.branchId));
			} else {
				this.branches.push(new Root(this.origin, random(-PI/3, PI/3), random(0, 60), random(10, 1), this.branchId));
			}
		}

		Tree.prototype.updateBranch = function() {
			for (var i = 0; i < this.branches.length; i++) {
				if (this.branches[i].isDone() && !this.branches[i].isGenerated) {
					this.branches[i].isGenerated = true;
					for (var j = 0; j < int(random(2, 5)); j++) {
						if (!this.isRoot  && this.branches[i].maxLen>10 && this.branches.length < 1800) {
							this.branches.push(this.branches[i].generate(this.branchId));
							this.branchId ++;
						} else {
							if (this.branches.length < 20  && this.branches[i].maxLen>10) {
								this.branches.push(this.branches[i].generate(this.branchId));
								this.branchId ++;
							}
						}
					}
				}
			}
		}


		Tree.prototype.run = function() {
			this.len = this.branches.length;
			if(this.len == this.lastLen) this.history++;
			else this.history = 0;
			if(this.history > 10) {
				noLoop();
			}
			this.updateBranch();
			for (var i = 0; i < this.branches.length; i++) {
				this.branches[i].update();
				this.branches[i].display();
			}
			this.lastLen = this.len;
		}