/**
* 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;
}