import ddf.minim.*;
/**
* Game 27: "now sir, a war is never even. sir, a war is won"
* Move the green dot above the red dots.
*
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;
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;
float WHEEL_RADIUS = 70;
float GRAVITY = 0.1;
PVector pivot;
float inertia;
float torque;
float omega;
PFont font;
Dot greendot;
boolean game_done;
int score;
int topscore;
int penalty;
ArrayList all_dots;
ArrayList grabbed_dots;
AudioPlayer bgm;
void audioInit()
{
minim = new Minim(this);
bgm = minim.loadFile("uneven.mp3", 2048);
bgm.loop();
}
void audioClose()
{
bgm.close();
minim.stop();
}
void setup()
{
size(550, 550);
frameRate(600);
audioInit();
font = loadFont("PressStartK-32.vlw");
newGame();
}
void newGame()
{
all_dots = new ArrayList();
int NUM_DOTS = 20;
for(int i = 0; i < NUM_DOTS; i++)
all_dots.add(new Dot(random(width), i*height/NUM_DOTS, random(3)+5, color(255, 0, 0)));
greendot = new Dot(width/2, height-20, 5, color(0, 255, 0));
all_dots.add(greendot);
grabbed_dots = new ArrayList();
game_done = false;
score = 0;
penalty = 0;
}
void stop()
{
audioClose();
super.stop();
}
void mousePressed()
{
if(game_done) newGame();
else
{
pivot = new PVector(mouseX, mouseY);
grabbed_dots.clear();
inertia = 0;
omega = 0;
Iterator adi = all_dots.iterator();
while(adi.hasNext())
{
Dot d = (Dot)adi.next();
if(inRadius(pivot, d.pos, WHEEL_RADIUS) && d.pos.y <= greendot.pos.y)
{
grabbed_dots.add(d);
float r = d.pos.dist(pivot);
inertia += r*r*d.mass;
}
}
}
}
void mouseReleased()
{
grabbed_dots.clear();
}
void physicsStep()
{
if(!grabbed_dots.isEmpty() && !game_done)
{
penalty++;
torque = 0;
for(int i = 0; i < grabbed_dots.size(); i++)
{
Dot d = (Dot) grabbed_dots.get(i);
torque += (d.pos.x - pivot.x)*d.mass*GRAVITY;
}
omega += torque/inertia;
for(int i = 0; i < grabbed_dots.size(); i++)
{
Dot d = (Dot) grabbed_dots.get(i);
d.pos.sub(pivot); //translate so we can do math relative to origin
float nx = d.pos.x*cos(omega)-d.pos.y*sin(omega);
float ny = d.pos.x*sin(omega)+d.pos.y*cos(omega);
d.pos.x = nx;
d.pos.y = ny;
d.pos.add(pivot); //and move it back.
}
}
score = 0;
boolean allbelow = true;
for(int i = 0; i < all_dots.size(); i++)
{
Dot d = (Dot) all_dots.get(i);
if(d.pos.y > greendot.pos.y) score += (int)(height - d.pos.y);
else if(d != greendot) allbelow = false;
}
score -= penalty;
if(allbelow) game_done = true;
//score += (int)(height - greendot.pos.y);
topscore = max(score, topscore);
}
void drawingStep()
{
background(32,64, 96);
strokeWeight(1);
noFill();
ellipseMode(RADIUS);
stroke(0, 128, 0);
line(0, greendot.pos.y, width, greendot.pos.y);
stroke(128);
if(!grabbed_dots.isEmpty())
{
stroke(255);
ellipse(pivot.x, pivot.y, WHEEL_RADIUS, WHEEL_RADIUS);
ellipse(pivot.x, pivot.y, 2, 2);
for(int i = 0; i < grabbed_dots.size(); i++)
{
Dot d = (Dot) grabbed_dots.get(i);
line(pivot.x, pivot.y, d.pos.x, d.pos.y);
}
fill(0, 128, 255);
textFont(font, 8);
textAlign(CENTER, BOTTOM);
text("-"+penalty, pivot.x, pivot.y - 3);
}
else
{
ellipse(mouseX, mouseY, WHEEL_RADIUS, WHEEL_RADIUS);
fill(128);
textFont(font, 8);
textAlign(CENTER, BOTTOM);
text("-"+penalty, mouseX, mouseY - 3);
}
for(int i = 0; i < all_dots.size(); i++)
{
Dot d = (Dot) all_dots.get(i);
fill(d.col);
noStroke();
if(d.pos.y > greendot.pos.y)
{
fill(255, 192, 0);
textFont(font, 8);
textAlign(CENTER, BOTTOM);
text("+"+(int)(height-d.pos.y), d.pos.x, d.pos.y - 6);
fill(160, 0, 0);
}
ellipse(d.pos.x, d.pos.y, d.mass, d.mass);
}
textFont(font);
fill(255, 128);
if(game_done) fill(255, 234, 128);
textAlign(LEFT, TOP);
text(""+score, 8, 8);
textFont(font, 16);
textAlign(RIGHT, TOP);
text("top: "+topscore, width-8, 8);
}
void draw()
{
cursor(CROSS);
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 == 'P' && !title) paused = !paused;
}
void up(int theKey)
{
println(theKey + " up");
}