float SZ = 500; MouseCatcher c = new MouseCatcher(); Catcher land; ArrayList penguins; ArrayList sinkers; int score; void setup() { size(500, 500); reset(); noCursor(); land = new Catcher(); land.y = SZ*5/8; land.x = SZ; //penguins.add(new Penguin()); } float MISSEDTOP = 45; float MISSEDLEFT = 150; void keyPressed() { if(key == ' ') reset(); } int flockSize; int waitingInThisFlock; boolean playing; int lives; void reset() { flockSize = 1; waitingInThisFlock = 1; penguins = new ArrayList(); sinkers = new ArrayList(); score = 0; playing = true; lives = 10; } void showScore() { fill(0); textSize(14); textAlign(CENTER); text("Rescued",60,20); text("Missed",300,20); textSize(40); if(playing && flockSize == 1) text("keep penguins\nout of the water!",SZ/2,SZ/4); if(!playing) fill(random(200,255)); text(score,60,60); if(!playing){ text("reset to play again!\n",SZ/2,SZ/4); } } void didSink() { lives--; if (lives < 0 ) lives = 0; if (lives <= 0) { playing = false; } } void addPenguin() { if (waitingInThisFlock <= 0) { flockSize++; waitingInThisFlock = flockSize; } waitingInThisFlock--; penguins.add(new Penguin()); } float findLeftmostPenguinX() { float left = 999999; for (Penguin p : penguins) { if (p.x < left) { left = p.x; } } return left; } void draw() { drawWaves(); if (playing) { int count = penguins.size(); if (count == 0) { addPenguin(); } else { if (count < flockSize) { //we want a penguin on there sometime soon if (findLeftmostPenguinX() >= SZ / flockSize) { addPenguin(); } } } } // penguins.add(new Penguin()); c.draw(); land.draw(); ArrayList toRemove = new ArrayList(); for(int i = 0; i < 10; i++){ fill(200,200,255); rect(MISSEDLEFT + i * 30, MISSEDTOP - 14, 25,25); } int missShow = 0; for (Penguin p : sinkers) { p.move(); p.draw(); if(missShow < 10){ p.drawMiss(missShow); } missShow++; } for (Penguin p : penguins) { p.move(); p.draw(); if (p.isSafe()) { toRemove.add(p); score++; } if (!p.isSunk() && p.isDunked()) { p.sink(); toRemove.add(p); sinkers.add(p); didSink(); } } penguins.removeAll(toRemove); showScore(); } class Penguin { float x, y, xs, ys; float sz = random(15, 25); ; boolean sinking = false; boolean landed = false; Penguin() { x = -sz ; y = SZ/4; float a = -PI / 4 + random(-.4, .4); xs = cos(a) * 3; ys = sin(a) * 3; } void move() { if (!sinking && !landed) { x += xs; ys += .1; y += ys; if (inCatcher(c) && ys > 0) { ys = -abs(ys); } if(inCatcher(land)){ landed = true; } } if(sinking) y += 1; if(landed) x += xs; } void draw() { float a = 0; if(sinking) a = PI; if (! sinking && !landed) a = map(ys, 0, 5, -PI/2, PI/2); drawPenguin(x, y, sz, true, a, .5, sinking); } void drawMiss(int pos){ drawPenguin(MISSEDLEFT + 13 + pos * 30, MISSEDTOP, sz, true, PI, .5, sinking); } boolean isSafe() { if(sinking) return false; return x > SZ + (sz *2); } boolean isDunked() { return y > calcSeaHeight(x) + SZ/5; } void sink() { sinking = true; } boolean isSunk() { return sinking; } boolean inCatcher(Catcher c) { return (x+ sz / 2 >= c.x-c.w/2 && x - sz/2 <= c.x+c.w/2) && (y + sz/2 >= c.y-c.h/2 && y -sz/2<= c.y+c.h/2); } } class Catcher { float x = 250; float y; float w = SZ/5; float h = SZ/20; void draw() { fill(255); ellipse(x, y, w, h); } } class MouseCatcher extends Catcher { void draw() { x = mouseX; y = calcSeaHeight(x) + SZ/8; super.draw(); } } float wavea ; void drawWaves() { wavea += .03; float off = cos(wavea) * SZ/12; background(SKY); fill(SEA); rect(0, SZ/2, SZ, SZ/2); fill(SKY); for (int i = -1; i < 8; i++) { float x = (i * SZ/6); ellipse(x, calcSeaHeight(x), SZ/5, SZ/5); // } } float calcSeaHeight(float x) { float i = (x * 6) / SZ; return SZ/2 + SZ/35 * cos(wavea + i); } color SKY = color(180, 180, 255); color SEA = color(60, 60, 180); color BEAKYELLOW = color(200, 200, 0); color BEAKYELLOW_WATER = color(200, 200, 128); color BLACK = color(0); color BLACK_WATER = color(0, 0, 128); color WHITE = color(255); color WHITE_WATER = color(128, 128, 255); //make a penguin w/ diaometer 100 * unit and radius 50* unit centered at x,y void drawPenguin(float x, float y, float diam, boolean forward, float tilt, //rotation angle float wingoff, //between 1 and 0 -- decrease by .3 per click? boolean underwater ) { // float diam = 100 * unit; float rad = diam / 2; noStroke(); pushMatrix(); translate(x, y); rotate(tilt); //feet if (underwater) fill(BEAKYELLOW_WATER); else fill(BEAKYELLOW); ellipse(cos(PI/2 - .72) * rad, sin(PI/2 - .72) * rad, rad * .38, rad*.38); ellipse(cos(PI/2 + .72) * rad, sin(PI/2 + .72) * rad, rad * .38, rad*.38); //wings if (underwater) fill(BLACK_WATER); else fill(BLACK); ellipse(cos(PI/2 - 1.312 - wingoff) * rad, sin(PI/2 - 1.312) * rad, rad * .528, rad*.528); ellipse(cos(PI/2 + 1.312 + wingoff) * rad, sin(PI/2 + 1.312) * rad, rad * .528, rad*.528); //body ellipse(0, 0, diam, diam); if (forward) { if (underwater) fill(WHITE_WATER); else fill(WHITE); //belly ellipse(0, rad * .4, rad, rad); //eyes ellipse(-rad * .372, - rad *.372, rad *.492, rad *.492); ellipse(rad * .372, - rad *.372, rad *.492, rad *.492); fill(0); ellipse(-rad * .372, - rad *.372, rad *.324, rad * .324); ellipse(rad * .372, - rad *.372, rad *.324, rad *.324); //beak if (underwater) fill(BEAKYELLOW_WATER); else fill(BEAKYELLOW); ellipse(0, rad * -0.068, rad * .38, rad*.38); } popMatrix(); }