/** Game 01: "No Rain Today"
Use left and right arrows to turn
Press space to flap upward
Press P to pause
Don't let it rain
Creative Commons License
This work by Nathan McCoy is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License. */ // ArrayList downKeys; float px, py, dx, dy; PFont font; int SPACE = 32; float OMEGA = 0.1; //float DRAG = 0.997; float DRAGCOEFF = 1.0/3000; float ROTDRAG = 1; float FLAP = 3; float STALLSPEED = 0; float PLAYER_RADIUS = 16; boolean paused = false; boolean gameover = true; ParticleSet particles; ParticleSet steampuffs; ParticleSet rainsplashes; ArrayList clouds; ArrayList rain; float RAINSPEED = 2.0; float RAINDAMAGE = 0.01; float INTENSITY_RATE = 1.0/3000; float CLOUDCOUNT = 100; float CLOUDMAX = 50; float CLOUDGROWTH = 0.02; float CLOUD_INTENSITY = 1.0/5000; float time = 0; float life = 1.0; int score = 0; int combo; float combofade; PVector combopos; boolean firstplay = true; class Cloud extends PVector { float radius = CLOUDMAX; Cloud(float x, float y) { super(x, y); } } class Particle { float x, y, dx, dy; int life; int maxlife; Particle(float px, float py, float vx, float vy, int lifespan) { x = px; y = py; dx = vx; dy = vy; life = lifespan; maxlife = lifespan; } void update() { x += dx; y += dy; life--; } float age() { return float(life)/maxlife; } } class ParticleSet extends ArrayList { void update() { Iterator i = iterator(); while(i.hasNext()) { Object o = i.next(); if(o instanceof Particle) { Particle p = (Particle) o; p.update(); if(p.life <= 0) i.remove(); } } } } void reset() { rain = new ArrayList(); particles = new ParticleSet(); steampuffs = new ParticleSet(); rainsplashes = new ParticleSet(); combo = 0; combofade = 0; combopos = new PVector(0, 0); clouds = new ArrayList(); for(int i=0; i < CLOUDCOUNT; i++) { clouds.add(new Cloud(random(width), random(height/4))); } smooth(); noStroke(); fill(255, 153); px = width/2; py = height/2; dx = 0; dy = 0; time = 0; life = 1.0; score = 0; } void setup() { font = loadFont("ARBERKLEY-48.vlw"); textFont(font, 32); size(640, 480); background(color(32+(1-life)*96, 128+40*life, 128+127*life)); frameRate(60); downKeys = new ArrayList(); reset(); } void rotateVel(float theta) { float newdx = cos(theta)*dx - sin(theta)*dy; float newdy = sin(theta)*dx + cos(theta)*dy; dx = newdx; dy = newdy; } void draw() { if(paused) { textAlign(LEFT, TOP); fill(#000000); text("paused", 8, 8); } else if(gameover) { textAlign(LEFT, TOP); fill(#000000); if(firstplay) { text("No Rain Today\n\npress P to play", 8, 8); fill(#FFFFFF); text("No Rain Today\n\npress P to play", 6, 6); } else { text("No Rain Today\nscore: "+ Integer.toString(score) +"\npress P to play", 8, 8); fill(#FFFFFF); text("No Rain Today\nscore: "+ Integer.toString(score) +"\npress P to play", 6, 6); } } else { time+= 1.0/frameRate; //add raindrops from clouds if(random(1) < time * INTENSITY_RATE) { PVector potentialDrop = new PVector(random(width), random(height/4)); for(int i = 0; i < clouds.size(); i++) { Cloud c = (Cloud)clouds.get(i); if(c.dist(potentialDrop) CLOUDMAX/2) { rain.add(potentialDrop); break; } } } float speed = sqrt(dx*dx + dy*dy); float turnpower = min(speed / STALLSPEED, 1); background(color(32+(1-life)*96, 128+40*life, 128+127*life)); float rot = 0; if(downKeys.contains(LEFT)) rot += -OMEGA * turnpower; if(downKeys.contains(RIGHT)) rot += OMEGA * turnpower; if(rot != 0) { rotateVel(rot); dx *= ROTDRAG; dy *= ROTDRAG; } //dx *= DRAG; //dy *= DRAG; float airdrag = speed * speed * DRAGCOEFF; if(speed != 0) { dx -= (dx/speed) * airdrag; dy -= (dy/speed) * airdrag; } dy += 0.1; px += dx; py += dy; if(px < 0) { dx *= -0.5; px = 0; } if(px > width) { dx *= -0.5; px = width; } if(py > height) { dy *= -0.5; py = height; } //fill(255, 153); //ellipse(px - dx*8/speed, py - dy*8/speed, 24, 24); //ellipse(px + dx*8/speed, py + dy*8/speed, 24, 24); //ellipse(px - dx, py - dy, 32, 32); //do rain stuff Iterator it = rain.iterator(); while(it.hasNext()) { Object o = it.next(); PVector p = (PVector) o; p.y += RAINSPEED; if(p.y > height) { it.remove(); life -= RAINDAMAGE; if(combo > 0) { combo = 0; combopos = new PVector(p.x, p.y-40); combofade = 1; } if(life <= 0) gameover = true; rainsplashes.add(new Particle(p.x, p.y, 0, 0, 30)); } else { float flicker = sin(p.x / 300 + p.y / 200 - time*10)*128+128; fill(color(flicker, flicker, 255)); ellipse(p.x, p.y, 3, 10); for(int i = 0; i CLOUDMAX) c.radius = CLOUDMAX; float distance = c.dist(new PVector(px, py)); if(distance < c.radius + PLAYER_RADIUS) c.radius = distance - PLAYER_RADIUS; fill(200+55*life, 200+55*life, 200+55*life, 255*((c.radius/CLOUDMAX)*10-4)); ellipse(c.x, c.y, c.radius*2, c.radius*2); } //draw combo counter fill(255, 255, 192, combofade*255); textAlign(CENTER, CENTER); text("x"+Integer.toString(combo), combopos.x, combopos.y); combofade *= 0.97; } } void down(int theKey) { println(theKey + " down"); if(theKey == 32 && !paused) dy -= FLAP; } void up(int theKey) { println(theKey + " up"); } void keyPressed() { if(key == 'p') { if(!gameover) paused = !paused; else{ reset(); firstplay = false; gameover = false; } } if(!downKeys.contains(keyCode)) { downKeys.add(keyCode); down(keyCode); } } void keyReleased() { if(downKeys.indexOf(keyCode)!= -1) { downKeys.remove(downKeys.indexOf(keyCode)); up(keyCode); } }