> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.rFlagR8XScA/rev.1002
 * 
 * authors: 
 *   
 *   
 *   
 *   Alex Stempel
 *   Alex Spielman
 *   

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



//press j to pause sketch and then j again to have it continue

Particle[] bodies = new Particle[1000];
Gravity gravObj;
float area;
float incr;
float xpos;
float ypos;
float countJ;
void setup() {
  size(800, 800);
  countJ = 0;
  area = width*height;
  incr = 243000/15000;
  xpos = 150;
  ypos = 150;
  gravObj = new Gravity();
  for (int i = 0; i < bodies.length; i++) {
    bodies[i] = (new Particle(xpos, ypos, 16));
    if (xpos > (650-incr)) {
      xpos = 150;
      ypos += incr;
    } else {
      xpos += incr;
    }
  }
}
void draw() {
  background(255); 
  gravObj.display();
  for (int i = 0; i < bodies.length; i++) {
    PVector force = gravObj.getForceVector(bodies[i]);
    bodies[i].accelWithGravity(force);
    bodies[i].update();
    bodies[i].create();
  }
}
void mousePressed() {
  gravObj.setLocation();
}

void keyPressed() {
  if (key == 'j') {
    countJ++;
    if (countJ%2 == 1) {
      for (int i = 0; i < bodies.length; i++) {
        bodies[i].storeVel(bodies[i]);
      }
      gravObj.keyPressD = true;
    }
   else if (countJ%2 == 0){
    gravObj.keyPressD = false;
    for (int i = 0; i < bodies.length; i++) {
      bodies[i].setVel(bodies[i]);
    }
  }
  }
}
class Gravity {
  float mass;    
  float g;       
  PVector location;
  public boolean keyPressD;
  Gravity() {
    location = new PVector(width/2, height/2);
    mass = 20;
    g = 1;
    keyPressD = false;
  }
  PVector getForceVector(Particle p) {
    if (keyPressD == true) {
      return new PVector(0, 0);
    }
    float r12 = dist(location.x, location.y, p.getX(), p.getY());
    r12 = constrain(r12, 30, 30);
    PVector unit_r12 = (PVector.sub(location, p.location));
    unit_r12.normalize();
    float m1m2 = (p.mass)*mass;
    PVector f12 = PVector.mult(unit_r12, (g*((m1m2)/pow(r12, 2))));
    return f12;
  }
  void display() {   
    fill(0);
    ellipse(location.x, location.y, mass*2, mass*2);
  }

  void setLocation() {
    location.x = mouseX;
    location.y = mouseY;
  }

  boolean above() {
    if (abs(mouseX - location.x) <= 20 || abs(mouseX - location.y) >= 0) {
      return true;
    }
    return false;
  }
}
class Particle {
  PVector location;
  PVector velocity;
  PVector storeV;
  PVector acceleration;
  float mass;
  float storeM;
  int colors;
  Particle(float x, float y, float m) {
    location = new PVector(x, y);
    velocity = new PVector(0, 0);
    acceleration = new PVector(0, 0);
    mass = m;
    //   float red = random(155, 255);
    // float blue = random(0, 100);
    //  float green = random(0, 10);
    //    colors = color(red, green, blue);   // would it be more effictint to use color = r | g | b | a and << notation
    x = x - 150;
    y = y - 150;
    int a = (int)(255);
    int r = (int)(500 - x);  
    if (x > width/2 -150) {
      r = (int)(x);
    }
    int b = (int)(500 - y); 
    if (y > height/2 -150) {
      b = (int)(y);
    }
    int g = (int)random(0); 
    a = a << 24; 
    r = r << 16;  
    g = g << 8;   
    // Equivalent to "color argb = color(r, g, b, a) but faster?
    colors =  (a | r | g | b);
  }
  void accelWithGravity(PVector force) {
    PVector accel = PVector.div(force, mass);
    acceleration.add(accel);
  }
  void update() {
    velocity.add(acceleration);
    location.add(velocity);
    acceleration.x = 0;
    acceleration.y = 0;
  }

  void storeVel(Particle p) {
    storeV = p.velocity;
    velocity = new PVector(0, 0);
  }

  void setVel(Particle p) {
    velocity = p.storeV;
  }

  void create() {
    fill(colors);
    noStroke();
    ellipse(getX(), getY(), mass, mass);
  }
  float getX() {
    return location.x;
  }
  float getY() {
    return location.y;
  }
}