import ddf.minim.*; import ddf.minim.signals.*; import ddf.minim.analysis.*; import ddf.minim.effects.*; /** * Game XX: "Name"
*
*
Go play more games at NMcCoy.net!
* Creative Commons License
This work by Nathan McCoy is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License. */ boolean[] keys = new boolean[256]; PFont font; ArrayList cores; ArrayList explosions; int score; int bombs; int time; int frames; int level; int target_score; int appear_timer; int level_timer; int LEVEL_TIME = 3000; boolean muted; int BOMB_LIFE = 10; float BOMB_RADIUS = 200; int APPEAR_TIME = 200; float FULL_RATIO = 0.25; boolean playing; Minim minim; AudioSample pulseSound; AudioSample explodeSound; AudioSample appearSound; AudioSample levelSound; ParticleList particles; void reset(int lev) { level = lev; level_timer = LEVEL_TIME; score = 0; target_score = level * 10000; cores = new ArrayList(); explosions = new ArrayList(); particles = new ParticleList(); frames = 0; appear_timer = APPEAR_TIME; playing = true; } void stop() { pulseSound.close(); explodeSound.close(); appearSound.close(); levelSound.close(); minim.stop(); super.stop(); } class Flare extends Particle { Flare(PVector p, PVector v) { super(p, v, 15); } void draw() { fill(255, map(life, maxlife, 0, 255, 0), 0); noStroke(); ellipse(pos.x, pos.y, life * 2, life * 2); } } void setup() { minim = new Minim(this); pulseSound = minim.loadSample("pulse.wav", 1024); pulseSound.setGain(-10); appearSound = minim.loadSample("appear.wav", 1024); appearSound.setGain(-10); explodeSound = minim.loadSample("explode.wav", 1024); explodeSound.setGain(-10); levelSound = minim.loadSample("levelup.wav", 1024); levelSound.setGain(-10); size(720, 480, P2D); frameRate(60); font = loadFont("PressStartK-32.vlw"); //reset(1); //cores.add(new Core(new PVector(width/2, height/2), new PVector(0, 0), 3)); } class Explosion { float x; float y; int life; Explosion(float px, float py) { x = px; y = py; life = BOMB_LIFE; } float radius() { return (1 - life * 1.0 / BOMB_LIFE) * BOMB_RADIUS; } void draw() { fill(255.0 * life / BOMB_LIFE); stroke(255); noStroke(); strokeWeight(1); ellipse(x, y, radius(), radius()); } void tick() { life--; } } class Core { float[] ring_angles; float[] ring_speeds; float fullness; float radius; int value; PVector pos; PVector vel; Core(PVector p, PVector v, int rings) { pos = p; vel = v; ring_angles = new float[rings]; ring_speeds = new float[rings]; for(int i = 0; i < rings; i++) { ring_angles[i] = random(TWO_PI); int sign = 1; if(i % 2 == 0) sign = -1; ring_speeds[i] = sign * (1 + random(3)) * 0.01; } fullness = 1; radius = 25 + rings * 5; } void tick() { pos.add(vel); if(pos.x < radius) { pos.x = radius; vel.x = -vel.x;} if(pos.x > width - radius) { pos.x = width - radius; vel.x = -vel.x;} if(pos.y < radius) {pos.y = radius; vel.y = -vel.y;} if(pos.y > height - radius) {pos.y = height - radius; vel.y = -vel.y;} vel.mult(0.99); for(int i = 0; i < ring_angles.length; i++) { ring_angles[i] += ring_speeds[i] * vel.mag()/2; while(ring_angles[i] < 0) ring_angles[i] += TWO_PI; while(ring_angles[i] > TWO_PI) ring_angles[i] -= TWO_PI; } fullness -= (1 + vel.mag())*0.001; value = (int) ((fullness - FULL_RATIO) * 1000 * ring_angles.length); } void draw() { ellipseMode(RADIUS); fill(255+fullness*255, fullness * 255, fullness * 128); noStroke(); ellipse(pos.x, pos.y, 20, 20); noFill(); strokeWeight(3); if(value > 0) stroke(128, 255, 255); else stroke(255, 0, 0); for(int i = 0; i < ring_angles.length; i++) { arc(pos.x, pos.y, 25 + 5*i, 25 + 5*i, ring_angles[i] - fullness * PI, ring_angles[i] + fullness * PI); } textFont(font, 8); fill(255); textAlign(CENTER, TOP); text(""+value, (int)pos.x, (int)pos.y + 30 + 5 * ring_angles.length); } boolean testPos(float x, float y) { float angle = atan2(pos.y - y, pos.x - x); for(int i = 0; i < ring_angles.length; i++) { boolean test = false; if(abs(angle - ring_angles[i]) < PI*(1-fullness)) test = true; if(abs(angle - ring_angles[i] + TWO_PI) < PI*(1-fullness)) test = true; if(abs(angle - ring_angles[i] - TWO_PI) < PI*(1-fullness)) test = true; if(test == false) return false; } return true; } } Core c; void draw() { if(playing) { if(score/10000 + 1 > level) { level++; level_timer = LEVEL_TIME; if(!muted) levelSound.trigger(); } level_timer--; frames++; appear_timer -= 1; if(cores.size() == 0) appear_timer = 0; if(appear_timer <= 0 && cores.size() < level) { appear_timer = APPEAR_TIME; if(!muted)appearSound.trigger(); PVector pos = new PVector(random(width), random(height)); int layers = (int)min(random(level), random(level)) +1; cores.add(new Core(pos, new PVector(0, 0), layers)); } background(0); Iterator ei = explosions.iterator(); while(ei.hasNext()) { Explosion e = (Explosion) ei.next(); e.tick(); if(e.life <= 0) ei.remove(); else e.draw(); } Iterator ci = cores.iterator(); while(ci.hasNext()) { Core c = (Core) ci.next(); c.tick(); ei = explosions.iterator(); while(ei.hasNext()) { Explosion e = (Explosion) ei.next(); if((e.x - c.pos.x)*(e.x - c.pos.x) + (e.y - c.pos.y)*(e.y - c.pos.y) < e.radius()*e.radius()) { if(c.testPos(e.x, e.y)) { if(!muted) explodeSound.trigger(); ci.remove(); PVector away = PVector.sub(c.pos, new PVector(e.x, e.y)); away.normalize(); for(int i = 0; i < 10; i++) { particles.add(new Flare(c.pos, PVector.mult(away, random(20)))); } score += c.value; break; } else { PVector propel = PVector.sub(c.pos, new PVector(e.x, e.y)); propel.normalize(); c.vel.add(propel); } } } c.draw(); } particles.tick(); particles.draw(); textAlign(LEFT, TOP); textFont(font, 16); fill(255); text("Score: "+score+"\nLevel: "+level+"\nTime: "+(max(level_timer, 0) * 100)/LEVEL_TIME+"%", 8, 8); if(level_timer <= 0) {textAlign(CENTER, CENTER); textFont(font, 16); fill(255); text("GAME OVER\nclick to play again", width/2, height/2); } } else { background(0); fill(255); textFont(font, 32); textAlign(CENTER, BOTTOM); text("Core Breach", width/2, height/2); textFont(font, 16); textAlign(CENTER, TOP); text("click to play\n\nuse ion pulses to penetrate barriers\nand destroy cores\n\nlevel up and time reset every 10000 points\n\nm to mute", width/2, height/2 + 8); } /* noFill(); if(c.testPos(mouseX, mouseY)) stroke(0, 255, 0); else stroke(255, 0, 0); strokeWeight(1); line(mouseX, mouseY, c.pos.x, c.pos.y); */ } void mousePressed() { if(playing && level_timer > 0) { explosions.add(new Explosion(mouseX, mouseY)); if(!muted) pulseSound.trigger(); } if(level_timer < -100 || !playing) { reset(1); } } void keyPressed() { if(!keys[keyCode]) { keys[keyCode] = true; down(keyCode); } } void keyReleased() { if(keys[keyCode]) { keys[keyCode] = false; up(keyCode); } } void down(int theKey) { println(theKey + " down"); if(theKey == 'M') muted = !muted; } void up(int theKey) { println(theKey + " up"); }