//starting x and y coordinates for star killer
float starkillerX = 200;
float starkillerY = 200;
//spawns planets on righthand side off screen for smoother transition
float planetX = 420;
float planetY;
//stores if the planet is currently onsecreen
boolean planetAlive = false;
//store random colour values for planets
float colourR;
float colourG;
float colourB;
//x and y co-ordinates for the ray
float rayX;
float rayY;
//set the total length of the ray
float rayLengthFront = 0;
float rayLengthBack = 25;
//if the ray is being fired or not
boolean fire = false;
//stroke weight of the ray
float rayThickness = 8;
//the number of planet respawns required for fighter to spawn
float spawnFighter = 4;
//current number of planet respawns
float spawnFighterCount = 0;
//current difficulty of the game
float resistanceLevel = 1;
//progress to the next level - number of planets destroyed
float changeLevel = 0;
//number of planets needed to increse difficulty
float resistanceChange = 6;
//details definig the fighter dimensions
float fighterY = -15;
float fighterX;
//controls respawn fuction for fighter
boolean fighterAlive = false;
//current number of lives - starts with 3
float lives = 3;
//details for lives bar
float livesX = 20;
float livesY = 30;
//Controls the game over screen
boolean gameOver = false;
//records the number of planets shot
int score = 0;
void setup() {
//set canvas size
size(400, 400);
//set rectangle and elipses modes
rectMode(CENTER);
ellipseMode(CENTER);
//set frame rate
frameRate(60);
}
void draw() {
background(3, 9, 23);
drawStars();
//update/dynamic statements
updateResistance();
fighterState();
planetState();
respawnFighter();
respawnPlanet();
shootRay();
updateLives();
moveStarkiller();
///Draw Objects///
drawStarkiller();
drawPlanet();
drawResistanceFighter();
//initiates the UI
drawLives();
//seperate from other update functions has UI text output
updateScore();
//is rendered last so that it covers the screen
checkGameOver();
}
/*User Defined Variables Below*/
///////////////////////////
/////DYNAMIC VARIABLES/////
//////////////////////////
void getPlanetCoordiantes() {
//random Y position between 60 and 340 so that star killer can always reach
planetY = random(60, 340);
}
void getPlanetColours() {
//get random colour for planet
colourR = random(0, 255);
colourG = random(0, 255);
colourB = random(0, 255);
}
void getFighterCoordintates() {
//chooses x coordinated between 40 and 360 so that its always in range of star killer
fighterX = random(40, 340);
}
////////////////////////////
/////MOVEMENT + UPDATES/////
////////////////////////////
void moveStarkiller() {
//change position of star killer when keys are pressed
//cant move while shooting / moving while shooting enabled user to hit a planet they had missed
//stops starkiller from moving off of the canvas
if (keyPressed && fire==false) {
////move up
if (key == 'w' && starkillerY-40>height-height || key == 'W' && starkillerY-40>height-height ||keyCode == UP && starkillerY-40>height-height) {
starkillerY = starkillerY - 2;
}
//move down
else if (key == 's' && starkillerY+40<height || key == 'S' && starkillerY+40<height ||keyCode == DOWN && starkillerY+40<height ) {
starkillerY = starkillerY + 2;
}
//move right
else if (key == 'd' && starkillerX+40<width || key == 'D' && starkillerX+40<width ||keyCode == RIGHT && starkillerX+40<width ) {
starkillerX = starkillerX + 2;
}
//move left
else if (key == 'a' && starkillerX-40>width-width || key == 'A' && starkillerX-40>width-width ||keyCode == LEFT && starkillerX-40>width-width ) {
starkillerX = starkillerX - 2;
} else if (fire == true) {
println("can't move while shooting");
}
}
}
//shootRay Adapted from Shape Shooter by Carsten Booth - 2017 Gallery
void shootRay() {
if (keyPressed) {
//press spacebar to fire ray
if (key == ' ')
//cause ray to fire
fire = true;
}
//if shooting has been set to true, create a laser based on the code-block below
if (fire == true) {
//match ray to Starkiller firing hole
stroke(193, 41, 46);
//make ray slightly smaller than firing hole
strokeWeight(rayThickness);
//Draw ray line
rayX = starkillerX+25;
rayY = starkillerY;
line(rayX+rayLengthBack, rayY, rayX+rayLengthFront, rayY);
//Create movement of ray. rayLengthBack disconnects ray from starkiller
rayLengthFront = rayLengthFront + 10;
rayLengthBack = rayLengthBack + 10;
}
//once ray touches end of screen reset it
if (rayLengthFront >= 400) {
fire = false;
}
//once ray goes offscreen reset ray
if (fire == false) {
rayLengthFront =0;
rayLengthBack = 25;
}
}
//checks if the planet has been destroyed
void planetState() {
//checks if the ray has hit the planet
if (rayX + rayLengthFront >= planetX-20 && rayY <= planetY+20 && rayY >= planetY-20) {
//setting to false allows planet to be reset
planetAlive = false;
//stops firing
fire = false;
//increases the score
score++;
//increases the difficulty
changeLevel++;
} else if (planetX+20<0) {
//checks if planet has moved offscreen
planetAlive = false;
}
}
void respawnPlanet() {
//boolean stops planet from constantly resetting
if (planetAlive == false) {
//resets planet X bak to left hand side of screen
planetX=380;
//new random Y position
getPlanetCoordiantes();
//new pandom colour
getPlanetColours();
//increases count till next fighter
spawnFighterCount++;
//planet is back onscreen
planetAlive = true;
}
}
void respawnFighter() {
//checks to see if fighter can be respawned
if (fighterAlive == false && spawnFighterCount >= spawnFighter) {
//resets planet X back to left hand side of screen
fighterY=-15;
//new random location for fighter
getFighterCoordintates();
//resets planet death counter
spawnFighterCount=0;
//fighter is now back on screen
fighterAlive = true;
}
}
//checks if fighter if offscreen
void fighterState() {
if (fighterY>=height) {
fighterAlive = false;
}
}
void updateLives() {
//checks if fighter has collided with star killer
if (fighterY+30 >= starkillerY-40 && fighterY+30 <= starkillerY+40 && fighterX+15 <= starkillerX+40 && fighterX+15 >= starkillerX-40 && fighterAlive==true) {
//fighter is no longer active
fighterAlive=false;
//decreased lives
lives--;
//transports fighter offscreen till next respawn
fighterY = 500;
}
}
void checkGameOver() {
//checks if player has lost all lives
if (lives==0) {
gameOver = true;
}
//displays a game over screen
if (gameOver == true) {
noStroke();
fill(3, 9, 23);
rect(200, 200, 400, 400);
fill(193, 41, 46);
textSize(24);
text("YOU have FAILED the First Order", 10, 180);
textSize(16);
text("Click to try Again", 130, 230);
}
}
//displays and keeps number of planets destroyed
void updateScore() {
textSize(16);
text("Planets Destroyed:"+score, 230, 35);
}
//updates difficulty level
void updateResistance() {
//checks if difficulty should be incresed
if (changeLevel>=resistanceChange) {
resistanceLevel++;
//resets next difficulty incrementor
changeLevel=0;
}
}
//resets game
//checks if game is over to avoid resetting while game is in progress
//sets core variables back to default
void mouseClicked() {
if (gameOver==true) {
lives = 3;
resistanceLevel = 1;
gameOver=false;
score = 0;
starkillerX=200;
starkillerY=200;
}
}
/////////////////////
//////DRAWINGS///////
////////////////////
void drawStarkiller() {
//clean minimalist aesthetic
noStroke();
//starkiller main planet
fill(167, 181, 186);
ellipse(starkillerX, starkillerY, 80, 80);
//starkiller firing strip
fill(94, 105, 115);
ellipse(starkillerX+25, starkillerY, 20, 20);
rect(starkillerX+7.5, starkillerY, 55, 10);
//firing hole
fill(193, 41, 46);
ellipse(starkillerX+25, starkillerY, 10, 10);
//notch in starkiller
fill(3, 9, 23);
rect(starkillerX+37.5, starkillerY, 5, 10);
}
//Code inspired by Touch the Stars by Saneliso Dube - 2018 Interactive Drawing
//twinkiling effect created by change in size from sin and cos
void drawStars() {
ellipse(60, 10, (cos(20+frameCount/20.04)*5), (cos(20+frameCount/20.04)*5));
ellipse(370, 30, (sin(20+frameCount/20.65)*5), (sin(20+frameCount/20.65)*5));
ellipse(160, 120, (cos(20+frameCount/20.65)*5), (cos(20+frameCount/20.65)*5));
ellipse(20, 280, (cos(20+frameCount/22.33)*5), (cos(20+frameCount/22.33)*5));
ellipse(200, 390, (sin(20+frameCount/22.33)*5), (sin(20+frameCount/22.33)*5));
ellipse(260, 230, (cos(20+frameCount/14.33)*5), (cos(20+frameCount/14.33)*5));
ellipse(140, 340, (cos(20+frameCount/14.33)*5), (cos(20+frameCount/14.33)*5));
ellipse(260, 360, (sin(20+frameCount/14.33)*5), (sin(20+frameCount/14.33)*5));
ellipse(240, 160, (sin(20+frameCount/23.65)*5), (sin(20+frameCount/23.65)*5));
ellipse(270, 40, (cos(20+frameCount/23.65)*5), (cos(20+frameCount/23.65)*5));
ellipse(200, 180, (sin(20+frameCount/18.65)*5), (sin(20+frameCount/18.65)*5));
ellipse(360, 80, (cos(20+frameCount/20.04)*5), (cos(20+frameCount/20.04)*5));
ellipse(300, 200, (sin(20+frameCount/20.65)*5), (sin(20+frameCount/20.65)*5));
}
void drawPlanet() {
noStroke();
//makes planet move to the left
planetX=planetX-resistanceLevel;
fill(colourR, colourG, colourB);
ellipse(planetX, planetY, 40, 40);
}
void drawResistanceFighter() {
noStroke();
fill(235, 235, 211);
triangle(fighterX, fighterY, fighterX+10, fighterY, fighterX+5, fighterY+30);
//makes fighter move down the screen at twice the speed of planets
fighterY=fighterY+resistanceLevel*2;
}
void drawLives() {
//UI Bar
noStroke();
fill(193, 41, 46, 128);
rect(200, livesY, 400, 20);
//spacing between lives circles
int spacing = 0;
//lives that have been drawn already
float livesDrawn = 0;
//continuously checks the the number of lives available
//while loop displays same circle a bit to the right
while (livesDrawn<lives) {
noStroke();
fill(167, 181, 186);
ellipse(livesX+spacing, livesY, 10, 10);
livesDrawn++;
spacing = spacing + 15;
}
}