> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.7YtaUTYHgQb/rev.1760
 * 
 * authors: 
 *   Ari Prasetyo

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



Particles particles;

/**
 * Particle
 */
class Part {
  float x, y;
  float v;
  float dir;
  float size;
  float orbit;
  
  float phase;
  
  float targetX, targetY;
    
  Part(float x0, float y0) {
    x = x0;
    y = y0;
    
    v = 2;
    
    size = random(2, 5);    
    phase = random(0, TWO_PI);
    orbit = random(10, 30);
  }
  
  void draw(float t) {
    float px = x;
    float py = y;
    
    float dx = size * cos(t - phase);
    float dy = size * sin(t - phase);
    
    float sz = 2 + cos(t - phase);

    stroke(#ffffff, 45);
    line(px - dx, py - dy, px + dx, py + dy);
    fill(#ffffff, 30);
    ellipse(
      px + orbit * cos(t - phase) * (1 + 0.3 * cos(1.7 * (t - phase))),
      py + orbit * sin(t - phase) * (1 + cos(t - phase)),
      sz,
      sz
    );
  }
  
  void calc(float t) {
    follow();
      
    dir = atan2(targetY - y, targetX - x) + sin(t + phase);
    
    x += v * cos(dir) + 0.5 * sin(t - phase);
    y += v * sin(dir) + 0.5 * cos(t - phase);
  }
  
  void follow() {
    goto(mouseX, mouseY);
  }
  
  void goto(float xx, float yy) {
    targetX = xx;
    targetY = yy;
  }
}

class Eye extends Part {
  void draw(float t) {
    size = 20 * cos(dist(mouseX, mouseY, x, y) / width);
      
    fill(#ffffff, 50);
    for (int i = 0; i < 50; i++) {
      float r = random(-size/2, size/2);
      float s = random(0, TWO_PI);
      
      ellipse(
        x + r * cos(s),
        y + r * sin(s),
        5,
        5
      );
    }
    
    float px = 0, py = 0;
    
    d = dist(x, y, mouseX, mouseY);
    if (d < size/2) {
      px = mouseX;
      py = mouseY;
    }
    else {
      a = atan2(mouseY - y, mouseX - x);
      px = x + (size / 2 - 3) * cos(a);
      py = y + (size / 2 - 3) * sin(a);
    }
    
    fill(#000000, 180);
    ellipse(px, py, 6, 6);
  }
}

/**
 * Particle Array
 */
class Particles extends ArrayList<Part> {
  Eye eye;
    
  Particles(int count) {
    for (int i = 0; i < count; i++) {
      this.add(new Part(
        random(0, width),
        random(0, height)
      ));
    }
    
    eye = new Eye(0, 0);
    eye.size = 20;
  }
  
  void draw(float t) {
    for (int i = 0; i < this.size(); i++) {
      Part p = this.get(i);
      
      stroke(#00ff00, 10);
      line(p.x, p.y, eye.x, eye.y);
      
      p.draw(t);
      p.calc(t);
    }
    
    calcCenter();
    
    eye.draw(t);
  }
  
  void calcCenter() {
    float ax = 0, ay = 0;
      
    for (int i = 0; i < this.size(); i++) {
      Part p = this.get(i);
      
      ax += p.x;
      ay += p.y;
    }
    
    eye.x = ax / this.size();
    eye.y = ay / this.size();
  }
  
  void randomize() {
    for (int i = 0; i < this.size(); i++) {
      Part p = this.get(i);
      
      p.x = random(0, width);
      p.y = random(0, height);
    }
  }
}

/**
 * Setup code
 */
void setup() {
  size(400, 400);
  smooth();
  
  background(0);
  
  particles = new Particles(100);
}

/**
 * Draw
 */
void draw() {
  float t = (float) millis() / 500;
    
  clear();
  
  particles.draw(t);
}

/**
 * Clear
 */
void clear() {
  fill(#000000, 20);
  noStroke();
  rect(0, 0, width, height);
}

/**
 *
 */
void keyPressed() {
  particles.randomize();
}