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

Leave a Reply