Created
April 3, 2015 11:04
-
-
Save FreedomGrenade/a4a8b12c9a53d6c4450f to your computer and use it in GitHub Desktop.
Whistle High notes or low notes to move the paddle.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ddf.minim.spi.*; | |
import ddf.minim.signals.*; | |
import ddf.minim.*; | |
import ddf.minim.analysis.*; | |
import ddf.minim.ugens.*; | |
import ddf.minim.effects.*; | |
Minim minim; | |
AudioInput input; | |
FFT fft; | |
int max, min; | |
float lowFrequency = 900; // change these if the frequency is uncomfortable to maintain or has a bias to one side | |
float highFrequency = 2000; | |
float cutOff = 10.0; // or try lowering this | |
Paddle pad; | |
Ball ball; | |
int mode = 0; | |
int waittime = 0; | |
float lowVal, highVal; | |
boolean wait = false; | |
boolean ready = false; | |
public void setup() { | |
size(500, 500); | |
minim = new Minim(this); // minim stuff | |
input = minim.getLineIn(Minim.MONO, 2048); | |
fft = new FFT(input.bufferSize(), input.sampleRate() ); | |
fft.window(FFT.HAMMING); | |
min = fft.freqToIndex(lowFrequency); | |
max = fft.freqToIndex(highFrequency); | |
menuSetup(); | |
} | |
public void draw() { | |
fft.forward(input.mix); | |
float n = highestPeak(); | |
switch (mode) { | |
case 0 : | |
menuScreen(n); | |
break; | |
case 1 : | |
gameScreen(n); | |
break; | |
case 2 : | |
gameOverScreen(); | |
break; | |
default : | |
exit(); | |
} | |
} | |
public void gameScreen(float n) { | |
background(128+n*64, 128-n*64, 192); | |
if (waittime <= millis() || pad.dead) { // current time has passed the wait time | |
pad.update(n); // display if paddle is dead, because I used the wait time to delay the gameOver also | |
ball.update(); | |
} | |
ball.display(); | |
pad.display(); | |
if (pad.dead) { | |
if (waittime <= millis()) { | |
background(0); | |
endGame(); | |
} else { | |
fill(0, 255 - (waittime - millis())*255/1000); // fade out | |
rect(0, 0, width, height); | |
} | |
} | |
} | |
public void menuSetup() { | |
wait = false; | |
lowVal = 0; | |
highVal = 0; | |
} | |
public void gameKill() { | |
if (!pad.dead) { | |
pad.killMe(); | |
wait = true; | |
waittime = millis() + 2000; | |
} | |
} | |
public void menuScreen(float n) { | |
background(0); | |
if (lowVal < height && n < -0.2) lowVal+=10; | |
if (highVal < height && n > 0.2) highVal+=10; | |
noStroke(); | |
fill(64, 192, 192); | |
rect(0, height, width*0.5, -lowVal); | |
fill(192, 64, 192); | |
rect(width*0.5, height, width*0.5, -highVal); | |
fill(255); | |
textSize(30); | |
textAlign(CENTER, CENTER); | |
text("Hold a high whistle then a low whistle", 0, 0, width, height); | |
if (lowVal >= height && highVal >= height) startGame(); | |
} | |
public void gameOverScreen() { | |
background(0); | |
if (waittime <= millis()) { // current time has passed the wait time | |
startGame(); | |
} else { // display message if still waiting | |
fill(255); | |
textSize(30); | |
textAlign(CENTER, CENTER); | |
text("You've failed everyone", 0, 0, width, height); | |
} | |
} | |
public void startGame() { | |
wait = true; | |
waittime = millis() + 1000; | |
pad = new Paddle(width*0.5, height -20); | |
ball = new Ball(width*0.5, height*0.5, (int)random(2.0)*2-1, 1); | |
mode = 1; | |
} | |
public void endGame() { | |
wait = true; | |
waittime = millis() + 3000; | |
mode = 2; | |
} | |
public void ballPaddleCollision(Ball b, Paddle p) { | |
float relx = b.x - p.x; | |
float rely = b.y - p.y; | |
boolean d0 = (rely < relx * p.ph/p.pw); // positions over/under diagonals | |
boolean d1 = (rely < -relx * p.ph/p.pw); | |
if (d0 & d1) b.y = p.y-p.ph-b.rad; // top | |
if (d0 & !d1) b.x = p.x+p.pw+b.rad; // right | |
if (!d0 & d1) b.x = p.x-p.pw-b.rad; // left | |
if (d0 ^ d1) { // under one, over the other (ball is 'beside' the paddle | |
b.xv = -b.xv; | |
} else { | |
if (d0 & d1) b.yv = -b.yv*1.5; // bounce and increase only if ball is above | |
} | |
} | |
public class Ball { | |
float x, y, xv, yv; | |
float rad = 20; | |
public Ball(float x, float y, float xv, float yv) { | |
this.x = x; | |
this.y = y; | |
this.xv = xv; | |
this.yv = yv; | |
} | |
public void update() { | |
x+=xv; | |
y+=yv; | |
if (x < rad || x >= width - rad) { | |
xv=-xv; | |
x+=xv; | |
} | |
if (y < rad) { | |
yv=-yv; | |
y+=yv; | |
} | |
if (y > height) gameKill(); | |
if (pad.collideWith(x, y, rad)) ballPaddleCollision(this, pad); | |
} | |
public void display() { | |
noStroke(); | |
fill(255); | |
ellipse(x, y, rad*2, rad*2); | |
} | |
} | |
public class Paddle { | |
float x, xv, y, yv; | |
int pw = 40; | |
int ph = 10; | |
boolean dead; | |
public Paddle(float x, float y) { | |
this.x = x; | |
this.y = y; | |
xv = 0; | |
yv = 0; | |
dead = false; | |
} | |
public void killMe() { | |
dead = true; | |
yv = -20; | |
} | |
public void update(float pos) { | |
if (dead) { // if dead , bump off the screen | |
yv=yv+1; | |
y+=yv; | |
} else { // move normally | |
xv+=pos; | |
xv*=0.9; | |
x+=xv; | |
if (x < pw || x >= width-pw) { // simple bounce for paddle on walls | |
x=constrain(x, pw, width-pw-1); | |
xv=-xv*0.5; | |
} | |
} | |
} | |
public boolean collideWith(float xb, float yb, float rb) { | |
return (xb >= x-pw-rb && xb <= x+pw+rb && yb >= y-ph-rb && yb <= y+ph+rb); | |
} | |
public void display() { | |
noStroke(); | |
fill(255); | |
rect(x-pw, y-ph, pw*2, ph*2); | |
} | |
} | |
public float highestPeak() { // find highest peak | |
boolean set = false; | |
int num = 0; | |
float highest = 0; | |
for (int i = min; i <= max; i++) { | |
float t = fft.getBand(i); | |
boolean r0 = (fft.getBand(i+1)-t) >= 0; | |
boolean r1 = (t-fft.getBand(i-1)) >= 0; | |
if (r1 != r0) { // if the slopes are different this is a peak or valley | |
if (highest < t || !set) { // check if it's the highest peak | |
highest = t; | |
num = i; | |
} | |
set = true; | |
} | |
} | |
if (highest >= cutOff && set) return map(num, min, max, -1, 1); // map num to left or right | |
return 0; // nothing valid, | |
} | |
public void stop() { | |
minim.stop(); | |
input.close(); | |
super.stop(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment