//Nicholas Short 2018
//ABOUT GAME
//Bumper cars 2.0
//Reach a score of 30 to win
//Bump cars from the back to earn points
//Watchout, if hit from another car by the front, you will lose points
//CONTROLS
//Press and hold LEFT keyboard to move to the left
//Press and hold RIGHT keyboard to move to the right
//Press and hold UP keyboard to go up
//Press and hold DOWN keyboard to go down
//Declare all global variables
//Declare movement false so that later on when key is pressed, they will become true and function properly
boolean carL=false;
boolean carR=false;
boolean carU=false;
boolean carD=false;
//Use random, to change car colours with the intent of confusing players
float R = random(150, 255);
float G = random(100, 255);
float B = random(100, 255);
//Declare and set the dimensions of the car including its x,y initial coordinate
float carx=300;
float cary=250;
float carw=60;
float carh=30;
//This will reduce code for hitboxes
float carLL, carRR, carUU, carDD;
float carLL2, carRR2, carUU2, carDD2;
//Speed for car
float carM=4;
//Human head on cars
float humanH=15;
// First enemy car
float tailw =20;
float tailx=150;
float taily=250;
float tailL, tailR, tailT, tailB;
// Second enemy car
float sTailx= 340;
float sTaily=250;
float sTailL, sTailR, sTailT, sTailB;
//Third enemy car/ first one to attack player
float stAilx=50;
float stAily=70;
float stAilL, stAilR, stAilT, stAilB;
//Fourth enemy car/second one to attack player
float ftailx=320;
float ftaily=320;
float ftailL, ftailR, ftailT, ftailB;
// score
int score=0;
int finish = 30;
//Statements that will be used with boolean type functions to create a hitbox
boolean checkTouch;
boolean checkTouch2;
boolean checkTouch3;
boolean checkTouch4;
//Blocks for bumper cars floor
float gridx=0;
float gridy=20;
//Replacing sin() and cos() for declared variables
float dcount=40;
float mcount=50;
void setup() {
size(400, 400);
//Making primitive shapes CENTERED will allow me to use carw/2 and carh/2
rectMode(CENTER);
ellipseMode(CENTER);
}
void draw() {
background(255);
//Use functions for modularity. Instead of condensing it all in draw(), code will become more legible in separate blocks
//Design background
backgroundNew();
grid();
//Draw player and enemy cars
bumperTry();
testHit();
testHit2();
testHit3();
testHit4();
//Update on player and enemy hitboxes
checkTouch=checkCircle();
checkTouch2=checkCircle2();
checkTouch3=checkCircle3();
checkTouch4=checkCircle4();
updateCollision();
//Congratulate player and restart game
youWin();
}
void backgroundNew() {
//background
float w=600;
float c=0;
c=constrain(c, 0, 255);
while (w>0) {
w=w-14;
c=c+3;
fill(c);
ellipse(200, 200, w, w);
}
}
//Function for floor effect
//Horizontal and vertical lines
void grid() {
float grid=0;
stroke(150);
strokeWeight(1);
//Translate multiple lines from one side of the screen to another
//Both vertically and horizontally
while (grid<400) {
fill(255);
line(grid, 0, grid, 400);
grid=grid+70;
line(0, grid, 400, grid);
}
noStroke();
}
//Player car
void bumperTry() {
//Composes car parts and colour
//Colour tone will change every game
fill(R, 0, 0);
stroke(0);
strokeWeight(4);
rect(carx, cary, carw, carh, 40);
fill(0);
rect(carx, cary+20, carw+20, carh-20, 50);
line(carx, cary-30, carx, cary-15);
fill(0);
ellipse(carx, cary-30, humanH, humanH);
//Variables are given the value of operation between other variables to shorten future code for hitboxes
carLL=carx-carw/2;
carRR=carx+carw/2;
carUU=cary-carh/2;
carDD=cary+carh/2;
carLL2=carx-carw/2;
carRR2=carx+carw/2;
carUU2=cary-carh/2;
carDD2=cary+carh/2;
//When LEFT key is pressed, car will face the left and move based on speed
if (carL) {
carx=carx-carM;
stroke(0);
fill(R, 0, 0);
line(carx+30, cary-60, carx+30, cary-10);
strokeWeight(4);
rect(carx, cary, carw, carh, 40);
fill(0);
rect(carx, cary+20, carw+20, carh-20, 50);
rect(carx+24, cary, carw-40, carh+10, 40);
fill(0);
line(carx-45, cary, carx-30, cary);
noStroke();
fill(0, 0, 255);
ellipse(carx-45, cary, 10, 10);
rect(carx+31, cary-61, 8, 8);
}
//When RIGHT key is pressed, car will face the right and move based on speed
if (carR) {
carx=carx+carM;
fill(R, 0, 0);
stroke(0);
line(carx-30, cary-60, carx-30, cary-10);
strokeWeight(4);
rect(carx, cary, carw, carh, 40);
fill(0);
rect(carx, cary+20, carw-20, carh-20, 50);
rect(carx-24, cary, carw-40, carh+10, 40);
fill(0);
line(carx+45, cary, carx+30, cary);
noStroke();
fill(0, 0, 255);
ellipse(carx+45, cary, 10, 10);
rect(carx-31, cary-61, 8, 8);
}
//When UP key is pressed car will move decrease on Y axis
if (carU) {
cary=cary-carM;
}
//When DOWN key is pressed car will move increase on the Y axis
if (carD) {
cary=cary+carM;
}
//Boundaries for car, so car is not lost outside of the setup size
if (carx-carw/2<0) {
carx=carx+carM;
}
if (carx+carw/2>width) {
carx=carx-carM;
}
}
//When keys are pressed car will move to assigned direction
void keyPressed() {
if (keyCode==LEFT) {
carL=true;
}
if (keyCode==RIGHT) {
carR=true;
}
if (keyCode==UP) {
carU=true;
}
if (keyCode==DOWN) {
carD=true;
}
}
//When keys are released car must stop moving
void keyReleased() {
if (keyCode==LEFT) {
carL=false;
}
if (keyCode==RIGHT) {
carR=false;
}
if (keyCode==UP) {
carU=false;
}
if (keyCode==DOWN) {
carD=false;
}
}
//First enemy car
void testHit() {
//Initialize car to always start moving to the right
tailx=tailx+2;
//When enemy reaches the end of screen, pull back to the beginning
if (tailx+carw/2>width) {
tailx=tailx-500;
}
//Shapes that brought together form the car
stroke(0);
fill(0, G, 0);
line(tailx+30, sin(frameCount/40)*50 + taily-60, tailx+30, sin(frameCount/40)*50 + taily-10);
strokeWeight(4);
rect(tailx, sin(frameCount/40)*50 + taily, carw, carh, 40);
fill(0);
rect(tailx, sin(frameCount/40)*50 + taily+20, carw+20, carh-20, 50);
rect(tailx+24, sin(frameCount/40)*50 + taily, carw-40, carh+10, 40);
fill(0);
line(tailx-45, sin(frameCount/40)*50 + taily, tailx-30, sin(frameCount/40)*50 + taily);
noStroke();
fill(0, 0, 255);
ellipse(tailx-45, sin(frameCount/40)*50 + taily, 10, 10);
rect(tailx+31, sin(frameCount/40)*50 + taily-61, 8, 8);
noStroke();
fill(0, 0, 255);
ellipse(tailx+30, sin(frameCount/40)*50 + taily, tailw, 30);
fill(0);
line(tailx, sin(frameCount/40)*50+taily-30, tailx, taily-15);
fill(0);
ellipse(tailx, sin(frameCount/40)*50 +taily-30, humanH, humanH);
//Global variables that reduce code and will establish a hitbox
tailL=tailx-carw/2;
tailR=tailx+carw/2;
tailT=taily-carh/2;
tailB=taily+carh/2;
}
//Second enemy car
void testHit2() {
//Car starts by moving to left downward
sTailx=sTailx-1.5;
sTaily=sTaily-1.9;
//If cars ever reach the end of the screen, pull them back to origin
if (sTailx-carw/2<0) {
sTailx=sTailx+500;
}
if (sTaily<0) {
sTaily=sTaily+300;
}
//Shapes that brought together form the car
stroke(0);
fill(50, 100, 150);
line(sTailx-30, sTaily-60, sTailx-30, sTaily-10);
strokeWeight(4);
rect(sTailx, sTaily, carw, carh, 40);
fill(0);
rect(sTailx, sTaily+20, carw+20, carh-20, 50);
rect(sTailx-24, sTaily, carw-40, carh+10, 40);
fill(0);
line(sTailx+45, sTaily, sTailx+30, sTaily);
noStroke();
fill(0, 0, 255);
ellipse(sTailx+45, sTaily, 10, 10);
rect(sTailx-31, sTaily-61, 8, 8);
noStroke();
fill(0, 0, 255);
ellipse(sTailx-30, sTaily, tailw, 30);
fill(0);
line(sTailx, sTaily-30, sTailx, sTaily-15);
fill(0);
ellipse(sTailx, sTaily-30, humanH, humanH);
//Global variables that reduce code and will establish a hitbox
sTailL=sTailx-carw/2;
sTailR=sTailx+carw/2;
sTailT=sTaily-carh/2;
sTailB=sTaily+carh/2;
}
//Third enemy car/first to attack player
void testHit3() {
//Car starts moving right downward
stAilx=stAilx+1;
stAily=stAily+2;
//If cars ever reach the end of the screen, pull them back to origin
if (stAilx+carw/2>400) {
stAilx=stAilx-500;
}
if (stAily>400) {
stAily=stAily-450;
}
//Shapes that brought together form the car
stroke(0);
fill(50, 180, B);
line(stAilx-30, stAily-60, stAilx-30, stAily-10);
strokeWeight(4);
rect(stAilx, stAily, carw, carh, 40);
fill(0);
rect(stAilx, stAily+20, carw+20, carh-20, 50);
rect(stAilx-24, stAily, carw-40, carh+10, 40);
fill(0);
line(stAilx+45, stAily, stAilx+30, stAily);
noStroke();
fill(0, 0, 255);
ellipse(stAilx+45, stAily, 10, 10);
rect(stAilx-31, stAily-61, 8, 8);
noStroke();
fill(0, 0, 255);
ellipse(stAilx-30, stAily, tailw, 30);
fill(0);
line(stAilx, stAily-30, stAilx, stAily-15);
fill(0);
ellipse(stAilx, stAily-30, humanH, humanH);
//Global variables that reduce code and will establish a hitbox
stAilL=stAilx-carw/2;
stAilR=stAilx+carw/2;
stAilT=stAily-carh/2;
stAilB=stAily+carh/2;
}
//Fourth enemy car/second to attack player
void testHit4() {
//Car starts moving to the left end of the screen
ftailx=ftailx-2.5;
//If cars ever reach the end of the screen, pull them back to origin
if (ftailx<0) {
ftailx=ftailx+500;
}
//Shapes that brought together form the car
stroke(0);
fill(200, 0, 100);
line(ftailx+30, cos(frameCount/dcount)*mcount+ftaily-60, ftailx+30, cos(frameCount/dcount)*mcount+ ftaily-10);
strokeWeight(4);
rect(ftailx, cos(frameCount/dcount)*mcount+ftaily, carw, carh, 40);
fill(0);
rect(ftailx, cos(frameCount/dcount)*mcount+ftaily+20, carw+20, carh-20, 50);
rect(ftailx+24, cos(frameCount/dcount)*mcount+ftaily, carw-40, carh+10, 40);
fill(0);
line(ftailx-45, cos(frameCount/dcount)*mcount+ftaily, ftailx-30, cos(frameCount/dcount)*mcount+ftaily);
noStroke();
fill(0, 0, 255);
ellipse(ftailx-45, cos(frameCount/dcount)*mcount+ftaily, 10, 10);
ellipse(ftailx+30, cos(frameCount/dcount)*mcount + ftaily, tailw, 30);
rect(ftailx+31, cos(frameCount/dcount)*mcount+ftaily-61, 8, 8);
fill(0);
ellipse(ftailx, cos(frameCount/dcount)*mcount+ftaily-30, humanH, humanH);
//Global variables that reduce code and will establish a hitbox
ftailL=ftailx-carw/2;
ftailR=ftailx+carw/2;
ftailT=ftaily-carh/2;
ftailB=ftaily+carh/2;
}
//Hitbox for first enemy car
boolean checkCircle() {
if (tailL<carRR&&tailR>carLL&tailB>carUU&tailT<carDD) {
return true;
} else {
return false;
}
}
//Hitbox for second enemy car
boolean checkCircle2() {
if (sTailL<carRR2&&sTailR>carLL2&&sTailB>carUU2&&sTailT<carDD2) {
return true;
} else {
return false;
}
}
//Hitbox for third enemy car
boolean checkCircle3() {
if (stAilL<carRR&&stAilR>carLL&stAilB>carUU&stAilT<carDD) {
return true;
} else {
return false;
}
}
//Hitbox for fourth enemy car
boolean checkCircle4() {
if (ftailL<carRR&&ftailR>carLL&ftailB>carUU&ftailT<carDD) {
return true;
} else {
return false;
}
}
//When NPCs touch player, player will be pushed away or enemy will be pushed away
//When Collision occurs player will earn points or lose points
void updateCollision() {
//Collision with first enemy car coming from the left
if (checkTouch) {
score=score+2;
println("nice you have " + score +" points");
tailx=tailx-100;
}
//Collision with second enemy car coming from the right
if (checkTouch2) {
score=score+2;
println("nice you have " + score +" points");
sTailx=sTailx+200;
}
//Collision with third car/ first one to attack player coming from the top left corner
if (checkTouch3) {
score=score-3;
println("ouch, that must of hurt. Now you have " + score + " points");
carx=carx+50;
}
//Collision with fourth car/ second one to attack player coming from the bottom right corner
if (checkTouch4) {
score=score-3;
println("ouch, that must of hurt. Now you have " + score + " points");
carx=carx-50;
}
}
//Congratulate and restart game
void youWin() {
//When player reaches 30 points, congratulate and restart score
if (score>=30) {
score=0;
println("Congrats! you won, try again");
}
}