Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
/////////////////HONG KONG 2000 OBJECT ORIENTED TOY////////////////////////
///////////////////////BY DEXTER TRUONG////////////////////////////////////

//HONG KONG 2000 IS A SEQUEL TO HAPPYSOFT'S HIT GAME FOR THE FAMICOM HONG KONG 97
//DEFEAT 1.2 BILLION OF THE UGLY REDS AND SAVE HONG KONG
//INSTRUCTIONS: CONTROL THE MOUSE WITH CHIN AND PRESS THE MOUSE TO SHOOT PINGPONG BALLS AT THE UGLY REDS. IF AN UGLY RED OR CAR TOUCHES YOU, YOU DIE. CARS CANNOT BE KILLED
//KILL AS MANY UGLY REDS AS POSSIBLE FOR A HIGH SCORE!!!!!!!!!!

////////////////////////////////////////////////////////////////////////////
//////////////////////////////VERY IMPORTANT////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//REMEMBER TO PLAY THE GAME WITH IT'S APPORPIRATE SOUNDTRACK IN THE BACKGROUND FOR A REAL HONG KONG 97 EXPERIENCE
//https://www.youtube.com/watch?v=MtYF_9e2azE
////////////////////////////////////////////////////////////////////////////
//////////////////////////////VERY IMPORTANT////////////////////////////////
////////////////////////////////////////////////////////////////////////////



///////////////START OF PROGRAM///////////////
//Keep track of player score
float score;

//Call upon objects
UglyRed[] uglyred;
Chin chin;
Car car;
ArrayList <PingPongBall> pingpongballs;



void setup() {
  //Setup size of window
  size(600, 600);

  //Initialize Ugly Red array
  uglyred = new UglyRed[5];

  //Ugly Red constructor
  for (int i = 0; i < uglyred.length; i++) {
    uglyred[i] = new UglyRed(random(width), 0, 0, int(random(3, 10)));
  }

  //Chin constructor
  chin = new Chin(100, 150);

  //Car constructor
  car = new Car(0, random(height), 3, 0);

  //Pingpong Ball constructor
  pingpongballs = new ArrayList();
}



void draw() {  
  {
    //Background colour
    background(0, 0, 75);

    //Call Ugly Reds
    for (int i=0; i < uglyred.length; i++) {
      uglyred[i].update();
      uglyred[i].waveOfReds();
      uglyred[i].display();
    }

    //Call Chin
    chin.update(); 
    chin.display();

    //Call car
    car.update();
    car.driveBy();
    car.display();

  //Call the Pingpong ball array
    PingPongFire();
   
  }


  //When Chin touches the Ugly Red, he dies
  for (int a = 0; a < uglyred.length; a++) {
    if (enemyIntersect(uglyred[a].position.x, uglyred[a].position.y, uglyred[a].position.x+uglyred[a].redBoxX, uglyred[a].position.y+uglyred[a].redBoxY, mouseX, mouseY, mouseX+chin.chinBoxX, mouseY+chin.chinBoxY) == true) {
      gameOver();      
      noLoop();
      println("Your score is" +score);
    }

    //When Chin touches the Car, he dies
    if (enemyIntersect(car.position.x, car.position.y, car.position.x+car.carBoxX, car.position.y+car.carBoxY, mouseX, mouseY, mouseX+chin.chinBoxX, mouseY+chin.chinBoxY) == true) {
      gameOver();
      noLoop();
      println("Your score is" +score);
    }

    //When the Pingpong ball hits the Ugly red, reset the position of the Ugly Red, cause and Atomic Explosion and add 1 to score
    for (int i = 0; i < uglyred.length; i++) {
      for (PingPongBall j : pingpongballs) {
        if (uglyRedPingPongIntersect(uglyred[i].position.x, uglyred[i].position.y, uglyred[i].redBoxX, uglyred[i].redBoxY, j.position.x, j.position.y, j.pingPongRadius) == true) {
          uglyred[i].redExplosion();
          uglyred[i].redKill();
          score++;
        }
      }
    }
  }
}

//When the player presses the mouse Chin fires Pingpong balls
void mousePressed() {
  PingPongBall shot = new PingPongBall(mouseX, mouseY, 0, -10);
  pingpongballs.add(shot);
}

//Function for handling array of Pingpong balls
void PingPongFire() {
  for (PingPongBall shot : pingpongballs) {
    //Call Pingpong balls
    shot.update();
    shot.display();
  }
}


//Game over screen when Chin dies
void gameOver() {
  textSize(90);
  text("CHIN IS DEAD", 0, 300); 
  fill(255, 0, 0); 
}



//Circle-Rect Intersection for Pingpong balls and Ugly Reds
//Inspired by REAS' sketch
//https://www.openprocessing.org/sketch/8004
boolean uglyRedPingPongIntersect(float redX, float redY, float redWidth, float redHeight, float pingPongX, float pingPongY, float pingPongRadius) {

  float pingPongDistanceX = abs(pingPongX - redX - redWidth/2);
  float pingPongDistanceY = abs(pingPongY - redY - redHeight/2);

  if (pingPongDistanceX > (redWidth/2 + pingPongRadius)) { 
    return false;
  }
  if (pingPongDistanceY > (redHeight/2 + pingPongRadius)) { 
    return false;
  }
  if (pingPongDistanceX <= redWidth/2) { 
    return true;
  } 
  if (pingPongDistanceY <= redHeight/2) { 
    return true;
  }

  float cornerDistance = pow(pingPongDistanceX - redWidth/2, 2) + pow(pingPongDistanceY - redHeight/2, 2);
  return cornerDistance <= pow(pingPongRadius, 2);
}


//Rect-Rect Intersection for Ugly Reds, Car and Chin
//Inspired by REAS' sketch
//https://www.openprocessing.org/sketch/8005
boolean enemyIntersect(float left, float top, float right, float bottom, 
  float otherLeft, float otherTop, float otherRight, float otherBottom) {
  return !(left > otherRight || right < otherLeft || top > otherBottom || bottom < otherTop);
}
//This is the object for the car, an enemy
class Car {

  //Values for the car's hitbox
  float carBoxX= 100;
  float carBoxY= 30;

  //Set PVector
  PVector position = new PVector(), velocity = new PVector();

  //Set initial values for the Car
  Car(float x, float y, float vx, float vy) {

    this.position.x = x;
    this.position.y = y;
    this.velocity.x = vx;
    this.velocity.y = vy;
  }

  //Move Car
  void update() {
    position.add(velocity);
  }

  //Draw the Car
  void display() {
    noStroke();
    fill(76, 107, 63);

    //Draw the car's body
    rect(position.x+20, position.y-20, 60, 30);
    rect(position.x, position.y, 100, 40);

    //Draw the car's wheels
    fill(75, 75, 75);
    ellipse(position.x+20, position.y+40, 30, 30);
    ellipse(position.x+80, position.y+40, 30, 30);

    //Draw the car's hitbox
    fill(0, 0, 0, 0);
    rect(position.x, position.y+5, carBoxX, carBoxY);
  }

  void driveBy() {
    if (position.x > width) {
      position.x = 0;
      position.y = random(height);
    } else if (position.x < 0) {
      position.x = width;
      position.y = random(height);
    }
  }
}
//This is the object for Chin, the player controlled character
class Chin {

  //Values for Chin's hitbox
  float chinBoxX= 20;
  float chinBoxY= 50;

  //Set PVector
  PVector position = new PVector();

  //Set initial values for Chin
  Chin(float x, float y) {

    this.position.x = x;
    this.position.y = y;
  }


  //Move Chin
  void update() {
    position.x = mouseX;
    position.y = mouseY;
  }

  //Draw Chin
  void display () {
    noStroke();
    fill(230, 230, 230);

    //Draw Chin's shirt
    rect(position.x+-25, position.y+50, 100, 20);
    rect(position.x-5, position.y+70, 60, 20);

    //Draw Chin'a pants
    fill(60, 60, 60);
    rect(position.x-5, position.y+90, 20, 40);
    rect(position.x+35, position.y+90, 20, 40);

    //Draw Chin's head
    fill(237, 220, 150);
    rect(position.x, position.y, 50, 50);

    //Draw Chin's hair
    fill(75, 75, 75);
    rect(position.x-5, position.y, 60, 20);
    triangle(position.x-5, position.y, position.x-5, position.y+40, position.x+20, position.y+10);
    triangle(position.x-5, position.y, position.x+30, position.y+40, position.x+30, position.y+10);
    triangle(position.x+25, position.y, position.x+55, position.y+40, position.x+55, position.y+10);

    //Draw Chin's eyes
    fill(0, 0, 0);
    rect(position.x+5, position.y+25, 15, 3);
    rect(position.x+30, position.y+25, 15, 3);

    //Draw Chin's hitbox
    fill(0, 0, 0, 0);
    rect(position.x+15, position.y+30, chinBoxX, chinBoxY);
  }
}
//This it the object for Pingpong balls, your projectile
class PingPongBall {

  //Set the float variables for pingpong ball
  float pingPongRadius = 10;

  //Set PVector
  PVector position = new PVector(), velocity = new PVector();

  //Set initial values for the Pingpong ball
  PingPongBall(float x, float y, float vx, float vy) {

    this.position.x = x;
    this.position.y = y;
    this.velocity.x = vx;
    this.velocity.y = vy;
  }

  //Move Pingpong Ball
  void update() {
    position.add(velocity);
  }  

  //Draw the Pingpong ball
  void display() {
    noStroke();
    fill(240, 240, 240);
    ellipse(position.x, position.y, pingPongRadius, pingPongRadius);
  }
}
//This is the object for Ugly Reds, the enemy you will be fighting
class UglyRed {

  //Set float vlaues for Ugly Red's hitbox
  float redBoxX = 80;
  float redBoxY = 130;

  float explodeTime = millis();
  float redTime = millis();

  //Set PVector
  PVector position = new PVector(), velocity = new PVector();

  //Set initial values for the Ugly Red
  UglyRed(float x, float y, float vx, float vy) {

    this.position.x = x;
    this.position.y = y;
    this.velocity.x = vx;
    this.velocity.y = vy;
  }


  //Move Ugly Red
  void update() {
    position.add(velocity);
  }

  //Draw Ugly Red
  void display () {
    noStroke();
    fill(109, 147, 39);

    //Draw Ugly Red's clothes
    rect(position.x+-25, position.y+50, 100, 20);
    rect(position.x-5, position.y+70, 60, 20);
    rect(position.x-5, position.y+90, 20, 40);
    rect(position.x+35, position.y+90, 20, 40);

    //Draw the Ugly Red's head
    fill(237, 220, 150);
    rect(position.x, position.y, 50, 50);

    //Draw the Ugly Red's hat
    fill(109, 147, 39);
    rect(position.x-5, position.y, 60, 20);

    //Draw the Ugly Red's eyes
    fill(0, 0, 0);
    rect(position.x+5, position.y+25, 15, 3);
    rect(position.x+30, position.y+25, 15, 3);

    //Draw the Ugly Red's hitbox
    fill(0, 0, 0, 0);
    rect(position.x-15, position.y, redBoxX, redBoxY);
  }

//Randomizes position of the Reds
  void waveOfReds() {
    if (position.y > height) {
      position.y = 0;
      position.x = random(width);
    } else if (position.y < 0) {
      position.y = height;
      position.x = random(width);
    }
  }

//When the Red dies, reset his position
  void redKill() {
    position.y =random(width);
    position.x = 650;
    redTime= 20;
  }

//When Reds die, blow up in a atomic explosion
  void redExplosion() {
    fill(255, 60, 0);
    ellipse(position.x, position.y, 200, 200);
  }
}