/**
** BUST THOSE GHOSTS!
** By: Jensen Verlaan
**
** It's almost Halloween and the ghosts of the graveyard are running rampant again!
** While some are friendly and well behaved, others are acting out and causing mischief around town!
** As the local witch doctor, it's up to you to calm these restless spirits!
** Shoot the bad spirits with your one-of-a-kind "Witch Doctor Zapper Gun" to return them to a peaceful slumber!
** The upper middle score will keep count of how many naughty spirits you send back to their graves!
** But watch out!!! Shooting peaceful spirits will lower your score.
** Happy hunting and Happy Halloween!!!
**
** This work was inspired by "gone_fishing_oo" by Nicolas Hesler and "Balloon Pop" by Ali O'Conner.
**/
//Declare objects as global variables
int numberOfGhosts = 10;
int score = 0;
FriendlyGhosts[] friendlyGhosts = new FriendlyGhosts[numberOfGhosts];
EvilGhosts[] evilGhosts = new EvilGhosts[numberOfGhosts];
Tombstone[] grave1 = new Tombstone[3];
Tombstone[] grave2 = new Tombstone[4];
Tombstone[] grave3 = new Tombstone[5];
void setup() {
//Set canvas size to 400 x 400 pixels
size(400, 400);
//set frame rate to 60
frameRate(60);
noStroke();
noCursor();
//Initialize objects in setup() by calling constructor
createFriendlyGhosts();
createEvilGhosts();
//hardcode locations values into each tombstone
grave1[0] = new Tombstone(20, 220, 40, 70);
grave1[1] = new Tombstone(160, 220, 40, 70);
grave1[2] = new Tombstone(320, 220, 40, 70);
grave2[0] = new Tombstone(-30, 150, 30, 40);
grave2[1] = new Tombstone(100, 150, 30, 40);
grave2[2] = new Tombstone(240, 150, 30, 40);
grave2[3] = new Tombstone(380, 150, 30, 40);
grave3[0] = new Tombstone(-20, 100, 20, 30);
grave3[1] = new Tombstone(80, 100, 20, 30);
grave3[2] = new Tombstone(180, 100, 20, 30);
grave3[3] = new Tombstone(280, 100, 20, 30);
grave3[4] = new Tombstone(380, 100, 20, 30);
}
//Add a number value to each Evil Ghost in the array from 0 - 19
void createEvilGhosts() {
for (int i = 0; i < evilGhosts.length; i++) {
evilGhosts[i] = new EvilGhosts();
}
}
//Add a number value to each Friendly Ghost in the array from 0 - 19
void createFriendlyGhosts() {
for (int i = 0; i < friendlyGhosts.length; i++) {
friendlyGhosts[i] = new FriendlyGhosts();
}
}
void draw() {
////////////////
/////UPDATE/////
////////////////
//update FriendlyGhosts
for (int i = 0; i < friendlyGhosts.length; i++) {
friendlyGhosts[i].update();
}
//updateEvilGhosts
for (int i = 0; i < evilGhosts.length; i++) {
evilGhosts[i].update();
}
/////////////////
/////DISPLAY/////
/////////////////
background(0);
//Draw the background
setting();
//Draw the tombstones
for (int i = 0; i < grave1.length; i++) {
grave1[i].display();
}
for (int i = 0; i < grave2.length; i++) {
grave2[i].display();
}
for (int i = 0; i < grave3.length; i++) {
grave3[i].display();
}
//Draw single cross grave
singleCrossGrave();
//display Friendly Ghosts
for (int i = 0; i < friendlyGhosts.length; i++) {
friendlyGhosts[i].display();
}
//display evil ghosts
for (int i = 0; i < evilGhosts.length; i++) {
evilGhosts[i].display();
}
aimingReticle();
//display the score
updateScore();
}
////////////////////////////
/////SINGLE CROSS GRAVE/////
////////////////////////////
//for the aesthetic
void singleCrossGrave() {
fill(75);
rect(180, 70, 30, 60, 7);
rect(170, 80, 50, 20, 7);
fill(125);
rect(180, 70, 20, 60, 7);
rect(170, 80, 40, 20, 7);
}
////////////////////
/////BACKGROUND/////
////////////////////
//Draw the background
void setting() {
noStroke();
fill(48, 53, 30);
rect(0, 125, width, height);
fill(84, 92, 61);
rect(0, 185, width, height);
fill(87, 103, 72);
rect(0, 280, width, height);
}
//////////////////////
///AIMING RETICLE/////
//////////////////////
//Create Crosshairs that follow the cursor's location
void aimingReticle() {
noFill();
stroke(100, 200, 100);
strokeWeight(3);
ellipse(mouseX, mouseY, 30, 30);
line(mouseX - 20, mouseY, mouseX -10, mouseY);
line(mouseX + 20, mouseY, mouseX + 10, mouseY);
line(mouseX, mouseY + 20, mouseX, mouseY +10);
line(mouseX, mouseY - 20, mouseX, mouseY - 10);
fill(255, 100, 100);
stroke(100, 200, 100);
strokeWeight(5);
point(mouseX, mouseY);
}
///////////////
/////SCORE/////
///////////////
//Create a score that will display in the upper middle of the canvas
void updateScore() {
fill(255);
textSize(32);
text(score, width/2, height/10);
}class EvilGhosts {
//Declare EvilGhost variables
PVector position = new PVector();
PVector velocity = new PVector();
float wide = 50;
float tall = 70;
boolean startWidth = true;
boolean startHeight = true;
EvilGhosts() {
initialize();
}
void initialize() {
//declare starting ghost values
//booleans allows ghosts to spawn in all corners
if (startWidth == true && startHeight == true) {
position.x=width;
position.y=height;
startWidth = false;
} else if (startWidth == false && startHeight == true) {
position.x=0;
position.y=height;
startHeight = false;
} else if (startWidth == false && startHeight == false) {
position.x=0;
position.y=0;
startWidth = true;
} else {
position.x=width;
position.y=0;
startHeight=true;
}
velocity.x = random(-5, 10);
velocity.y = random(-5, 10);
}
void display() {
rectMode(CORNER);
ellipseMode(CENTER);
//body
fill(255, 125);
rect(position.x, position.y, wide, tall, 10);
//tail that wiggles
triangle(position.x + 5, position.y + tall, position.x + wide, position.y + tall, position.x + wide + random(10, 20), position.y + tall + random(10, 20));
//skull
fill(255);
ellipse(position.x + wide/2, position.y + 10, wide-15, wide-15);
//teeth
ellipse(position.x + wide/3, position.y +25, wide-40, wide-35);
ellipse(position.x + wide/2, position.y + 25, wide - 40, wide - 30);
ellipse(position.x + wide/3*2, position.y + 25, wide - 40, wide - 35);
//eyes
fill(0);
ellipse(position.x + wide/3, position.y + 10, wide-40, wide-30);
ellipse(position.x + wide/3*2, position.y + 10, wide-40, wide-30);
//angry eyebrows
fill(255);
quad(position.x + 10, position.y, position.x + 25, position.y + 10, position.x + 25, position.y, position.x + 10, position.y);
quad(position.x + 40, position.y, position.x + 25, position.y + 10, position.x + 25, position.y, position.x + 40, position.y);
}
void update() {
position.add(velocity);
//if ghost had moved off screen, re-initialise ghost
if (position.x < -50 || position.y < -50 || position.x > 450 || position.y > 450) {
initialize();
}
//if ghost is shot, increase score
if (dist(mouseX, mouseY, position.x, position.y) < 30 && mousePressed) {
initialize();
score = score+1;
}
}
}class FriendlyGhosts {
//Declare FriendlyGhost variables
PVector position = new PVector();
PVector velocity = new PVector();
float wide = 50;
float tall = 70;
boolean startWidth = true;
boolean startHeight = true;
FriendlyGhosts() {
initialize();
}
void initialize() {
//declare starting ghost values
//booleans allows ghosts to spawn in all corners
if (startWidth == true && startHeight == true) {
position.x=width;
position.y=height;
startWidth = false;
} else if (startWidth == false && startHeight == true) {
position.x=0;
position.y=height;
startHeight = false;
} else if (startWidth == false && startHeight == false) {
position.x=0;
position.y=0;
startWidth = true;
} else {
position.x=width;
position.y=0;
startHeight=true;
}
velocity.x = random(-5, 10);
velocity.y = random(-5, 10);
}
void display() {
rectMode(CORNER);
ellipseMode(CENTER);
//body
fill(255, 125);
rect(position.x, position.y, wide, tall, 10);
//tail that wiggles
triangle(position.x + 5, position.y + tall, position.x + wide, position.y + tall, position.x + wide + random(10, 20), position.y + tall + random(10, 20));
//skull
fill(255);
ellipse(position.x + wide/2, position.y + 10, wide-15, wide-15);
//eyes
fill(0);
ellipse(position.x + wide/3, position.y + 10, wide-40, wide-30);
ellipse(position.x + wide/3*2, position.y + 10, wide-40, wide-30);
//eye smile
fill(255);
rect(position.x+ 10, position.y +15, 30, 5);
//smile
fill(0);
triangle(position.x + wide/2 - 5, position.y +20, position.x + wide/2 + 5, position.y + 20, position.x + wide/2, position.y +25);
}
void update() {
position.add(velocity);
//if ghost had moved off screen, re-initialise ghost
if (position.x < -50 || position.y < -50 || position.x > 450 || position.y > 450) {
initialize();
}
//if ghost is shot, decrease score
if (dist(mouseX, mouseY, position.x, position.y) < 30 && mousePressed) {
initialize();
score = score-1;
}
}
}//Create a class that draws a tombstone
class Tombstone {
//Declare Tombstone variables
float positionX;
float positionY;
float wide;
float tall;
//Define Tombstone constructor
Tombstone(float tempPositionX, float tempPositionY, float tempWide, float tempTall) {
positionX = tempPositionX;
positionY = tempPositionY;
wide = tempWide;
tall = tempTall;
}
//Create a display function for the tombstones
void display() {
noStroke();
rectMode(CORNER);
ellipseMode(CENTER);
fill(63, 65, 64);
rect(positionX + 10, positionY, wide, tall, 7);
fill(99, 102, 100);
rect(positionX, positionY, wide, tall, 7);
fill(0);
textSize(wide/3);
text("R.I.P.", positionX + wide/8, positionY + tall/2);
fill(38, 21, 10);
ellipse(positionX + wide/2 - 5, positionY + tall+5, wide + 40, tall - 20);
}
}