Midterm: It’s all under control…

Building upon what I had already, I decided to develop my game much further.

Initial issues

I had many issues at first which include: pressing any key would make Trump move in place, if you held down an arrow key and jumped you stopped moving once you landed, the jump was very abrupt and strictly vertical which was weird for the level of realism in the game, shooting would stop the motion of Trump, and the bullets would appear but not move at all.

Resolving issues, help from Jack

I resolved these issues using many different lines of code where instead of doing most of the work in the main code, I kept creating functions which do the tasks in order for me to be able to keep calling them in multiple situations. I made sure to add “keyCode = …” under each if condition if keyPressed and otherwise just keep direction = direction, which even enabled me to allow motion using w, a, s, d as well. Instead of just using keyPressed in draw loop for all, I used the function one outside to call on the act of shooting and jumping just once whenever the keys are pressed and not every frame.

By asking Jack for some help, we figured out I must also use the keyReleased function outside the draw loop to decide what the game should look like the moment the player releases the important keys to keep the playing going. Jack also helped me with the concept of flying the bullet where I had the code in the main tab and the motion was called upon once in the draw loop but we made it a function in the class instead that is called upon continuously. I also added a small increment/decrement in the x-dimension for Trump when he jumps sideways to make it more realistic.

Jack also introduced the concept of saving the previous frame to me, where I used it to make sure no two bullets are created within a certain amount of frames, and similarly with the coronas. This made the game so much more realistic and intuitive, especially when you keep holding the shooting key.

Further development

I then brought an image of a sanitizer and made it smaller, and then made it seem as though Trump is holding it in his right hand (because he is right-handed) by ordering the image printing accordingly. I had many options for choosing the corona character but I chose this funky one because it is rather satirical, which is the obvious theme of my game, and because it is visible in the green without disturbing the eye like if it was red.

I chose the title based on the actual quote of Trump about COVID-19, and I chose the sentence printed out when you lose as also another quote from Trump about COVID-19, which just fits the theme perfectly. I added the US flag and used an online photo editor called “Pixlr X” to make it more transparent and to add the individual instructions all on the background. I decided to make the instructions visually aesthetic so as to not bore the player and to be very intuitive, and because the game is satirical in nature so it need not be too complicated or serious. I added that face at the end and then added the sound from a YouTube video of a mashup of Trump saying ‘no’ to resemble his hilarious failure and annoyance from getting infected with the virus, which happened in real life despite him making fun of COVID’s repercussions. Also, the sound is annoying to encourage the player to restart the game.

original flag background
background after edits

I added some sound effects for the shooting (squirt sound), killing a corona particle (pop sound) which were both dropped down in amplitude to not be too noisy, and a background music of the US national anthem but an 8bit version of it from YouTube to go along with the clipart theme of the game while maintaining Trump’s Republican Party’s patriotic notion. The music drops down in volume as soon as you start playing so as to draw you attention to the visuals, so you can hear the pop and squirt sounds, and so it does not become too noisy and loud.

I used processing examples to build the button used for playing the game, making it clickable and changing its color when you hover over it.

As suggested in the class, I added a black fence resembling the real one in the White House to show where exactly Trump cannot run anymore on the ground in a visibly clear manner.

fence I used to show the limit of trump’s motion

Personal Feeling

The game has a fun a political taste to it while being very relevant to our current situation in the COVID-19 pandemic. I am a Muslim Arab man and Trump is a very significant man in my life because of the actions he has done towards immigrants of my race and because he is the president of the most influential country in the world. Even though I am an American citizen, I am still very pissed off by what he has done and I have many loved ones who were harmed by the consequences of his actions. As an Egyptian, our way of expressing emotions is always through satire and comedy, and this is my simple way of expressing how I feel about this man right now in 2020.

starting page with game instructions
how the game itself looks
what comes up when you lose

Final Version

If you want to try out the game yourself, here is a zip file of the code:

midterm

Main Code:

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

PImage whiteHouse, sanitizer, laser, corona, trumpBack, americaFlag, fence;     //all images needed
PImage spritesheet;      //sprites of trump
boolean gameOn;        //condition for game
float prevFrame = 0;      //initializing value for previous frame
float randX, randY;      //random numbers for coordinates of creation of corona particles
ArrayList <Laser> lasers;    //initializing arraylist for sanitizer bullets
ArrayList <Corona> coronas;    //initializing array list for corona particles
int score = 0;          //initializing score to 0
PFont f;              //f object for all the texts in the game
int luck;            //randomizing number to make corona particles start motion towards the left or the right
int buttonX, buttonY;      // Position of button
int buttonWidth, buttonHeight;     //dimensions of play button
color buttonColor, baseColor;    //colors of play button
color buttonHighlight;
color currentColor;
boolean buttonOver;
boolean instructions;        //condition for whether instructions page is open or not
SoundFile click, squirt, pop, trumpSound, anthem;      //all sounds in the game

Trump trumps;      //initializing trump character 


//button logic inspired from https://processing.org/examples/button.html

void setup() {
  size(720,477);
  
  instructions = true;      //start game with instructions page
  buttonOver = false;      //start with condition of button pressed false
  gameOn = false;          //don't start game till play is clicked
  
  
  f = createFont("Raleway-Bold.ttf",72);      //aesthetic font that fits teh theme
  
  whiteHouse = loadImage("house4.png");      //white house background pic
  spritesheet = loadImage("trump.png");    //sprites of trump
  sanitizer = loadImage("sanitizer.png");    //sanitizer image
  laser = loadImage("laser.png");            //sanitizer bullet image
  corona = loadImage("corona3.png");          //corona particle image
  trumpBack = loadImage("trumpbackground.jpg");      //trump face when loses image
  americaFlag = loadImage("americaFlag3.jpg");      //america flag background in the beginning with the instructions image
  fence = loadImage("fence4.png");      //black fence image
  
  click = new SoundFile (this, "click.mp3");      //sound when you click
  squirt = new SoundFile (this, "squirt.mp3");       //sound when you shoot
  pop = new SoundFile (this, "pop.mp3");      //sound when you kill corona particle
  trumpSound = new SoundFile (this, "no.mp3");      //long sound playing when you lose until you click anywhere to restart
  anthem = new SoundFile (this, "anthem (6).mp3");      //8bit anthem background music
  
  trumps = new Trump(width/2, height -40);        //creates instance of class trump
  lasers = new ArrayList();        //initializes sanitizer bullets list
  coronas = new ArrayList();      //initializes coronas list
  
  buttonColor = color(0);
  buttonHighlight = color(51);
  baseColor = color(102);
  currentColor = baseColor;
  buttonWidth = 150;
  buttonHeight = 60;
  buttonX = width/2;
  buttonY = 3*height/4 + 30;        //initializations of the button color, color when hovered upon, dimensions, and position
  
  anthem.loop();      //keep the anthem playing on loop always
  trumpSound.amp(0.001);      //reduce the amplitude of trump sound to nothing so it is not heard now
  trumpSound.loop();      //keep the trump sound playing continuously in the background
  
  rectMode(CENTER);
  imageMode(CENTER);
}

void draw() {
  
  if (gameOn == true && instructions == false) {      //if game is one the instructions page is not opened
    //trumpSound.pause();
    background(whiteHouse);
    image(fence, width/6, height -145, width/3, 80);
    image(fence, width/3 + width/6, height -145, width/3, 80);
    image(fence, 2*width/3 + width/6, height -145, width/3, 80);      //draw the fence three times side by side
    
    if (keyPressed) {
        if (keyCode == DOWN || key == 's') {
          keyCode = DOWN;                    //handling keyCode when key = s is pressed instead, because I use keyCode throughout teh code
          trumps.direction = 0;
          trumps.move();
        }
          
        else if (keyCode == LEFT || key == 'a') {
          keyCode = LEFT;
          trumps.direction = 3;
          trumps.move();
        }
        else if (keyCode == RIGHT || key == 'd') {
          keyCode = RIGHT;
          trumps.direction = 1;
          trumps.move();
        }
        
        else if (keyCode == UP || key == 'w') {
          keyCode = UP;
          trumps.direction = 2;
          trumps.move();                                    //handling the moements of trump, whether using keys or using w, a, s, d
        } 
        else {
          trumps.direction = trumps.direction;
        }
    }
      
      if (trumps.direction == 3) {
        pushMatrix();
        translate(trumps.x - 23, trumps.y + 15);
        //rotateY(radians(180));
        image(sanitizer, 0, 0);
        popMatrix();                      //draw sanitizer direction right
      }
      
       if (trumps.direction == 2) {
        image(sanitizer, trumps.x + 20, trumps.y + 8);      //draw sanitizer direction up
      }
      
  
      image(trumps.sprites[trumps.direction][trumps.step], trumps.x, trumps.y);      //drawing trump himself
      trumps.update();                    //calling on gravity
      
      if (trumps.direction == 1) {
        image(sanitizer, trumps.x + 23, trumps.y + 15);      //draw sanitizer direction left
      }
      
      if (trumps.direction == 0) {
        image(sanitizer, trumps.x - 15, trumps.y + 20);        //draw sanitizer direction down
      }
      
      if (frameCount % 100 == 0) {
        if (coronas.size() < 8) {            //setting limit of 8 coronas at a time
           luck = (int)random(100);
           randX = random(100, width - 100);
           randY = random (100, height - (190 + trumps.h));
           
           
           Corona temp = new Corona(randX, randY, luck);
           coronas.add(temp);
        }
      }                                                   //create coronas after a certain number of frames at random starting positions and random starting direction of left or right
      
      for (int i = coronas.size()-1; i >= 0; i--) {
        Corona current = coronas.get(i);
        current.display();
        current.move();                                    //call on functional methods of corona class for each of them
        
        if (current.checkTrump(trumps.x, trumps.y)) {          //checking if corona collided with trump
          anthem.stop();          //stop the background music
          gameOn = false;          //game condition false
          break;                //break from the conditions to enter others
        }
      }
      
      for (int i = lasers.size()-1; i >= 0; i--) {
        Laser laser = lasers.get(i);
        laser.display();
        laser.fly();                //call on functional methods of sanitizer bullets for each object
        
        if (laser.checkEdges()) {        //check if laser is out of frame to remove it
          lasers.remove(laser);
        }
        
        for (int j = coronas.size()-1; j >= 0; j--){        //iterate through all coronas
          Corona important = coronas.get(j);
          if (laser.checkCollision(important.coronaX, important.coronaY, important.coronaWidth)) {      //if bullet hits corona
            pop.amp(0.1);
            pop.play();      //make pop sound
            coronas.remove(important);       //remove hit corona
            lasers.remove(laser);           //remove the bullet that hit it too
            score += 10;        //increment score by 10
          }
          //pop.stop();
        }
        
      }
      
      textAlign(CORNER);
      String Score = "Score: ";          //constantly show score at the corner
      //fill(0);
      //rect(width - 130 , height - 100, textWidth(Score) + 10, 50);
      textFont(f,20);
      fill(255);
      
      
      text(Score + score, width - 115, height - 20);        //score text bottom right
    
  }
  
  else if (instructions == true && gameOn == false) {        //starting phase of instructions pre-game
    
    background(255);
    update();
  
    if (buttonOver) {
      fill(buttonHighlight);            //if mous hovers over button change color
    } 
    else {
      fill(buttonColor);
    }
    
    image(americaFlag, width/2, height/2);        //image of flag with game instructions on it
    
    stroke(255);
    rect(buttonX, buttonY, buttonWidth, buttonHeight, 20);      //play button
    
    textFont(f,25); 
    textAlign(CENTER, CENTER);
    fill(255);
    String play = "PLAY";          //text in play button to clarify it
    text(play, buttonX , buttonY - 3);
  }
  
  else if (instructions == false && gameOn == false) {      //if player loses
    anthem.stop();      //stop background music
    //trumpSound.play();
    trumpSound.amp(0.8);      //increase trump saying no to be heard

    
    
    background(trumpBack);      //trump's face
    textAlign(CENTER);
    
    textFont(f,40); 
    //same shade as in the flag
    fill(#BF0A30);
    String first = "'This was unexpected...'";
    text(first, width/2 , (height/4) - 90);
    
    textFont(f,24);
    //same shade as in the flag
    fill(#002868);
    String second = "CLICK ANYWHERE TO TRY AGAIN";
    text(second, width/2 - 5, height/2 + 215);      //game over text
    
    textAlign(CORNER);
    textFont(f,20);
    fill(0);
    String third = "Score: ";
    text(third + score, width - 115, height -20);      //final score text
    
   
  }
}

void keyPressed()
{
   if(key == ' '){
      if (frameCount - prevFrame > 15) {      //only allow jumping constantly after certain number of frames
        prevFrame = frameCount;
        trumps.jump();      
      }
   }
   
   if(key == 'e') {          //shoot sanitizer bullet
   trumps.recoil();           //recoil when trump shoots
      if (frameCount - prevFrame > 20) {        //only allow multiple shooting after certain number of frames if key is held
        squirt.amp(0.2);        //play squirt sound
        squirt.play();
        prevFrame = frameCount;
        Laser temp = new Laser(trumps.x, trumps.y, trumps.direction);        //create new bullet
        lasers.add(temp);      //add it to teh list
      }
    }
}

void update() {
  if ( overButton(buttonX, buttonY, buttonWidth, buttonHeight) ) {      //check if mouse is over the button to change color
    buttonOver = true;
  } 
  else {
    buttonOver = false;
  }
}

void keyReleased() {
  if(key == ' ') {          //keep trump in correct direction and keep moving even while/after jumping
    if (trumps.direction == 0) {
        keyCode = DOWN;              
      }
        
      if (trumps.direction == 3 ) {
        keyCode = LEFT;
      }
      if (trumps.direction == 1) {
        keyCode = RIGHT;
      }
      
      if (trumps.direction == 2) {
        keyCode = UP;
      } 
  }
  
  if(key == 'e') {        //keep trump in correct direction and keep moving even while/after shooting
    //squirt.stop();
    if (trumps.direction == 0) {
        keyCode = DOWN;
      }
        
      if (trumps.direction == 3 ) {
        keyCode = LEFT;
      }
      if (trumps.direction == 1) {
        keyCode = RIGHT;
      }
      
      if (trumps.direction == 2) {
        keyCode = UP;
      } 
  }
}

boolean overButton(int x, int y, int buttonWidth, int buttonHeight)  {            //check if mouse is over button
  if (mouseX >= x - buttonWidth/2 && mouseX <= x + buttonWidth/2 && mouseY >= y - buttonHeight/2 && mouseY <= y + buttonHeight/2) {
    return true;
  } else {
    return false;
  }
}

void mouseClicked() {
  if (buttonOver) {      //check if mouse is clicked over button then start game
    
      click.amp(0.3);
      click.play();
      instructions = false;
      
     if (gameOn == false){        //if mouse is clicked when the game is off, turn it on and reset everything to zero and empty lists
        //trumpSound.stop();
        //instructions = false;
        score = 0;
        gameOn = true;
        anthem.amp(0.4);
        anthem.loop();        //replay background music
        trumpSound.amp(0.001);
        for (int i = coronas.size()-1; i >= 0; i--) {       //reset coronas list
          coronas.remove(i); 
        }
        for (int i = lasers.size()-1; i >= 0; i--) {         //reset bullets list
          lasers.remove(i);   
        }
      
    }
    
  }
  
}

Corona class, contains three functions: displaying, moving around, and checking if it collided with Trump:

class Corona {
  float coronaX, coronaY;
  float xSpeed;
  float ySpeed;
  float xDirection, yDirection;
  float coronaWidth, coronaHeight;
  int rand;
  
  
  Corona(float _x, float _y, int _rand) {
    
    coronaX = _x;
    coronaY = _y;
    
    coronaWidth = 100;
    coronaHeight = 100;
    
    xDirection = 1;
    yDirection = 1;
    
    xSpeed = 2;
    ySpeed = 2;
    
    rand = _rand;
    
  }
  
  void display() {
    image(corona, coronaX, coronaY, coronaWidth, coronaHeight);      //display corona image
  }
  
  void move() {
    
    if (rand > 50) {              //if random number is this then move in right direction
      coronaX += (xSpeed * xDirection);
      coronaY += (ySpeed * yDirection);
    }
    
    else {                    //if random number is less tha or equal to 50, move in the left direction
      coronaX -= (xSpeed * xDirection);
      coronaY -= (ySpeed * yDirection);
    }
    
    if ((coronaX + (coronaWidth/2) > width) || (coronaX - (coronaWidth/2) < 0)) {      //if corona hits either walls horizontally switch direction of motion to bounce
      xDirection *= -1;
    }
    
    if ((coronaY + (coronaHeight/2) > height) || (coronaY - (coronaHeight/2) < 0)) {        //if corona hits either walls vertically switch direction of motion to bounce
      yDirection *= -1;
    }
   
  }
  
  boolean checkTrump(float _x, float _y) {          //check if it collided with trump
     float otherX = _x;
     float otherY = _y;
     if (dist(coronaX, coronaY, otherX, otherY) < coronaWidth/2) {
       return true;
     } 
     else {
       return false;
     }
  }


}

Sanitizer Class, has 4 functions: displaying the sanitizer bullet, flying the bullet in the appropriate direction, checking if it collided with a corona particle, and checking if it is outside the frame of the game:

//code inspired from https://forum.processing.org/two/discussion/1324/how-to-create-a-bullet-array-for-asteroids-game
class Laser {

  int laserDirection;
  float laserX, laserY;
  float xSpeed;
  float ySpeed;
  float laserWidth, laserHeight;


  Laser(float _x, float _y, int direction) {
    
    laserDirection = direction;
    xSpeed = 8;
    ySpeed = 8;
    
    if (laserDirection == 0) {
      laserX = _x - 15;
      laserY = _y + 23;
    }
    if (laserDirection == 1) {
      laserX = _x + 23;
      laserY = _y + 15;
    }
    if (laserDirection == 2) {
      laserX = _x + 23;
      laserY = _y - 15;
    }
    if (laserDirection == 3) {
      laserX = _x - 23;
      laserY = _y + 15;
    }
                                          //initialize direction of laser so it remains so even if trump changes his direction later
    laserWidth = 60;
    laserHeight = 20;
    
   }
  
   void display() {
     if (laserDirection == 2){
       pushMatrix();
         translate(laserX, laserY - 20);
         rotate(HALF_PI);
         image(laser, 0, 0, laserWidth, laserHeight);
       popMatrix();
       
     }                                                  //rotate bullet to shoot up
     
     else if( laserDirection==0) {
     pushMatrix();
         translate(laserX, laserY + 25);
         rotate(HALF_PI);
         image(laser, 0, 0, laserWidth, laserHeight);
       popMatrix();
     }                                            //rotate bullet to shoot down
     
     else if ( laserDirection==1){
       image(laser, laserX + 28, laserY - 18, laserWidth, laserHeight);      //bullet shoot right
     }
     
     else if ( laserDirection==3){
       image(laser, laserX - 28, laserY - 18 , laserWidth, laserHeight);      //bullet shoot left
     }
   }
   
   void fly() {
     if (laserDirection == 3) {        //left
       laserX -= xSpeed;
     }
     
     if (laserDirection == 1) {        //right
       laserX += xSpeed;
     }
     
     if (laserDirection == 2) {        //up
       laserY -= ySpeed;
     }
     
     if (laserDirection == 0) {        //down
       laserY += ySpeed;
     }
                                                        //movement according to the direction
   }
   
   boolean checkCollision (float _x, float _y, float w) {      //check collision with corona coordinates
     float otherX = _x;
     float otherY = _y;
     if (dist(laserX, laserY, otherX, otherY + 10) < w/2 ) {
       return true;
     } 
     else {
       return false;
     }
   }
   
   boolean checkEdges() {
     if ((laserX - laserWidth/2 > width) || (laserX + laserWidth/2 < 0) || (laserY - laserHeight/2 > height) || (laserY + laserHeight/2 < 0)) {      //check if laser is outside frame to remove it
       return true;
     }
     else {
       return false;
     }
   }
  

}

Trump class, has 4 functions: updating the y-position of Trump according to gravity,  moving the character around in the appropriate directions, recoiling Trump backwards whenever he shoots to make it more realistic, and jumping:

class Trump {
  
  PImage[][] sprites;
  int direction = 1;
  int step = 0;
  int w, h;
  float x, y;
  float xspeed = 6;
  float yspeed = 6;
  float gravity;
  
  Trump(float _x , float _y){
  sprites = new PImage[4][6];
  
  w = spritesheet.width/6;
  h = spritesheet.height/4;
  
  gravity = 0.0001;

  for (int y=0; y < 4; y++) {
    for (int x=0; x< 6; x++) {
      sprites[y][x] = spritesheet.get(x*w, y*h, w, h);      //creating each instance's individual sprite from spritesheet
    }
  }

  x = _x;
  y =_y;
  
  }
  
  void update() {        //if trump is in the air make him go down through gravity
  
    if (y - h/2 < height - 190.5) {
      yspeed = yspeed + gravity;
      y += yspeed;
    }
  }
  
  void move() {
    if (direction == 0) {
      if (y + (h/2) < height) {    //move down until frame limit
          y += yspeed;
      }
    }
    if (direction == 1) {      //right till wall
      if (x + (w/2) < width) {
          x += xspeed;
        }
    }
    if (direction == 2) {      //up till fence
      if (y - (h/2) > height - 189) {
          y -= yspeed;
        }
    }
    if (direction == 3) {      //left till wall
      if (x - (w/2) > 0) {
          x -= xspeed;
        }
    }                                //move according to direction
    
    if (frameCount % xspeed == 0) {      //transition from one sprite to another
        step = (step+1) % 6;
    }
  }
  
  void recoil() {        //push trump slightly backwards when he shoots to be more realistic
    if (direction == 0) {      //down
      if (y - (h/2) > height - 189) {    //go up till fence
          y -= yspeed/4;
      }
    }
    if (direction == 1) {      //right
      if (x - (w/2) > 0) {      //left till wall
          x -= xspeed/4;
        }
    }
    if (direction == 2) {      //up
      if (y + (h/2) < height) {    //down till frame limit
          y += yspeed/4;
        }
    }
    if (direction == 3) {      //left
      if (x + (w/2) < width) {      //right till wall
          x += xspeed/4;
        }
    }
    
    //if (frameCount % xspeed == 0) {
    //    step = (step+1) % 6;
    //}
  }

  void jump() {
    
    if (y - (h/2) > height - 191) {      //if trump is not already flying make him jump
      y -= 150;
      
      if (direction == 3 ) {      //if he was moving to left push him slightly to left
        if (x - (w/2) > 0) {
          x-= 20;
        }
      }
      else if (direction == 1) {      //if he was moving to right push him slightly to right
        if (x + (w/2) < width) {
          x += 20;
        }
      }
    }
      
  }
  
  
}

 

 

Leave a Reply