import ddf.minim.*;
/**
* Friday Prototype: "Energy Combo"
*
*
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];
boolean title;
boolean paused;
boolean muted;
boolean game_over;
int score;
int top_score;
int drawing_ms_last;
int physics_ms_last;
int CORE_FPS = 540;
int DRAWING_FPS = 60;
int PHYSICS_FPS = 180;
int DRAW_MS = 1000 / DRAWING_FPS;
int PHYS_MS = 1000 / PHYSICS_FPS;
Minim minim;
AudioSample lightAttack;
AudioSample heavyAttack;
AudioSample readySound;
AudioSample hitSound;
PVector avatar;
void audioInit()
{
minim = new Minim(this);
lightAttack = minim.loadSample("light.wav", 1024);
heavyAttack = minim.loadSample("heavy.wav", 1024);
hitSound = minim.loadSample("hit.wav", 1024);
readySound = minim.loadSample("ready.wav", 1024);
}
void audioClose()
{
lightAttack.close();
heavyAttack.close();
readySound.close();
hitSound.close();
minim.stop();
}
float energy = 1;
boolean exhausted = false;
int DOTS = 10;
float RECHARGE_RATE = 1.0;
float ATTACK_COST = 0.29;
float ATTACK_DELAY = 0.4;
float delay_timer = 0;
float avspeed = 0.7;
GameList foes = new GameList();
ParticleList parts = new ParticleList();
void setup()
{
size(720, 480);
frameRate(600);
audioInit();
info_font = loadFont("PressStartK-16.vlw");
setTitle();
avatar = new PVector(width/2, height/2);
}
void setTitle()
{
title = true;
game_over = true;
}
void newGame()
{
game_over = false;
title = false;
score = 0;
}
void stop()
{
audioClose();
super.stop();
}
void tryAttack()
{
if(!exhausted)
{
energy -= ATTACK_COST;
if(energy <= 0)
{
exhausted = true;
finishAttack();
}
else normalAttack();
}
}
void hit(float rad, int dmg)
{
parts.add(new Flash(avatar, rad));
for(int i = 0; i < foes.size(); i++)
{
Foe f = (Foe) foes.get(i);
if(PVector.dist(f.pos, avatar) < rad + f.radius)
{
PVector away = PVector.sub(f.pos, avatar);
away.normalize();
away.mult(5 * dmg);
f.pos.add(away);
f.harm(dmg);
}
}
}
void normalAttack()
{
lightAttack.trigger();
delay_timer = ATTACK_DELAY;
hit(15, 1);
}
void finishAttack()
{
heavyAttack.trigger();
delay_timer = ATTACK_DELAY;
hit(26, 2);
}
void physicsStep()
{
if(!title)
{
//main game loop
delay_timer -= 1.0/PHYSICS_FPS;
if(delay_timer <= 0)
energy += RECHARGE_RATE/PHYSICS_FPS;
if(energy >= 1.0)
{
energy = 1.0;
if(exhausted) readySound.trigger();
exhausted = false;
}
foes.tick();
parts.tick();
if(keys[UP]) avatar.y -= avspeed;
if(keys[DOWN]) avatar.y += avspeed;
if(keys[LEFT]) avatar.x -= avspeed;
if(keys[RIGHT]) avatar.x += avspeed;
top_score = max(score, top_score);
}
//jukebox stuff
info_time --;
}
void drawingStep()
{
if(title)
{
drawTitle();
}
else
{
background(32,64,96);
ellipseMode(RADIUS);
if(paused) drawPauseOverlay();
fill(120, 230, 230);
stroke(100, 255, 200);
ellipse(avatar.x, avatar.y, 6, 6);
foes.draw();
parts.draw();
String energy_stars = "";
textAlign(LEFT, BOTTOM);
for(int i = 0; i < DOTS; i++)
{
energy_stars += "*";
}
if(exhausted) fill(0, 0, 64);
else fill(128, 64, 32);
noStroke();
text(energy_stars, 8, height-8);
energy_stars = "";
for(int i = 0; i < int(DOTS * energy); i++)
{
energy_stars += "*";
}
if(exhausted) fill(128,64,128);
else if(delay_timer > 0) fill(255, 192, 0);
else fill(255, 255, 128);
text(energy_stars, 8, height-8);
fill(192);
textAlign(LEFT, TOP);
text("[Q/W] Recharge rate: "+RECHARGE_RATE+"\n[E/R] Attack cost: "+ATTACK_COST+"\n[T/Y] Attack delay: "+ATTACK_DELAY, 8, 8);
}
//jukebox stuff
drawSongInfo();
}
void drawTitle()
{
background(128, 0, 128);
fill(255);
textFont(info_font, 32);
textAlign(CENTER, CENTER);
text("Energy Combo Prototype", width/2, height/2);
textFont(info_font, 16);
text("x to attack, arrows to move\ns to spawn small foe, b to spawn big foe\npress enter", width/2, height*2/3);
}
void drawPauseOverlay()
{
rectMode(CORNER);
strokeWeight(1);
noStroke();
fill(0, 128);
rect(0, 0, width, height);
fill(255);
textFont(info_font, 16);
textAlign(CENTER, CENTER);
text("[ PAUSED ]", width/2, height/2);
}
void draw()
{
while(physics_ms_last + PHYS_MS < millis())
{
if(!paused)
{
physicsStep();
}
physics_ms_last += PHYS_MS;
}
if(drawing_ms_last + DRAW_MS < millis())
{
drawingStep();
drawing_ms_last = millis();
}
}
void keyPressed()
{
if(keyCode < 256)
if(!keys[keyCode])
{
keys[keyCode] = true;
down(keyCode);
}
}
void keyReleased()
{
if(keyCode < 256)
if(keys[keyCode])
{
keys[keyCode] = false;
up(keyCode);
}
}
void down(int theKey)
{
println(theKey + " down");
if(theKey == 'M') jbToggleMute();
if(theKey == 'P' && !title) paused = !paused;
if(!paused && !title)
{
if(theKey == 'X') tryAttack();
if(theKey == 'S') foes.add(new Foe());
if(theKey == 'B') foes.add(new BigFoe());
if(theKey == 'Q') RECHARGE_RATE -= 0.1;
if(theKey == 'W') RECHARGE_RATE += 0.1;
if(theKey == 'E') ATTACK_COST -= 0.1;
if(theKey == 'R') ATTACK_COST += 0.1;
if(theKey == 'T') ATTACK_DELAY -= 0.1;
if(theKey == 'Y') ATTACK_DELAY += 0.1;
}
if(theKey == ENTER && game_over) newGame();
}
void up(int theKey)
{
println(theKey + " up");
}