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!
* 
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");
}