Tree tree;
float frame = 0;
void setup() {
size(400,600);
strokeCap(SQUARE);
tree = new Tree();
}
void draw() {
frame += 0.05;
background(90, 130, 250);
tree.trunk.display(tree.x, height);
fill(255);
textAlign(CENTER);
text("Click to create a new tree!", width / 2, 30);
}
void mousePressed() {
tree = new Tree();
}
class Tree {
float x = width / 2; //Where the base of the tree is
int branchesAtBreak = (int) random(2, 5); //How many branches at each break
int numberOfBreaks = (int) random(4, 6); //How many breaks
float trunkWidth = random(1, 4) * (float) numberOfBreaks; //Width of trunk
float branchSpread = random(1, 7); //How much should the branches spread out
float branchSplay = random(0.2, 1.1); //The lower the number the shorter the outer branches are
float branchLengthMulti = random(0.2, 0.95); //How much branches shrink length wise each break
float branchWidthMulti = random(0.4, 0.7); // Same as above except with width
float breezeStrength = random(1)+3; //How strong is the "breeze" that sways the tree
float leafSize = random(15, 30); //Size of the leaves
Branch trunk = new Branch(this, PI, 0, height/random(2,3), trunkWidth, branchesAtBreak, numberOfBreaks); //Creates tree trunk and provides tree info to the rest of the tree
}
class Branch {
boolean endOfBranch = false;
float xpos, globalAngle, localAngle, branchLength;
int branchesAtBreak, numberOfBreaks;
float trunkWidth;
Branch[] branches = new Branch[0];
Tree tree;
float waveOffset = random(-1, 1);
Branch(Tree tempT, float tempGA, float tempLA, float tempL, float tempTW, int tempBAB, int tempNOB) {
tree = tempT;branchesAtBreak = tempBAB;numberOfBreaks = tempNOB;trunkWidth = tempTW;globalAngle = tempGA;localAngle = tempLA;branchLength = tempL;
if (numberOfBreaks == 0) {
endOfBranch = true; //Lets tree know once it has hit the end of the branch
} else {
endOfBranch = false;
branches = new Branch[branchesAtBreak];
float minimumAngle = -((tree.branchSpread*(branchesAtBreak-1))/2); //Calculates minimum angle of a branch
for (int i=0; i<branches.length;i++) {
float thisBranchAngle = ((tree.branchSpread * i) + minimumAngle + random(-0.5,0.5))*(tree.branchSplay/numberOfBreaks); //Randomizes angle of branch
float thisBranchLenDiv = (float) abs(i - ((tree.branchesAtBreak - 1 ) / 2)) + 1; //Number that length of branches are divided by
branches[i] = new Branch(tree, globalAngle + thisBranchAngle, thisBranchAngle, //
(branchLength*tree.branchLengthMulti)/thisBranchLenDiv, // Adds child branch
trunkWidth * tree.branchWidthMulti, branchesAtBreak, numberOfBreaks-1); //
}
}
branchLength *= random(0.2, 1.2); //Randomizes trunk length after finishing all other branches
}
void display(float startX, float startY){
float breeze = (sin(frame+waveOffset)/branchLength)*tree.breezeStrength; //Calculates the offset caused by the breeze
float endX = (float)(startX + (sin((globalAngle+breeze))*branchLength)); //Determines the end position of the branch
float endY = (float)(startY + (cos((globalAngle+breeze))*branchLength)); // /\
//Draws Branches
pushMatrix();
stroke(83, 49, 24);
strokeWeight(trunkWidth + 1);
line(startX,startY,endX,endY);
popMatrix();
//Draws all child branches
for (int i = 0; i < branches.length; i++){
branches[i].display(endX,endY);
}
//Draws leaves once you hit the end of the branch
if (branches.length == 0) {
pushMatrix();
stroke(143, 221, 44);
strokeWeight(1);
fill(143, 221, 44);
ellipse(endX,endY,tree.leafSize,tree.leafSize);
popMatrix();
}
}
}