/** * Keys:

* 1: water
2: land
3: erase
4: change color
5: liquify
6: make water white
7: clear */ int water[] = new int[10]; int waterCount = 0; int waterpixels[]; int pixelids[]; int waterColor = 0xFF0000FF; int alphaColor = 0xFF000000; int bgColor = 0x00C8C8FF; int bgColor2 = 0xFFC8C8FF; int toolbarColor = 0xFF8080A0; Random rand; PImage waterImage; final int WATER = 0; final int LAND = 1; final int ERASE = 2; int inputMode = WATER; int pmouseX,pmouseY; void setup() { Dimension d = getSize(); size(256,256,P3D); loadPixels(); waterpixels = pixels; hint(DISABLE_TEXT_SMOOTH); textFont(loadFont("Verdana-9.vlw")); // waterpixels = new int[width*height]; // waterImage = new PImage(waterpixels,width,height,RGBA); for (int i=0; i=0;) { x = water[i]>>16; y = water[i]&0xFFFF; waterpixels[x+y*width]=0xFFFFFFFF; } break; case '7': for (int i=waterpixels.length; --i>=10*width;) { waterpixels[i] = bgColor; pixelids[i] = 0; } waterCount = 0; break; } } void draw() { // background(200); if (mousePressed) { for (int y=-2;y<=2;y++) for (int x=-2;x<=2;x++) { switch (inputMode) { case WATER: addWater(mouseX+x,mouseY+y,waterColor); break; case LAND: addLand(mouseX+x,mouseY+y,0xFFB77E39); break; case ERASE: erase(mouseX+x,mouseY+y); break; } } drawParticleCount(); } moveWater(); // image(waterImage,0,0); pmouseX=mouseX; pmouseY=mouseY; } void moveWater() { int x,y,id,c; boolean l,r; for (int i=waterCount; --i>=0;) { x = water[i]>>16; y = water[i]&0xFFFF; id = x+y*width; if (pixelids[id]-1 != i) continue; c = mixColor(x,y); waterpixels[id] = bgColor; pixelids[id] = 0; if (!solid(x,y+1)) y++; else { l = solid(x-1,y); r = solid(x+1,y); if (l&&r) /*nothing*/; else if (l) x += rand.nextInt(2); else if (r) x -= rand.nextInt(2); else x += rand.nextInt(3)-1; } id = x+y*width; water[i] = (x<<16)|y; waterpixels[id] = c; pixelids[id] = i+1; } } final private int mix(int c1, int c2) { return alphaColor | ((((c1&0xFEFEFF))+((c2&0xFEFEFF)))>>1); } final private int mixColor(int x, int y) { int c=waterpixels[x+y*width]; if (rand.nextInt(5)>0) return c; /* switch (rand.nextInt(4)) { case 0: if (liquid(x,y-1)) waterpixels[x+(y-1)*width]=c=mix(c,waterpixels[x+(y-1)*width]); break; case 1: if (liquid(x,y+1)) waterpixels[x+(y+1)*width]=c=mix(c,waterpixels[x+(y+1)*width]); break; case 2: if (liquid(x+1,y)) waterpixels[x+1+y*width]=c=mix(c,waterpixels[x+1+y*width]); break; case 3: if (liquid(x-1,y)) waterpixels[x-1+y*width]=c=mix(c,waterpixels[x-1+y*width]); break; } */ if (liquid(x,y-1)) waterpixels[x+(y-1)*width]=c=mix(c,waterpixels[x+(y-1)*width]); if (liquid(x,y+1)) waterpixels[x+(y+1)*width]=c=mix(c,waterpixels[x+(y+1)*width]); if (liquid(x+1,y)) waterpixels[x+1+y*width]=c=mix(c,waterpixels[x+1+y*width]); if (liquid(x-1,y)) waterpixels[x-1+y*width]=c=mix(c,waterpixels[x-1+y*width]); waterpixels[x+y*width] = c; return c; } final private boolean liquid(int x, int y) { if (x<0||y<10||x>=width||y>=height) return false; int id = x+y*width; return ((0xFF000000&waterpixels[id])!=0) && pixelids[id]>0; } final private boolean solid(int x, int y) { if (x<0||y<10||x>=width||y>=height) return true; return ((0xFF000000&waterpixels[x+y*width]) != 0); } void addWater(int x, int y, int c) { int i = x+y*width; if (liquid(x,y)) waterpixels[i]=c; if (solid(x,y)) return; addWater(i,c); } void addWater(int i, int c) { if (waterCount >= water.length) { int t[] = water; water = new int[t.length*2]; System.arraycopy(t,0,water,0,t.length); t = null; } int x = i%width; int y = i/width; water[waterCount++] = (x<<16)|y; waterpixels[i] = c; pixelids[i] = waterCount; } void erase(int x, int y) { if (x<0 || y<10 || x>=width || y>=height) return; int i = x+y*width; waterpixels[i] = bgColor; pixelids[i] = 0; int id = pixelids[i]; if (id <= 0 || id>=waterCount) return; id--; waterCount--; water[id] = water[waterCount]; } void addLand(int x, int y, int c) { if (solid(x,y)) return; pixelids[x+y*width] = 0; waterpixels[x+y*width] = c; }