createCanvas(windowWidth, windowHeight)
for (let i = 0; i < 6; i++) {
figures.push(new Figure([
pos: createVector(map(i, 0, 5, -1, 1)*w*0.45, 0),
pos: createVector(0, map(i, 0, 5, -130, -100)).rotate(map(i, 0, 5, PI*0.2, 0)),
{ pos: createVector(0, -40).rotate(map(i, 0, 5, PI*0.2, 0)), type: 'circle' },
...[-1, 1].map(side => ({
pos: createVector(20 * side, map(i, 0, 5, 100, 80)),
{ pos: createVector(10 * -side, map(i, 0, 5, 100, 80)) }
...[-1, 1].map(side => ({
pos: createVector(60 + 5 * -side, 20).lerp(createVector(5 * -side, 100), i/5),
pos: createVector(-40, 80).lerp(createVector(5 * -side, 100), i/5),
{ pos: createVector(20, 0) }
textAlign(CENTER, BOTTOM)
text('behold: evolution', width/2, height*0.95)
translate(width/2, height/2 + (s*300)/2)
for (const figure of figures) {
figure.dna[0].pos.x -= map(frameCount, 60, 120, 0, 5, true)
if (figures[0].dna[0].pos.x < -w/2 - w*0.18) figures.shift()
if (figures.at(-1).dna[0].pos.x < w/2) {
const mutated = figures.at(-1).clone()
mutated.dna[0].pos.x = w/2 + w*0.18
for (const figure of figures) {
for (const gene of this.dna) {
if (gene.type === 'circle') {
circle(gene.pos.x/2, gene.pos.y/2, gene.pos.mag())
} else if (gene.type === 'root') {
line(0, 0, gene.pos.x, gene.pos.y)
translate(gene.pos.x, gene.pos.y)
for (const child of (gene.children || [])) {
return new Figure(this.dna.map(gene => this.cloneGene(gene)))
const cloned = { ...gene, pos: gene.pos.copy() }
cloned.children = cloned.children.map(child => this.cloneGene(child))
this.dna.forEach(gene => this.mutateGene(gene))
if (gene.type !== 'root') {
gene.pos.add(random(-5, 5), random(-5, 5))
gene.pos.rotate(random(-1, 1) * PI * 0.1)
if (gene.type !== 'root' && random() < 0.1) {
gene.type = random() < 0.1 ? 'circle' : undefined
gene.children = gene.children || []
pos: createVector(random(20, 20), random(20, 20)),
type: random() < 0.1 ? 'circle' : undefined,
gene.children = gene.children.filter(() => random() < 0.99)
for (const child of gene.children) {
base = max(base, gene.pos.y + off)
for (const child of (gene.children || [])) walk(child)
for (const gene of this.dna) walk(gene)
for (const gene of this.dna) gene.pos.y -= base