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