Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
//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;
  }
}