> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.o793JTNaYCT/rev.181
 * 
 * authors: 
 *   Andy Stanford

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



 

float ballX = 400;
float ballY = 300;
float ballDiameter = 10;
float speed = 3;
color ballColor = color(14, 255, 3);
float minStartingDistance = 100;

ArrayList<Enemy> enemies;

color textColor = color(255, 255, 255);

int number_of_starting_enemies = 0;
int frame_rate = 40;
int frame_count = 0;
int seconds_between_spawns = 2;
int enemiesPerSpawn =1;
int color_counter = 0;

int health = 100;
int healthDeclineRate = 1;

boolean gamePaused = true;
boolean gameLost = false;
boolean gamestarted = false;
boolean keyup = false;
boolean keyleft = false;
boolean keyright = false;
boolean keydown = false;
boolean keyspace = false;

int f_size = 14;


void setup() {

  size(800, 600);
  frameRate(30);
  fill(ballColor);
  

  textSize(f_size);

  enemies = new ArrayList<Enemy>();

  int enemies_created = 0;
  while (enemies_created < number_of_starting_enemies) {

    float x = random(0, width);
    float y = getRandomStartingY(x);
    float spd = random(speed * .1, speed * .25);
    color c = color(int(random(100, 255)), 0, int(random(0, 255)));

    enemies.add( new Enemy(x, y, ballDiameter / 2, spd, c));
    enemies_created += 1;
  }
}
float getRandomStartingY(float x) {
  float y;
  if (300 > x) {
    y = random (0, height);
  }
  else if (500 < x) {
    y = random (0, height);
  }
  else {
    boolean goUnder = randomBoolean();

    if (goUnder == true) {
      y = random(400, height);
    }
    else {
      y = random(200, 0);
    }
  }
  return y;
}
float getRandomStartingX() {
  float x = random(0, width);
  return x;
}
ArrayList<Float> getRandomSpawningPosition() {
  float x = random(-10, width + 10);
  float y = random(-10, height + 10);

  while ( x < width && x > 0 && y < height && y > 0) {
    x = random(-10, width + 10);
    y = random(-10, height + 10);
  }
  ArrayList<Float> coordinates = new ArrayList<Float>();
  coordinates.add(x);
  coordinates.add(y);
  return coordinates;
}

void draw() {
  background(0, 0, 0);
  fill(ballColor);
  ellipse(ballX, ballY, ballDiameter, ballDiameter); 

  //draw enemies
  int i = 0;
  while (i < enemies.size ()) {
    enemies.get(i).draw();
    i++;
  }

  if (gameLost) {
    fill(#00B0FF);
    textAlign(CENTER, CENTER);
    textSize(f_size+5);
    text("GAME OVER", width / 2, height / 2);   
    text("You survived for " + secondsPassed() + " seconds!", width / 2, (height / 2) + 50);  
    text("Press spacebar to play again ", width / 2, (height / 2) + 100);
    textSize(f_size); 
  }
  else{
    fill (textColor);
    textAlign(LEFT, TOP);
    String secondsDisplay = "Seconds: ";
    
    if (secondsPassed() == 0.0){
      secondsDisplay += int(secondsPassed());
    }else{
      String temp = "" + int(secondsPassed());
      secondsDisplay += nf(secondsPassed(), temp.length() , 2);
    }
    
    if (gamestarted == false) {
            textAlign(CENTER, CENTER);
       textSize(f_size + 100);
       text("GLOBSTER", width/2, height / 2 - 200);
       textSize(f_size);
       text("Go into full screen mode.\n\nControls: Press spacebar to start game or pause.\nUse arrow keys to try to survive...", width / 2, height / 2 + 75);  
       
       //text("", width / 2 - 100, height / 2 + 200);  
    }
    
    textAlign(LEFT, TOP);
    text(secondsDisplay, 0, 0);
    if (health <= 30) {
      text ("WARNING: Health is dangerously low!", width / 2 - 110, height / 2);
    } 
    
    
    noStroke();
    fill(255, 255, 255);
    rect(width / 2 - 150, 10, 300, 10 + textAscent() + textDescent());
    
     fill(#FF0000);
     float redBarWidth = 294 * float(health) / 100;
    rect(width / 2 - 147, 13, redBarWidth, 4 + textAscent() + textDescent());
    
    text("Health: " + health + "%", 0,  textAscent() + textDescent());
  }

  if (!gamePaused) {
    frame_count ++;

    //move enemies
    stepEnemiesForward();

    // add new enemies every seconds_between_spawns seconds
    if (secondsPassed() % seconds_between_spawns == 0) {
     
      if (health < 100)
        health += 1;
      
      int enemiesAdded = 0;
      while (enemiesAdded < enemiesPerSpawn) {
        
        // add a new enemy
        ArrayList<Float> coords = getRandomSpawningPosition();
        float x = coords.get(0);
        float y = coords.get(1);
        float spd = random(speed * .1, speed * .25);
        color c = color(int(random(100, 255)), 0, int(random(0, 255)));

        enemies.add( new Enemy(x, y, ballDiameter / 2, spd, c));
        enemiesAdded++;
      }
      enemiesPerSpawn ++;
    }

    //Change color if recently injured  
     if (color_counter > 0) {
        color_counter = color_counter - 1;
        ballColor = color(#FA2A0A);
     }
     
     if (color_counter == 0) {
      ballColor = color(14, 255, 3);
      }

   //Movements of player
    if (keyup)
      ballY -= speed;
    if (keydown)
      ballY += speed;
    if (keyleft)
      ballX -= speed;
    if (keyright)
      ballX += speed;

    if (ballY < 0) {
      ballY = height - 2;
    }
    if (ballY > height) {
      ballY = 2;
    }
    if (ballX < 0) {
      ballX = width - 2;
    }
    if (ballX > width ) {
      ballX = 2;
    }
  }
} 



void keyPressed() {
  if (key == CODED) {
    if (keyCode == UP) {
      keyup = true;
    }
    else if (keyCode == DOWN) {
      keydown = true;
    }
    else if (keyCode == LEFT) {
      keyleft = true;
    }
    else if (keyCode == RIGHT) {
      keyright = true;
    }
  }
  else {
  }
}

void keyReleased() {
  if (key == CODED) {
    if (keyCode == UP) {
      keyup = false;
    }
    else if (keyCode == DOWN) {
      keydown = false;
    }
    else if (keyCode == LEFT) {
      keyleft = false;
    }
    else if (keyCode == RIGHT) {
      keyright = false;
    }
  }
  else {
  }
}

void keyTyped() {
  if (key == ' ') {
      gamestarted = true;
    if (gamePaused && gameLost) {
      //reset the game
      ballX = width / 2;
      ballY = height / 2;
      gameLost = false;
      health = 100;
      frame_count = 0;
      color_counter = 0;
      enemies = new ArrayList<Enemy>();
      enemiesPerSpawn = 1;

      //move enemies back to spawn locations
      resetEnemies();
      
    }
    gamePaused = !gamePaused;
  }
}

void resetEnemies() {
  //reset enemies
  int i = 0;
  while (i < enemies.size ()) {

    float new_x = getRandomStartingX();
    float new_y = getRandomStartingY(new_x);

    enemies.get(i).reset(new_x, new_y);
    i++;
  }
}

void stepEnemiesForward() {
  int i = 0;
  while (i < enemies.size ()) {

    enemies.get(i).moveTo(ballX, ballY);

    boolean hasCollided = enemies.get(i).checkCollision(ballX, ballY, ballDiameter / 2);

    if (health <= 0) {
      gamePaused = true;
      gameLost = true;
    }

    if (hasCollided && (health > 0)) {
      health = health - healthDeclineRate;
      ballColor = color(#FAFF00);
      color_counter = 4;
    }

    i++;
  }
}

float secondsPassed() {
  return float(frame_count) / float(frame_rate);
}

boolean randomBoolean() {
  return (random(0, 1) > .5);
}


public class Enemy {
  float x;
  float y;
  float diam;
  float spd;
  color myColor;
  
  public Enemy(float x, float y, float diam, float spd, color c){
    this.x = x;
    this.y = y;
    this.diam = diam;
    this.spd = spd;
    this.myColor = c;
  }
  
  public void draw(){
    noStroke();
    fill(this.myColor);
    ellipse(x, y, diam, diam);
  } 
  
  public void reset(float new_x, float new_y){
   this.x = new_x;
   this.y = new_y; 
  }
  
  public void moveTo(float tar_x, float tar_y){
    this.x = constrain(tar_x, this.x - this.spd, this.x + spd);
    this.y = constrain(tar_y, this.y - this.spd, this.y + spd);
  }
  
  public boolean checkCollision(float tar_x, float tar_y, float tar_radius){
    return dist(this.x, this.y, tar_x, tar_y) < (this.diam / 2+ tar_radius);
  }
}