/* Robot Etching Acid number 6 Paver or River */ paving [] p; int w,h,count; BImage swap,map; int drawit = 1; void setup(){ count = 0; swap = loadImage("b.gif"); map = swap.copy(); for(int i = 0; i < map.pixels.length; i++){ map.pixels[i] = #000000; } w = swap.width; h = swap.height; size(600,442);//applet //size(w*2,h);//non applet with bot collision map //size(w,h);//print mode println("Canvas size: width:"+w+" height:"+h); p = new paving[2000]; for (int i = 0; i < p.length/2; i++){ int rw = int(random(w)); int rh = int(random(h)); p[i] = new paving(rw,rh,true); } for (int i = p.length/2; i < p.length; i++){ int rw = int(random(w)); int rh = int(random(h)); p[i] = new paving(rw,rh,false); } } void loop(){ image(swap,0,0); //image(map,w,0);//bot collision map for (int i = 0; i < p.length; i++){ p[i].pave(); p[i].check(); p[i].move(); if(drawit == 0){ p[i].draw();//reminder this line to not draw paver sprites } } } void mousePressed(){ save("pavers.tif"); println("save count "+count++); } void keyPressed(){ drawit++; drawit %= 2; } class paving{ int x,y,d,thresh,step; boolean male; paving(int x, int y, boolean male){ this.x = x; this.y = y; this.thresh = grey(swap.pixels[x + y * w]); this.male = male; d = 0; step = 10; if (male){ step = -10; } map.pixels[x + y * w] = #00FF00; } void draw(){ color c = swap.pixels[x + y * w]; noStroke(); fill(c); ellipse(x-2,y-2,5,5); } void move(){ map.pixels[x + y * w] = #000000; switch(d){ case 0: x = (x+1)%w; break; case 1: y = (y+1)%h; break; case 2: x = wr(x-1,w-1); break; case 3: y = wr(y-1,h-1); break; } map.pixels[x + y * w] = #00FF00; } void check(){ d = 5; if (male){ if (grey(swap.pixels[((x+1)%w) + y * w]) <= thresh && map.pixels[((x+1)%w) + y * w] == #000000){ d = 0; } else if (grey(swap.pixels[x + ((y+1)%h) * w]) <= thresh && map.pixels[x + ((y+1)%h) * w] == #000000){ d = 1; } else if (grey(swap.pixels[wr(x-1,w-1) + y * w]) <= thresh && map.pixels[wr(x-1,w-1) + y * w] == #000000){ d = 2; } else if (grey(swap.pixels[x + wr(y-1,h-1) * w]) <= thresh && map.pixels[x + wr(y-1,h-1) * w] == #000000){ d = 3; } } else { if (grey(swap.pixels[((x+1)%w) + y * w]) >= thresh && map.pixels[((x+1)%w) + y * w] == #000000){ d = 0; } else if (grey(swap.pixels[x + ((y+1)%h) * w]) >= thresh && map.pixels[x + ((y+1)%h) * w] == #000000){ d = 1; } else if (grey(swap.pixels[wr(x-1,w-1) + y * w]) >= thresh && map.pixels[wr(x-1,w-1) + y * w] == #000000){ d = 2; } else if (grey(swap.pixels[x + wr(y-1,h-1) * w]) >= thresh && map.pixels[x + wr(y-1,h-1) * w] == #000000){ d = 3; } } } void pave(){ int [] opt = new int[4]; d = 5; //calculate threshold deltas if(male){ opt[0] = grey(swap.pixels[((x+1)%w) + y * w]) - thresh; opt[1] = grey(swap.pixels[x + ((y+1)%h) * w]) - thresh; opt[2] = grey(swap.pixels[wr(x-1,w-1) + y * w]) - thresh; opt[3] = grey(swap.pixels[x + wr(y-1,h-1) * w]) - thresh; }else{ opt[0] = thresh - grey(swap.pixels[((x+1)%w) + y * w]); opt[1] = thresh - grey(swap.pixels[x + ((y+1)%h) * w]); opt[2] = thresh - grey(swap.pixels[wr(x-1,w-1) + y * w]); opt[3] = thresh - grey(swap.pixels[x + wr(y-1,h-1) * w]); } int val = 255; for (int i = 0; i < opt.length; i++){ if (opt[i] < val && opt[i] > 0){ d = i; val = opt[i]; } } switch(d){ case 0: swap.pixels[((x+1)%w) + y * w] = tone(swap.pixels[((x+1)%w) + y * w],step); break; case 1: swap.pixels[x + ((y+1)%h) * w] = tone(swap.pixels[x + ((y+1)%h) * w],step); break; case 2: swap.pixels[wr(x-1,w-1) + y * w] = tone(swap.pixels[wr(x-1,w-1) + y * w],step); break; case 3: swap.pixels[x + wr(y-1,h-1) * w] = tone(swap.pixels[x + wr(y-1,h-1) * w],step); break; } } } //screen wrap around function int wr(int v, int lim){ if (v < 0){ v = lim; } return v; } color tone (color c, int val){ int r=c>>16&0xff; int g=c>>8&0xff; int b=c&0xff; r += val; g += val; b += val; return color(r,g,b); } int grey(color p){ int r=p>>16&0xff; int g=p>>8&0xff; int b=p&0xff; return (r+g+b)/3; }