class Mycelium { Tip[] growth = new Tip[1000]; int n; PImage foodImg; Mycelium(PImage f) { foodImg = f; } void display() { // dub sez... less food affinity //for(int i=n; --i>=0;) growth[i].react(0.125, 3, 0.15, 4); for(int i=n; --i>=0;) growth[i].react(0.125, 3, 0.25, 2); for(int i=n; --i>=0;) { growth[i].update(); if(growth[i].x<0 || growth[i].x>width-1 || growth[i].y<0 || growth[i].y>height-1) kill(i); else growth[i].display(); } } void spore(float x, float y, int ns) { for(int i=ns; --i>=0;) { if(n == growth.length) kill((int)random(n)); growth[n++] = new Tip(x,y,random(-2,2),random(-2,2)); } } void spore(double x, double y, double xv, double yv) { if(n == growth.length) kill((int)random(n)); growth[n++] = new Tip(x,y,xv,yv); } void kill(int i) { if(i < n-1) System.arraycopy(growth, i+1, growth, i, n-1-i); n--; } float food(double x, double y) { // dub sez... constrain to size int maxx = constrain((int)x, 0, width-1); int maxy = constrain((int)y, 0, height-1); int c = foodImg.pixels[maxx+maxy*foodImg.width]; // dub sez.. why 765? return (red(c)+blue(c)+green(c))/768.0; } DVector2 brightVector(double x, double y, int[] pix, int w, int h, int spread, int limit) { // Find the vector to the brightest area int intx = (int)x; int inty = (int)y; float br; float cbr = 0; // Cumulative Brightness float brx = 0; float bry = 0; int maxx = constrain(intx+spread, 0, w-1); int maxy = constrain(inty+spread, 0, h-1); for(int i=constrain(intx-spread, 0, w-1); i <= maxx; i++) { for(int j=constrain(inty-spread, 0, h-1); j <= maxy; j++) { br = (red(pix[j*w+i])+green(pix[j*w+i])+blue(pix[j*w+i]))/768.0; if(limit > 0 && sq((float)x-i)+sq((float)y-j) > limit*limit) { br = 0; /*print("-------- ");*/ } //else print(nf(sqrt(sq((float)x-i)+sq((float)y-j)),0,6)+" "); cbr += br; brx += i*br; bry += j*br; } //println("/"); } if(cbr != 0) return new DVector2(brx/cbr-x, bry/cbr-y); else return new DVector2(0,0); } class Tip extends DParticle { double lastx, lasty; Tip(double ix, double iy, double ixv, double iyv) { super(ix,iy,ixv,iyv); } void react(float selfam, int selfsp, float foodam, int foodsp) { DVector2 selfbr = brightVector(x,y, pixels,width,height, selfsp, selfsp); DVector2 foodbr = brightVector(x,y, foodImg.pixels,width,height, foodsp, foodsp); // Move away from self if(selfbr.x != 0 && selfbr.y != 0) { xv = mix(xv, -selfbr.x, selfam); yv = mix(yv, -selfbr.y, selfam); } // Move toward food if(foodbr.x != 0 && foodbr.y != 0) { xv = mix(xv, foodbr.x, foodam); yv = mix(yv, foodbr.y, foodam); } } void update() { lastx = x; lasty = y; xv += random(-.1, .1); yv += random(-.1, .1); float myfood = food(x,y); // Approach a normalized velocity double mag = Math.sqrt(xv*xv + yv*yv); xv += ((xv/mag)*mix(0.25,1,myfood)-xv)*0.5; yv += ((yv/mag)*mix(0.25,1,myfood)-yv)*0.5; super.update(); if((int)random(lerp(200,40,myfood))==0) spore(lastx,lasty,xv+random(-0.1,0.1),yv+random(-0.1,0.1)); } void display() { // dub sez... blend factor aapixel((float)x,(float)y,color(255,224,192),0.33); //aapixel((float)x,(float)y,color(255,255,255),0.15); //aapixel((float)x,(float)y,color(255,255,255),0.25); } } }