float NEW_TREE_PROB = 0.05;
float MAX_BRANCH_PROB = 0.5;
float MIN_DYING_PROB = 0.05;
float BRANCH_PROB_DIFF = 0.03;
float DYKING_PROB_DIFF = 0.05;
float MAX_BRANCH_GROWTH = 2.0;
ArrayList<Tree> trees;
void setup(){
size(500, 500);
smooth();
frameRate(24);
background(255);
trees = new ArrayList<Tree>();
trees.add(new Tree());
}
void draw(){
if(random(1) < NEW_TREE_PROB){
trees.add(new Tree());
}
for(Tree tree: trees){
tree.grow();
}
ArrayList<Tree> newTrees = new ArrayList<Tree>();
for(Tree tree: trees){
if(!tree.isDead()){
newTrees.add(tree);
}
}
trees = newTrees;
}
class Tree{
ArrayList<Branch> activeBranches;
Tree(){
activeBranches = new ArrayList<Branch>();
activeBranches.add(new Branch());
}
boolean isDead(){
if(activeBranches.size() == 0){
return true;
} else {
return false;
}
}
void grow(){
ArrayList<Branch> dyingBranches = new ArrayList<Branch>();
for(Branch b: activeBranches){
if(random(1) < b.dyingProb){
dyingBranches.add(b);
}
}
for(Branch b: dyingBranches){
activeBranches.remove(b);
}
ArrayList<Branch> newBranches = new ArrayList<Branch>();
for(Branch b: activeBranches){
if(random(1) < b.branchProb){
newBranches.add(new Branch(b));
}
}
for(Branch b: newBranches){
activeBranches.add(b);
}
for(Branch b: activeBranches){
b.grow();
}
}
}
class Branch{
PVector tip;
PVector growth;
float grey;
float branchProb;
float dyingProb;
Branch(){
tip = new PVector(random(width), random(height));
growth = new PVector(random(2) - 1, random(2) - 1);
growth.normalize();
growth.mult(MAX_BRANCH_GROWTH);
grey = random(255);
branchProb = random(MAX_BRANCH_PROB);
dyingProb = random(MIN_DYING_PROB);
}
Branch(Branch b){
tip = new PVector(b.tip.x, b.tip.y);
growth = new PVector(b.growth.x, b.growth.y);
growth.div(sqrt(2));
growth.rotate(random(PI) - HALF_PI);
grey = b.grey;
branchProb = b.branchProb - BRANCH_PROB_DIFF;
dyingProb = b.dyingProb + DYKING_PROB_DIFF;
}
void grow(){
stroke(grey);
strokeWeight(1);
PVector newTip = PVector.add(tip, growth);
line(tip.x, tip.y, newTip.x, newTip.y);
tip = newTip;
}
}