Project Members: 
Alana
daniela
Isaac Salier-He...
Ken-ichi Ueda
Description
Twista is a version of the game Twister except played with the fingers and using musical notes to signal where players should place their fingers. Ideally, the computer will play a note, and the first player must press a colored key that corresponds to that note (3 colors, 3 notes). Once they've successfully done so, they hold their finger on that key, and the computer plays another note for the second player. The process continues until all keys are pressed or a player lifts a finger and loses.
Components
Processing Code
import ddf.minim.*;
boolean DEBUG = true;
AudioSample c3; // Audio for the note C
AudioSample e3; // Audio for the note E
AudioSample g3; // Audio for the note G
AudioSample cheer; // Audio for cheering
AudioSample woops; // Audio for shaming
AudioSample studioCheer; // Audio for ending well
AudioSample doh; // Audio for ending badly
AudioSample sample; // temp holder for samples
float eRadius;
boolean waiting = false; // whether the system is waiting for player response
char tone; // current tone
int rand; // random number holder
int keyInt; // integer version of key pressed
boolean correct = false; // whether the most recent key pressed is correct
// stores whether a number has already been chosen or not
boolean[] chosenNumbers = {false, false, false, false,
false, false, false, false, false, false};
// index key numbers to notes
char[] keyTones = {'x','c','c','c','e','e','e','g','g','g'};
// GUI vars
int winH = 512;
int winW = 512;
int butHeight = winH / 5;
int butWidth = winW / 2;
int butX = (winW/2) - (butWidth/2);
int butY = (winH/2) - (butHeight/2) + 70;
int boxSize = 80;
PFont trebuchet;
boolean startWait = true;
// solves for the key being held sending multiple keyPressed events (or, it should)
boolean onePressed = false;
boolean twoPressed = false;
boolean threePressed = false;
boolean fourPressed = false;
boolean fivePressed = false;
boolean sixPressed = false;
boolean sevenPressed = false;
boolean eightPressed = false;
boolean ninePressed = false;
void setup()
{
size(winW, winH);
// always start Minim before you do anything with it
Minim.start(this);
Minim.debugOn();
// load BD.wav from the data folder, with a 512 sample buffer
c3 = Minim.loadSample("50A-1GA1-C3.aif", 512);
g3 = Minim.loadSample("50A-1GA5-G3.aif", 512);
e3 = Minim.loadSample("50A-1GA1-E3.aif", 512);
cheer = Minim.loadSample("kids_cheering-short.mp3", 512);
studioCheer = Minim.loadSample("cheering_crown_studio-short.mp3", 512);
woops = Minim.loadSample("woops.wav", 512);
doh = Minim.loadSample("doh.wav", 512);
// load SD.wav from the data folder
// Load font for title screen and start button.
trebuchet = loadFont("Trebuchet.vlw");
}
void draw()
{
// GUI
// Draw title screen and start button.
if(startWait) {
background(0,0,0);
fill(255);
textFont(trebuchet);
text("Twista", 180, 140);
textFont(trebuchet, 16);
text("Alana Pechon, Daniela Rosner," , 144, 200);
text("Isaac Salier-Hellendag, Ken-ichi Ueda", 120, 218);
stroke(255);
fill(159,39,39);
rect(butX, butY, butWidth, butHeight);
textFont(trebuchet, 32);
fill(255);
text("Click to start!", 156, 339);
if(mouseX < (butX + butWidth) && mouseX > butX && mouseY < (butY + butHeight) && mouseY > butY) {
cursor(HAND);
} else {
cursor(ARROW);
}
}
// Draw the boxes and waveforms.
if(!startWait) {
cursor(ARROW);
background(0);
// Draw rects to represent the board.
stroke(80);
// Yellow boxes
for(int j = 7 ; j < 10 ; j++) {
if(!chosenNumbers[j])
// fill(203, 100, 138);
fill(0, 255, 0);
else
/* fill(66, 42, 51);*/
fill(0, 105, 0);
rect((winW * (j - 6) / 4) - (boxSize / 2), (winH * 1 / 4) - (boxSize / 2), boxSize, boxSize);
}
// Red boxes
for(int j = 4 ; j < 7 ; j++) {
if(!chosenNumbers[j])
/* fill(76, 89, 212);*/
fill(255, 0, 0);
else
// fill(29, 32, 59);
fill(105, 0, 0);
rect((winW * (j - 3) / 4) - (boxSize / 2), (winH * 2 / 4) - (boxSize / 2), boxSize, boxSize);
}
// Green boxes
for(int j = 1 ; j < 4 ; j++) {
if(!chosenNumbers[j])
// fill(66, 217, 102);
fill(255, 255, 0);
else
// fill(21, 43, 26);
fill(105, 105, 0);
rect((winW * j / 4) - (boxSize / 2), (winH * 3 / 4) - (boxSize / 2), boxSize, boxSize);
}
stroke(180);
// use the mix buffer to draw the waveforms.
// because these are MONO files, we could have used the left or right buffers and got the same data
float[] csamp = c3.mix.toArray();
float[] esamp = e3.mix.toArray();
float[] gsamp = g3.mix.toArray();
for (int i = 0; i < c3.bufferSize() - 1; i++)
{
line(i, (winH * 1 / 4) - gsamp[i]*50, i+1, (winH * 1 / 4) - gsamp[i+1]*50); // draw waveforms
line(i, (winH * 2 / 4) - esamp[i]*50, i+1, (winH * 2 / 4) - esamp[i+1]*50);
line(i, (winH * 3 / 4) - csamp[i]*50, i+1, (winH * 3 / 4) - csamp[i+1]*50);
}
playGame();
}
}
void mouseClicked() {
// If the user clicks the start button, start the game!
if(mouseX < (butX + butWidth) && mouseX > butX && mouseY < (butY + butHeight) && mouseY > butY) {
background(0);
startWait = false;
}
}
void playGame() {
/*
PSEUDOCODE
if waitState -- note, this went in the keyHandler method below
if key corresponds to tone
celebrate
set playState
if playState
if all numbers chosen
end game
else
choose a random number between 1 and 9
if number not already chosen
play tone corresponding to that number (1-3, 4-6, 7-9)
set wait state
*/
if (!waiting) {
if (DEBUG) println("Playing...");
if (chosenNumbers[1] && // if all #s are chosen, end the game
chosenNumbers[2] &&
chosenNumbers[3] &&
chosenNumbers[4] &&
chosenNumbers[5] &&
chosenNumbers[6] &&
chosenNumbers[7] &&
chosenNumbers[8] &&
chosenNumbers[9]) {
if (DEBUG) println("All numbers chosen, ending the game");
studioCheer.trigger();
stop();
}
else {
// choose a random number
rand = (int) random(1,9);
if (DEBUG) print("Random Index: "); println(rand);
// if rand hasn't already been chosen...
if (chosenNumbers[rand] == false) {
if (DEBUG) { print("keyTones[rand]: "); println(keyTones[rand]);}
sample = getSample(keyTones[rand]); // get the audio matching that number
delay(3000); // delay while the audio for the players key press plays
sample.trigger(); // play the new tone
tone = keyTones[rand];
waiting = true; // wait for input
}
}
}
}
// just maps a note like 'g' to its corresponding AudioSample
AudioSample getSample(char note) {
if (note == 'c') {
return c3;
}
else if (note == 'e') {
return e3;
}
else {
return g3;
}
}
// print the state of the board to the console
void printKeys() {
for (int i = 1; i <= 9; i++) {
if (chosenNumbers[i]) print(i + " ");
else print(". ");
if (i % 3 == 0) println();
}
}
void keyPressed()
{
// play selected tone on initial key press event
if ( key == '1' && !onePressed) {
c3.trigger();
onePressed = true;
keyHandler();
}
else if ( key == '2' && !twoPressed) {
c3.trigger();
twoPressed = true;
keyHandler();
}
else if ( key == '3' && !threePressed) {
c3.trigger();
threePressed = true;
keyHandler();
}
else if ( key == '4' && !fourPressed) {
e3.trigger();
fourPressed = true;
keyHandler();
}
else if ( key == '5' && !fivePressed) {
e3.trigger();
fivePressed = true;
keyHandler();
}
else if ( key == '6' && !sixPressed) {
e3.trigger();
sixPressed = true;
keyHandler();
}
else if ( key == '7' && !sevenPressed) {
g3.trigger();
sevenPressed = true;
keyHandler();
}
else if ( key == '8' && !eightPressed) {
g3.trigger();
eightPressed = true;
keyHandler();
}
else if ( key == '9' && !ninePressed) {
g3.trigger();
ninePressed = true;
keyHandler();
}
}
// Decide whether the right key was pressed or not
void keyHandler() {
keyInt = (int) key - (int) '0'; // stupid java...
if (DEBUG) {
print("keyInt: ");
println(keyInt);
}
// if the user hit a key matching the selected tone...
if (keyTones[keyInt] == tone) {
cheer.trigger(); // celebrate
waiting = false; // return to the playing state
chosenNumbers[keyInt] = true; // cross this number off the list
correct = true; // variable for allowing them to lift finger or not
printKeys();
}
// if the user hit a key that does not match the selected tone...
else {
woops.trigger(); // shame
waiting = false; // return to the playing state
correct = false; // variable for allowing them to lift finger or not
printKeys(); // play another tone
}
}
void keyReleased()
{
// end the game if a player releases a key they should be holding down
if ( correct ) {
doh.trigger();
stop();
}
}
void stop()
{
// always close Minim audio classes when you are done with them
delay(7000);
c3.close();
e3.close();
g3.close();
cheer.close();
studioCheer.close();
woops.close();
doh.close();
super.stop();
}
Pictures
Twista Screen
Twista board