int teaNum = 0; Tea[] teaList = new Tea[teaNum]; float flow; float teapotX, teapotY; float rotZ = 0; int count = 0; water theWater; float Gvt = 1.5; PImage tex_teapot; PImage tex_puf; void setup (){ size (500, 400, P3D); noStroke (); teapotX = width / 2; teapotY = height / 2; tex_teapot = loadImage ("teapot.jpg"); tex_teapot.mask (getAlpha ("teapot_mask.jpg", tex_teapot.width, tex_teapot.height)); tex_puf = loadImage ("puf.jpg"); tex_puf.mask (getAlpha ("puf_mask.jpg", tex_puf.width, tex_puf. height)); theWater = new water (); } void draw (){ // calculate rotation rotZ = (mouseX / - 130.0) - 5; // calculate position teapotX = mouseX; teapotY = mouseY; // calculate flow flow = (rotZ + TWO_PI) * -10; if (rotZ < -8){ flow += (8 + rotZ) * 23; } // make tea flow for (int i = 0; i < floor (flow); i ++){ moreTea (); count ++; } background (255); pushMatrix (); // draw teas and forget the one we don't care for (int i = 0; i < teaNum;){ if (teaList[i].flowing){ teaList[i].update (); teaList[i].draw (); i ++; }else{ teaNum --; teaList[i] = teaList[teaNum]; } } translate (teapotX, teapotY); rotateZ (rotZ); // draw teapot scale (.5); translate (tex_teapot.width / -2, tex_teapot.height / -2); image(tex_teapot, 0, 0); popMatrix (); // update and draw water theWater.update (); theWater.draw (); } class Tea { float px, py; float dx, dy; float ox, oy; float rotZ, myRotZ; float size, speed, trueY; boolean flowing; Tea (float a, float f, float x, float y) { flowing = true; ox = x; oy = y; myRotZ = random (PI); dy = -1 * ((10 - f) / 10.0); if (a < -8){ dx = -1 - ((a + 8) / 3.0); }else{ dx = -1; } dx += random (-.5, .5); dy += random (-.2, .2); speed = f / 2; flowing = true; py = px = 0; rotZ = a; size = random (6, 12); // what is my position relative to the screen ? trueY = (((height / 2) - 50) + (sin ((a + TWO_PI + 0.3) * -1) * 180)); } void draw (){ pushMatrix (); translate (ox, oy); translate (px, py); rotateZ (rotZ); translate (-105, -30); rotateZ (myRotZ); translate ((size*1.5) / -2, (size*1.5) / -2); image (tex_puf, 0, 0, size*1.5, size*1.5); popMatrix (); } void update (){ px += dx * speed; py += dy * speed; myRotZ += .1; dy += .3; size += .2; // make a small wave if (py + trueY > height - 100){ theWater.impact (floor ((px + ox) / theWater.Step), 5, .025); } // if this become true then we can be sure it's not on screen anymore if (py > height){ flowing = false; } } } void moreTea (){ // backup Tea[] temp = new Tea[teaNum]; for (int i = 0; i < temp.length; i ++){ temp[i] = teaList[i]; } teaNum ++; // restore teaList = new Tea[teaNum]; for (int i = 0; i < temp.length; i ++){ teaList[i] = temp[i]; } // add teaList[teaNum - 1] = new Tea(rotZ, flow, teapotX, teapotY); } // return an Alpha Mask PImage getAlpha (String mask, int w, int h){ PImage maskImage = loadImage (mask); PImage tmpImage = new PImage (w, h); maskImage.loadPixels (); tmpImage.loadPixels (); for (int j = 0; j < w*h; j++) { tmpImage.pixels[j] = color (brightness (maskImage.pixels[j])); } return tmpImage; } //---------------------------------- // WATER //---------------------------------- class water { point[] linePoint; int PLnum; int level; int Step; water (){ // number of dot PLnum = round (width / 10.0); // water level level = round (height / 1.2); // how many pixel beteween two dot Step = width / PLnum; // show one more dot out of the left side of the screen PLnum ++; linePoint = new point[PLnum]; // Spread points for (int i = 0; i < PLnum; i ++){ linePoint[i] = new point (i * Step, level); } } void draw (){ noStroke (); fill (255, 230, 245, 200); beginShape (QUADS); for (int i = 1; i < PLnum; i ++){ vertex (linePoint[i].px, linePoint[i].py); vertex (linePoint[i].px, height); vertex (linePoint[i-1].px, height); vertex (linePoint[i-1].px, linePoint[i-1].py); } endShape (); stroke (255, 40, 190); strokeWeight (3); noFill (); beginShape (LINES); curveVertex (linePoint[0].px, linePoint[0].py); for (int i = 0; i < PLnum; i ++){ curveVertex (linePoint[i].px, linePoint[i].py); } curveVertex (linePoint[PLnum-1].px, linePoint[PLnum-1].py); endShape (); } void update (){ // compute points for (int i = 0; i < PLnum; i ++){ linePoint[i].update (level); } // wave effect for (int i = 1; i < PLnum-2; i ++){ linePoint[i].vy -= (((linePoint[i-1].oy - linePoint[i-1].py) + (linePoint[i+1].oy - linePoint[i+1].py)) / 2.1) * Gvt; } } void impact (int x, int w, float s){ int n; for (float i = w*-1; i < w; i ++){ n = int (x + i); if (n > -1 && n < PLnum){ linePoint[n].py -= s * (1 - (abs (i) / w)); } } } } //---------------------------------- // POINT //---------------------------------- class point { float px, py, vx, vy, ox, oy; float weight = 1.025; point (float a, float b){ ox = px = a; oy = py = b; vx = vy = 0; } void update (float l){ oy = l; // translation vector vx += (ox - px) * Gvt; vy += (oy - py) * Gvt; // loose vx /= weight; vy /= weight; // update position px += vx; py += vy; } }