/**
* 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[];
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(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;) {
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) {
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;
}
}
}
moveWater();
drawParticleCount();
// image(waterImage,0,0);
}
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(16)-8;
if (dx<-1) dx=-1;
else if (dx>1) dx=1;
else 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;
sleepers[pos] = false;
// waterpixels[pos] = 0xFF808000;
pixelids[pos] = 0;
// calculate new square
pos = x+y*width;
// 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 id = x+y*width;
return 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) {
// 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;
// continue if there is no water id
if (id < 0 || id>=waterCount) return;
// set water id to zero
sleepers[pos] = true;
waterpixels[pos] = 0xFF000080;
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