Randomly Generating Trees

Trees are found all around the world yet none look quite exactly the same. Games like The Long Dark or Firewatch both take place in environments filled with trees. Having different styles for trees is

crucial in games like these to avoid making the game look dull or boring. Including different variations of certain things can be very important in making a game feel more professional whether the variations be randomly generated or from a man-made set.
To start off with creating trees with code you have to figure out what you could compare them to, this happens to be what’s known as
fractals. Fractals are immensely complicated abstract objects that typically resemble objects found in nature. The image below shows a fractal that looks similar to a tree.

Here’s a program that generates random fractal-like trees. This program creates trees based off of random values such as: the number of break-offs, the number of branches that grow from each break-off, how much the branches spread apart, etc. It then creates new branches based off of these values and once it hits the end of the branch it adds a “leaf”. You can test it down below or find it at:
https://www.ktbyte.com/projects/project/73151.
[raw]
[/raw]
After going through the example you should try changing the variables up to create different styles of trees or possibly trying to create other plants like flowers, bushes, etc. This could be done by editing the colors, changing the branch sizes and other small tweaks like these.
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();
}
}
}