Final Project – F.R.I.E.N.D.S Tribute

This project is very special for me because it’s centered around the first show I have ever watched and one of my favorites ever. I have tried to encapsulate every aspect of the theme of the show into the project as possible and the result is pretty satisfying.

Main Challenge:

One of the biggest challenges for me was to be able to do all the functionalities I wanted efficiently. Passing by reference cannot be done in Java except using objects types so I had to find my way around that. I created a matrix of arrays storing answers for the questions with each row representing a character in the show. But in order for me to randomize the order of the answers every single time the game is played, I used the StringList class. I created a list for every answer, which is a copy of a row in the matrix, then I shuffle using the shuffle() function and I display. The original matrix is kept for me to be able to check which answer exactly is chosen to increment the respective character’s score accordingly. I created a function to check which character’s answer exactly was chosen, and I use the same code for every question page with the appropriate changes. But in order for me to to have all these if conditions to not change question unless a button was pressed and to be able to identify the answer properly, I had to actually write numerous lines of code. But the runtime of the code is actually not that long because it is just mainly if conditions which have a runtime of O(1).

Implementation:

I used the main theme song in the background at all times and the player can lower the volume because it can be too repetitive. The frames of the options and in the instructions and the buttons on the Arduino board all have the same pattern of colors in the same order (red, blue, yellow, red, yellow blue). I used the same shade of purple and gold as in Monica’s apartment throughout the game. I also used the same font as in the original series’ logo. The yellow bulb indicates that the game is waiting for you to choose an answer, the blue blinks while you are pressing, and the green lights up when you finish the trivia. I made it so the instructions appear only during the first time you start the game and not if you replay because by then you surely know how to play. I made it so the choices change color if you hover over them using the mouse to make it more interactive. I was worried people might think this means they can click to choose, but then if they try to click nothing will happen, and the instructions page at the start actually explains that they should click on the Arduino board, so it should be clear enough. Whenever an option is chosen, the choice color changes momentarily as well like when the mouse hovers over it to indicate what exactly was actually chosen. I used 4 questions from the websites I included as reference in the code just to have an existing reference, but I made up the remaining 7 questions on my own in order to make it more personal. The questions at first are very easy, meaning that you can guess right away which answer represents which of the six characters. But as you go further, the answers are less direct and you cannot always guess right away who is who, which  is just because the player is improving in answering the questions by time and to make it more interesting and as if it’s an actual realistic test that is interactive.

This was the Arduino progress in the first stage.

Background Image of the trivia.

This was how I built the logic for the volume knob of the theme song.

The result screens I designed at the end of the trivia based on the answers.

I actually tried to choose the most general traits of the characters so that regardless of the combination of answers leading to such a final result, the player will most likely have at least most of the things which I included in the short paragraph describing their character. I also made it 11 questions (a prime number) so that there will never be a tie in answers where I will have to choose one as winner or put both which is just lame.

This is the final result from the Arduino perspective.

Instructions for the trivia. I tried to make it as visual and realistic as possible, and I even used the same colors to make it clearer for the player. The same font is used consistently in order to maintain the theme at all times.

This is the actual final result on the computer.

Following is the Arduino code for the project:

int choice1 = 0;
int choice2 = 0;
int choice3 = 0;
int choice4 = 0;
int choice5 = 0;
int choice6 = 0;
int last = 0;
int start = 0;        //some variables to store the values from the serial by parseInt

int one = 7;
int two = 6;
int three = 5;
int four = 4;
int five = 3;
int six = 2;          //outlets of the six buttons

int ledYellow = 8;
int ledBlue = 9;
int ledGreen = 10;      //outlets of the three led bulbs

void setup() {
  Serial.begin(9600);
  Serial.println("0,0,0");
 
  pinMode(ledYellow, OUTPUT);
  pinMode(ledBlue, OUTPUT);
  pinMode(ledGreen, OUTPUT);

  pinMode(one, INPUT);
  pinMode(two, INPUT);
  pinMode(three, INPUT);
  pinMode(four, INPUT);
  pinMode(five, INPUT);
  pinMode(six, INPUT);
}

void loop() {
  while (Serial.available()) {
    choice1 = Serial.parseInt();
    choice2 = Serial.parseInt();
    choice3 = Serial.parseInt();
    choice4 = Serial.parseInt();
    choice5 = Serial.parseInt();
    choice6 = Serial.parseInt();
    last = Serial.parseInt();           //stores whether or not the game is off
    start = Serial.parseInt();          //stores whether or not the game has started

    if (Serial.read() == '\n') {
      int sensor = analogRead(A0);
      delay(1);
      int button1 = digitalRead(one);
      delay(1);
      int button2 = digitalRead(two);
      delay(1);
      int button3 = digitalRead(three);
      delay(1);
      int button4 = digitalRead(four);
      delay(1);
      int button5 = digitalRead(five);
      delay(1);
      int button6 = digitalRead(six);
      delay(1);

     if (start == 1) {        //as soon as the game begins after instructions yellow lights
        if (button1 == HIGH || button2 == HIGH || button3 == HIGH || button4 == HIGH || button5 == HIGH || button6 == HIGH) { //while any button is pressed, light blue and dim rest
          digitalWrite(ledBlue, HIGH);
          digitalWrite(ledYellow, LOW);
        }
        else {              //otherwise only keep yellow lit
          digitalWrite(ledBlue, LOW);
          digitalWrite(ledGreen, LOW);
          digitalWrite(ledYellow, HIGH);
        }
      }
      else {              //if game is not on switch yellow and blue off
        digitalWrite(ledYellow, LOW);
        digitalWrite(ledBlue, LOW);
        if (last == 1) {          //if it was specifically on the end page where a pic of character shows, light up the green bulb signifiying end
          digitalWrite(ledGreen, HIGH);  
        }
        else { digitalWrite(ledGreen, LOW);} 
      }
     
      Serial.print(button1);
      Serial.print(",");
      Serial.print(button2);
      Serial.print(",");
      Serial.print(button3);
      Serial.print(",");
      Serial.print(button4);
      Serial.print(",");
      Serial.print(button5);
      Serial.print(",");
      Serial.print(button6);
      Serial.print(",");
      Serial.println(sensor);               //print everything back to complete the handshake
    }
  }
}

Following is the Processing Code:

import processing.serial.*;
import processing.sound.*;    //importing sound library

Serial myPort;
int choice1 = 0;
int choice2 = 0;
int choice3 = 0;
int choice4 = 0;
int choice5 = 0;
int choice6 = 0;

int finish;
int blink;

float prevFrame = 0;

PImage rachelBackground, phoebeBackground, chandlerBackground, rossBackground, monicaBackground, joeyBackground;
PImage bg1, bg2;

float volume = 0;
float volumeWidth;

boolean page0 = false;
boolean page1 = false;
boolean page2 = false;
boolean page3 = false;
boolean page4 = false;
boolean page5 = false;
boolean page6 = false;
boolean page7 = false;
boolean page8 = false;
boolean page9 = false;
boolean page10 = false;
boolean page11 = false;

String[] answers1 = new String[6];
String[] answers2 = new String[6];
String[] answers3 = new String[6];
String[] answers4 = new String[6];
String[] answers5 = new String[6];
String[] answers6 = new String[6];
String[] answers7 = new String[6];
String[] answers8 = new String[6];
String[] answers9 = new String[6];
String[] answers10 = new String[6];
String[] answers11 = new String[6];

StringList[] shuffler = new StringList[11];

StringList shuffler1 = new StringList();
StringList shuffler2 = new StringList();
StringList shuffler3 = new StringList();
StringList shuffler4 = new StringList();
StringList shuffler5 = new StringList();
StringList shuffler6 = new StringList();
StringList shuffler7 = new StringList();
StringList shuffler8 = new StringList();
StringList shuffler9 = new StringList();
StringList shuffler10 = new StringList();
StringList shuffler11 = new StringList();

String[][] answersList = {answers1, answers2, answers3, answers4, answers5, answers6, answers7, answers8, answers9, answers10, answers11};

Score rossScore;
Score phoebeScore;
Score chandlerScore;
Score monicaScore;
Score rachelScore;
Score joeyScore;

IntList scoreList;

//Questions inspired from:
//https://www.beano.com/posts/which-friends-character-are-you
//https://www.radiox.co.uk/games-quizzes/which-friends-character-are-you/
//https://heywise.com/quiz/which-friends-character-are-you/3/
//https://www.zimbio.com/quiz/O6sFuc_NvOh/Friends+Character

String question1 = "What do you consider to be your best quality?";
String question2 = "What is your dream job?";
String question3 = "What do you consider to be your worst quality?";
String question4 = "How do you feel about animals?";
String question5 = "What is your favorite food?";
String question6 = "What is something you cannot live without?";
String question7 = "What do you like to do for fun?";
String question8 = "What pisses you off the most?";
String question9 = "What do you think about marriage?";
String question10 = "Favourite movie genre?";
String question11 = "You value friendship because";

String[] ross = {"Your intelligence","Professor", "Arrogance", "Monkeys are my favorite animals.", "Mashed potatoes with lumps", "Education", "Watching the discovery channel", "Superstitious people", "Cannot get enough of it", "Foreign movies", "Friends are what makes me popular"};
String[] phoebe = {"Your laid back approach to life", "Singer", "Delusional", "Love them! We should not eat them", "Vegetables", "Principles", "Playing with dollhouses", "Arrogance", "Willing to do it once with the right person", "Happy movies", "Friends are the only family I have"};
String[] chandler = {"Your sense of humour", "Advertising executive", "Insecurity", "I do not really like dogs", "Anything but thanksgiving food", "Sarcasm", "Arcade games", "Men wearing makeup", "Freaks me out", "Musicals", "Friends tolerate my awkwardness"};
String[] monica = {"Your cleanliness", "Caterer", "Competitiveness", "They are fine.", "Anything with garlic", "People to boss around", "Competing", "Carelessness", "Ultimate happiness", "Mysteries", "Friends are not afraid to tell me when I am wrong"};
String[] rachel = {"Your good taste", "Fashion consultant", "Selfishness", "Cats with no hair are cool", "Small salads", "Shopping", "Anything but sports", "Touching someone's eye", "Pathetically need it", "Romance", "Friends make the best lovers"};
String[] joey = {"Your looks", "Actor", "Clumsiness", "They taste gooood!", "Fried stuff with cheese", "Food", "Foosball", "Body Shaming", "Not worth it", "Animation", "Friends introduce me to all their hot friends"};

PFont f;
Button button1, button2, button3, button4, button5, button6;
Button start;
Button menu, proceed;
boolean gameOn;
boolean instructions;
boolean end;

SoundFile friends;
SoundFile saturday;

void setup(){
  size(960,720);
  printArray(Serial.list());
  String portname=Serial.list()[2];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
  
  f = createFont("GABRWFFR.TTF",72);      //aesthetic font that fits teh theme
  
  start = new Button(width/2, 3*height/4 - 75, 150, 60, 255);
  menu = new Button(width - 100, 50, 150, 60, 255);
  proceed = new Button(width/4, 3*height/4 +50, 200, 80, 0);
  gameOn = false;
  instructions = true;
  end = false;
  
  button1 = new Button(width/6, height/3, 250, 150, #FF4238);
  button2 = new Button(width/2, height/3, 250, 150, #42A2D6);
  button3 = new Button(5*width/6, height/3, 250, 150, #FFDC00);
  button4 = new Button(width/6, height/3 + 3*button1.buttonHeight/2, 250, 150, #FF4238);
  button5 = new Button(width/2, height/3 + 3*button1.buttonHeight/2, 250, 150, #FFDC00);
  button6 = new Button(5*width/6, height/3 + 3*button1.buttonHeight/2, 250, 150, #42A2D6);
  
  for (int i = 0; i<11; i++) {
    answersList[i][0] = ross[i];
    answersList[i][1] = phoebe[i];
    answersList[i][2] = chandler[i];
    answersList[i][3] = monica[i];
    answersList[i][4] = rachel[i];
    answersList[i][5] = joey[i];
    
    //printArray(answersList[i]);
  }
  
  shuffler[0] = shuffler1;
  shuffler[1] = shuffler2;
  shuffler[2] = shuffler3;
  shuffler[3] = shuffler4;
  shuffler[4] = shuffler5;
  shuffler[5] = shuffler6;
  shuffler[6] = shuffler7;
  shuffler[7] = shuffler8;
  shuffler[8] = shuffler9;
  shuffler[9] = shuffler10;
  shuffler[10] = shuffler11;
  
  for (int i = 0; i < 6; i++) {
    shuffler[0].append(answersList[0][i]);
    shuffler[1].append(answersList[1][i]);
    shuffler[2].append(answersList[2][i]);
    shuffler[3].append(answersList[3][i]);
    shuffler[4].append(answersList[4][i]);
    shuffler[5].append(answersList[5][i]);
    shuffler[6].append(answersList[6][i]);
    shuffler[7].append(answersList[7][i]);
    shuffler[8].append(answersList[8][i]);
    shuffler[9].append(answersList[9][i]);
    shuffler[10].append(answersList[10][i]);
  }
  for (int i = 0; i < 11; i++) {
    shuffler[i].shuffle();
    shuffler[i].shuffle();
    shuffler[i].shuffle();
  }
  
  rossScore = new Score();
  phoebeScore = new Score();
  chandlerScore = new Score();
  monicaScore = new Score();
  rachelScore = new Score();
  joeyScore = new Score();
  
  scoreList = new IntList();
  
  rachelBackground = loadImage("rachel.jpg");
  monicaBackground = loadImage("monica.jpg");
  phoebeBackground = loadImage("phoebe.jpg");
  rossBackground = loadImage("ross.jpg");
  chandlerBackground = loadImage("chandler.jpg");
  joeyBackground = loadImage("joey.jpg");
  
  bg1 = loadImage("finalback.jpg");
  bg2 = loadImage("finalback2.png");

  rectMode(CENTER);
  imageMode(CENTER);
  
  friends = new SoundFile(this, "friends2.mp3");
  saturday = new SoundFile(this, "chandler_saturday.mp3");
  friends.loop(); 
  strokeWeight(1);
}


void draw(){
  background(255);
  friends.amp(volume);
  
  if (instructions && !gameOn && !page0) {
    background(bg1);
    start.update(0);
    start.display();
    textFont(f,24); 
    textAlign(CENTER, CENTER);
    fill(255);
    String play = "PLAY";          //text in play button to clarify it
    text(play, start.buttonX , start.buttonY);
    stroke(#E5DCC6);
    fill(#9385B9);
    rect(width/2,height-40,volumeWidth, 30);
    
  }
  else if (page0 && !gameOn && !instructions) {
    background(255);
    image(bg2, width/2, height/2);
    proceed.update(0);
    proceed.buttonColor = color(#9385B9);
    proceed.display();
    textFont(f,24); 
    textAlign(CENTER, CENTER);
    fill(255);
    String cont = "CONTINUE";          //text in play button to clarify it
    text(cont, proceed.buttonX , proceed.buttonY);
    stroke(#E5DCC6);
    fill(#9385B9);
    rect(width/2,height-40,volumeWidth, 30);
  }
  else if (gameOn) {
    background(#9385B9);
    button1.update(choice1);
    button1.display();
    button2.update(choice2);
    button2.display();
    button3.update(choice3);
    button3.display();
    button4.update(choice4);
    button4.display();
    button5.update(choice5);
    button5.display();
    button6.update(choice6);
    button6.display();
    
    if (page1) {
      textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question1, width/2, height/8);
      textFont(f,22); 
      fill(255); 
      String one1 = shuffler[0].get(0);
      String two1 = shuffler[0].get(1);
      String three1 = shuffler[0].get(2);
      String four1 = shuffler[0].get(3);
      String five1 = shuffler[0].get(4);
      String six1 = shuffler[0].get(5);
      
      text(one1, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two1, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three1, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four1, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five1, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six1, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;       
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one1, 0, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page2 = true; 
            page1 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two1, 0, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page2 = true; 
            page1 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three1, 0, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page2 = true; 
            page1 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four1, 0, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page2 = true; 
            page1 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five1, 0, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page2 = true; 
            page1 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six1, 0, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page2 = true; 
            page1 = false;  
          }
        }    
      }   
    }
   else if (page2) {
      textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question2, width/2, height/8, width - 100);
      textFont(f,22); 
      fill(255); 
      String one2 = shuffler[1].get(0);
      String two2 = shuffler[1].get(1);
      String three2 = shuffler[1].get(2);
      String four2 = shuffler[1].get(3);
      String five2 = shuffler[1].get(4);
      String six2 = shuffler[1].get(5);
      
      text(one2, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two2, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three2, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four2, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five2, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six2, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one2, 1, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page3 = true; 
            page2 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two2, 1, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page3 = true; 
            page2 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three2, 1, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page3 = true; 
            page2 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four2, 1, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page3 = true; 
            page2 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five2, 1, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page3 = true; 
            page2 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six2, 1, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page3 = true; 
            page2 = false;  
          }
        }
        
        
      }
   }
   else if (page3) {
     textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question3, width/2, height/8);
      textFont(f,22); 
      fill(255); 
      String one3 = shuffler[2].get(0);
      String two3 = shuffler[2].get(1);
      String three3 = shuffler[2].get(2);
      String four3 = shuffler[2].get(3);
      String five3 = shuffler[2].get(4);
      String six3 = shuffler[2].get(5);
      
      text(one3, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two3, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three3, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four3, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five3, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six3, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one3, 2, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page4 = true; 
            page3 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two3, 2, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page4 = true; 
            page3 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three3, 2, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page4 = true; 
            page3 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four3, 2, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page4 = true; 
            page3 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five3, 2, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page4 = true; 
            page3 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six3, 2, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page4 = true; 
            page3 = false;  
          }
        }
        
        
      }
   }
   else if (page4) {
     textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question4, width/2, height/8);
      textFont(f,22); 
      fill(255); 
      String one4 = shuffler[3].get(0);
      String two4 = shuffler[3].get(1);
      String three4 = shuffler[3].get(2);
      String four4 = shuffler[3].get(3);
      String five4 = shuffler[3].get(4);
      String six4 = shuffler[3].get(5);
      
      text(one4, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two4, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three4, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four4, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five4, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six4, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one4, 3, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page5 = true; 
            page4 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two4, 3, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page5 = true; 
            page4 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three4, 3, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page5 = true; 
            page4 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four4, 3, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page5 = true; 
            page4 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five4, 3, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
           page5 = true; 
            page4 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six4, 3, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page5 = true; 
            page4 = false;  
          }
        }
        
        
      }
   }
   else if (page5) {
     textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question5, width/2, height/8);
      textFont(f,22); 
      fill(255); 
      String one5 = shuffler[4].get(0);
      String two5 = shuffler[4].get(1);
      String three5 = shuffler[4].get(2);
      String four5 = shuffler[4].get(3);
      String five5 = shuffler[4].get(4);
      String six5 = shuffler[4].get(5);
      
      text(one5, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two5, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three5, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four5, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five5, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six5, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one5, 4, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page6 = true; 
            page5 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two5, 4, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page6 = true; 
            page5 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three5, 4, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page6 = true; 
            page5 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four5, 4, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page6 = true; 
            page5 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five5, 4, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page6 = true; 
            page5 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six5, 4, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page6 = true; 
            page5 = false;  
          }
        }
        
        
      }
   }
   else if (page6) {
     textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question6, width/2, height/8);
      textFont(f,22); 
      fill(255); 
      String one6 = shuffler[5].get(0);
      String two6 = shuffler[5].get(1);
      String three6 = shuffler[5].get(2);
      String four6 = shuffler[5].get(3);
      String five6 = shuffler[5].get(4);
      String six6 = shuffler[5].get(5);
      
      text(one6, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two6, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three6, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four6, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five6, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six6, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one6, 5, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page7 = true; 
            page6 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two6, 5, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page7 = true; 
            page6 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three6, 5, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page7 = true; 
            page6 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four6, 5, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page7 = true; 
            page6 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five6, 5, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page7 = true; 
            page6 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six6, 5, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page7 = true; 
            page6 = false;  
          }
        }
        
        
      }
   }
   else if (page7) {
     textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question7, width/2, height/8);
      textFont(f,22); 
      fill(255); 
      String one7 = shuffler[6].get(0);
      String two7 = shuffler[6].get(1);
      String three7 = shuffler[6].get(2);
      String four7 = shuffler[6].get(3);
      String five7 = shuffler[6].get(4);
      String six7 = shuffler[6].get(5);
      
      text(one7, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two7, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three7, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four7, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five7, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six7, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one7, 6, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page8 = true; 
            page7 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two7, 6, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page8 = true; 
            page7 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three7, 6, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page8 = true; 
            page7 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four7, 6, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page8 = true; 
            page7 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five7, 6, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page8 = true; 
            page7 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six7, 6, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page8 = true; 
            page7 = false;  
          }
        }
        
        
      }
   }
   else if (page8) {
     textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question8, width/2, height/8);
      textFont(f,22); 
      fill(255); 
      String one8 = shuffler[7].get(0);
      String two8 = shuffler[7].get(1);
      String three8 = shuffler[7].get(2);
      String four8 = shuffler[7].get(3);
      String five8 = shuffler[7].get(4);
      String six8 = shuffler[7].get(5);
      
      text(one8, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two8, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three8, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four8, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five8, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six8, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one8, 7, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page9 = true; 
            page8 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two8, 7, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page9 = true; 
            page8 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three8, 7, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page9 = true; 
            page8 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four8, 7, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page9 = true; 
            page8 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five8, 7, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page9 = true; 
            page8 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six8, 7, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page9 = true; 
            page8 = false;  
          }
        }
        
        
      }
   }
   else if (page9) {
   textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question9, width/2, height/8);
      textFont(f,22); 
      fill(255); 
      String one9 = shuffler[8].get(0);
      String two9 = shuffler[8].get(1);
      String three9 = shuffler[8].get(2);
      String four9 = shuffler[8].get(3);
      String five9 = shuffler[8].get(4);
      String six9 = shuffler[8].get(5);
      
      text(one9, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two9, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three9, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four9, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five9, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six9, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one9, 8, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page10 = true; 
            page9 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two9, 8, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page10 = true; 
            page9 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three9, 8, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page10 = true; 
            page9 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four9, 8, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page10 = true; 
            page9 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five9, 8, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page10 = true; 
            page9 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six9, 8, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page10 = true; 
            page9 = false;  
          }
        }
        
        
      }
   }
   else if (page10) {
   textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question10, width/2, height/8);
      textFont(f,22); 
      fill(255); 
      String one10 = shuffler[9].get(0);
      String two10 = shuffler[9].get(1);
      String three10 = shuffler[9].get(2);
      String four10 = shuffler[9].get(3);
      String five10 = shuffler[9].get(4);
      String six10 = shuffler[9].get(5);
      
      text(one10, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two10, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three10, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four10, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five10, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six10, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one10, 9, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page11 = true; 
            page10 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two10, 9, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page11 = true; 
            page10 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three10, 9, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page11 = true; 
            page10 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four10, 9, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page11 = true; 
            page10 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five10, 9, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page11 = true; 
            page10 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six10, 9, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            page11 = true; 
            page10 = false;  
          }
        }
        
        
      }
   }
   else if (page11) {
     textFont(f,35); 
      textAlign(CENTER, CENTER);
      fill(0);
      text(question11, width/2, height/8);
      textFont(f,22); 
      fill(255); 
      String one11 = shuffler[10].get(0);
      String two11 = shuffler[10].get(1);
      String three11 = shuffler[10].get(2);
      String four11 = shuffler[10].get(3);
      String five11 = shuffler[10].get(4);
      String six11 = shuffler[10].get(5);
      
      text(one11, button1.buttonX , button1.buttonY, button1.buttonWidth - 20, button1.buttonHeight-10);
      text(two11, button2.buttonX , button2.buttonY, button2.buttonWidth - 20, button2.buttonHeight-10);
      text(three11, button3.buttonX , button3.buttonY, button3.buttonWidth -20, button3.buttonHeight-10);
      text(four11, button4.buttonX , button4.buttonY, button4.buttonWidth-20, button4.buttonHeight-10);
      text(five11, button5.buttonX , button5.buttonY, button5.buttonWidth-20, button5.buttonHeight-10);
      text(six11, button6.buttonX , button6.buttonY, button6.buttonWidth-20, button6.buttonHeight-10);
      
      if (choice1 == 1 || choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1) {
        
        if (frameCount - prevFrame > 40) {      //only allow jumping constantly after certain number of frames
          prevFrame = frameCount;
          if (choice1 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(one11, 10, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            end = true;
            gameOn = false;
            page11 = false;
          }
          else if (choice2 ==1 && !(choice1 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(two11, 10, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            end = true;
            gameOn = false;
            page11 = false;  
          }
          else if (choice3 ==1 && !(choice2 == 1 || choice1 == 1 || choice4 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(three11, 10, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            end = true;
            gameOn = false;
            page11 = false;  
          }
          else if (choice4 ==1 && !(choice2 == 1 || choice3 == 1 || choice1 == 1 || choice5 == 1|| choice6 == 1)) {
            checker(four11, 10, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            end = true;
            gameOn = false;
            page11 = false;  
          }
          else if (choice5 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice1 == 1|| choice6 == 1)) {
            checker(five11, 10, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            end = true;
            gameOn = false;
            page11 = false;  
          }
          else if (choice6 ==1 && !(choice2 == 1 || choice3 == 1 || choice4 == 1 || choice5 == 1|| choice1 == 1)) {
            checker(six11, 10, rossScore, phoebeScore, chandlerScore, monicaScore, rachelScore, joeyScore);
            end = true;
            gameOn = false;
            page11 = false;  
          }
        }  
      }
    }
    stroke(#E5DCC6);
    fill(#9385B9);
    rect(width/2,height-40,volumeWidth, 30);
  }
  
  else if (end && !gameOn) {
   scoreList.append(rossScore.value);
   scoreList.append(phoebeScore.value);
   scoreList.append(monicaScore.value);
   scoreList.append(chandlerScore.value);
   scoreList.append(joeyScore.value);
   scoreList.append(rachelScore.value);
   
   if (scoreList.max() == rossScore.value) {background(rossBackground);}
   else if (scoreList.max() == phoebeScore.value) {background(phoebeBackground);}
   else if (scoreList.max() == monicaScore.value) {background(monicaBackground);}
   else if (scoreList.max() == chandlerScore.value) 
     {
       background(chandlerBackground);
       
     }
   else if (scoreList.max() == joeyScore.value) {background(joeyBackground);}
   else {background(rachelBackground);}
   
   menu.update(0);
   menu.buttonColor = color(#808080);
   menu.display();
   textFont(f,24); 
   textAlign(CENTER, CENTER);
   fill(255);
   String back = "BACK";
   text(back, menu.buttonX, menu.buttonY);
  }
}

void checker(String test, int index, Score rossScore, Score phoebeScore, Score chandlerScore, Score monicaScore, Score rachelScore, Score joeyScore) {
  if (test == answersList[index][0]) {
    rossScore.add();
  }
  else if (test == answersList[index][1]) {
    phoebeScore.add();  
  }
  else if (test == answersList[index][2]) {
    chandlerScore.add();  
  }
  else if (test == answersList[index][3]) {
    monicaScore.add();  
  }
  else if (test == answersList[index][4]) {
    rachelScore.add(); 
  }
  else if (test == answersList[index][5]) {
    joeyScore.add(); 
  }
}

void mousePressed() {
  if (start.buttonOver && instructions && !gameOn) {
    instructions = false;
    gameOn = false;
    page0 = true;
  }
 if (proceed.buttonOver && page0) {
   gameOn = true;
   page1 = true;
   page0 = false;
 }
 if (menu.buttonOver && !instructions && !gameOn && end) {
   instructions = true;
   rossScore.value = 0;
   rachelScore.value = 0;
   monicaScore.value = 0;
   phoebeScore.value = 0;
   joeyScore.value = 0;
   chandlerScore.value = 0;
   for (int i = 0; i < 11; i++) {
    shuffler[i].shuffle();
  }
 }
}

void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    println(s);
    int values[]=int(split(s,','));
    if (values.length==7){
      choice1 = (int)values[0];
      choice2 = (int)values[1];
      choice3 = (int)values[2];
      choice4 = (int)values[3];
      choice5 = (int)values[4];
      choice6 = (int)values[5];
      volume = (float)map(values[6], 0, 1023, 0.0, 1.0);
      volumeWidth = map(values[6],0,1023,0, width/3);
      if (end) finish = 1;
      else finish = 0;
      if(gameOn) blink = 1;
      else blink = 0;
    }
  }
  myPort.write(choice1+","+choice2+","+choice3+","+choice4+","+choice5+","+choice6+","+finish+","+blink+"\n");
}

Following is the Button Class:

class Button {
  float buttonX, buttonY;
  int buttonWidth, buttonHeight;
  color buttonColor, baseColor, frame;
  color buttonHighlight, currentColor;
  boolean buttonOver;
  
  
  Button(float _x, float _y, int w, int h, color outline) {
    
  buttonX = _x;
  buttonY = _y;
  frame = outline;
  buttonColor = color(0);
  buttonHighlight = color(51);
  baseColor = color(102);
  currentColor = baseColor;
  buttonWidth = w;
  buttonHeight = h;
    
  }
  
  boolean overButton(float x, float y, int buttonWidth, int buttonHeight, int clickState)  {            //check if mouse is over button
    if ((mouseX >= x - buttonWidth/2 && mouseX <= x + buttonWidth/2 && mouseY >= y - buttonHeight/2 && mouseY <= y + buttonHeight/2) || (clickState == 1)) {
      return true;
    } else {
      return false;
    }
  }
  
  void update(int clickState) {
    if ( overButton(buttonX, buttonY, buttonWidth, buttonHeight, clickState) ) {      //check if mouse is over the button to change color
      buttonOver = true;
    } 
    else {
      buttonOver = false;
    }
  }
  
  void display() {
    stroke(frame);
    if (buttonOver) {
      fill(buttonHighlight);            //if mous hovers over button change color
      rect(buttonX, buttonY, buttonWidth, buttonHeight, 20);      //play button
    }
    else {
      fill(buttonColor);
      strokeWeight(8);
      rect(buttonX, buttonY, buttonWidth, buttonHeight, 20);      //play button
    }   
  }
  
};

 

Following is the Score Class:

class Score {
  int value;
  
  Score() {  
  value = 0;  
  }
  
  void add() {
    value++;
  }
}

Final Project File if you want to download it:

finalProcessing

 

Final IM project – sound visualizer

Documentation:

Idea: To create motion graphics that respond to sound frequency and amplitude and have input from Arduino to change the appearance of the visuals.

Artistic concept: Using geometry , 3D boxes specifically.

What was done well:

I think the composition of the 3D shapes is aesthetically pleasing.

I successfully mapped potentiometer values to color change in the visuals.

What could I have done better:

Maybe included more input from the user side, like more sensors , but I was short on time.

Tidier code – as this was a learning process for me the code might be harder to follow.

What I learned:

How to use the minim and sound library, the project taught me a-lot about motion graphics and 3D design in processing.

//I used inspiration from this persons work
//https://github.com/KartikShrivastava/3d-Audio-Visualizer-P3D/commit/d811270ff38dff160a2bf211b38068cab54f1b50
//Song from :https://www.youtube.com/watch?v=MtbzPhj0biE
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;

import processing.serial.*;
Serial myPort;

int xColor=0;
int xColor1=0;


FFT fft;
AudioPlayer player;
Minim minim;
float rotateAll = 0;
int depth, flashTimer = 0;
boolean flash=false;
float x;
int spacing = 100;
int border = spacing*2; 
int amplification = 50;
int y = spacing; 

void setup() {
  stroke(0, 239, 135); 
  strokeWeight(5);
  printArray(Serial.list());
  String portname=Serial.list()[4];
  println(portname);
  myPort = new Serial(this, portname, 9600);

  size(900, 900, P3D);

  background(0);
  minim = new Minim(this);
  player = minim.loadFile("jingle.mp3");  
  player.play();

  fft = new FFT(player.bufferSize(), player.sampleRate());
}

void draw() {
  background(0, 20, 20);

  lights();
  //colorchange();
  drawback(); //background

  fft.forward(player.mix);

  pushMatrix();
  translate(width/2, height/2, -120);

  for (int i=0; i<24; i++) {
    pushMatrix();

    rotateY(180);

    x=x+1*0.01;
    translate(x, 200, 0);
    if (fft.getBand(i)*1 > 300) {

      if (i==4 && fft.getBand(i)*1 > 1000) {
        flash = true;
      }
    } else {
      //stroke(0, 239, 135); 

      float r=0 ;
      float b=255 ;
   
      r = map(xColor, 0, 600, 0, 100);
      b = map(xColor, 0, 600, 100, 0);
    
      //fill(0, 254, 179, 33); 
      fill(r, 300, b, r); 
      stroke(r, 0, b);
    }
    //box 1
    box(50, (-fft.getBand(i)*5) - 80, 50); 
    rotateY(270);
    popMatrix();
    pushMatrix();
    translate(width/2+x, height/2, 0);
    //box 2
    box(50, (-fft.getBand(i)*5) - 80, 50); 
    popMatrix();
    pushMatrix();
    translate(width/2, height/2+x, -200);
    //box3
    box(50, (-fft.getBand(i)*5) - 80, 50); 
    popMatrix();
    pushMatrix();
    translate(width/3, height/3+x, -200);
    //box4
    box(150, (-fft.getBand(i)*5) - 80, 50); 
    popMatrix();
    pushMatrix();
    translate(-100+x, 100, -400);
    //box5
    rotateX(180);
    box(150, (-fft.getBand(i)*5) - 80, 50); 
    popMatrix();
    rotateX(180);
    box(150, (-fft.getBand(i)*5) - 80, 50);
  }
  popMatrix();
}

void drawback() {

  strokeWeight(4);
  rectMode(CENTER);

  stroke(#ff6ec7);


  player.play();
  float amplitude = player.mix.level();
  fill(random(0), amplitude*155);
  int x = int(map(player.position(), 0, player.length(), 0, width/2));
  float frequency = player.mix.get(int(x))*spacing*amplification;


  rect(width/2, height/2, frequency, frequency);
  stroke(#1b03a3); 
  ellipse(width/2, height/2, frequency*100, frequency*100);
  filter( BLUR, 0.5 );
}

void serialEvent(Serial myPort) {
  xColor=myPort.read();

}
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  int sensor = analogRead(A0);

  delay(1); //avoid getting noisy values.
  sensor /= 4; //why is it incrementally devided by 4? maybe slow it down
  //also 2^8 is 256 or 1024/4 sends one byte at a time to the serial,


  Serial.write(sensor);

}

🌏 👽 SPACE DEFENSE 🚀 🛸

It’s been quite a journey. I put tremendous time and effort trying to perfect the details and coordinations of everything in the game. Hope you like it. At first I had a bit of trouble deciding which idea to stick to, but I am glad I ended up coming through with the “SPACE DEFENSE” game. As same as other final projects for this course, I brought Arduino and Processing together to make the game. When I first designed the development of the game, I broke it down into three main milestones with the respective order of priority:

  1. Processing game design
  2. Arduino architecture
  3. Serial connection

Accomplishing the first milestone, therefore, took up the most time. I initially made the game without the Arduino part and included the use of the keyboard to make the development more convenient and seamless. This is because it seemed rather easier for me to replace the keyboard use with the button use through serial communication than leaving numerous chunks blank. I still commented out not all but most of the parts necessary to run the keyboard to play the game. So find parts as shown below and simply uncomment them to use the keyboard instead! (apart from the uncommenting you need to do some tweaking into the code of course)

In terms of the code in Processing, I have in total of 4 classes (Player, Laser, Item, and Asteroid). I used polygons instead of images on asteroids for three reasons. First, I resized the images in Processing and that made the whole game slow. After talking with Aaron, I realized I could have cropped or resized images outside of Processing. However, there was another reason I preferred not to use an image for an asteroid. I thought it would be awkward to recreate the specific movement effect on an image, and the way my code generated different shapes, sizes, trajectories made the game more resourceful. Lastly, employing shapes instead of simply importing images seemed like a bigger challenge to me so I went with it. This is because these polygons have different shapes and vertices and so the collision effect on them required more thinking and effort than on uniform images.

The biggest challenge for me was controlling and coordinating the movement of different objects. This is because I had to manage a set of situations where different objects collide with one another. The next challenge was serial communication. I just had to spend some time figuring out the use of data transferred from Arduino within different classes. Also because when an error arose I had to check both Processing and Arduino, so that required extra investigation on a broader scope. After completing the general skeleton code of the game, I initially connected the maneuvering of the spaceship to the potentiometer. So depending on the degree of rotation, the spaceship would either move left or right. But after trying this for a while, I realized how inconvenient and clumsy it gets when using the potentiometer. The rotation of the button was simply too difficult to carry out that it was annoying to invest so much energy when playing the game. Below is a little sneak peak of how the potentiometer was set up in my Arduino board at first.

With this problem and user experience in mind, I decided to use push buttons. I also decided to get rid of UP & DOWN buttons because it made physiologically little sense that LEFT & RIGHT & UP & DOWN buttons are all aligned next to each other. So the spaceship was only allowed to move sideways and this was enough. I then added two push buttons – one for shooting bullets and the other for resetting the game. Below is how my Arduino looked like in the end:

In terms of the design, I tried to make it sort of retro. The song, the font, the color, the spaceship have all been designed in a way that it makes you feel nostalgic (at least for me). The sound track of the game is from a 1996 arcade game called “Out Run”, which is a car racing game but it also suits well in my game in my opinion. Here are the images and sounds I used.

starship (player)

earth (item)

ouch.mp3 (when the player collides with an asteroid)

laser.mp3 (when shooting bullets)

soundtrack.mp3 (sound track from Out Run 1996 arcade game)

life.mp3 (when the player gets an item and health goes up)

crash.mp3 (when an asteroid collides with the land)

 

Of course, a simple set of instructions are displayed before the game is initiated with the game title on top. I did not add any extra effects on this part because it is retro. To talk about how the game is run, the player can maneuver the starship left and right in order to shoot bullets at the falling “asteroids” that are polygons. I have limited the maneuver to left and right for the reason mentioned earlier. If a player collides with an asteroid he/she will lose 2 health points. If an asteroid collides with the earth, the health will also decrease by 10, as it is a fatal and collateral damage to the global community. If a player successfully hits an asteroid with a bullet, the asteroid will vanish and will be deducted from the total number of asteroids in the current level. There will be earth-looking items falling too and you should shoot at it to get 10+ on your health. Your level goes up when you eliminate all the asteroids in the level. Each level you go up, there will be 1 less earth item and 2 more asteroids. Without further ado, here’s a demo video.

// Main

import ddf.minim.*;

/************* Serial **************/
import processing.serial.*;
Serial myPort;
int xPos=0;
int left, right, b, reset;
/************* Serial **************/

Player player; 
Item item;
PFont font, font2;
PImage starship, earth, galaxy;
ArrayList<Asteroid> asteroids;
ArrayList <Laser> laser; 
ArrayList<Item> items;
boolean instruction = true;
boolean [] keys = new boolean[128];
String message;
int[] land;
int health, asteroidCount, itemCount;
int asteroid_ = 0;
int item_ = 0;
int level = 1;
int count = 1;

//sound effect
Minim minim;
AudioPlayer soundtrack, sound, sound2, sound3, sound4;

void setup() {
  size(480, 640);
  
  if (count == 1){
    /************* Serial **************/
    printArray(Serial.list());
    String portname = Serial.list()[5];
    println(portname);
    myPort = new Serial(this,portname,9600);
    myPort.clear();
    myPort.bufferUntil('\n');
    /***********************************/
    }
  
  // Sound effect processing
  minim = new Minim(this);
  soundtrack = minim.loadFile("soundtrack.mp3");
  sound = minim.loadFile("laser.mp3");
  sound2 = minim.loadFile("crash.mp3");
  sound3 = minim.loadFile("ouch.mp3");
  sound4 = minim.loadFile("life.mp3");
  sound2.setGain(-10);

  // Images
  starship = loadImage("starship.png");
  earth = loadImage("earth.png");
  
  // Font
  font2 = createFont("Cambria-bold",60);
  font = createFont("Phosphate-Inline",60);
  
  // asteroid_ ==  0 means when you start the game
  // else meanse after Level 1
  health = 100;
  if (asteroid_ == 0 && count == 1){
    asteroidCount = 10;
    itemCount = 5;
    soundtrack.rewind();
    soundtrack.play();
  }
  else {
    asteroidCount = 10 + asteroid_;
    itemCount = 5 + item_;}

  /********** Initiating Objects ***********/
  // Player
  player = new Player();
  // Meteor
  asteroids = new ArrayList<Asteroid>();
  for (int i=0; i < asteroidCount; i++) { 
    asteroids.add(new Asteroid());}
  // Bullet
  laser = new ArrayList();
  // Earth item
  items = new ArrayList<Item>();
  for (int i=0; i < itemCount; i++) { 
    items.add(new Item());}
 /*******************************************/

  // Background
  land = new int [width/10+1];
  for (int i = 0; i < land.length; i++) { 
    land[i] = int(random(10));}
    
  message = "Level ";
  
}

void draw() {
  
  
  if (instruction){
    galaxy = loadImage("instruction_background.jpg");
    //Using the width and height of the photo for the screen size
    galaxy.resize(width,height); 
    image(galaxy,0,0);
    textAlign(CENTER);
    textFont(font);
    fill(#FFFF00);
    text("SPACE DEFENSE",width/2,height/2-120);
    textFont(font2);
    textSize(20);
    fill(255);
    text("Protect the planet from falling asteroids!\n* * *\nPress YELLOW to move left\nPress BLUE to move right\nPress RED to shoot\nPress GREEN to restart\n* * *\nClick anywhere to proceed",width/2,height/2);
    return;
  }
  
  background(0);
  fill(255);
  noStroke();
  ellipse(random(width), random(height-50), 3, 3);

  textSize(32);
  fill(255);
  text(message+level, width/2, 100);

  drawEarth();

  for (int i= asteroids.size()-1; i >= 0; i--) {
    Asteroid p = asteroids.get(i);
    p.update();
    p.display();
    if (player.checkCollision(p)) {
      if (health > 0) {
        health -= 2;
      }
      sound3.rewind();
      sound3.play();
    }
    for (int j= laser.size()-1; j >= 0; j--) {
      Laser b = laser.get(j);
      // If an asteroid appears on screen and collides with a bullet
      if ((p.pos.y + p.r > 0) && (p.checkCollision(b))) {
        if (asteroids.size() > 0){
          asteroids.remove(i);
          laser.remove(j);
          asteroidCount = asteroids.size();
        }
        sound2.rewind();
        sound2.play();
      }
    }
  }

  for (int i= items.size()-1; i >= 0; i--) {
    Item it = items.get(i);
    it.update();
    it.display();
    for (int j= laser.size()-1; j >= 0; j--) {
      Laser b = laser.get(j);
      // If an item appears on screen and collides with a bullet
      if ((it.po.y + 25) > 0 && (it.checkCollision(b))) {
        if (items.size() > 0){
          laser.remove(j);
          items.remove(i);
          if (health >= 100) {
            continue;
          }
          health += 10;
          sound4.rewind();
          sound4.play();
        }
      }
    }
  }

  if (asteroids.size() <= 0) {
    delay(1000);
    count = 0;
    asteroid_ += 2;
    item_ -= 1;
    setup();
    level += 1;
    
  }

  player.display();
  player.move();

  for (int i= laser.size()-1; i >= 0; i--) {
    Laser b = laser.get(i);
    b.move();
    b.display();
  }
  
  if (b == 1) {
    Laser temp = new Laser(player.pos.x+16, player.posy);
    laser.add(temp);
    sound.rewind();
    sound.play();
  }
  
  if (reset == 0) {
    count = 0;
    asteroid_ = 0;
    item_= 0;
    level = 1;
    setup();
  }

  textSize(32);
  if (health > 0) {
    text(health, width - 100, 50);
  } else {
    text(0, width - 100, 50);
  }

  if (health <= 0) {
    String over = "Game Over";
    textSize(60);
    text(over, width/2, height/2);
  }
  textSize(32);
  fill(255, 0, 0);
  text(asteroidCount, 100, 50);
}


void asteroidShape(float a, float b, float r, int vertices) {
  float x = map(r, 0, 40, 50, 255);
  float degree = TWO_PI / vertices;
  color col = color(x/2, x/3, 100);
  beginShape();
  for (float i = 0; i < TWO_PI; i += degree) {
    float sx = a + cos(i) * r;
    float sy = b + sin(i) * r;
    fill(col);
    noStroke();
    //curveVertex(sx, sy);
    vertex(sx, sy);
  }
  endShape(CLOSE);
}


void drawEarth() {

  fill(250, 150, 0, 60); 
  noStroke();
  beginShape();
  vertex(0, 640);
  for ( int i=0; i < land.length; i++) {
    vertex( i * 11, 640 - 40 - land[i] );
  } 
  vertex(480, 640);
  endShape(CLOSE);
}


void mousePressed() {
  if (instruction) {
    instruction = false;
  }
  //level = 1;
}


void keyPressed() {
  keys[keyCode] = true;
}


void keyReleased() {
  keys[keyCode] = false;
}



/************* Serial **************/
void serialEvent(Serial myPort){
  String s = myPort.readStringUntil('\n');
  s = trim(s);
  if (s != null){
    int values[] = int(split(s,','));
    if (values.length == 4){
      left = int(values[0]);
      right = int(values[1]);
      b = int(values[2]);
      reset = int(values[3]);
    }
  }
  myPort.write('0');
  
  // For key board use:
  //float xPos = myPort.read();
  //player.pos.x = map(xPos, 0.0, 225.0, 0.0, 390.0)
  //myPort.write(0);
}
/************* Serial **************/
// Laser class

class Laser{
  PVector p;
  PVector a;
  PVector v;
  int w, h;
  
  Laser(float tx, float ty){
     p = new PVector(tx, ty);
     a = new PVector(0,-0.2);
     v = new PVector(0, -2.5);
  }
  
  void display(){
     noStroke();
     fill(random(255), random(255), random(255));
     rect(p.x, p.y, 5, 12);
  }
  
  void move(){
    v.add(a);
    p.add(v);
  }
}
// Item class

class Item{
  PVector po;
  PVector ac;
  PVector ve;

  Item(){
    po = new PVector(random(width), random(-height, 0));
    ac = new PVector(0, 0.001);
    ve = new PVector(0, 0);
  }
  
  void update(){
    ve.add(ac);
    ve.limit(1);
    po.add(ve);
 
    // Readjust location if the player goes off screen on the side
    if((po.x < -25) || (po.x > width + 25)){
      po.x = random(width);
      po.y = random(-height+100, 0);
    }
    if (po.y > height - 25){
      po.y = random(-height+100,0);
      po.x = random(width);
      // meteor crash
      sound2.rewind();
      sound2.play();
    }
  }
  
  void display(){
    pushMatrix();
    translate(po.x, po.y);
    image(earth, 0, 0);
    popMatrix();
  }
  
  
  boolean checkCollision(Laser b){
    if((b.p.y + 6) <= po.y + 25 && b.p.x >= po.x - 10 && b.p.x <= po.x + 50){
      sound.rewind();
      sound.play();
      return true;
    } 
    else {
      return false;
    }
  }
}
// Asteroid class

class Asteroid{
  PVector pos;
  PVector acc;
  PVector vel;
  int vertices;
  float r;
  color c;

  Asteroid(){
    pos = new PVector(random(width), random(-height, 0));
    acc = new PVector(random(-0.1, 0.1), random(0.1, 0.7));
    vel = new PVector(0, 0);
    vertices = int(random(3, 15)); // what type of polygon? triangle ~ 15-gon
    r = random(10, 45);
  }
  
  void update(){
    vel.add(acc);
    vel.limit(2);
    pos.add(vel);
    
    // Readjust location if the player goes off screen on the side
    if((pos.x + r < 0) || (pos.x - r > width)){
      pos.x = random(0, width);
      pos.y = random(-height, 0);
    }
    if (pos.y + r > height){
      if (health > 0){
        health -= 10; // reduce health
      }
      pos.y = random(-height,0);
      pos.x = random(0, width);
      // meteor crash
      sound2.rewind();
      sound2.play();
    }
  }
  
  void display(){
    pushMatrix();
    translate(pos.x, pos.y);
    rotate(frameCount / 50.0);
    asteroidShape(0, 0, r, vertices);
    popMatrix();
  }
  
  boolean checkCollision(Laser b){
    if((b.p.y + 6) <= pos.y + r && b.p.x >= pos.x - r && b.p.x <= pos.x + r){
      sound.rewind();
      sound.play();
      return true;
    } 
    else {
      return false;
    }
  }
}
// Player class

class Player{
  PVector acc;
  PVector vel;
  PVector pos;
  float posy = height-100;
  
  Player(){
    pos = new PVector(width, height - 100);
    acc = new PVector(0.2, 0.2);
    vel = new PVector(0,0);
  }
  
  void display(){
    image(starship, pos.x, posy); 
  }
  
  void move(){
    acc.normalize();
    vel.mult(5);
    vel.limit(10); 
    vel = vel.add(acc);
    
    if(left == 1){
      pos.x -= vel.x;}
    if(right == 1){
      pos.x += vel.x;}
    
    /* Un-comment for keyboard use
    
    if(keys[LEFT]){
      pos.x -= vel.x;}
    if(keys[RIGHT]){
      pos.x += vel.x;}
    if(keys[UP]){
      pos.y -= vel.y;}
    if(keys[DOWN]){
      pos.y += vel.y;}
    if(pos.y >= height - 50){
      pos.y = height - 82.5;}
    _____________________________*/
    
    if(pos.x < -19){
      pos.x = width -19; 
    }
    if(pos.x > width - 19){
      pos.x = -19;  
    }

  }
  
  boolean checkCollision(Asteroid p){
    if (dist(pos.x, posy, p.pos.x, p.pos.y) <= p.r) {
      textSize(24);
      text("Collision!", width - 60, height - 12);
      return true;
    } 
    else {
      return false;
    }
  }
}
// Arduino

int turnOn = 1;
int prevButtonState = 0;

void setup(){
  Serial.begin(9600);
  Serial.println("0,0,0,0");
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  }

void loop(){
  if(Serial.available()>0){
    char incoming = Serial.read();
    int a1 = digitalRead(2);
    delay(1);
    int a2 = digitalRead(3);
    delay(1);
    int a3 = digitalRead(4);
    delay(1);
    int a4 = digitalRead(5);
    delay(1);

    Serial.print(a1);
    Serial.print(",");
    Serial.print(a2);
    Serial.print(",");
    if (a3 == 0 && prevButtonState == 1) {
      Serial.print(turnOn);
    }
    prevButtonState = a3;
    Serial.print(",");
    Serial.print(a4);
    Serial.println();
    }
  }

 

Here’s also a zip file of my game. Hope you enjoy!

Main2

Final Project Documentation by Ryan

Main Idea/Concept of My Game 

The game is sort of a recreation of the Flappy Bird game but I added my own features to make it different from the normal Flappy Bird game that we are all familiar with.

The main idea of the game is for the user to be able to control the Bird through two different methods of their own choosing at the start of the game: Photoresistor or Microphone, and the objective is to control the bird and avoid all of the incoming covid 19 viruses. If the user manages to stay alive for 30 seconds, then the user wins. However, I added a twist where each time the user wins, the covid viruses’ speed will be even faster, therefore increasing the level of difficulty for the user.

Walkthrough of the Game

  1. When first started, the screen will display several things for the users first such as the Instructions, the types of controls that the user can choose to play with (Photoresistor or Microphone), a brief tutorial for the user about the two types of controls and how to use them, and with a brief note for the users about how the virus will increase in speed each time the user wins. Once finished reading, there will be a start button for the user to press to start playing.
  2. Once the user has either won or lost, there will be a win or lose screen with instructions for the user to press the mouse to restart and to play again.
  3. Press the start button again to play once more!

Difficulties/Challenges

Throughout the entire process of creating this, the hardest part was definitely with the coding ,whereas the hardwiring part was extremely easy as compared to the coding.

Regarding some of the major difficulties I encountered in coding, only some because I had encountered a lot of big and small ones, I’m just going to go through each one by one.

The first part where I struggled a bit would be mapping the microphone values to the up and down movement of the bird. The reason I struggled with this is because I have never done anything like this before, so I had to search up the basics through the Processing forum about amplitude and what is it and other tutorial videos online to learn about how to incorporate it into my game. Also, I sought out help with Professor to know more about how to use various things such as what is an amplitude analyzer, etc. However, in the end, I managed to learn more about this new feature that I’ve never used before thanks to this experience.

The second part that I struggled quite a lot with as well would most likely be when I wanted to add both modes (photoresistor and microphone) into a single file and to even add the option for the user to be able to choose which mode they want to play in using the input coming from the Arduino board as it will be decided with the buttons. However, I was able to get over this difficulty as well by consulting with Jack and Aaron.

There are definitely a lot more difficulties that I had encountered throughout this entire process, but mostly are minor coding mistakes as compared to the aforementioned ones. These are also easily overcame by myself by simply looking at the problem in a different perspective and to not overthink some solutions as the answer could just simply be a slight change of position for a piece of code or something.

Pictures Used 

Virus Picture

https://www.google.com/search?q=cartoon+virus+png&tbm=isch&ved=2ahUKEwjUupvkzL7tAhUPdZQKHc4MCrcQ2-cCegQIABAA&oq=cartoon+virus+png&gs_lcp=CgNpbWcQAzICCAAyAggAMgYIABAIEB4yBggAEAgQHjIGCAAQCBAeMgYIABAIEB4yBggAEAgQHjIGCAAQCBAeMgYIABAIEB4yBggAEAgQHjoECCMQJ1CVBliMFGC8F2gAcAB4AIABpQGIAZEGkgEEMTAuMZgBAKABAaoBC2d3cy13aXotaW1nwAEB&sclient=img&ei=Q47PX5SNJI_q0QTOmai4Cw&bih=762&biw=1440&safe=active&hl=en#imgrc=mwUFi4Tig-yYgMBird Picture 

https://www.cleanpng.com/png-pigeons-and-doves-homing-pigeon-english-carrier-pi-6970159/preview.html

Cloud Picture

https://www.vhv.rs/viewpic/wbwxmJ_clouds-png-animated-cute-cartoon-cloud-png-transparent/

Sounds Effects/Music 

Gameplay Music:

Win Music:

Lose Music:

Final Product Demonstration/Explanation 

Arduino Setup 

Zip File for the Game (TRY IT OUT YOURSELF!)

IM_Final_Project_1_4_FINISHED_

Code

Arduino Code

const int blueSwitch = 3;
const int redSwitch = 4;
const int sensor = A0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("0,0");
  pinMode(blueSwitch, INPUT);
  pinMode(redSwitch, INPUT);
  pinMode(sensor, INPUT);
}

void loop() {
  if (Serial.available() > 0) {
    char inByte = Serial.read();
    int photoresistor = analogRead(sensor);
    delay(10);
    int sensor2 = digitalRead(blueSwitch);
    int sensor3 = digitalRead(redSwitch);
    Serial.print(photoresistor);
    Serial.print(',');
    Serial.print(sensor2);
    Serial.print(',');
    Serial.println(sensor3);
  }
}

Processing Code

Code for Main Sketch

import processing.serial.*;
import processing.sound.*;
Amplitude amp;
AudioIn in;
float smoothedNum = 0;

Serial myPort;

Virus [] virus;
Clouds [] cloud;
Bird bird;
Timer timer;

PImage Birdimg;
PImage Virusimg;
PImage Cloudimg;

boolean buttonPressed;

int gameState;
int numberOfVirus = 1;
int buttonX, buttonY, buttonW, buttonH;
int numberofClouds = 5;
int interactionMode;

String S= "You Win! \n Press the mouse to restart";
String Instructions= "Instructions: \n Control the Bird Up & Down and Avoid All Viruses  \n \n Choose Control Mode: \n Red Button = Photoresistor \n Blue Button = Microphone\n\nControl Tutorial:\n Photoresistor= Hover your hand over the photoresistor and move your hand up and down to control the bird \nMicrophone= Control the Bird with your voice \n\n NOTE: \n Each time you win, the Viruses will become faster next round \n \n"; 

SoundFile gameplayBGMusic;
SoundFile WinBGMusic;
SoundFile LoseBGMusic;

void setup() {
  size (1400, 600);
  printArray(Serial.list());
  String portname=Serial.list()[4];
  println(portname);
  myPort = new Serial(this, portname, 9600);
  //myPort.clear();
  //myPort.bufferUntil('\n');
  gameState=0;
  //Assume the start button has not been pressed
  buttonPressed = false;
  //Parameters for the start button
  buttonW=335;
  buttonH=100;
  textSize(buttonH);
  buttonX=(width-buttonW)/2;
  buttonY=(height-buttonH)/2;
  Birdimg= loadImage("Bird Picture #1.png");
  Virusimg= loadImage("Virus Picture #1.png");
  Cloudimg = loadImage ("Clouds.png");
  cloud = new Clouds [numberofClouds];
  for (int i=0; i<cloud.length; i++) {
    cloud[i] = new Clouds(Cloudimg);
  }
  virus = new Virus [numberOfVirus];
  for (int i=0; i< virus.length; i++) {
    virus[i] = new Virus(Virusimg);
  }
  bird = new Bird(Birdimg);
  timer = new Timer();
  amp = new Amplitude(this);
  in = new AudioIn(this, 0);
  in.start();
  amp.input(in);


  gameplayBGMusic = new SoundFile(this, "Gameplay BG Music.mp3");
  WinBGMusic = new SoundFile(this, "Win BG Music.mp3");
  LoseBGMusic = new SoundFile(this, "Lose BG Music.mp3");
}

void draw() {
  background(173, 253, 255);
  //start screen w/ instructions 
  println(interactionMode);
  if (gameState == 0) {
    //insert starting screen code here
    background(255);
    fill(237, 203, 29);
    //String Instructions= "Instructions: \n Control the Bird Up & Down and Avoid All Viruses  \n \n Choose Control Mode: \n Red Button = Photoresistor \n Blue Button = Microphone\n\nControl Tutorial:\n Photoresistor= Hover and move your hand up and down the photoresistor \nMicrophone= Control the Bird with your voice \n\n NOTE: \n Each time you win, the Viruses will become faster next round \n \n"; 
    textAlign(CENTER);
    textSize(20);
    text(Instructions, width/2, height/2-250);
    fill(139, 0, 139);
    rect(buttonX, buttonY+200, buttonW+65, buttonH);
    fill(255);
    textSize(50);
    text("PRESS TO START", buttonX+200, buttonY+200+buttonH-10);
  } else if (gameState == 1) { //gameplay screen for Photoresistor Mode
    //insert game code here

    for (int i=0; i<virus.length; i++) {
      virus[i].drawVirus();
      virus[i].moveVirus();
    }
    for (int i=0; i<cloud.length; i++) {
      cloud[i].drawClouds();
      cloud[i].moveClouds();
    }
    bird.drawUserBird();
    bird.checkEdge();
    timer.showTimer();
    collisiondetection();

    if (interactionMode == 1) {
      float temporaryAmplitude;
      temporaryAmplitude = amp.analyze();
      temporaryAmplitude = map(temporaryAmplitude, 0, 0.2, height, 0);
      temporaryAmplitude = constrain(temporaryAmplitude, 0, height);

      //controlling the speed at which the object is reaching its destination
      //takes more frames to arrive at its destination
      bird.locy += (temporaryAmplitude- bird.locy)*.1;
    }
  } else if (gameState == 2) { //Win Screen
    //insert win screen code here
    //numberOfVirus= +1;
    //for (int i=0; i<virus.length; i++) {
    //  virus[i].xspeed -=5;
    //}
    gameplayBGMusic.stop();
    background(0);
    fill(random(255), random(255), random(255));
    textAlign(CENTER);
    textSize(80);
    text(S, width/2, height/2);
    if (mousePressed) {
      for (int i=0; i<virus.length; i++) {
        virus[i].xspeed -=10;
        virus[i].locx = width+50; //this makes them appear from off the screen
        virus[i].locy = random(height); //this makes it appear at random heights
        virus[i].timer1= millis()+1000; // this is the time interval for each virus appearing
      }
      WinBGMusic.stop();
      reset();
    }
  } else if (gameState == 3) { // Lose Screen
    //insert lose screen code here
    String G="You Lose! Game Over";
    String R="Press the mouse to restart";
    background(0);
    fill(random(255), random(255), random(255));
    textAlign(CENTER);
    textSize(80);
    text(G, width/2, height/2);
    textSize(50);
    text(R, width/2, height/2+100);
    if (mousePressed) {
      for (int i=0; i<virus.length; i++) {
        virus[i].locx = width+50; //this makes them appear from off the screen
        virus[i].locy = random(height); //this makes it appear at random heights
        virus[i].timer1= millis()+1000; // this is the time interval for each virus appearing
      }
      LoseBGMusic.stop();
      reset();
    }
  }
}


//if the start button is pressed
void mousePressed() {
  if ( mouseX > buttonX && mouseX < buttonX+buttonW+65 && mouseY > buttonY+200 && mouseY < (buttonY+200)+buttonH) {
    //buttonPressed=true;
    gameState=1;
    gameplayBGMusic.play();
    timer= new Timer();
  }
}


void reset() {
  gameState=0;
  //Assume the start button has not been pressed
  //buttonPressed = false;
  //Parameters for the start button
  buttonW=335;
  buttonH=100;
  textSize(buttonH);
  buttonX=(width-buttonW)/2;
  buttonY=(height-buttonH)/2;
  //Birdimg= loadImage("Bird Picture #1.png");
  //Virusimg= loadImage("Virus Picture #1.jpeg");
  //virus = new Virus [numberOfVirus];
  //for (int i=0; i< virus.length; i++) {
  //  virus[i] = new Virus(Virusimg);
  //}
  bird = new Bird(Birdimg);
  timer = new Timer();
}

void collisiondetection() {
  for (int i=0; i<virus.length; i++) {
    if (dist(virus[i].locx, virus[i].locy, bird.locx, bird.locy)< virus[i].viruswidth + bird.radius) {
      //println(dist(balls[i].locx, balls[i].locy, myBall.locx, myBall.locy));
      gameplayBGMusic.stop();
      LoseBGMusic.play();
      gameState=3; //if it collides, changes the boolean to true, making the lose screen appear
    }
  }
}

void serialEvent(Serial myPort) {
  //read string of information
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  //if there's sth in s
  if (s!=null) {
    //split the string s based on commmas and put it into integer array "values"
    int values[]=int(split(s, ','));
    /*as long as there's a total of three arrays of information from Arduino
     */
    if (values.length==3 ) {
      if (interactionMode == 0) {
        //photoresistor value
        int temporaryBirdValue;
        temporaryBirdValue = values[0];
        //bird.locy=values[0];
        temporaryBirdValue =  (int(map(temporaryBirdValue, 390, 833, height, 0)));
        temporaryBirdValue = constrain(temporaryBirdValue, 0, height);

        //this is the smoothing algorithm for the bird movement 
        bird.locy += (temporaryBirdValue - bird.locy)*.05;
      }
      //this is values for blueswitch 
      if (values[1] ==1) { //if the blueswitch is pressed change to photoresistor mode
        interactionMode = 0;
      }
      //this is values for redswitch
      if (values[2] == 1) { //if the redswitch is pressed change to microphone mode
        interactionMode = 1;
      }
      //code to map the values of the photoresistor to the width of the screen
      //gotta change the values for the range of the photoresistor
    }
  }
  //println(xPos);
  myPort.write('0');
}

Code for Bird

class Bird {
  PImage Birdimg;
  //int locx, locy;
  float locx, locy;
  float Birdwidth, Birdheight;
  //no x speed as the x coordinates will be determined by values of photoresistor
  float yspeed=5;
  float radius=30;// for now, as we'll use a ball to determine the range of collision for the bird image
  

  Bird(PImage birdimg) { //constructor for the Bird object
    Birdimg= birdimg;
    locx = width/4;
    locy = height/2;
    Birdwidth = 4*radius;
    Birdheight = 4*radius;
  }
  
  void drawUserBird(){
    //fill(255,10,243);
    //stroke(255);
    //ellipse(locx, locy, Birdwidth, Birdheight);
    image(Birdimg, locx, locy, Birdwidth, Birdheight);
  }
  
  void checkEdge(){
    if (locy+10 < 0){
      locy +=10;
    }
    if (locy+10 >height){
      locy -=10;
    }
    if (locx+10 < 0){
      locx +=10;
    }
    if (locx+10 >width){
      locx -=10;
    }
  }
}

Code for Clouds

class Clouds {
  float locx, locy;
  float cloudwidth, cloudheight;
  float speed = -3;
  PImage Cloudimg;
  long timer1;


  Clouds(PImage _img) {
    Cloudimg = _img;
    locx = random(0+10, width-10);
    locy = random(0+10, height-10);
    cloudwidth = 120;
    cloudheight = 120;
    timer1= millis()+1000; // this is the time interval for each virus appearing
  }

  void drawClouds() {
    imageMode(CENTER);
    //ellipse(locx, locy, cloudwidth, cloudheight);
    image(Cloudimg, locx, locy, cloudwidth, cloudheight);
  }
  void moveClouds() {
    if (millis()>timer1) {
      locx += speed; //only move the x positions
    }
    if (locx<-20) {
      locx = width+50;
      locy = int(random(20, height-20));
    }
  }
}

Code for Timer

class Timer {
  //basic definitions for Timer 
  float locx, locy;
  float timerwidth, timerheight;
  int countdown=30;
  int seconds;
  float startTime;

  Timer() {// constructor for Timer object
    textSize(50);
    startTime= millis()/1000 + countdown;
    seconds = int(startTime- millis()/1000);
  }
  void showTimer() {
    if (seconds<0) {
      startTime= millis()/1000 + countdown;//resets the timer and restarts it when less than 0
      //if seconds is zero, display "game over"
      gameplayBGMusic.stop();
      WinBGMusic.play();
      gameState=2; //if the time ends, it means the person has won and avoided all figures
    } else {
      seconds = int(startTime- millis()/1000);
      fill(255, 0, 0);
      text(seconds, width/2, 100);
    }
  }
}

Code for Viruses

class Virus {
  int locx;
  float locy;
  long timer1;
  float viruswidth, virusheight;
  //the virus balls only need xspeed as it will only move towards the left 
  float xspeed= -10;//it's negative 10 as it moves to the left
  int radius=30;
  PImage Virusimg;

  //constructor for the Virus objects
  Virus(PImage _img) {
    Virusimg = _img;
    locx = width+50; //this makes them appear from off the screen
    locy = random(height); //this makes it appear at random heights
    viruswidth = 4*radius;
    virusheight = 4*radius;
    timer1= millis()+1000; // this is the time interval for each virus appearing
  }
  void drawVirus() {
    //stroke(0);
    //ellipse(locx, locy, viruswidth, virusheight);
    imageMode(CENTER);
    image(Virusimg, locx, locy, viruswidth, virusheight);
  }
  void moveVirus() {
    if (millis()>timer1) {
      locx += xspeed; //only move the x positions
    }
    if (locx<-20){
      locx = width+50;
      locy = int(random(20, height-20));
    }
  }
}

 

Final Project by Amina & Susanne [Documentation]

Are you tired yet of Zoom? Maybe not the meetings and the people but just the ever repeating procedure of logging in? Whether your answer would be yes or no, let us propose a more engaging way to join a Zoom meeting, one that involves more than your sense of touch when typing on your keyboard:

Try our musically gamified way to enter your next Zoom meeting!

How it works

    1. You start (our new) Zoom app (Processing).
    2. You are prompted to observe  and listen to a password pattern presented in sound and light which makes it more accessible as it offers the same information as different sensory data. The sound is played by Arduino (Arduino).
    3. Repeat the password pattern with the Arduino buttons (Arduino).
    4. If you repeated the correct password pattern, you will now join our Zoom meeting, see yourself in your own little participant window, and receive a welcome message from us (Processing). If you entered a wrong password, you can try again.
    5. If you decide to leave the meeting, you will see a final congratulation notes and then have the possibility to play this “musically game” to join our meeting again (Processing).

Technical Design in Arduino

Arduino circuit

Visual Design in Processing

Step 1: Open our version of Zoom and click to join our meeting.
Step 2: Observe and/or listen to the password pattern presented to you.

 

Step 3: Repeat the Password using the colored buttons on Arduino.
Step 4: Welcome! You entered the correct password and made it to our meeting. You will see yourself in your own participant window.
Step 5: You left the meeting, congrats for finding the password. Do you want to play again?

Challenges & Learning

In the initial development phase of this project, after agreeing on the details of the user’s journey and the functionality, we worked independently: Amina focused on Arduino while Susanne focused on P5.js. Then bringing both parts together seemed a bit more difficult at first glance as we had previously mainly worked with serial communication between Arduino and Processing but decided to use P5.js in this project as it would allow the live camera input of the user’s camera when joining our Zoom meeting. We shared our code and tried following online tutorials that involved downloading the App p5.serialcontrol for indirect serial communication. Susanne unnecessarily run into trouble because she downloaded the app for the wrong operation system. Moving on with the appropriate App for Apple OS, some individual and communal experimentation and debugging, our Arduino and  P5.js sketches eventually became friends 🙂 Happy that their idea came into life, Amina and Susanne could not stop playing their own game for some time… 🙂

Considerations for future Improvements

The current version of our musically Zoom game uses only one level of difficulty as we focused less on levels but more on the whole narrative of entering Zoom for the first development. Future versions could be improved by generating new, random password patterns every time the game is played. Currently, the use can enter the password pattern again after submitting a wrong password but needs to rely on memory. For a future version, we could possibly present the password pattern again after faulty user input to assist their success.

For now we are happy to present our concept in a working game but are always happy to hear your feedback for future version!

You want to play, too?

In order to play our game follow these simple steps:

    1. Download the P5.serialcontrol application appropriate for your operating system.
    2. Download our Arduino code. Make sure to create a pitches.h tab.
    3. Open our P5.js code in your browser.
    4. Rebuild our circuit based on the image in this post and the Arduino sketch.
    5. Run the Arduino sketch.
    6. Choose your appropriate port in the P5.serialcontrol app.
    7. Run the P5.js sketch in your browser.
    8. Try your best 😉
    9. … Smile, you are on camera! (if you entered the correct password)

Week 12: Ryan’s Final Project Progress Report

Current Progress

For now, I’ve managed to figure out the majority of the code for everything, such as the movement of the bird controlled by the photoresistor values as well as controlled by the microphone, the movement of the viruses, the collision detection code, the switching of game states when the user presses start or when the user wins or loses, etc.

Challenges From Before 

Before, I struggled with trying to make my microphone as my input where its values determined from the amplitude values will correspond to the up and down movement of the bird. I wasn’t able to figure out why I couldn’t make the bird move no matter how loud I screamed into it (quite embarrassing). However, after talking to Jack, I’ve managed to resolve the issue and now I am able to control the bird’s up and down movement via the microphone.

New Challenges/Problems

Some of the problems that I’m encountering right now would include trying to configure the collision detection code to make it detect collision more accurately around the images as I’ve noticed that sometimes when the bird only grazes the virus, it does not detect a collision. It does detect only when the center of the bird collides with the center of the viruses.

Another problem right now is how I am able to incorporate the two types of input (photoresistor and microphone) to control the bird within the same game. This is a problem because I’m afraid that if I added the microphone input code into the serial event code for my photoresistor values, it might mess up the entire code. So, right now, I’m kind of struggling to find a solution where I can allow the user to choose to use which type of mode to play in, whether by the photoresistor or by the microphone.

Possible Additions 

A few extra ideas that I’ve thought of adding to my game could be applied to both the bird and the viruses.

One idea that I’ve came up with is that I could probably alter the speed of each appearing virus and set their speeds to be random so that each virus will be moving in different speeds to raise the difficulty.

Another idea that I’ve had is where every time the viruses pass the left side of the screen, I could add a score board which will add a score to it every time the virus touches the left side of the screen. After the game ends, it can display the score of the user to compare with other players. However, if I used this idea, I wouldn’t need a timer because then the objective is to now avoid as many as the user can instead of trying to survive and not touch the viruses within the limited time. But, it’s just an idea for me to think about and to work on if I have time.

Brief Demonstration 

Photoresistor Mode 

Microphone Mode 

Week 12: Amina & Susanne Update

This week, Amina and Susanne worked independently on the physical and visual sides of their project. Amina built the Arduino circuit while Susanne created the visuals in P5.js. The main challenge for Amina working on getting input from Arduino in the form of entering a password was how to send the input to Processing (used for prototyping purposes before connecting to P5.js) without breaking. Susanne’s main challenge was to arrange video input in P5.js as x and y coordinates behaved unexpectedly.

Now, we need to debug the Arduino side of our project possibly sending multiple input at once and figure out the serial communication between Arduino and P5.js which needs another ‘communicator’ in between as we cannot send directly to the web.

After the independent work stretch, we now shared our code to debug together, looking at previous examples and seeking support from Aaron and the Internet.

Finals Update – Nathan

Arduino Board

Currently, I have wired up the Arduino with everything I want to include in my final. It includes:

  • An ultrasonic distance sensor
  • A piezo
  • A photoresistor
  • A button
  • A knob (potentiometer)

Here is a picture of the layout:

Code

For code, I currently have coded in the conditions for when the piezo is making sounds, as well as how its sound is being made. I also have the distance sensor and photoresistor coded in as functions, but I have not fully integrated them with the system in general.

I haven’t gotten to the processing side of the code yet, but I am planning to make several boolean values on the Arduino side to represent the signals being sent to processing. For example, if there is a friendly ghost, I will simply send the boolean to processing. I think this approach simplifies communication between the platforms. In my opinion, the more complicated alternative would be to send the raw values of the sensors and buttons on the Arduino to processing.

Here is the code I have now:

#include "pitches.h"

int piezo = 2;
bool piezoState = false;
int trig = 3;
int echo = 4;
int button = 5;
int buttonState = 0;
int prevButton = 0;
//photoresistor A0;
//knob = A1;
long timer;
int timerlength = 200;

void setup() {
  Serial.begin (9600);
  timer = millis() + timerlength;
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  pinMode(button, INPUT);
}

void loop() {
  
//  int knobValue = analogRead(A1);
////  Serial.println(knobValue);

  buttonState = digitalRead(button);
  Piezo();
}

void Piezo() {
  if (piezoState == false){
    if (millis() > timer){
      tone(piezo, C5);
      timer = millis() + timerlength;
    }
    else if (millis() == timer){
      noTone(piezo);
    }
  }
  
  if (buttonState == HIGH && prevButton == LOW){
    piezoState = true;
  }

  if (piezoState == true){
    noTone(piezo);
  }

  prevButton = buttonState;
}

void Brightness(){
  int brightness;
  brightness = analogRead(A0);

  return brightness;
}

void Distance() {
  int time;
  int distance;
  
  digitalWrite(trig, HIGH);
  delay(0.01);
  digitalWrite(trig, LOW);
    
  time = pulseIn(echo, HIGH);
    
//  speed of sound = 343 m/s = 0.0343 cm/µs
//  distance = time * speed
  distance = time * 0.0343 / 2;
  Serial.print(distance);
  Serial.println(" cm");

  return distance;
}

 

[UPDATED] Refined Final Project Idea + Progress

Last time I spoke in class, I was very much set on the idea of making a “big brother” surveillance camera. BUT, I realized that I would require a few equipments that are not in our sparkfun arduino kit. These equipments included a set of female jump wires, a separate breadboard(?) that can be attached to the servo, and another type of converter looking wire that I forgot the name of. Due to these technical difficulties, I thought my surveillance camera would become boring to the audience and so I decided to switch to a different idea.

Therefore, I resorted to my initial idea, which was to make a “spacewar” game. It is a game in which a spaceship (player) defends objects falling towards the earth from the outer-space. This has always been one of my favorite games since childhood and I loved the idea that I could realize it on my own.

Space War X on the App Store

I am currently in the process of developing the processing part first. I will get to the arduino once I have a working version on my computer. The arduino part will be incorporated with a push buttons to shoot shrapnels/bullets, another push button to accelerate, and a potentiometer to maneuver left and right directions.

I have accomplished my first milestone which is to have the starship maneuver and shoot bullets. I am not entirely sure if I am satisfied with the sprite that I am using, so this is subject to change. Below I have attached the video of the working version of my first milestone and the codes.

/*
David Lee
Main Code - version w/o arduino
*/

ArrayList <Bullet> bullets; 
Player player; 
PImage starship;

boolean [] keys = new boolean[128];


void setup(){
  size(480, 640);
  bullets = new ArrayList();
  player = new Player();
  starship = loadImage("starship6.png");
}

void draw() {
  background(0);
  for(Bullet temp : bullets){
    temp.move();
  }
  for(Bullet temp : bullets){
    temp.display(); 
  }
  //removeToLimit(30);
  
  player.display();
  player.move();
}


void keyPressed(){
  keys[keyCode] = true;
  if(keys[32]){
     Bullet temp = new Bullet(player.pos.x+80, player.pos.y);
     bullets.add(temp);
  }
}

void keyReleased(){
  keys[keyCode] = false;
}

void removeToLimit(int maxLength){
    while(bullets.size() > maxLength){
       bullets.remove(0); 
    }
  }
//Bullet Class

class Bullet{
  PVector pos;
  PVector acc;
  PVector vel;
  
  Bullet(float tx, float ty){
     pos = new PVector(tx, ty);
     acc = new PVector(0,-0.2);
     vel = new PVector(0, -2.5);
  }
  
  void display(){
     stroke(255);
     //point(x, y);
     rect(pos.x, pos.y, 3, 10);
  }
  
  void move(){
    vel.add(acc);
    pos.add(vel);
     //pos.y -= 2.5;
    
  }
}
//Player Class

class Player{
  PVector pos;
  PVector acc;
  PVector vel;
  
  Player(){
    pos = new PVector(width/2, height - 100);
    acc = new PVector(0.0, 0);
    vel = new PVector(4,4);
  }
  
  void display(){
    image(starship, pos.x, pos.y); 
  }
  
  
  void move(){
    vel = vel.add(acc);
    if(keys[LEFT])
      pos.x -= vel.x;
    if(keys[RIGHT])
      pos.x += vel.x;
    if(keys[UP])
      pos.y -= vel.y;
    if(keys[DOWN])
      pos.y += vel.y;
      
    if(pos.x < -50){
      pos.x = width; 
    }
    if(pos.x > width){
      pos.x = -50;  
    }
    if(pos.y > height){
      pos.y = -59; 
    }
    if(pos.y < -59){
      pos.y = height; 
    }
  }
}

 

Final Project Progress

For the final project, I intend to have FRIENDS theme song play as you start the program on loop, and the potentiometer knob acts like a volume knob so the player can change it whenever they want to. There will be six buttons and they will be used to choose answers A, B, C, D, E, or F. The colors of the buttons will match those in the logo of FRIENDS and in the same order (but I might use white instead of yellow). Instructions will display at the beginning, telling the player the knob decreases volume and that each button corresponds to which answer on screen.  The yellow bulb lights up as soon as the game starts, and for 1 second as the player clicks and answer, the blue bulb blinks. Questions will generally become harder (it’s harder for the player to match each answer with a character). When all of the trivia is done, green bulb lights and yellow and blue are dim. The screen will show a picture of the character you are most similar to, and a description based on the answers. There will be a clickable button where if clicked plays a famous catchphrase of that character. Another button will be to restart the trivia questions.

I will use example 6 from the files that Aaron uploaded as a reference for my work.

The questions I have so far:

  1. How do you feel about animals?
    1. Love them! We shouldn’t eat them…
    2. They’re fine.
    3. Monkeys are my favorite animals.
    4. I don’t really like dogs
    5. They taste gooood!
    6. Cats with no hair are cool.
  2. What do you consider to be your best quality?
    1. Your looks
    2. Your intelligence
    3. Your cleanliness
    4. Your sense of humour
    5. Your good taste
    6. Your laid-back approach to life
  3. What is your dream job:
    1. Singer
    2. Professor
    3. Fashion consultant
    4. Actor
    5. Advertising executive
    6. Caterer
  4. What do you consider to be your worst quality?
    1. Clumsiness
    2. Arrogance
    3. Competitiveness
    4. Selfishness
    5. Insecurity
    6. Delusional
  5. You value friendship because…
    1. Friends are not afraid to tell me when I’m wrong
    2. Friends make the best lovers
    3. Friends are the only family I have
    4. Friends are what makes me popular
    5. Friends tolerate my awkwardness
    6. Friends introduce me to all their hot friends

https://www.beano.com/posts/which-friends-character-are-you

https://www.radiox.co.uk/games-quizzes/which-friends-character-are-you/

https://heywise.com/quiz/which-friends-character-are-you/3/

https://www.zimbio.com/quiz/O6sFuc_NvOh/Friends+Character