/* vine.pde v0.07.03 written by: j. neele erasmus neeley@littlesecretsrecords.com written using processing, an open project initiated by Ben Fry and Casey Reas http://processing.org */ public class vine extends PApplet{ // Declare global constants static private float WORLD_RND_AFFECT = 500; // Value for randomly determining whether to affect a leaf positively or negatively static private int WORLD_GIVE_TIME = 5000; // How long the world should take giving to a leaf static private int TRUNK_WEIGHT = 10; // Weight of stroke for drawing trunk static private float TRUNK_METER_WEIGHT = 1; // Weight of stroke for meter on trunk static private float TRUNK_METER_SCALE = 0.2; // Scale to draw resource meter on trunk static private float TRUNK_NEIGHBOR_INTERVAL = 200; // How wide to look for neighbors when determining where to grow a new branch static private float TRUNK_IDEAL_NEIGHBORS = 60; // Value of ideal neighbors for determining where to grow a new branch static private int TRUNK_RECEIVE_TIME = 5000; // How long the trunk should take receiving resources from a branch static private float BRANCH_MIN_COST = 5.0; // min resource cost of new branch static float BRANCH_MAX_COST = 15.0; // max resource cost of new branch static private float BRANCH_RAND_BIRTH = 700.0; // Value for randomly determining whether to grow a branch static private int BRANCH_WEIGHT = 5; // Weight of stroke for drawing branches static private int BRANCH_MARGIN = 30; // Margin on branch in which there are no leaves static private float BRANCH_FADE_TIME = 2000.0; // Branch fade time on birth and death in ms static private int BRANCH_RECEIVE_TIME = 5000; // How long a branch should take receiving resources from a leaf static private float BRANCH_RND_DIE_FACTOR = 500.0; // Factor for randomly killing branches static private float BRANCH_OFFSET = 4; // Offset of branches from trunk static private float BRANCH_METER_WEIGHT = 1; // Weight of stroke for meter on branches static private float BRANCH_METER_SCALE = 3; // Scale to draw resource meter on branches static private float BRANCH_NEIGHBOR_INTERVAL = 75; // How wide to look for neighbors when determining where to grow a new leaf static private float BRANCH_IDEAL_NEIGHBORS = 50; // Value of ideal neighbors for determining where to grow a new branch static private float BRANCH_TAX = 0.5; // How much of positive resources received from a leaf the branch has to give to the trunk static private float LEAF_MIN_COST = 1.0; // min resource cost of new leaf static private float LEAF_MAX_COST = 5.0; // max resource cost of new leaf static private float LEAF_RAND_BIRTH = 800.0; // Value for randomly determining whether to grow a leaf static private int LEAF_WEIGHT = 5; // Weight of stroke for drawing leaves static private int LEAF_LENGTH = 25; // Length for drawing leaves static private int LEAF_DIAMETER = 20; // Diameter for drawing leaf circles static private float LEAF_FADE_TIME = 1500.0; // Leaf fade time on birth and death in ms static private float LEAF_RND_DIE_FACTOR = 500.0; // Factor for randomly killing leaves static private float LEAF_METER_WEIGHT = 1; // Weight of stroke for meter on leaves static private float LEAF_METER_SCALE = 4; // Scale to draw resource meter on leaves static private float LEAF_TAX = 0.5; // How much of positive resources received from the world the leaf has to give to its branch static private int LEAF_RECEIVE_TIME = 5000; // How long a leaf should take receiving resources from a branch // Define variables for main Trunk myTrunk; Leaf leafGivingTo; boolean giving; int timeStartedGiving; float amountGiving; float xBegin, yBegin, xEnd, yEnd; void setup() { size(800, 600); //size(screen.width, screen.height); rectMode(CENTER); noCursor(); loop(); giving = false; myTrunk = new Trunk(500); } void draw() { background(0); // affect a random leaf either positively or negatively maybe if (!giving && myTrunk.getNumLeaves()>0 && random(WORLD_RND_AFFECT)<=1.0) { LinkedList branchesWithLeaves = myTrunk.getBranchesWithLeaves(); int branchNum, branchNumIndex; //branchNum = tempBranchNum = (int)random(branchesWithLeaves.size()-1); branchNumIndex = (int)random(branchesWithLeaves.size()-1); branchNum = ((Integer)branchesWithLeaves.get(branchNumIndex)).intValue(); int leafNum=0; while (branchNumIndex>0 && branchesWithLeaves.get(branchNumIndex-1)==branchesWithLeaves.get(branchNumIndex)) { leafNum++; branchNumIndex--; } leafGivingTo = myTrunk.getBranch(branchNum).getLeaf(leafNum); amountGiving = random(-2.0, 2.0); if (amountGiving!=0 && leafGivingTo.getLifeStage()=="normal") { //println("giving to branch = " + branchNum + " leaf = " + leafNum); giving = true; timeStartedGiving = millis(); leafGivingTo.givingResources(); // Make moving line come from outside of the view if (random(9) < 5) { // maybe::50% xBegin = random(-500, 0); } else { xBegin = random(width+1, width+500); } if (random(9) < 5) { // maybe::50% yBegin = random(-500, 0); } else { yBegin = random(height+1, height+500); } // Determine location of leaf head if (leafGivingTo.getParentTop()) { yEnd = height*0.5+leafGivingTo.getYpos(); } else { // !leafGivingTo.parentTop yEnd = height*0.5-leafGivingTo.getYpos(); } if (leafGivingTo.right) { xEnd = leafGivingTo.getParentXpos()+LEAF_LENGTH+LEAF_DIAMETER*0.5; } else { xEnd = leafGivingTo.getParentXpos()-LEAF_LENGTH-LEAF_DIAMETER*0.5; } } } // Draw trunk, and by extension branches and leaves myTrunk.update(); myTrunk.draw(); // If giving draw line, or stop giving if done if (giving) { if (millis()-timeStartedGiving > WORLD_GIVE_TIME) { // stop giving leafGivingTo.gaveResources(amountGiving); giving = false; } else { // draw giving line if (amountGiving<0) { stroke(255, 0, 0); } else { stroke(0, 255, 0); } noFill(); drawMovingLine(xBegin, yBegin, xEnd, yEnd); } } } void drawMovingLine(float x1, float y1, float x2, float y2) { float xBegin, xEnd, yBegin, yEnd; strokeWeight(4); float totalLength = sqrt(sq(x2-x1) + sq(y2-y1)); float theta = atan(abs(y2-y1)/abs(x2-x1)); float segmentLength = 20; float offset = ((float)(millis()%1000)/1000.0)*2*segmentLength; float i = 0-segmentLength; while (i < totalLength-segmentLength) { if (x1b) { return a; } else { return b; } } /******************************************************* ******************Class Definitions******************** *******************************************************/ //*********************Trunk**************************** public class Trunk { // Define Private Variables for trunk private LinkedList myBranches; // List containing all branches on trunk private String lifeStage; // What stage of life trunk is in: normal, receiving private float maxResources; // Constraining resources meter box private float resources; // actual current resources private int timeStartedReceiving; // Time started receiving resources from a branch Trunk(float startingResources) { this.myBranches = new LinkedList(); this.lifeStage = "normal"; this.maxResources = this.resources = startingResources; } // Get how many total leaves are on branches an the trunk public int getNumLeaves() { int count=0; for(int i=0; i 0) { branchesWithLeaves.addLast(new Integer(branchNum)); leafCount--; } } return branchesWithLeaves; } public Branch getBranch(int branchNum) { if (branchNum >= this.myBranches.size()) { branchNum = this.myBranches.size()-1; println("Trunk.getBranch called with branchNum=" + branchNum + ", size=" + this.myBranches.size()); } return (Branch)this.myBranches.get(branchNum); } private void growBranch() { float branchCost=random(BRANCH_MIN_COST,BRANCH_MAX_COST); if (branchCost <= this.resources) { // only grow a branch if we have enough resources boolean top, bestTop; float xPos, bestXpos; int neighborVal, bestNeighborVal; // Initialize best top, xPos, and neighborVal if (random(9) < 5) { // maybe::50% bestTop = false; } else { bestTop = true; } bestXpos = random(width); bestNeighborVal = 0; for (int i=0; iBRANCH_FADE_TIME) { this.resources += ((Branch)this.myBranches.get(i)).getResources(); this.myBranches.remove(i); } else if (this.lifeStage=="receiving" && ((Branch)this.myBranches.get(i)).getLifeStage()=="givingDown" && millis()-timeStartedReceiving>TRUNK_RECEIVE_TIME) { // stop taking resources when time runs out float bumpUp = ((Branch)this.myBranches.get(i)).doneTakingResources(); this.maxResources += bumpUp; this.resources += bumpUp; this.lifeStage = "normal"; ((Branch)this.myBranches.get(i)).increaseFavored(bumpUp); ((Branch)this.myBranches.get(i)).update(); } else if (this.lifeStage=="normal" && ((Branch)this.myBranches.get(i)).getLifeStage()=="excess") { // collect excess from branch & update it this.timeStartedReceiving = millis(); this.lifeStage = "receiving"; ((Branch)this.myBranches.get(i)).takeResources(); ((Branch)this.myBranches.get(i)).update(); } else { ((Branch)this.myBranches.get(i)).update(); } } } public void draw() { // Draw trunk noFill(); stroke(255); strokeWeight(TRUNK_WEIGHT); line(0, height*0.5, width, height*0.5); // Draw all branches for (int i=0; i= this.myLeaves.size()) { leafNum = this.myLeaves.size()-1; println("Branch.getLeaf called with leafNum=" + leafNum + ", size=" + this.myLeaves.size()); } return (Leaf)this.myLeaves.get(leafNum); } public float getResources() { return this.resources; } // Called by trunk when ready to receive excess resources (tax) public void takeResources() { //println("i am giving excess to the trunk"); this.lifeStage = "givingDown"; } // Called by trunk when done taking excess resources public float doneTakingResources() { //println("i am done giving this much to the trunk: " + this.excess); float oldExcess = this.excess; this.excess = 0; this.lifeStage = "normal"; return oldExcess; } public float getFavored() { return this.favored; } public void increaseFavored(float increase) { this.favored += increase; //println(" BRANCH: my new favored is " + this.favored); } public int getDeathTime() { return this.deathTime; } public void kill() { this.deathTime = millis(); this.lifeStage = "dead"; } public void growLeaf() { float leafCost = random(LEAF_MIN_COST, LEAF_MAX_COST); if (leafCost<=this.resources) { // only grow leaf if we have enough resources boolean right, bestRight; float yPos, bestYpos; int neighborVal, bestNeighborVal; // Initialize bestRight if (random(9) < 5) { // maybe::50% bestRight = false; } else { bestRight = true; } // Initialize bestYpos bestYpos = random(((height*0.5)-(BRANCH_MARGIN*2)))+BRANCH_MARGIN; // Initialize bestNeighobrVal bestNeighborVal = 0; for (int i=0; ib) { return a; } else { return b; } } public void update() { // move from lifeStage birthing to normal when appropriate if (this.lifeStage=="birthing" && millis()>this.birthTime+BRANCH_FADE_TIME) { this.lifeStage = "normal"; } // add new leaf maybe if (!(this.lifeStage=="dead") && !(this.lifeStage=="birthing")) { if (random(LEAF_RAND_BIRTH-this.resources)<=1.0) { this.growLeaf(); } } // Update all leaves and bury the dead for (int i=0; iLEAF_FADE_TIME) { // kill dead resources this.resources += ((Leaf)this.myLeaves.get(i)).getResources(); this.myLeaves.remove(i); } else if (this.lifeStage=="receiving" && ((Leaf)this.myLeaves.get(i)).getLifeStage()=="giving" && millis()-this.timeStartedReceiving>BRANCH_RECEIVE_TIME) { // stop taking resources when time runs out float bumpUp = ((Leaf)this.myLeaves.get(i)).doneTakingResources(); this.maxResources += bumpUp*(1-BRANCH_TAX); this.resources += bumpUp*(1-BRANCH_TAX); this.excess = bumpUp*BRANCH_TAX; this.lifeStage = "excess"; ((Leaf)this.myLeaves.get(i)).increaseFavored(bumpUp); ((Leaf)this.myLeaves.get(i)).update(); } else if (this.lifeStage=="normal" && ((Leaf)this.myLeaves.get(i)).getLifeStage()=="excess") { // collect excess from leaf & update it this.timeStartedReceiving = millis(); this.lifeStage = "receiving"; ((Leaf)this.myLeaves.get(i)).takeResources(); ((Leaf)this.myLeaves.get(i)).update(); } else if (this.lifeStage=="givingUp" && ((Leaf)this.myLeaves.get(i)).getLifeStage()=="healing" && millis()-this.timeStartedGiving>LEAF_RECEIVE_TIME) { // stop giving up to leaf when time runs out float amountHelping = ((Leaf)this.myLeaves.get(i)).getInjuries()*less(1-(2-((Leaf)this.myLeaves.get(i)).getFavored()), 1); ((Leaf)this.myLeaves.get(i)).increaseFavored(amountHelping*-0.5); ((Leaf)this.myLeaves.get(i)).healed(amountHelping); this.lifeStage = "normal"; ((Leaf)this.myLeaves.get(i)).update(); } else if (this.lifeStage=="normal" && ((Leaf)this.myLeaves.get(i)).getLifeStage()=="injured") { // help an injured leaf maybe if (((Leaf)this.myLeaves.get(i)).getFavored()>1.0 && this.resources>((Leaf)this.myLeaves.get(i)).getInjuries()) { this.leafGivingTo = ((Leaf)this.myLeaves.get(i)).getSelf(); this.timeStartedGiving = millis(); this.lifeStage = "givingUp"; //println(" Branch: I am giving up"); this.leafGivingTo.healing(); this.leafGivingTo.update(); } else { ((Leaf)this.myLeaves.get(i)).increaseFavored(((Leaf)this.myLeaves.get(i)).getInjuries()*-1); ((Leaf)this.myLeaves.get(i)).suckItUp(); ((Leaf)this.myLeaves.get(i)).update(); } } else { // everything is normal - just update the leaf ((Leaf)this.myLeaves.get(i)).update(); } } // randomly die maybe if (this.lifeStage!="dead" && this.myLeaves.size()==0 && random(this.resources*BRANCH_RND_DIE_FACTOR)<=1) { this.kill(); } } public void draw() { // Draw branch noFill(); strokeWeight(BRANCH_WEIGHT); if (this.lifeStage=="birthing") { // Determine stroke color based on lifeline stroke(((float)(millis()-this.birthTime)/BRANCH_FADE_TIME)*255.0); float grownHeight = ((((float)(millis()-this.birthTime))/BRANCH_FADE_TIME)*(height*0.5)); if (this.top) { line(this.xPos, height*0.5+(TRUNK_WEIGHT-BRANCH_OFFSET), this.xPos, (height*0.5+(TRUNK_WEIGHT-BRANCH_OFFSET))+grownHeight); } else { line(this.xPos, height*0.5-(TRUNK_WEIGHT-BRANCH_OFFSET), this.xPos, (height*0.5+(TRUNK_WEIGHT-BRANCH_OFFSET))-grownHeight); } } else if (this.lifeStage=="dead") { // street spirit (fade out) stroke(((float)(BRANCH_FADE_TIME-(float)(millis()-this.deathTime))/BRANCH_FADE_TIME)*255.0); if (this.top) { line(this.xPos, height*0.5+(TRUNK_WEIGHT-BRANCH_OFFSET), this.xPos, height); } else { line(this.xPos, height*0.5-(TRUNK_WEIGHT-BRANCH_OFFSET), this.xPos, 0); } } else { // Normal life time stroke(255); if (this.top) { line(this.xPos, height*0.5+(TRUNK_WEIGHT-BRANCH_OFFSET), this.xPos, height); } else { line(this.xPos, height*0.5-(TRUNK_WEIGHT-BRANCH_OFFSET), this.xPos, 0); } } // Draw all leaves for (int i=0; ib) { return a; } else { return b; } } public void update() { // move from lifeStage birthing to normal when appropriate if (this.lifeStage=="birthing" && millis()>this.birthTime+LEAF_FADE_TIME) { this.lifeStage = "normal"; } // randomly die maybe if (this.lifeStage=="normal" && random(this.resources*LEAF_RND_DIE_FACTOR)<=1) { this.kill(); } } public void draw() { // Draw leaf noFill(); strokeWeight(LEAF_WEIGHT); stroke(255); if (this.lifeStage=="birthing" && millis() < (this.birthTime+LEAF_FADE_TIME*0.75)) { // fade in line while birthing // Determine stroke color based on lifeline stroke(((float)(millis()-this.birthTime)/(LEAF_FADE_TIME*0.75))*255.0); float grownLength = ((((float)(millis()-this.birthTime))/LEAF_FADE_TIME*0.75)*LEAF_LENGTH); if (this.parentTop) { // parent branch on top if (this.right) { line(this.parentXpos+BRANCH_WEIGHT, height*0.5+this.yPos, this.parentXpos+BRANCH_WEIGHT+grownLength, height*0.5+this.yPos); } else { line(this.parentXpos-BRANCH_WEIGHT, height*0.5+this.yPos, this.parentXpos-BRANCH_WEIGHT-grownLength, height*0.5+this.yPos); } } else { // parent branch on bottom if (this.right) { line(this.parentXpos+BRANCH_WEIGHT, height*0.5-this.yPos, this.parentXpos+BRANCH_WEIGHT+grownLength, height*0.5-this.yPos); } else { line(this.parentXpos-BRANCH_WEIGHT, height*0.5-this.yPos, this.parentXpos-BRANCH_WEIGHT-grownLength, height*0.5-this.yPos); } } } else if (this.lifeStage=="birthing" && millis() < (this.birthTime+LEAF_FADE_TIME)) { // fade in circle while birthing if (this.parentTop) { // parent branch on top if (this.right) { stroke(255); line(this.parentXpos+BRANCH_WEIGHT, height*0.5+this.yPos, this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH, height*0.5+this.yPos); stroke(((float)(millis()-(this.birthTime+LEAF_FADE_TIME*0.75))/(LEAF_FADE_TIME*0.25))*255.0); ellipse(this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH+LEAF_DIAMETER*0.5, height*0.5+this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } else { stroke(255); line(this.parentXpos-BRANCH_WEIGHT, height*0.5+this.yPos, this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH, height*0.5+this.yPos); stroke(((float)(millis()-(this.birthTime+LEAF_FADE_TIME*0.75))/(LEAF_FADE_TIME*0.25))*255.0); ellipse(this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH-LEAF_DIAMETER*0.5, height*0.5+this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } } else { // parent branch on bottom if (this.right) { stroke(255); line(this.parentXpos+BRANCH_WEIGHT, height*0.5-this.yPos, this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH, height*0.5-this.yPos); stroke(((float)(millis()-(this.birthTime+LEAF_FADE_TIME*0.75))/(LEAF_FADE_TIME*0.25))*255.0); ellipse(this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH+LEAF_DIAMETER*0.5, height*0.5-this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } else { stroke(255); line(this.parentXpos-BRANCH_WEIGHT, height*0.5-this.yPos, this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH, height*0.5-this.yPos); stroke(((float)(millis()-(this.birthTime+LEAF_FADE_TIME*0.75))/(LEAF_FADE_TIME*0.25))*255.0); ellipse(this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH-LEAF_DIAMETER*0.5, height*0.5-this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } } } else if (this.lifeStage=="dead") { // street spirit (fade out) stroke(((float)(LEAF_FADE_TIME-(float)(millis()-this.deathTime))/LEAF_FADE_TIME)*255.0); if (this.parentTop) { // parent branch on top if (this.right) { line(this.parentXpos+BRANCH_WEIGHT, height*0.5+this.yPos, this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH, height*0.5+this.yPos); ellipse(this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH+LEAF_DIAMETER*0.5, height*0.5+this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } else { line(this.parentXpos-BRANCH_WEIGHT, height*0.5+this.yPos, this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH, height*0.5+this.yPos); ellipse(this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH-LEAF_DIAMETER*0.5, height*0.5+this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } } else { // parent branch on bottom if (this.right) { line(this.parentXpos+BRANCH_WEIGHT, height*0.5-this.yPos, this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH, height*0.5-this.yPos); ellipse(this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH+LEAF_DIAMETER*0.5, height*0.5-this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } else { line(this.parentXpos-BRANCH_WEIGHT, height*0.5-this.yPos, this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH, height*0.5-this.yPos); ellipse(this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH-LEAF_DIAMETER*0.5, height*0.5-this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } } } else { // normal life stage stroke(255); if (this.parentTop) { // parent branch on top if (this.right) { line(this.parentXpos+BRANCH_WEIGHT, height*0.5+this.yPos, this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH, height*0.5+this.yPos); ellipse(this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH+LEAF_DIAMETER*0.5, height*0.5+this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } else { line(this.parentXpos-BRANCH_WEIGHT, height*0.5+this.yPos, this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH, height*0.5+this.yPos); ellipse(this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH-LEAF_DIAMETER*0.5, height*0.5+this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } } else { // parent branch on bottom if (this.right) { line(this.parentXpos+BRANCH_WEIGHT, height*0.5-this.yPos, this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH, height*0.5-this.yPos); ellipse(this.parentXpos+BRANCH_WEIGHT+LEAF_LENGTH+LEAF_DIAMETER*0.5, height*0.5-this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } else { line(this.parentXpos-BRANCH_WEIGHT, height*0.5-this.yPos, this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH, height*0.5-this.yPos); ellipse(this.parentXpos-BRANCH_WEIGHT-LEAF_LENGTH-LEAF_DIAMETER*0.5, height*0.5-this.yPos, LEAF_DIAMETER, LEAF_DIAMETER); } } } if (!(this.lifeStage=="dead") && !(this.lifeStage=="birthing")) { // Draw resource meter strokeWeight(LEAF_METER_WEIGHT); stroke(0); fill(0); float blackLength; float greenLength; // Vibrate meter if receiving resources if ((this.lifeStage=="receiving" || this.lifeStage=="healing") && (millis()%500)<250) { blackLength = this.maxResources*LEAF_METER_SCALE*0.6; greenLength = this.resources*LEAF_METER_SCALE*0.6; } else { blackLength = this.maxResources*LEAF_METER_SCALE; greenLength = this.resources*LEAF_METER_SCALE; } if (this.parentTop) { if (this.right) { rect(this.parentXpos+LEAF_LENGTH*0.5, height*0.5+this.yPos, blackLength, LEAF_WEIGHT-3); // resource container fill(0, 255, 0); rect(this.parentXpos+LEAF_LENGTH*0.5, height*0.5+this.yPos, greenLength, LEAF_WEIGHT-3); // actual resources } else { // this.parentTop && !this.right rect(this.parentXpos-LEAF_LENGTH*0.5, height*0.5+this.yPos, blackLength, LEAF_WEIGHT-3); // resource container fill(0, 255, 0); rect(this.parentXpos-LEAF_LENGTH*0.5, height*0.5+this.yPos, greenLength, LEAF_WEIGHT-3); // actual resources } } else { // !this.parentTop if (this.right) { rect(this.parentXpos+LEAF_LENGTH*0.5, height*0.5-this.yPos, blackLength, LEAF_WEIGHT-3); // resource container fill(0, 255, 0); rect(this.parentXpos+LEAF_LENGTH*0.5, height*0.5-this.yPos, greenLength, LEAF_WEIGHT-3); // actual resources } else { // !this.parentTop && !this.right rect(this.parentXpos-LEAF_LENGTH*0.5, height*0.5-this.yPos, blackLength, LEAF_WEIGHT-3); // resource container fill(0, 255, 0); rect(this.parentXpos-LEAF_LENGTH*0.5, height*0.5-this.yPos, greenLength, LEAF_WEIGHT-3); // actual resources } } } // Draw moving line if giving resources to branch if (this.lifeStage=="giving") { float xBegin, yBegin, yEnd; noFill(); stroke(0, 255, 0); if (this.parentTop) { yBegin = height*0.5+this.yPos; yEnd = height*0.75; } else { yBegin = height*0.5-this.yPos; yEnd = height*0.25; } if(this.right) { xBegin = this.parentXpos+LEAF_LENGTH*0.5; } else { xBegin = this.parentXpos-LEAF_LENGTH*0.5; } drawMovingLine(xBegin, yBegin, this.parentXpos, yEnd); } } } }