/** * Keys:

* 1: water
2: land
3: erase
4: change color
5: liquify
6: make water white
7: clear */ FPS fps = new FPS(); int water[] = new int[10]; int waterCount = 0; int waterpixels[]; int pixelids[]; boolean sleepers[]; 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; void setup() { Dimension d = getSize(); size(400,400,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;) { waterpixels[water[i]]=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) { int dx=pmouseX-mouseX; int dy=pmouseY-mouseY; if (dx==0&&dy==0) drawPoint(mouseX,mouseY); else { double x=mouseX,y=mouseY; double units=Math.max(Math.abs(dx),Math.abs(dy)); double hunit=dx/units; double vunit=dy/units; for (int ii=(int)units; --ii>=0;) { x+=hunit; y+=vunit; drawPoint((int)x,(int)y); } } } moveWater(); fps.frame(); drawParticleCount(); // image(waterImage,0,0); } void drawPoint(int xx, int yy) { for (int y=-2;y<=2;y++) for (int x=-2;x<=2;x++) { switch (inputMode) { case WATER: addWater(xx+x,yy+y,waterColor); break; case LAND: addLand(xx+x,yy+y,0xFFB77E39); break; case ERASE: erase(xx+x,yy+y); break; } } } void moveWater() { int x,y,pos,c; boolean l,r; for (int i=0; i0) { wake(x-1,y); wake(x,y-1); x++; } else continue; // nothing moved } else if (r) { if (rand.nextInt(5)>0) { wake(x+1,y); wake(x,y-1); x--; } else continue; // nothing moved } else { int dx = rand.nextInt(3)-1; if (dx==0) continue; // nothing moved x += dx; wake(x,y-1); } } else { /* nothing solid beneath */ wake(x-1,y); wake(x+1,y); wake(x,y-1); y++; } // clear old square color and pixel id waterpixels[pos] = bgColor; // waterpixels[pos] = 0xFF808000; pixelids[pos] = 0; // calculate new square pos = x+y*width; if (sleepers[pos]) { println("Trying to overwrite sleeper ["+x+","+y+"]"); c = 0xFFFF0000; } if (pixelids[pos]>0) { println("Trying to overwrite water ["+x+","+y+"]"); c = 0xFF000000; } // update water's position water[i] = pos; // update color and pixel id waterpixels[pos] = c; pixelids[pos] = 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 (true) return c; 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 pos = x+y*width; return pixelids[pos]>0; } final private boolean solid(int x, int y) { if (x<0||y<10||x>=width||y>=height) return true; int pos = x+y*width; return ((0xFF000000&waterpixels[pos]) != 0) || pixelids[pos]>0; } void addWater(int x, int y, int c) { // Don't overwrite land if (solid(x,y)) return; // If square is already water, just change its color int pos = x+y*width; if (liquid(x,y)) { waterpixels[pos]=c; return; } // otherwise, add it! addWater(pos,c); } void addWater(int pos, int c) { // Make sure there is enough room to add water if (waterCount >= water.length) { int t[] = water; water = new int[t.length*2]; System.arraycopy(t,0,water,0,t.length); t = null; } // add water at very end and increment counter water[waterCount++] = pos; // set color waterpixels[pos] = c; // set pixel id (this is +1 from the actual id, but we already did waterCount++ above) pixelids[pos] = waterCount; // not asleep sleepers[pos] = false; } int asleep=0; void sleep(int x, int y) { if (x<0 || y<10 || x>=width || y>=height) return; // get position int pos = x+y*width; // get water id int id = pixelids[pos]-1; pixelids[pos] = 0; // continue if there is no water id if (id < 0 || id>=waterCount) return; // set water id to zero sleepers[pos] = true; //waterpixels[pos] = 0xFF000080; pixelids[pos] = 0; asleep++; // decrement water count (this deletes water) waterCount--; // copy last water and replace the deleted water id with that if (id!=waterCount) { water[id] = water[waterCount]; water[waterCount] = 0; pixelids[water[id]] = id+1; } } void wake(int x, int y) { if (x<0 || y<10 || x>=width || y>=height) return; int pos = x+y*width; if (!sleepers[pos]) return; if (asleep<=0) { println("Trying to wake up more than we've put to sleep!"); return; } asleep--; sleepers[pos] = false; // Make sure there is enough room to add water if (waterCount >= water.length) { int t[] = water; water = new int[t.length*2]; System.arraycopy(t,0,water,0,t.length); t = null; } water[waterCount++] = pos; pixelids[pos] = waterCount; //waterpixels[pos] = 0xFF0000FF; } void erase(int x, int y) { if (x<0 || y<10 || x>=width || y>=height) return; // calculate position int pos = x+y*width; // clear color waterpixels[pos] = bgColor; // get id and check if the cell has water int id = pixelids[pos]-1; if (id>=0 && id