> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.tkO6pBWaDNN/rev.4014
 * 
 * authors: 
 *   Joonjae Bang

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



//GLOBAL SETUP------------------------------------------------------------------------
float keyLeft;
float keyRight;
float keyDown;
float keyUp;
float space;
int canvasX = 600;
int canvasY = 600;
ArrayList units;
ArrayList bullets;
units = new ArrayList();
bullets = new ArrayList();
float startT;
Player player = new Player(300, 650);

//SETUP------------------------------------------------------------------------
void setup() {
    startT = millis();
    colorMode(RGB);
    rectMode(CENTER);
    size(600, 700);
    background(255);
    smooth();
    frameRate(30);
    units.add(new Enemy(300, 100));
} 

//DRAW FUNCTION------------------------------------------------------------------------
void draw() {
    background(255);
    player.update();
    for(int i=units.size()-1; i>=0; --i){
       Unit temp = (Unit) units.get(i);
       temp.update();
    }
    for(int i = bullets.size()-1; i>=0; --i){
        Bullet temp2 = (Bullet) bullets.get(i);
        temp2.update();
        if(!temp2.valid)
            bullets.remove(i);
    }
}

//UNIT SUPERCLASS------------------------------------------------------------------------
class Unit{
    bool valid;
    float xPos, yPos;
    float nextX, nextY;
    Unit(float startX, float startY){
        valid = true;
        xPos = startX;
        yPos = startY;
    }
    void update(){
        
    }
}

//ENEMY SUBCLASS MECHANICS------------------------------------------------------------------------
class Enemy extends Unit{
    float enemySpeed;
    float timeAlive;
    Enemy(float startX, float startY){
        super(startX, startY);
        enemySpeed = 10;
    }
    
    void shoot(){
        bullets.add(new EnyFire(xPos, yPos + 3));
    }
    
    void update(){
        timeAlive = millis();
        nextX = xPos + cos(timeAlive*0.002)*enemySpeed;
        nextY = yPos + sin(timeAlive*0.002)*enemySpeed;
        fill(255, 124, 0);
        triangle(nextX, nextY+10, nextX-6, nextY-5, nextX+6, nextY-5);
        xPos = nextX;
        yPos = nextY;
        if(timeAlive%20 == 4)
            shoot();
    }
}

//PLAYER SUBCLASS MECHANICS------------------------------------------------------------------------
class Player extends Unit{
    float playerSpeed;
    Player(float startX, float startY){
        super(startX, startY);
        playerSpeed = 8;
    }
    
    void shoot(){
        if(1 == space){
            bullets.add(new PlyFire(xPos, yPos-7));
        }
    }
    
    void update(){
        nextX = xPos + (keyRight-keyLeft)*playerSpeed;
        if(nextX > 5 && nextX < 595)
            xPos = nextX;
        nextY = yPos+(keyDown-keyUp)*playerSpeed;
        if(nextY > 5 && nextY < 695) 
            yPos = nextY;
        fill(14, 122, 114);
        rect(xPos, yPos, 15, 15);
        if(1 == space){
            shoot();
        }
    }
}

//BULLET MECHANICS------------------------------------------------------------------------
class Bullet{
    bool valid;
    float xPos, yPos;
    float vel, accel;
    float velMax;
    Bullet(float startX, float startY){
        xPos = startX;
        yPos = startY;
        vel = 0;
        accel = 20.0;
        velMax = 30.0;
        valid = true;
    }
    void update(){
        float nextVel = vel + accel;
        if(nextVel < velMax)
            vel = nextVel;
        float nextY = yPos - vel;
        if(nextY < 700)
            yPos = nextY;
        else
            valid = false;
        if(valid){
            fill(255,0,0);
            ellipse(xPos, yPos, 5, 5);
        }
    }
}

//ENEMY FIRE SUBCLASS MECHANICS------------------------------------------------------------------------
class EnyFire extends Bullet{
    float xRatio, yRatio;
    EnyFire(float startX, float startY){
        xPos = startX;
        yPos = startY;
        vel = 0;
        accel = 20.0;
        velMax = 30.0;
        valid = true;
        xRatio = -(startX-player.xPos)/distance(startX, player.xPos, startY, player.yPos);
        yRatio = -(startY-player.yPos)/distance(startX, player.xPos, startY, player.yPos);
    }
    void update(){
        float nextVel = vel+accel;
        if(nextVel < velMax)
            vel = nextVel;
        float nextX = xPos+vel*xRatio;
        float nextY = yPos+vel*yRatio;
        if((nextX < 300 && nextX > 0) && (nextY < 700 && nextY > 0)){
            xPos = nextX;
            yPos = nextY;
        }
        else
            valid = false;
        if(distance(xPos, yPos, player.xPos, player.yPos) < 5){
            valid = false;
            player = new Player(300, 650);
        }
        if(valid){
            fill(255, 0, 0);
            ellipse(xPos, yPos, 5, 5);
        }
    }
}

//PLAYER FIRE SUBCLASS MECHANICS------------------------------------------------------------------------

class PlyFire extends Bullet{
    PlyFire(float startX, float startY){
        xPos = startX;
        yPos = startY;
        vel = 0;
        accel = 20.0;
        velMax = 30.0;
        valid = true;
    }
    
    void update(){
        float nextVel = vel + accel;
        if(nextVel < velMax)
            vel = nextVel;
        float nextY = yPos - vel;
        if(nextY < 700)
            yPos = nextY;
        else
            valid = false;
        for(int i=units.size()-1; i>=0; --i){
            Unit temp = (Unit) units.get(i);
            if(distance(xPos, yPos, temp.xPos, temp.yPos) < 10){
                valid = false;
                units.remove(i);
            }
        }
        if(valid){
            fill(255,0,0);
            ellipse(xPos, yPos, 5, 5);
        }
    }
}

//KEYPRESS MECHANICS------------------------------------------------------------------------
void keyPressed(){
    if(key == ' ')
        space = 1;
    if(key == CODED){
        if(keyCode == LEFT)
            keyLeft = 1;
        if(keyCode == RIGHT)
            keyRight = 1;
        if(keyCode == UP)
            keyUp = 1;
        if(keyCode == DOWN)
            keyDown = 1;
    }
}

void keyReleased(){
    if(key == ' ')
        space = 0;
    if(key == CODED){
        if(keyCode == LEFT)
            keyLeft = 0;
        if(keyCode == RIGHT)
            keyRight = 0;
        if(keyCode == UP)
            keyUp = 0;
        if(keyCode == DOWN)
            keyDown = 0;
    }
}

//DISTANCE CALCULATION
int distance(float x1, float y1, float x2, float y2){
    return sqrt(pow((x1-x2),2) + pow((y1-y2), 2));
}