xxxxxxxxxx
240
let trees = [];
const clickSize = 10;
let treeAngle;
let transitionX = 0;
let transitionY = 0;
let transitionR = 0;
let transitionSpeed = 0.05; // Adjust this value for the transition speed
let currentX = 0;
let currentY = 0;
let currentR = 0;
let transitionActive = false;
let rotationActive = false;
function setup() {
createCanvas(windowWidth, windowHeight);
treeAngle = PI / 8;
let tree = new FractalTree(width / 2, height, -PI / 2, 100, 5, treeAngle,false);
trees.push(tree);
}
function draw() {
background(255);
if (transitionActive) {
// Interpolate the current view values toward the target values
currentX = lerp(currentX, transitionX, transitionSpeed);
currentY = lerp(currentY, transitionY, transitionSpeed);
// Check if the transition is complete
let distanceX = abs(currentX - transitionX);
let distanceY = abs(currentY - transitionY);
if (distanceX < 0.5 && distanceY < 0.5) {
transitionActive = false;
newTree(trees[0].clickedBranch);
}
}
if(rotationActive){
currentR = lerp(currentR,transitionR, transitionSpeed);
let distanceR = abs(currentR - transitionR);
if (distanceR < 0.01){
rotationActive = false;
// append(trees,new FractalTree(width / 2, height, -PI/2, 100, 5, treeAngle,true))
// trees.splice(0,1);
// currentX = 0;
// currentY = 0;
// currentR = 0;
}
}
push();
translate(currentX, currentY);
rotate(currentR);
let grownTrees = 0;
for (let i = trees.length - 1; i >= 0; i--) {
if(trees[i].grown){grownTrees++;}
trees[i].show();
}
pop();
//handle getting rid of the old tree
if(grownTrees > 1){
append(trees,new FractalTree(0, 0, transitionR, 100, 5, treeAngle,true))
trees.splice(0,2);
currentX = width/2;
currentY = height;
rotationActive = true;
}
}
function transition(branch) {
// Calculate target translation and rotation
transitionX = width / 2 - branch.begin.x;
transitionY = height - branch.begin.y;
transitionR = -PI/2 - atan2(branch.end.y - branch.begin.y, branch.end.x - branch.begin.x);
// Activate the transition
transitionActive = true;
}
function newTree(branch) {
const origin = branch.begin;
const angle = atan2(branch.end.y - branch.begin.y, branch.end.x - branch.begin.x);
let newTree = new FractalTree(origin.x, origin.y, angle, 100, 5, treeAngle,false);
trees.push(newTree);
}
function mouseClicked() {
for (let branchLevel of trees[0].branches) {
for (let branch of branchLevel) {
if (
pointToLineDistance(
mouseX,
mouseY,
branch.begin.x,
branch.begin.y,
branch.end.x,
branch.end.y
) < clickSize
) {
branch.clicked = true;
trees[0].clickedBranch = branch; // Store the clicked branch for the new tree
transition(branch);
}
}
}
}
class Branch {
constructor(x1, y1, x2, y2, thickness, turtle) {
this.begin = createVector(x1, y1);
this.end = createVector(x2, y2);
this.thickness = thickness;
this.turtle = new Turtle(x1, y1, x2, y2);
this.turtle.setWidth(thickness);
this.grown = false;
this.clicked = false;
}
show() {
if (!this.clicked) {
stroke(0);
} else {
stroke(255, 0, 0);
}
strokeWeight(this.thickness);
line(this.begin.x, this.begin.y, this.end.x, this.end.y);
}
grow() {
this.grown = this.turtle.forward(10);
}
}
class FractalTree {
constructor(x, y, direction, length, depth, angle, grown) {
this.branches = [];
this.origin = createVector(x, y);
for (let i = 0; i < depth; i++) {
this.branches[i] = [];
}
this.grownBranches = [];
this.depth = depth;
this.angle = angle;
this.currentLevel = depth - 1;
this.clickedBranch = null;
this.grown = grown;
this.generate(x, y, direction, length, depth);
}
generate(x1, y1, direction, length, depth) {
if (depth > 0) {
let x2 = x1 + length * cos(direction);
let y2 = y1 + length * sin(direction);
this.branches[depth - 1].push(new Branch(x1, y1, x2, y2, depth * 0.5));
this.generate(x2, y2, direction - this.angle, length, depth - 1);
this.generate(x2, y2, direction + this.angle, length, depth - 1);
}
}
show() {
if(this.grownBranches.length == this.branches.length){
this.grown = true;
}
if(this.grown){
for (let branchLevel of this.branches) {
for (let branch of branchLevel) {
branch.show();
}
}
}else{
for (let i of this.grownBranches) {
let branchLevel = this.branches[i];
for (let branch of branchLevel) {
branch.show();
}
}
}
if (this.currentLevel < 0) {
return;
}
for (let i = 0; i < this.branches[this.currentLevel].length; i++) {
this.branches[this.currentLevel][i].grow();
}
if (this.branches[this.currentLevel][0].grown == true) {
append(this.grownBranches, this.currentLevel);
this.currentLevel--;
}
}
}
function pointToLineDistance(x, y, x1, y1, x2, y2) {
let A = x - x1;
let B = y - y1;
let C = x2 - x1;
let D = y2 - y1;
let dot = A * C + B * D;
let len_sq = C * C + D * D;
let param = -1;
if (len_sq != 0) param = dot / len_sq;
let xx, yy;
if (param < 0) {
xx = x1;
yy = y1;
} else if (param > 1) {
xx = x2;
yy = y2;
} else {
xx = x1 + param * C;
yy = y1 + param * D;
}
let dx = x - xx;
let dy = y - yy;
return sqrt(dx * dx + dy * dy);
}