/*
Spooky Scary Skeleton Boss
By Sebastian Scaini
How to play:
Move with the mouse and dodge the spooky scary skeleton's bullets.
Click to shoot your bullets at him. You have to hit his head or he won't take damage!
But be careful, if his bullets hit you you'll take damage.
May the best player/skeleton win!
*/
// Make various variables to create player, skeleton, hyperdrive and control the flow of the game.
int numberOfEffects = 400;
int timeCheck;
ship playerShip;
hyperdriveEffect[] hyperdrive;
boss skeleton;
healthBar bossHealth;
healthBar playerHealth;
String status;
void setup() {
ellipseMode(RADIUS);
size(400, 600);
//create all the in-game elements.
playerShip = new ship();
hyperdrive = new hyperdriveEffect[numberOfEffects];
skeleton = new boss(160, 0, 600);
bossHealth = new healthBar(0, 0, skeleton.health, 10, #FF0000);
playerHealth = new healthBar(0, 590, 10, playerShip.health, #08E813);
//start the timeCheck
timeCheck = millis();
//create the hyperdrive effect
for (int i = 0; i < hyperdrive.length; i++) {
hyperdrive[i] = new hyperdriveEffect(random(0, 400), -10, 0, random(5, 20));
}
}
void draw() {
background(#0E1538);
//control and display the hyperdrive effect
for (int i = 0; i < hyperdrive.length; i++) {
hyperdrive[i].make();
hyperdrive[i].move();
}
//control and display the player's bullets
playerShip.moveBullets();
//control and display the player's ship
playerShip.move();
//update player's health bar
playerHealth.barWidth = playerShip.health;
//update skeleton's health bar
bossHealth.barHeight = skeleton.health;
playerShip.display();
//display the skeleton's health bar
bossHealth.display();
//display the player's health bar
playerHealth.display();
//display the skeleton boss
skeleton.display();
// shoot when the mouse is pressed and delay it to shoot every few milliseconds.
if (mousePressed) {
if (millis() >= timeCheck + 100) {
playerShip.shoot();
timeCheck = millis();
}
}
//check the status of the game (win/lose)
checkGameStatus();
}
//inspired by the circle_overlap adventures in code excersize and http://www.openprocessing.org/sketch/8005
//Check collisions of the player's bullets with the skeleton's head
boolean checkPBCollision() {
if (dist(playerShip.bullet.position.x, playerShip.bullet.position.y, skeleton.bossCollision.position.x, skeleton.bossCollision.position.y) < playerShip.bullet.bulletRadius + skeleton.bossCollision.collisionWidth) {
playerShip.bullet.moved = true;
return true;
} else {
return false;
}
}
// check the collisions of the skeleton's left hand's bullets and the player's ship
String checkLeftEBCollision() {
if (dist(skeleton.leftHand.bullet1.position.x, skeleton.leftHand.bullet1.position.y, playerShip.shipCollision.position.x, playerShip.shipCollision.position.y) < skeleton.leftHand.bullet1.bulletRadius + playerShip.shipCollision.collisionWidth) {
skeleton.leftHand.bullet1.removeBullet = true;
return "L1";
}
if (dist(skeleton.leftHand.bullet2.position.x, skeleton.leftHand.bullet2.position.y, playerShip.shipCollision.position.x, playerShip.shipCollision.position.y) < skeleton.leftHand.bullet2.bulletRadius + playerShip.shipCollision.collisionWidth) {
skeleton.leftHand.bullet2.removeBullet = true;
return "L2";
}
if (dist(skeleton.leftHand.bullet3.position.x, skeleton.leftHand.bullet3.position.y, playerShip.shipCollision.position.x, playerShip.shipCollision.position.y) < skeleton.leftHand.bullet3.bulletRadius + playerShip.shipCollision.collisionWidth) {
skeleton.leftHand.bullet3.removeBullet = true;
return "L3";
}
if (dist(skeleton.leftHand.bullet4.position.x, skeleton.leftHand.bullet4.position.y, playerShip.shipCollision.position.x, playerShip.shipCollision.position.y) < skeleton.leftHand.bullet4.bulletRadius + playerShip.shipCollision.collisionWidth) {
skeleton.leftHand.bullet4.removeBullet = true;
return "L4";
} else {
return null;
}
}
// check the collisions of the skeleton's right hand's bullets and the player's ship
String checkRightEBCollision() {
if (dist(skeleton.rightHand.bullet1.position.x, skeleton.rightHand.bullet1.position.y, playerShip.shipCollision.position.x, playerShip.shipCollision.position.y) < skeleton.rightHand.bullet1.bulletRadius + playerShip.shipCollision.collisionWidth) {
skeleton.rightHand.bullet1.removeBullet = true;
return "R1";
}
if (dist(skeleton.rightHand.bullet2.position.x, skeleton.rightHand.bullet2.position.y, playerShip.shipCollision.position.x, playerShip.shipCollision.position.y) < skeleton.rightHand.bullet2.bulletRadius + playerShip.shipCollision.collisionWidth) {
skeleton.rightHand.bullet2.removeBullet = true;
return "R2";
}
if (dist(skeleton.rightHand.bullet3.position.x, skeleton.rightHand.bullet3.position.y, playerShip.shipCollision.position.x, playerShip.shipCollision.position.y) < skeleton.rightHand.bullet3.bulletRadius + playerShip.shipCollision.collisionWidth) {
skeleton.rightHand.bullet3.removeBullet = true;
return "R3";
}
if (dist(skeleton.rightHand.bullet4.position.x, skeleton.rightHand.bullet4.position.y, playerShip.shipCollision.position.x, playerShip.shipCollision.position.y) < skeleton.rightHand.bullet4.bulletRadius + playerShip.shipCollision.collisionWidth) {
skeleton.rightHand.bullet4.removeBullet = true;
return "R4";
} else {
return null;
}
}
//check the game's status. Trigger game over if win/lose conditions are met.
void checkGameStatus() {
if (skeleton.health <= 0) {
status = "win";
gameOver();
}
if (playerShip.health <= 0) {
status = "lose";
gameOver();
}
}
//end the game by filling the screen with black and showing win/lose text.
void gameOver() {
fill(0);
rect(0, 0, 400, 600);
fill(255);
if (status == "win") {
textSize(50);
text("You win!", 100, 300);
} else if (status == "lose") {
textSize(50);
text("You lose!", 100, 300);
}
}class boss {
// variables
PVector position = new PVector(), velocity = new PVector();
float health;
bossHand leftHand = new bossHand(100, 70, 1, 0, 40, 140, "left"), rightHand = new bossHand(300, 70, 1, 0, 260, 360, "right");
collision bossCollision;
//set variables for this object
boss(float tempPosX, float tempPosY, float tempHealth) {
this.position.x = tempPosX;
this.position.y = tempPosY;
this.health = tempHealth;
bossCollision = new collision(position.x + 40, position.y + 30, 40, 40);
}
void display() {
//draw the head
drawHead();
//draw and update the left arm and hand
leftHand.move();
leftHand.display();
drawLeftArm();
//draw and update the right arm and hand
rightHand.move();
rightHand.display();
drawRightArm();
//update collision ellipse on the boss head.
bossCollision.update();
}
//draw the head
void drawHead() {
stroke(0);
fill(255);
rect(position.x, position.y, 80, 60);
rect(position.x + 20, position.y + 60, 40, 20);
strokeWeight(3);
line(position.x + 30, position.y + 15, position.x + 30, position.y + 35);
line(position.x + 50, position.y + 15, position.x + 50, position.y + 35);
line(position.x + 30, position.y + 65, position.x + 30, position.y + 75);
line(position.x + 40, position.y + 65, position.x + 40, position.y + 75);
line(position.x + 50, position.y + 65, position.x + 50, position.y + 75);
strokeWeight(1);
}
//draw the left arm
void drawLeftArm() {
stroke(0);
fill(255);
quad(160, 0, 160, 20, leftHand.position.x + 20, leftHand.position.y + 15, leftHand.position.x, leftHand.position.y);
}
//draw the right arm
void drawRightArm() {
stroke(0);
fill(255);
quad(240, 0, 240, 20, rightHand.position.x - 20, rightHand.position.y + 15, rightHand.position.x, rightHand.position.y);
}
//take damage
void takeDamage() {
health -= 0.3;
}
}class bossHand {
// make variables
PVector position = new PVector(), velocity = new PVector();
float leftBounds, rightBounds;
int timeCheck = millis();
boolean swap = true;
String type;
ArrayList<enemyBullet> bossBullets;
enemyBullet bullet1, bullet2, bullet3, bullet4;
//set variables for this object
bossHand(float tempPosX, float tempPosY, float tempVelX, float tempVelY, float tempBoundL, float tempBoundR, String tempType){
this.position.x = tempPosX;
this.position.y = tempPosY;
this.velocity.x = tempVelX;
this.velocity.y = tempVelY;
this.type = tempType;
this.leftBounds = tempBoundL;
this.rightBounds = tempBoundR;
bossBullets = new ArrayList();
}
void display(){
//draw hand
stroke(0);
fill(255);
triangle(position.x, position.y, position.x + 20, position.y + 15, position.x - 20, position.y + 15);
rect(position.x - 20, position.y + 15, 5, 10);
rect(position.x - 7.5, position.y + 15, 5, 10);
rect(position.x + 5, position.y + 15, 5, 10);
rect(position.x + 15, position.y + 15, 5, 10);
//shoot with a random time interval
if (millis() >= timeCheck + random(50, 100)){
shoot();
timeCheck = millis();
}
//move bullets
moveBullets();
}
//move hands
void move(){
//swap swaps directions based off true or false
if (swap){
position.add(velocity);
if (position.x == rightBounds){
swap = false;
}
}
else if (!swap){
position.sub(velocity);
if (position.x == leftBounds){
swap = true;
}
}
}
//shoot bullets
void shoot(){
bullet1 = new enemyBullet(position.x - 20, position.y + 15, random(-10, 10), random(2, 8), 5, #E82C0C);
bullet2 = new enemyBullet(position.x - 7.5, position.y + 15, random(-10, 10), random(2, 8), 5, #E82C0C);
bullet3 = new enemyBullet(position.x + 5, position.y + 15, random(-10, 10), random(2, 8), 5, #E82C0C);
bullet4 = new enemyBullet(position.x + 15, position.y + 15, random(-10, 10), random(2, 8), 5, #E82C0C);
bossBullets.add(bullet1);
bossBullets.add(bullet2);
bossBullets.add(bullet3);
bossBullets.add(bullet4);
}
//move bullets
void moveBullets(){
for (enemyBullet bullet1 : bossBullets){
bullet1.update();
bullet1.display();
//check collisions for bullets from left hand with the player's ship, remove if collided
if (type == "left"){
if (checkLeftEBCollision() == "L1" && !bullet1.hit){
bullet1.removeBullet = true;
bullet1.hit = true;
playerShip.health -= 0.5;
}
else if (checkLeftEBCollision() == "L2" && !bullet2.hit){
bullet2.removeBullet = true;
bullet2.hit = true;
playerShip.health -= 0.5;
}
else if (checkLeftEBCollision() == "L3" && !bullet3.hit){
bullet3.removeBullet = true;
bullet3.hit = true;
playerShip.health -= 0.5;
}
else if (checkLeftEBCollision() == "L4" && !bullet4.hit){
bullet4.removeBullet = true;
bullet4.hit = true;
playerShip.health -= 0.5;
}
}
//check collisions for bullets from right hand, remove if collided
else if (type == "right"){
if (checkRightEBCollision() == "R1" & !bullet1.hit){
bullet1.removeBullet = true;
bullet1.hit = true;
playerShip.health -= 0.5;
}
else if (checkRightEBCollision() == "R2" & !bullet2.hit){
bullet2.removeBullet = true;
bullet2.hit = true;
playerShip.health -= 0.5;
}
else if (checkRightEBCollision() == "R3" & !bullet3.hit){
bullet3.removeBullet = true;
bullet3.hit = true;
playerShip.health -= 0.5;
}
else if (checkRightEBCollision() == "R4" & !bullet4.hit){
bullet4.removeBullet = true;
bullet4.hit = true;
playerShip.health -= 0.5;
}
}
}
}
}class collision{
//make variables
PVector position = new PVector();
float collisionWidth, collisionHeight;
//set variables
collision(float tempX, float tempY, float tempWidth, float tempHeight){
this.position.x = tempX;
this.position.y = tempY;
this.collisionWidth = tempWidth;
this.collisionHeight = tempHeight;
}
void update(){
//draw invisible collision ellipse
noStroke();
fill(0, 0, 0, 0);
ellipse(position.x, position.y, collisionWidth, collisionHeight);
}
}class enemyBullet{
// make variables
PVector position = new PVector(), velocity = new PVector();
color bulletColour;
boolean removeBullet = false, hit = false;
float bulletRadius;
//set variables
enemyBullet(float tempPX, float tempPY, float tempVX, float tempVY, float tempRadius, color tempColour){
this.position.x = tempPX;
this.position.y = tempPY;
this.velocity.x = tempVX;
this.velocity.y = tempVY;
this.bulletRadius = tempRadius;
this.bulletColour = tempColour;
}
void display(){
//if the bullet is not removed, draw bullet
if(!removeBullet){
stroke(0);
fill(bulletColour);
ellipse(position.x, position.y, bulletRadius, bulletRadius);
}
// if the bullet goes out of bounds, remove it
if(position.y > 620 || position.x < 0 || position.x > 400){
removeBullet = true;
}
}
void update(){
//if the bullet is not removed, move it
if(!removeBullet){
position.add(velocity);
}
}
}class healthBar {
float x, y, barHeight, barWidth;
color barColor;
healthBar(float tempX, float tempY, float tempHeight, float tempWidth, color tempColor){
this.x = tempX;
this.y = tempY;
this.barHeight = tempHeight;
this.barWidth = tempWidth;
this.barColor = tempColor;
}
void display(){
//draw the health bar
stroke(0);
fill(barColor);
rect(x, y, barWidth, barHeight);
}
}class hyperdriveEffect {
PVector position = new PVector(), velocity = new PVector();
hyperdriveEffect(float tempPosX, float tempPosY, float tempVelX, float tempVelY){
this.position.x = tempPosX;
this.position.y = tempPosY;
this.velocity.x = tempVelX;
this.velocity.y = tempVelY;
}
void make(){
//draw the effect
noStroke();
fill(255, 255, 255, 150);
rect(position.x, position.y, random(1, 2), 10);
}
void move(){
//move it
position.add(velocity);
//if the y position is offscreen, reset the y position at a new x position and a new random velocity
if(position.y > 610){
position.y = -10;
position.x = random(0, 400);
velocity.y = random(5, 20);
}
}
}class playerBullet {
PVector position = new PVector(), velocity = new PVector();
float bulletRadius;
color bulletColour;
boolean moved = false, hit = false;
playerBullet(float tempPositionX, float tempPositionY, float tempRadius, float tempVelocityX, float tempVelocityY, color tempColour) {
this.position.x = tempPositionX;
this.position.y = tempPositionY;
this.bulletRadius = tempRadius;
this.velocity.x = tempVelocityX;
this.velocity.y = tempVelocityY;
this.bulletColour = tempColour;
}
void display() {
//draw bullet
if (!moved){
fill(bulletColour);
ellipse(position.x, position.y, bulletRadius, bulletRadius);
}
}
void move() {
//move bullet. remove if it goes offscreen
if(!moved){
position.sub(velocity);
if (position.y < -20) {
moved = true;
}
}
}
}class ship {
ArrayList <playerBullet> bulletArrayList;
PVector position = new PVector();
float health = 400;
playerBullet bullet, bullet2;
collision shipCollision;
ship() {
bulletArrayList = new ArrayList();
shipCollision = new collision(position.x, position.y, 20, 20);
}
void display() {
//draw ship
stroke(0);
fill(#FF6300);
rect(position.x - 5, position.y, 10, 20);
fill(255);
triangle(position.x - 7.5, position.y, position.x, position.y - 10, position.x + 7.5, position.y);
rect(position.x - 12.5, position.y + 12, 3, -10);
rect(position.x + 10, position.y + 12, 3, -10);
fill(#FFEA02);
triangle(position.x - 5, position.y + 5, position.x - 20, position.y + 20, position.x - 5, position.y + 20);
triangle(position.x + 5, position.y + 5, position.x + 20, position.y + 20, position.x + 5, position.y + 20);
//update collisions to follow ship
shipCollision.update();
}
void move() {
//move ship relative to mouse location
if (mouseY > 100) {
position.x = mouseX;
position.y = mouseY;
shipCollision.position.x = mouseX + 1;
shipCollision.position.y = mouseY + 10;
}
// prevent the ship from going higher than 100
else {
position.x = mouseX;
shipCollision.position.x = mouseX + 1;
}
}
void shoot() {
//make and shoot bullets
bullet = new playerBullet(position.x - 12.5, position.y, 3, 0, 10, #FFEA02);
bullet2 = new playerBullet(position.x + 12.5, position.y, 3, 0, 10, #FFEA02);
bulletArrayList.add(bullet);
bulletArrayList.add(bullet2);
}
void moveBullets() {
//move and display bullets
for (playerBullet bullet : bulletArrayList) {
bullet.move();
bullet.display();
// check bullet collisions if they have collided with the skeleton
if (checkPBCollision() && !bullet.hit) {
skeleton.takeDamage();
bullet.hit = true;
}
}
}
}