import ddf.minim.*;
/**
* Game 29: "Grabitas"
* Z to grab enemies
* Shooters won't shoot if you're close to them
* Collect greenthings for life and points
*
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 cheat = false;
int ENEMY_SPAWN_TIME = 180;
int PLAYER_LIFE = 10;
int MINION_LIFE = 2;
float KICK_STRENGTH = 7;
int KICK_STUN = 90;
int HIT_STUN = 30;
float PLAYER_HURT_KICK = 2;
float ENEMY_AVOID_BUFFER = 20;
float GRAB_DISTANCE = 20;
float GRAB_RADIUS = 20;
int GRAB_TIME = 15;
int grab_timer;
float MAX_GRAB_SIZE = 10;
float SHOT_SPEED = 3;
int GREENIE_POINTS = 5;
int HIT_POINTS = 1;
float POINT_BLANK_LIMIT = 120;
int score;
int topscore;
int rank;
boolean[] keys = new boolean[256];
boolean title;
boolean paused;
boolean muted;
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 grabSound;
AudioSample bounceSound;
AudioSample hitSound;
AudioSample flingSound;
AudioSample poofSound;
AudioSample gripSound;
AudioSample getSound;
AudioSample shotSound;
AudioPlayer bgm;
PFont font;
void audioInit()
{
minim = new Minim(this);
grabSound = minim.loadSample("grab.wav", 1024);
bounceSound = minim.loadSample("bounce.wav", 1024);
bounceSound.setGain(-5);
hitSound = minim.loadSample("hit.wav", 1024);
flingSound = minim.loadSample("fling2.wav", 1024);
poofSound = minim.loadSample("poof.wav", 1024);
gripSound = minim.loadSample("grippy.wav", 1024);
getSound = minim.loadSample("get.wav", 1024);
shotSound = minim.loadSample("shot.wav", 1024);
bgm = minim.loadFile("grabitational.mp3", 2048);
bgm.loop();
}
void audioClose()
{
grabSound.close();
bounceSound.close();
hitSound.close();
flingSound.close();
poofSound.close();
gripSound.close();
getSound.close();
shotSound.close();
minim.stop();
}
Player player;
GameList enemies;
GameList bullets;
GameList loot;
Ship grabbed;
ParticleList smoke;
GameList eye_candy;
void setup()
{
size(550, 550);
frameRate(600);
audioInit();
newGame();
font = loadFont("PressStartK-32.vlw");
}
void newGame()
{
player = new Player(width/2, height/2);
player.life = player.max_life = PLAYER_LIFE;
player.radius = 10;
score = 0;
rank = 0;
enemies = new GameList();
bullets = new GameList();
eye_candy = new GameList();
loot = new GameList();
for(int i = 0; i < 10; i++)
eye_candy.add(new Tracer());
smoke = new ParticleList();
grabbed = null;
grab_timer = 0;
title = true;
//populate();
}
void populate()
{
rank++;
int remain = rank * 2;
while(remain > 0)
{
int level = max(1, remain / 3);
enemies.add(newFoe(level));
remain -= level;
}
}
Enemy newFoe(int strength)
{
PVector at = new PVector(width/2, height/2);
PVector disp = randomVector(width*0.4);
at.add(disp);
Enemy e;
// int enlarges = 0;
// if(strength > 3)
// {
// enlarges = strength/3;
// strength -= enlarges * 3;
// }
if(strength == 1)
e = new Enemy(at.x, at.y);
else if(strength == 2)
e = new Hunter(at.x, at.y);
else //if(strength >= 3)
e = new Shooter(at.x, at.y);
// else e = new Enemy(at.x, at.y);
// for(int i = 0; i < enlarges; i++)
// bigger(e);
return e;
}
void stop()
{
audioClose();
super.stop();
}
void physicsStep()
{
topscore = max(score, topscore);
if(!title)
{
if(!player.removal_flag) player.tick();
bullets.tick();
enemies.tick();
smoke.tick();
loot.tick();
if(enemies.size() == 1)
{
if(((Enemy)enemies.get(0)).life > 0)
enemies.add(newFoe(1));
}
if(enemies.size() == 0)
{
populate();
}
}
}
void drawingStep()
{
background(32,64, 96);
eye_candy.tick();
eye_candy.draw();
if(!title)
{
smoke.draw();
loot.draw();
enemies.draw();
bullets.draw();
if(!player.removal_flag) player.draw();
fill(255, 192);
textFont(font, 16);
textAlign(LEFT, TOP);
if(!title) text("Life: "+player.life+"/"+player.max_life+"\nScore: "+score, 8, 8);
if(player.removal_flag)
{
textFont(font, 32);
textAlign(CENTER, CENTER);
fill(255);
text("Game Over", width/2, height/2);
textFont(font, 16);
textAlign(CENTER, CENTER);
fill(255);
text("press space", width/2, height*2/3);
}
}
else
{
fill(255, 192);
textFont(font, 16);
textAlign(LEFT, TOP);
text("Top Score: "+topscore, 8, 8);
textFont(font, 32);
textAlign(CENTER, CENTER);
fill(255);
text("Grabitas", width/2, height/2);
textFont(font, 16);
textAlign(CENTER, CENTER);
fill(255);
text("press space to begin", width/2, height*2/3);
}
}
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(!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;
if(muted) bgm.mute();
else bgm.unmute();
}
if(theKey == ' ' && title)
{
title = false;
}
if(theKey == ' ' && player.removal_flag)
{
newGame();
}
if(theKey == 'X' && cheat)
{
Iterator ie = enemies.iterator();
while(ie.hasNext())
{
Enemy e = (Enemy) ie.next();
e.life = 0;
}
}
if(theKey == 'P' && !title) paused = !paused;
if(theKey == 'Z' && !paused && !player.removal_flag)
{
if(grabbed == null)
{
if(grab_timer <= 0)
{
grab_timer = GRAB_TIME;
if(!muted) gripSound.trigger();
}
}
else
{
PVector away = new PVector(cos(player.angle_heading), sin(player.angle_heading));
away.mult(KICK_STRENGTH);
grabbed.vel = away;
grabbed.stun_timer = KICK_STUN;
grabbed = null;
if(!muted) flingSound.trigger();
}
}
}
void up(int theKey)
{
println(theKey + " up");
}