class GrowingObject{ constructor(){ this.growing = true; } show(){ for (let i = 0; i < this.positions.length && this.positions[i + 1] != null; i++){ let p1 = p5.Vector.add(this.positions[i], this.pos.root); let p2 = p5.Vector.add(this.positions[i + 1], this.pos.root); strokeWeight((this.positions.length - i) / this.positions.length * this.width); line(p1.x, p1.y, p2.x, p2.y); } } grow(){ this.pos.current.add(this.vel); this.vel.add(this.acc); if (this.positions != null && this.width != null){ this.positions.push(this.pos.current.copy()); if (this.width < this.maxWidth) this.width++; } else { this.radius = this.pos.current.mag(); if (this.radius > this.maxRadius) this.growing = false; } } } class Palm extends GrowingObject{ constructor(x){ super(); this.pos = {root: createVector(x, getDesert(x)), current: createVector(0, 0)}; this.vel = createVector(0, random(-10, -12)); this.acc = createVector(random(-0.1, 0.1), 0.1); this.positions = [this.pos.current.copy()]; colorMode(HSB); this.color = color(35, random(30, 100), 35); this.width = 0; this.maxWidth = 40; this.leaf = []; let dispo = random(TWO_PI); for (let i = 0; i < 8; i++){ let root = this.pos.root.copy(); let direction = i / 4 * PI + dispo; this.leaf.push(new Leaf(direction, root)); } this.coconuts = []; } update(){ let coconutsReady = true; stroke(this.color); this.show(); if (this.growing){ this.grow(); coconutsReady = false; } stroke(this.leaf[0].color); for (let l of this.leaf){ if (this.growing) l.update(this.pos); else l.update(null); if (l.growing) coconutsReady = false; } if (this.coconuts.length > 0){ fill(this.coconuts[0].color); stroke(0); } for (let c of this.coconuts) c.update(); if (abs(this.vel.x) > abs(this.vel.y)) this.growing = false; if (coconutsReady && this.coconuts.length == 0) this.createCoconuts(); } createCoconuts(){ let count = int(random(2, 8)); let dispo = random(TWO_PI); for (let i = 0; i < count; i++){ let root = p5.Vector.add(this.pos.root, this.pos.current); let direction = i / (count / 2) * PI + dispo; this.coconuts.push(new Coconut(direction, root)); } } } class Leaf extends GrowingObject{ constructor(direction, root){ super(); this.pos = {root: root, current: createVector(0, 0)}; this.vel = p5.Vector.mult(createVector(p5.Vector.fromAngle(direction).x, p5.Vector.fromAngle(direction).y), 6); this.acc = createVector(0, 0.1); this.positions = [this.pos.current.copy()]; colorMode(HSB); this.color = color(135, 100, random(50, 80)); this.width = 0; this.maxWidth = 40; } update(pos){ if (pos != null) this.pos.root.set(p5.Vector.add(pos.root, pos.current).x, p5.Vector.add(pos.root, pos.current).y); this.show(); if (this.growing) this.grow(); if (this.positions.length > 40) this.growing = false; } } class Coconut extends GrowingObject{ constructor(direction, root){ super(); this.pos = {root: root, current: createVector(0, 0)}; this.vel = p5.Vector.fromAngle(direction); this.acc = createVector(0, 0); this.radius = 0; this.maxRadius = random(10, 20); this.color = color("#6c4c2a"); } update(){ if (this.growing) this.grow(); this.show(); } show(){ let pos = p5.Vector.add(this.pos.root, this.pos.current); ellipse(pos.x, pos.y, this.radius * 2); } }