> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.C9xqONTO0b5/rev.2500
 * 
 * authors: 
 *   Mitch Davis

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



// Pressing Control-R will render this sketch.

int i = 0; 
Planet[] planets = new Planet[1];
Ship ship = new Ship(400,300);
Planet[] stars = new Planet[200];
boolean instructions = true;
int simulate = 300;
boolean[] keys = new boolean[255];

void setup() {  // this is run once.   
    
    
    // set the background color
    background(0);
    
    // canvas size (Variable aren't evaluated. Integers only, please.)
    size(800, 600); 
      
    // smooth edges
    smooth();
    
    // limit the number of frames per second
    frameRate(30);

    for (int i = 0; i < planets.length(); i++) {
        planets[i] = new Planet(-1);
    }
    
    for (int i = 0; i < stars.length(); i++) {
        stars[i] = new Planet(1);
    }
    
    
    // set the width of the line. 
    strokeWeight(3);
} 

void draw() {  // this is run repeatedly.  
    background(0);

    
    
    if(keys[DOWN])  { ship.yVelocity+=.05; }
    if(keys[UP])    { ship.yVelocity-=.05; } 
    if(keys[LEFT])  { ship.xVelocity-=.05; }
    if(keys[RIGHT]) { ship.xVelocity+=.05; } 
     
    

    for (int i = 0; i < stars.length(); i++) {
        //println("TEST");
        stars[i].draw();
    }

    for (int i = 0; i < planets.length(); i++) {
        //println("TEST");
        planets[i].draw();
    }
    
    
    //println("HEY");
    
    if (ship.moving) {
        ship.update();
        ship.draw();
    } else {
        ship.simulate(simulate);
    }
    
    
    
    if (instructions) {
        textSize(30);
        text("Use Arrow Keys to change trajectory", 15, 60); 
        text("Press ENTER to play/pause", 15, 100);
        
        textSize(15);
        text("After you've got the hang of that, try these", 15, 140);
        text("Use 1-9 to change planets", 15, 160);
        text("Press Z to reverse direction (Go backward)", 15, 180);
        text("Press +/- to change prediction length", 15, 180);
        //text("Press i/o to zoom in/out", 15, 200);
    }
}

public void keyPressed() {
     
     if(keyCode == ENTER) {
         ship.moving = ! ship.moving;
         instructions = false;
     }
     
     if (key >= '1' && key <= '9') {
         planets = new Planet[key - '0'];
         setup();    
     }
     
     if (key == 'z') {
         ship.xVelocity = -ship.xVelocity;
         ship.yVelocity = -ship.yVelocity;   
     }
     
     if (key == '+' || key == '=') {
          simulate ++;   
     }
     
     if (key == '-') {
          simulate --;   
     }
     
     keys[keyCode] = true;
}

public void keyReleased() {
     keys[keyCode] = false;   
}

public class Planet {
    int radius;
    int x, y;
    int r,g,b = 0;
    float mass;
    
    public Planet(int size) {
        //Create a random position, and then make
        //sure it doesn't collide with anything.
        
        r = random(255);
        g = random(255);
        b = random(255);
        
        if (size < 0) {
            radius = random(20,100);
        } else {
            radius = size;
            r = g = b = 255;
        }
        
        x = random(radius, width-radius);
        y = random(radius, height-radius);
        
        
        
        mass = (radius * radius);
    }
    
    void draw() {
        fill(r,g,b,255);
        stroke(r/2,g/2,b/2,255);
        
        ellipse(x,y,radius,radius);
    }
    
    void applyGravity(Ship ship) {
        int deltaX = x-ship.x;
        int deltaY = y-ship.y;
        float distance = Math.sqrt((deltaX*deltaX) + (deltaY*deltaY));
        
        
        float pull = mass / distance;
        pull /= distance;
        
        float unitX = deltaX / distance;
        float unitY = deltaY / distance;
        
        ship.xVelocity += (pull * unitX);
        ship.yVelocity += (pull * unitY);
        
        //Apply this pull in the direction of the planet
        
    }
}

public class Ship {
     float x,y;
     float xVelocity, yVelocity;
     
     boolean moving = false;
     
     public Ship(int x, int y) {
        this.x = x;
        this.y = y;
        
        yVelocity = 5;
        xVelocity = 5;
     }   
     
    public void update() {
        //Check each planet
        for (int i = 0; i < planets.length(); i++) {
            planets[i].applyGravity(this);
        }
        
        x += xVelocity;
        y += yVelocity;
    }
    
    public void draw() {
        fill(255,255,255,255);
        stroke(150,150,150,255);
        
        ellipse(x,y,10,10);
    }
    
    public void simulate(int times) {
        //Show velocity
        
        
        //Save everything
        int oldX = x;
        int oldY = y;
        float oldXVel = xVelocity;
        fkiat oldYVel = yVelocity;
        
        for (int i = 0; i < times; i++) {
            update();
            draw();
        }
        
        //Restore everything
        x = oldX;
        y = oldY;
        xVelocity = oldXVel;
        yVelocity = oldYVel;
        
        stroke(255,0,0,255);
        int x2 = x + (xVelocity*10);
        int y2 = y + (yVelocity*10);
        line(x,y,x + (xVelocity*10), y + (yVelocity*10));
    }
}