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));
    }
  }
}

 

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 

Final Project Idea

For my Final Project, I have managed to narrow it down to a single idea as explained below.

MAIN IDEA #1

For this, I wanted to recreate the Flappy Bird game but make it a Covid 19 edition, where the user will be able to control the bird’s up & down movement with a photoresistor or distance sensor and to control its left & right movement with a switch or potentiometer.

another possible idea…if i have enough time of course…

I wanted to also introduce another type of input instead of using the photoresistor only, which would be a microphone. So, instead of being able to control the up and down movement with only your hand, it would move the bird’s location base on the user’s amplitude value within the volume, or how loud they scream.

Objective of the Game

The goal of the game would be to avoid the incoming Covid viruses that will be constantly appearing from the right side of the screen and disappearing off the left side of the screen. If the user touches any of the Covid viruses, he or she loses.

Another idea…

I also wanted to introduce more elements such as live counts, where the player will have a total of 3 total lives or something. Another idea would also probably involve different levels??

Mini Sketch

 

Week 10: Mini Game for Arduino & Processing Serial Communication

IDEA 

For this week’s assignment, I could not really think of another creative or original game so I just decided to create a simpler version of the game that I had created for my Midterm project but with a little twist. That twist is that instead of controlling the user ball with only arrow keys, I made it available to control the left & right movement of the ball with a potentiometer on the Arduino along with two buttons (Red and Green buttons) that controls the up and down movement of the user ball, Red being up and Green being down.

Challenges/Difficulties

There was not as much difficulties faced throughout the process of making it, but I would say that the most difficult part I encountered was understanding the relationship between Arduino and Processing as I was not able to fully grasp all of the information from our last lab session. However, after talking with Professor Aaron, I was able to get a clearer idea of serial communication.

Setup

Final Demonstration 

Arduino Code

const int greenSwitch = 3;
const int redSwitch = 4;

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

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

Processing Code 

import processing.serial.*;
Serial myPort;
int xPos=0;
Balls [] balls;
//Timer timer;
userBall myBall;
int numberofballs = 15;
int amountcollided;
void setup() {
  size(1280, 960);
  //printing out all the available ports
  printArray(Serial.list());
  //make the chosen port from the list as a string or a name 
  String portname=Serial.list()[4];
  /*initializes the class "Serial"
   the 9600 is the baud (kinda the rate that bytes are being uploaded or transferred
   */
  myPort = new Serial(this, portname, 9600);
  //timer = new Timer();
  myBall = new userBall();
  balls = new Balls [numberofballs];
  for (int i=0; i<balls.length; i++) {
    balls[i] = new Balls();
  }
}
void draw() {
  background(255);
  //fill(0);
  //ellipse(xPos, height/2, 50, 50);
  for (int i=0; i<balls.length; i++) {
    balls[i].drawBalls();
  }
  myBall.drawuserBall();
  myBall.checkEdge();
  collisionDetection();
  //timer.showTimer();
}

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) {
      //potentiometer value
      myBall.xPos=values[0];
      //sthis is values for greenswitch 
      if (values[1] ==1) {
        myBall.yPos +=3;
      }
      //this is values for redswitch
      if (values[2] == 1) {
        myBall.yPos -=3;
      }
      myBall.xPos = int (map(myBall.xPos, 0, 1023, 0, width));
    }
  }
  //println(xPos);
  myPort.write('0');
}

void collisionDetection() {
  amountcollided = 0;
  for (int i=0; i<balls.length; i++) {
    //if the x and y location distance of any NPC ball and user ball added together is smaller than the radius of the NPC ball and user ball, then it means it has collided
    if (dist(balls[i].locx, balls[i].locy, myBall.xPos, myBall.yPos)< balls[i].radius + myBall.radius) {
      //println(dist(balls[i].locx, balls[i].locy, myBall.locx, myBall.locy));
      //balls[i].iscollided=true; //if it collides, changes the boolean to true, changing the image
      //if (balls[i].iscollided == true) {
      //  amountcollided +=1;
        stroke(255);
        fill(139,0,139);
        ellipse(balls[i].locx, balls[i].locy, balls[i].ballwidth, balls[i].ballheight);
      //}
    }
  }
}
class Balls {
  float locx, locy;
  float ballwidth, ballheight;
  int radius=25;
  boolean iscollided=false;

  Balls() {
    locx=random(width); //putting random will let the balls appear at different locations
    locy=random(height);
    ballwidth=2*radius;
    ballheight=2*radius;
  }
  void drawBalls() {
    stroke(166, 134, 230);
    fill(255, 0, 0);
    ellipse(locx, locy, ballwidth, ballheight);
    
  }
  void collided() {
    if (iscollided == true) {
      stroke(255);
      fill(255);
      ellipse(locx, locy, ballwidth, ballheight);
    }
  }
}
class Timer {
  float locx, locy;
  float timerwidth, timerheight;
  int countdown=20;
  int seconds; 
  float startTime;


  Timer() {// ask about the logic behind this and how to create a countdown timer? 
    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"
    } else {
      seconds = int(startTime- millis()/1000);
      fill(255, 0, 0);
      text(seconds, width/2-100, 100);
    }
  }
}
class userBall {
  float xPos, yPos;
  float ballwidth, ballheight;
  //float xspeed=5;
  //float yspeed=5;
  float radius=30;

  userBall() {//the constructor for this userBall object
    //xPos=width/2;
    xPos = 0;
    yPos=0;
    ballwidth=2*radius;
    ballheight=2*radius;
  }
  void drawuserBall() {
    fill(0);
    stroke(0, 0, 255);
    ellipse(xPos, yPos, ballwidth, ballheight);
  }
  void checkEdge() {
    if (yPos < 0) {
      yPos = height;
    }
    if (yPos >height){
      yPos = 0;
    }
  }
}

 

Intro to IM Week 9: Musical Instruments

IDEA

For this week’s instrument, I wanted to replicate one of the first musical instruments that I have ever learned: a piano. When I first learned the piano at a young age, the first few pieces of music I had learned were “Mary Had a Little Lamb” and “Twinkle Twinkle Little Stars”. Also, I added another scale to play because I remember always playing scales first as a warmup before I played any other pieces. So, I wanted to be able to replicate me playing these two pieces of music and the scale with my assignment.

MAIN DIFFICULTIES & ADJUSTMENTS

Originally,  I decided to make my button  be able to switch between the different pieces to play at a random order and to simply play the notes in each piece with the twist of the potentiometer.

However, I thought of a major problem which is that every time I press the button, there’s a possibility that it won’t switch to another piece of music to be played by landing on the same piece again due to the random factor. Therefore, I decided to make an index where whenever the button was pressed, it’ll add to the index with it being no greater than 2 (because there’s only three pieces of music in total, 0 being first, 1 being second, 2 being the third piece). By doing, this, I can guarantee that it will not repeat the same piece of music to be played but also let me be clearer upon what I’m going to be playing.

Another major problem I encountered was that I was unable to hear repeated notes from the piazo disk clearly most likely because the loop  was causing it to be played too fast for me to clearly hear that it was two notes.

Mary Had A Little LambTwinkle Twinkle Little Star

To resolve this problem, I added another button to help create the repeated notes by making it play when pressed and not when not pressed.

SETUP

CODE 

int prevButtonState = LOW;
int randomNum;

#include "pitches.h"
// tere are 3 different sets of arrays consisting of 10 different notes
int notesIndex = 0;
int notes[3][10] = { {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_D5, NOTE_E5}, {NOTE_E4, NOTE_D4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_D4, NOTE_E4, NOTE_G4 }, {NOTE_C4,NOTE_G4,NOTE_A4, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_D4, NOTE_C4 }};
const int button = 5;
const int button2 =  3;
const int speaker = 4;
const int durations[10];



void setup() {
  Serial.begin(9600);
}

void loop() {
  buttonpress();
  if ( digitalRead(button2) == HIGH) {
    knobturn();
  }else{
    noTone(speaker);
  }
}

void buttonpress() { // whenever the button's pressed, it switches to a different array of notes
  int currentbuttonstate = digitalRead(button);
  if (currentbuttonstate == HIGH && prevButtonState == LOW) {
    if ( notesIndex < 2) { // if notes index is less than 2
      notesIndex++;
    } else {
      notesIndex = 0; //go back to first array of notes
    }
    //    randomNum = random(1, 4); //pick a random number between 1-3, 1 for an array of notes, 2 for another array, 3 for another array
    Serial.println(notesIndex);
  }
  prevButtonState = currentbuttonstate;
}



void knobturn() {
  int knob = analogRead(A0);
  Serial.println(knob);
  //  tone(4, notes[val]);
  //  int rate = 1000 / durations[whichNote];

  //change the values of the knob to 0 to 9, corresponding to the number of notes in the array
  if (notesIndex == 0) {
    knob = map(knob, 0, 1023, 0, 9);
    tone(speaker, notes[0][knob]);
  }
  // if random number is 2, play the notes 2 array of notes according to the knob
  if (notesIndex == 1) {
    knob = map(knob, 0, 1023, 0, 8);
    tone(speaker, notes[1][knob]);
  }

  if (notesIndex == 2) {
    knob = map(knob, 0, 1023, 0, 8);
    tone(speaker, notes[2][knob]);
  }
}

/*************************************************
 
 * Public Constants
 
 *************************************************/
 
#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978

FINAL PRODUCT  (how do I include the youtube video?)

https://youtu.be/9z_CXOcHvvM

Week 8 Assignment: Analog Input and output, Mapping, data types, printing

INITIAL IDEA #1

For this week’s assignment, I originally thought of an idea where I would have different rows of LED lights on the breadboard along with a switch and a knob on a different row.

Whenever the switch is pressed, it will generate a random set of pattern or sequence that will light up different LED lights that will also be blinking on the breadboard. On the other hand, the knob will be able to control the blinking speed of those LED lights that are lit up.

IDEA #1.1

However, after thinking about the level of difficulty to make a total of 9 LED lights to light up in different patterns, I decided to decrease the amount of lights to just three. Also, I had changed my idea to not make the lights blink and to make 3 other LED lights to be controlled by the knob separately from the switch.

Initial Ideas for Setup
The LED Light patternsFinal Setup

Main Difficulties 

One of the major difficulties regarding the programming process for switching of LED light patterns was whenever I clicked the button, it does not switch to any of the other designated LED pattern. But, after a bit of debugging, I realized that I have to manually turn off all the LED lights everytime  the button starts to press and randomly generate a LED light pattern again.

One of the major difficulties regarding the programming behind making the LED lights dim or become brighter based on the knob is figuring out the entire logic behind it. I had to consult from Aaron regarding this problem and we had to search for an entire bell curve equation first, and figure out how to convert that into Arduino.

FINAL PRODUCT 

 

Interesting Thing…

I just found out that if I comment out one of my functions, the knobturn function, and leave the LEDfade 1,2,and 3 in the loop, it creates another amazing effect as originally in the knobturn function, I assigned every LED light with the brightness integer. However, I assigned it separately for each LED light (LEDfade1, LEDfade2, LEDfade3), therefore creating a fade effect.

MY CODE 

const int button = 2;

//digital LED lights
const int RedLed = 4;
const int YellowLed = 7;
const int BlueLed = 8;

//analog LED lights
const int RedLed1 = 3;
const int YellowLed1 = 5;
const int BlueLed1 = 6;

int RedLedState = LOW;
int YellowLedState = LOW;
int BlueLedState = LOW;

const int knob = A0;

int prevButtonState = LOW;
int randomNum;

//change spread to make bell curve wider or narrower
int spread = 60;

// set the postion to start above the screen so the first circle is dark
int bellCurveCenter = -spread;
//rewrite the array form in arduino
int ledPos [] = {
  160, 320, 480
};
int ledPosCount = 3; // the number of pins (i.e. the length of the array)
int ledIndex [] = {3, 5, 6};

void setup() {
  // put your setup code here, to run once:
  pinMode(button, INPUT);
  pinMode(knob, INPUT);

  pinMode(RedLed, OUTPUT);
  pinMode(YellowLed, OUTPUT);
  pinMode(BlueLed, OUTPUT);

  ////  ledPos = new int[3];
  //  // three different heights to put three different circle on screen
  //  ledPins[0] = 640/4;
  //  ledPins[1] = 640/2;
  //  ledPins[2] = 640 - 640/4;

  Serial.begin(9600);
}
//light up all three lights altogether first
//Each time the button's pressed, choose a random number (1-4)
//Light up the pattern that the chosen number corresponds to:
// If the number is 1, light up Green and Yellow
// If the number is 2, light up Green and Blue
// If the number is 3, light up Blue and Yellow
// If the number is 4, light up Green and Yellow and Blue
void loop() {
  buttonpress();
  LEDpattern();
  knobturn();
  LEDfade1();
  LEDfade2();
  LEDfade3();
}



void buttonpress() {

  int currentbuttonstate = digitalRead(button); //read current state of button
  if (currentbuttonstate == HIGH && prevButtonState == LOW) {
    randomNum = random(1, 5); //pick random number between 1 to 4
    Serial.println(randomNum);
  }
  prevButtonState = currentbuttonstate;
}

void LEDpattern() {
  //turn all LED lights offf irst
  digitalWrite(RedLed, LOW);
  digitalWrite(YellowLed, LOW);
  digitalWrite(BlueLed, LOW);

  if (randomNum == 1) {
    digitalWrite(RedLed, HIGH);
    digitalWrite(YellowLed, HIGH);
  }
  if (randomNum == 2) {
    digitalWrite(RedLed, HIGH);
    digitalWrite(BlueLed, HIGH);
  }
  if (randomNum == 3) {
    digitalWrite(YellowLed, HIGH);
    digitalWrite(BlueLed, HIGH);
  }
  if (randomNum == 4) {
    digitalWrite(RedLed, HIGH);
    digitalWrite(YellowLed, HIGH);
    digitalWrite(BlueLed, HIGH);
  }
}

void knobturn() {
  for (int thisPin = 3; thisPin < 7; thisPin++) {
    //taking the position of the circle and finding the distance of each LED from the center of our bell curve
    float distance = abs(ledPos[thisPin] - bellCurveCenter);
    // this is the formula for the bell curve, multiply by 255 to put in the proper range for brightness
    float brightness = exp(-0.5 * pow(distance / spread, 2.)) * 255;
    analogWrite(ledIndex[0], brightness);
    analogWrite(ledIndex[1], brightness);
    analogWrite(ledIndex[2], brightness);
  }
}

void LEDfade1() {
  int knobvalue = analogRead(knob);
  Serial.print(knobvalue);

  //might need to add an int before map, but test it out first
  bellCurveCenter = map(knobvalue, 0, 1023, -200, 640 + spread);

  //  for (int thisPin = 3; thisPin < 7; thisPin++) {
  //taking the position of the circle and finding the distance of each LED from the center of our bell curve
  float distance = abs(ledPos[0] - bellCurveCenter);
  // this is the formula for the bell curve, multiply by 255 to put in the proper range for brightness
  float brightness = exp(-0.5 * pow(distance / spread, 2.)) * 255;
  analogWrite(RedLed1, brightness);
}

void LEDfade2() {
  int knobvalue = analogRead(knob);
  Serial.print(knobvalue);

  //might need to add an int before map, but test it out first
  bellCurveCenter = map(knobvalue, 0, 1023, -200, 640 + spread);
  float distance = abs(ledPos[1] - bellCurveCenter);
  float brightness = exp(-0.5 * pow(distance / spread, 2.)) * 255;
  analogWrite(YellowLed1, brightness);
}

void LEDfade3() {
  int knobvalue = analogRead(knob);
  Serial.print(knobvalue);

  //might need to add an int before map, but test it out first
  bellCurveCenter = map(knobvalue, 0, 1023, -200, 640 + spread);
  float distance = abs(ledPos[2] - bellCurveCenter);
  float brightness = exp(-0.5 * pow(distance / spread, 2.)) * 255;
  analogWrite(BlueLed1, brightness);
}


 

Week 7: Reaction Game with LED Lights and Buttons

 

MAIN IDEA OF GAME

For this week’s assignment, I decided to create a small reaction game where the user will have to press the button corresponding to the color of the LED light that will be lightened up in a random order within a small interval, which is 3 seconds. When the right button is pressed, it will turn off that LED light and another one will light up again. 
Sketch of original idea

SETTING IT UP

When it came to setting up the hardware part on the breadboard and microcontroller, surprisingly I did not encounter any difficulties as my setup was overall not that complex or confusing.  However,  it  is  after a couple days that I realized I had misplaced one of my pins for the red button one row lower than it should be and this caused me to spend hours figuring out why that one button wouldn’t work.

Also, as seen in the first picture above of my original idea, I originally wanted to place the buttons that are the same color as the LED lights in the same row. But later, I decided it would be more interesting and kind of more difficult for the user if the buttons were not in the same row as the LED lights that were the same color.


CODING 

This was where I had the most difficulties in mainly because I was not able to code in this new environment aside from Processing, as we’ve been coding on that for so long now.

Coding for randomly lighting up LED lights

For this section of code for the LED lights to light up randomly, I struggled with it originally as I just simply just told it to choose a random number and turn on that random number in correspondence to the LED light, have a little delay, then light up another random one. But, later, I realized that there was so much more needed in it for it to work, such as the fact that during the delay, it won’t do anything so that means that my buttons will not be able to work, therefore I could not use the delay function.

Luckily, I found the “Blink without Delay” example in Arduino and I incorporated that into my own code while configuring it to include the random element.

Coding for Button Press

When coding for the buttons to turn off the corresponding LED lights, I had the most difficulty in understanding the concept about previous and current button states, where after the button is pressed and released in the current frame, I have to set LOW to the previous button state so that the next time it can fit the condition to be a new button press again. (Not sure if I explained it clearly, but that’s the gist.)

My Code

const int GreenLed = 2;
const int RedLed = 3;
const int YellowLed = 4;

int GreenLedState = LOW;
int RedLedState = LOW;
int YellowLedState = LOW;

const int Redbutton = 10;
const int Yellowbutton = 9;
const int Greenbutton = 8;

int prevGreenButtonState = LOW;
int prevRedButtonState = LOW;
int prevYellowButtonState = LOW;

int randomNum; //pick random light to turn on (from pin 2 to pin 4)

unsigned long previousMillis = 0; // will store last time LED was updated

const long interval = 3000; //interval at which to blink (milliseconds)

void setup() {
  // setup all LED pins as outputs
  for (int i = 2; i < 5; i++) {
    pinMode(i, OUTPUT);
  }

  Serial.begin(9600);
  Serial.println(randomNum);

  //setup all button pins as inputs
  for (int i = 8; i < 11; i++) {
    pinMode(i, INPUT);
  }

}
void loop() {
  LEDLightSequence();
  Greenbuttonpress();
  Redbuttonpress();
  Yellowbuttonpress();
}

void LEDLightSequence() {//code to light up random LED light
  randomNum = random(2, 5);//pick random light to turn on (from pin 2 to pin 4)
  Serial.println(randomNum);
  unsigned long currentMillis = millis();
  // check to see if it's time to blink the LED; that is,
  //save the last time you blinked the LED

  //if the difference between the current time and last time you blinked the LED is bigger than
  //the interval at which you want to blink the LED.
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    //if the LED is off turn it on and vice versa
    if (randomNum == GreenLed && GreenLedState == LOW) {
      GreenLedState = HIGH;
    } else {
      GreenLedState = LOW;
    }
    // set the LED with the ledState of the variable:
    digitalWrite(GreenLed, GreenLedState);

    if (randomNum == RedLed && RedLedState == LOW) {
      RedLedState = HIGH;
    } else {
      RedLedState = LOW;
    }
    digitalWrite(RedLed, RedLedState);

    if (randomNum == YellowLed && YellowLedState == LOW) {
      YellowLedState = HIGH;
    } else {
      YellowLedState = LOW;
    }
    digitalWrite(YellowLed, YellowLedState);
  }
}

void Greenbuttonpress() {
  int currentGreenbutton = digitalRead(Greenbutton); // check if green button is pressed
  if (currentGreenbutton == HIGH && prevGreenButtonState == LOW) { //if the randm number chosen is 2, the Green LED light is lit and the greenbutton was pressed, turn off the green led light
    if (GreenLedState == HIGH) {
      GreenLedState = LOW;
    }
  }

  digitalWrite(GreenLed, GreenLedState);
  prevGreenButtonState = currentGreenbutton;
}

void Redbuttonpress() {
  int currentRedButton = digitalRead(Redbutton); // check if green button is pressed
  if (currentRedButton == HIGH && prevRedButtonState == LOW) { //if current red button is pressed and the previous red button in the last frame wasn't pressed (wasn't pressed before)
    if (RedLedState == HIGH) { //if the red led light is on
      RedLedState = LOW; //turn the red led light off
    }
  }
  digitalWrite(RedLed, RedLedState);
  prevRedButtonState = currentRedButton; //after button is pressed (HIGH) and released (LOW) in current frame, set LOW to prevButtonstate so next time it can be newly pressed again
}

void Yellowbuttonpress() {
  int currentYellowButton = digitalRead(Yellowbutton); // check if green button is pressed
  if (currentYellowButton == HIGH && prevYellowButtonState == LOW) { //if current red button is pressed and the previous red button in the last frame wasn't pressed (wasn't pressed before)
    if (YellowLedState == HIGH) { //if the red led light is on
      YellowLedState = LOW; //turn the red led light off
    }
  }
  digitalWrite(YellowLed, YellowLedState);
  prevYellowButtonState = currentYellowButton; //after button is pressed (HIGH) and released (LOW) in current frame, set LOW to prevButtonstate so next time it can be newly pressed again
}

 

FINAL PRODUCT

Ryan’s Midterm Project

Initial Stage

When I first started thinking about ideas for my Midterm Project, I simply thought of just finishing one of my unfinished Brick Breaker games. However, we were reminded that it should be original, so this first idea was out of the window.

Afterwards, I tried to think of an original and creative idea of mine like the other people by trying to get some inspiration from other games that are currently out there. However, still, nothing came into my mind. So, I decided to at least think of  a theme for my game first, and I managed to settle on the theme of the situation that we are all in together, which is covid 19.  I thought this was a pretty good theme to work with because I was hoping to make a game that can reflect the situation that we’re all in and at the same time raise people’s awareness of this global epidemic. At first, I wrote down a list of ideas that was covid themed while trying to see if it can be applied with the similar mechanics of other games.

However, I wanted to find a way to make this game a bit more casual or comical to alleviate the tension around our world that is caused by this whole epidemic. Coincidentally, the news about Donald Trump getting Covid was released and I thought that it was a perfect opportunity to incorporate him into my game by having the users be able to control him and make him wear a face mask. I also saw this chance to make my game act as a reminder for the public to always to wear a face mask, or else you will “lose” to Covid.

After deciding on my main idea that I’m going to work with, I proceeded to brainstorm on how I could make this a game. After a while, I decided on a game where the user will control a ball, and the main objective of the user is to try to touch and tag all of the other balls that are originally images of Donald Trump not wearing a face mask and change them into images of Donald Trump wearing a face mask by touching all of them within a time limit of 30 seconds.

Sketches of game layout and examples

(these are pictures of my notes and sketches for my game’s layout)

Images Used 

For my images, I simply just searched different png images of Donald Trump online (not that hard to find). But I had to manually crop out some of the background of the second image and convert it to a png file.

Donald Trump just being Donald Trump
Donald Trump wearing a face mask image

Background music 

Link: https://www.youtube.com/watch?v=xy_NKN75Jhw&list=PLya__OBTLMkONuQDu0kHDCrml2xuEINSi&index=1

Main Difficulties

Some of the major difficulties that I had encountered throughout this entire process range from simply just importing an image or sound file to coding for collision detection between the objects, changing of images upon contact, starting the game when the mouse is clicked within a certain shape, telling the game to stop after the timer ends or ending it before the timer when the user has successfully tagged all of the shapes, and many many more.

However, after talking to both Aaron and Jack , I was finally able to resolve a lot of the different problems that I had experienced (too much to even list them all out). But, at the same time, I have also learned a lot throughout this experience about how to code more efficiently or how to streamline a specific function to another if something is pressed or triggered, and all those stuff.

Zip File

IM_Midterm_Project_2

All the code 

import processing.sound.*;

Balls [] balls;//the [] brackets indicate an array; it contains a whole list of NPC balls
userBall myBall;// this calls forward the User Ball class in the name of "myBall"
Timer timer;
PImage Ballsimg;
PImage collidedBallImg;
boolean buttonPressed;
int buttonX, buttonY, buttonW, buttonH;
int amountcollided;//the amount of times that the balls have collided
String S= "You Win! \n Press the mouse to restart";
SoundFile backgroundmusic;
int gameState;
int numberofballs=10;

void setup() {
  size(1280, 800);
  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;
  Ballsimg= loadImage("Donald Trump Face.png");
  collidedBallImg= loadImage("Donald Trump wearing Facemask.png");
  balls= new Balls [numberofballs];// this allows it to contain 10 of the NPC Balls; this calls the constructor 
  for (int i=0; i<balls.length; i++) {// as long as i is less than 10, it's going to keep on calling on the "Balls" constructor, basically creating new balls 
    balls[i]= new Balls(Ballsimg, collidedBallImg);
  }
  backgroundmusic= new SoundFile(this, "Instruction BG Music.mp3");
  myBall= new userBall();//calls on the userBall constructor to create the user Ball in the name of "myBall"
}

void draw() {
  background(255);
  //code for instructions and start button
  if (gameState==0) { //if the Start button is pressed, run the game code 
    //timer.showTimer();//shows the timer on screen
    fill(random(144), random(230), random(166));
    String Instructions= "Instructions: \n Use the arrow keys on your keyboard to control and move the ball around the screen. \n The objective of the game is to make all the other Donald Trump balls wear his mask properly, \n and you will do that by tagging or touching all of them within the time limit of 30 seconds. \n You win if you manage to make all the Donald Trump balls wear a mask. \n You lose if there are still remainig Donald Trump balls not wearing a mask when the time ends."; 
    textAlign(CENTER);
    textSize(20);
    text(Instructions, width/2, height/2-200);
    fill(random(255), random(255), random(255));
    rect(buttonX, buttonY+200, buttonW+65, buttonH);
    fill(255, 0, 0);
    textSize(50);
    text("PRESS TO START", buttonX+200, buttonY+200+buttonH-10);
  } else if (gameState==1) {//the gameplay screen with game code
    for (int i=0; i<balls.length; i++) {
      balls[i].drawBalls();//allows all the NPC balls to be drawn on the window
      balls[i].moveBalls();//allows all the NPC balls to move around the window
      balls[i].Ballscheckedge();//allows all the NPC balls to bounce of the edges of the window
    }
    collisiondetection();
    myBall.drawuserBall();
    timer.showTimer();//shows the timer on screen
  } else if (gameState==2) {//win
    //numberofballs+=1;
    background(0);
    fill(random(255), random(255), random(255));
    textAlign(CENTER);
    textSize(80);
    text(S, width/2, height/2);
    if (mousePressed) {
      reset();
    }
  } else if (gameState==3) {//lose
    String G="Time's Up! 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) {
      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;
    backgroundmusic.play();
    timer= new Timer();
  }
}
//code to control the user's ball
void keyPressed() { //code for controlling the user's Ball by arrow keys
  if (keyCode== UP && myBall.locy-myBall.radius >=0) myBall.locy-=25;//if the y location of the user's Ball minus the radius of the ellipse is greater or equal to 0, it will move upwards
  else if (keyCode== DOWN && myBall.locy+myBall.radius <=height) myBall.locy+=25;
  else if (keyCode == LEFT && myBall.locx-myBall.radius>=0) myBall.locx-=25;
  else if (keyCode == RIGHT && myBall.locx+myBall.radius<= width) myBall.locx+=25;
}

void collisiondetection() {
  amountcollided=0;
  //putting in aloop for all of the NPC balls 
  for (int i=0; i<balls.length; i++) {
    //if the x and y location distance of any NPC ball and user ball added together is smaller than the radius of the NPC ball and user ball, then it means it has collided
    if (dist(balls[i].locx, balls[i].locy, myBall.locx, myBall.locy)< balls[i].radius + myBall.radius) {
      //println(dist(balls[i].locx, balls[i].locy, myBall.locx, myBall.locy));
      balls[i].iscollided=true; //if it collides, changes the boolean to true, changing the image
    }
    //each time it collides, the boolean is true, making the amountcollided to increment by 1
    if (balls[i].iscollided==true) {
      amountcollided+=1;
    }
  }
  println(amountcollided);
  //the the amount of collisions added up before the timer ends is greater or equal to 20
  if (amountcollided >=balls.length) {//if greater than the amount of balls in the game
    backgroundmusic.stop();
    gameState=2;
  }
}



//this is the state or the code from setup basically in order for the game to be restarted 
void reset() {
  //Assume the start button has not been pressed
  //buttonPressed = false;
  gameState=0;

  //Parameters for the start button 
  buttonW=335;
  buttonH=100;
  textSize(buttonH);
  buttonX=(width-buttonW)/2;
  buttonY=(height-buttonH)/2;
  Ballsimg= loadImage("Donald Trump Face.png");
  collidedBallImg= loadImage("Donald Trump wearing Facemask.png");
  balls= new Balls [numberofballs];// this allows it to contain 10 of the NPC Balls; this calls the constructor 
  for (int i=0; i<balls.length; i++) {// as long as i is less than 10, it's going to keep on calling on the "Balls" constructor, basically creating new balls 
    balls[i]= new Balls(Ballsimg, collidedBallImg);
  }
  backgroundmusic= new SoundFile(this, "Instruction BG Music.mp3");
  myBall= new userBall();//calls on the userBall constructor to create the user Ball in the name of "myBall"
}
class Balls {
  //basic information for building a bouncing ball
  float locx, locy;
  float ballwidth, ballheight;
  //these are the speed for all the balls; make it random to have different speed for each of them
  float xspeed=random(10);
  float yspeed=random(10);
  int radius=25;
  PImage Ballsimg;
  PImage collidedBallImg;
  boolean iscollided=false;
  

  Balls(PImage _img,PImage _collidedBallImg) {// this is my constructor or a setup function for my "Ball" object
   
    locx=random(width); //putting random will let the balls appear at different locations
    locy=random(height);
    ballwidth=2*radius;
    ballheight=2*radius;
    Ballsimg= _img;// this is inserting the image file loaded previously to every array of the NPC bouncing balls
    collidedBallImg= _collidedBallImg;// the donald trump w/ facemask image inserted for every array of NPC
}
  void drawBalls() {
    stroke(255,0,0);
    //ellipse(locx, locy, ballwidth, ballheight);
    imageMode(CENTER);
    if( iscollided==true){// if collided, it'll show this new collided image
      image(collidedBallImg, locx, locy, ballwidth+30, ballheight+20);
    }else{ //if not collided, it'll show this original image 
    image(Ballsimg, locx, locy, ballwidth+30, ballheight+20);
    }
  }
  void moveBalls() {//causes the NPC Balls to move around 
    locx+=xspeed;
    locy+=yspeed;
  }
  void Ballscheckedge() {//allows the Balls to bounce off the edges
    if (locx+radius >=width || locx+radius<=0) {
      xspeed*=-1;
    }
    if (locy+radius >=height || locy+radius<=0) {
      yspeed *=-1;
    }
  }
}
class Timer {
  float locx, locy;
  float timerwidth, timerheight;
  int countdown=30;
  int seconds; 
  float startTime;


  Timer() {// ask about the logic behind this and how to create a countdown timer? 
    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"
      backgroundmusic.stop();
      gameState=3;
      
    } else {
      seconds = int(startTime- millis()/1000);
      fill(255, 0, 0);
      text(seconds, width/2-100, 100);
    }
  }
}
class userBall {
  //pretty much the exact same as the NPC Balls
  float locx, locy;
  float ballwidth, ballheight;
  float xspeed=5;
  float yspeed=5;
  float radius=30;


  userBall() {//the constructor for this userBall object
    locx=width/2;
    locy=height/2;
    ballwidth=2*radius;
    ballheight=2*radius;
  }
  void drawuserBall() {
    fill(0);
    stroke(0, 0, 255);
    ellipse(locx, locy, ballwidth, ballheight);
  }
  
}

FINAL PRODUCT

Week 5: Image Manipulation

For this week’s assignment, I was not sure about what I wanted to accomplish or work on. Therefore, I just searched online for some image manipulation examples and tried to recreate some of the ones that I thought was interesting or cool, or in this case makes me go “wow”. I stumbled upon this video that demonstrated changing the pixels of an original image in whatever way the person wanted, and that made me go “wow”, so I decided to try to recreate it.

Not only did I learn how to manipulate with the colors of each pixel, but I also learned a tiny tip from the video of how to make a “replica” or “copy” of the original image in order to guarantee that the original image is going to be the way it is while tampering with the replica whatever way we wanted to.

I mainly wanted to try out to two different image manipulation effects: The first one being able to manipulate the pixel colors and create an image filter. The second one being able to control the different grey scaled color gradients in accordance to my position values of my mouse.

Initially, of course, I had no idea how to create it from scratch. But, after looking through many videos and class examples, I learned different functions such as the brightness function from online and also several other techniques from the class. I mainly struggled with understanding the logic behind the codes (since like day one) due to my inexperience in coding, but I realized I am slowly understanding it, and emphasis on the “slow”.

PImage froggie;

void setup() {
  size(940, 412);
  //load image into sketch
  froggie= loadImage("colorful frog.jpg");
}

void draw() {
  displayfrog();
  changefrogcolor();
  changebwfrog();
  updatePixels();
}

void displayfrog() {
  //display image
  image(froggie, 0, 0);
  //loads the pixel data of the picture into the pixel [] array 
  loadPixels();
  //might not be necessary to load pixels, but better to load it. 
  froggie.loadPixels();
}

void changefrogcolor() {
  if (mousePressed) {
    for (int x=0; x<width; x++) {
      for (int y=0; y<height; y++) {
        int loc = x+y*width; 
        //this gets the pixels from the desert image and puts it on the screen at the same location, like making a replica of the original image to mess with the pixels 
        //gets the red part of the pixels 
        float r = red(froggie.pixels[loc]);
        //gets the green part of the pixels 
        float g = green(froggie.pixels[loc]);
        //gets the blue part of the pixels
        float b=blue(froggie.pixels[loc]);
        //places these new colors into the window 
        pushMatrix();
        //float factor=random(0,20);
        pixels[loc]=color(random(g), random(b), random(r));
        popMatrix();
      }
    }
  }
}
//the interaction between the black and white color pixels of the frog image
void changebwfrog() {
  if (keyPressed) {
    for (int x=0; x<width; x++) {
      for (int y=0; y<height; y++) {
        int loc = x+y*width;
        //extracts the brightness value from each color of each pixel of the image
        float b=brightness(froggie.pixels[loc]);
        //if the brightness of each pixel is greater than mouse X and less than mouse Y, it'll change a random grey scale color, or else it'll turn into black color
        if (b>mouseX && b<mouseY ) {
          //turns the color that are not greater than mouse X or less than mouse Y into a random grey scale 
          pixels[loc]=color(random(255));
        } else {
          //turns the pixels that are not greater than mouse X or less than mouse Y into black 
          pixels[loc]=color(0);
        }
      }
    }
  }
}

 

Week 4 Assignment: Generative Text Output

For this week’s assignment, I was not able to really come up with my very own original creative idea, so I had to search online for some  examples online that had to do with some Generative Text Output. Firstly, when I was fumbling through countless Youtube videos with examples, I stumbled on this video where it showed how by repeating a bunch of short sentences and making them appear at different places on the screen really quick could create this kind of blurry image on the screen, just like how when our TV screen would act weird and these white and black bars would flicker on and off.

After I created this blurry image on the screen, I wanted to make a Typewriter effect for my text where my text would appear one by one, but I wasn’t sure how to incorporate that effect to the entire text (maybe because I had to create an array to make this effect for each character of my text?). So, after this wasn’t working, I wanted to make another effect and I thought I could use the mousePressed function to make it freeze or stop creating this blurry image when the mouse is pressed and at the same time create another text, but that did not work as well. So, I settled for making it change color each time the mouse was pressed.

String text1="Hello, my name is Ryan.";
String text2="Hi, I've stopped.";
PFont font;
int counter;
float i, x, y;

void setup() {
  size(800, 600, P2D);
  frameRate(5);
  smooth();
  font=createFont("Georgia", 30);
  textFont(font, 20);
  fill(0);
  counter=0;
}

void draw() {    
  background(255);
  translate(mouseX, mouseY);
  //typewriteText()
  for (i=0; i < 1000; i++) {
    float x = random(width);
    float y = random(height);
    text(text1, x, y);

    if ( mousePressed) {
      noLoop();
      fill(random(255), random(255), random(255));
      for (int i = 0; i < random(1000); i++) {
        textFont(font, random(50));
        x = random(width);
        y = random(height);
        text(text2, x, y);
      }
    } else {
      loop();
      background(255);
      for (i=0; i < 1000; i++) {
        x = random(width);
        y = random(height);
        text(text1, x, y);
      }
    }
  }
}