> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.ENbMPL170m8/rev.1321
 * 
 * authors: 
 *   Marco Disce

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



ArrayList <Mover> bouncers;

ArrayList <PVector> path = new ArrayList<PVector>();
ArrayList <PVector> path2 = new ArrayList<PVector>();

int i = 0; 
color bgcolor;
bgcolor=lerpColor(color(0,0,0),color(random(255),random(255),random(255)),0.3);
color moltitude = color(80,80,80);
int focus=0;

void setup() {  // this is run once.   
    
    // set the background color
    background(bgcolor);
    
    // canvas size (Variable aren't evaluated. Integers only, please.)
    size(300, 300); 
      
    // smooth edges
    smooth();
    
    // limit the number of frames per second
    frameRate(30);
    
    // set the width of the line. 
    strokeWeight(12);
    
     bouncers = new ArrayList();

  for (int i = 0; i < 200; i++)
  {
    Mover m = new Mover();
    bouncers.add (m);
  }
   bouncers.get(focus).c=color(255,255,255); 
} 

void draw() {  // this is run repeatedly.  

//background(bgcolor);
fill(bgcolor);
rect(0,0,width,height);

stroke(135);
strokeWeight(1);
line(0,0,0,height);
line(0,0,width,0);
line(0,height-1,width,height-1);
line(width-1,0,width-1,height);

 int i = 0;
  while (i < bouncers.size () )
  {
    Mover m = bouncers.get(i);
    m.update();
    m.interact(bouncers);
    

    i = i + 1;
  }
  
  PVector node = new PVector();
  node.x=bouncers.get(focus).location.x;
  node.y=bouncers.get(focus).location.y;
  path.add(node);
  
  i=0;
  int s=0;
  s=path.size();
  path2.clear();
  
  maxSize=10000;
  while (i<s){
      /*
      noStroke();
      fill(255,255,255,10);
      ellipse(path.get(i).x,path.get(i).y,10,10);
      */
      colorMode(HSB);
      //strokeWeight(2);
      stroke((255*(1-i/s)+100)%255,255*sqrt(1-i/s),255,255*sqrt(i/s));
      colorMode(RGB);
      if(i>1){
          line(path.get(i).x,path.get(i).y,path.get(i-1).x,path.get(i-1).y);
          }
      i=i+1;
      }
      
  if(s==maxSize){
    path.remove(0);    
  }
  
}

class Mover
{
  PVector direction;
  PVector location;

  float speed;
  float SPEED;

  float ellipseSize;
  
  color c;


  Mover () // Konstruktor = setup der Mover Klasse
  {
    setRandomValues();
  }

  Mover (float x, float y) // Konstruktor = setup der Mover Klasse
  {
    setRandomValues ();
  }

  // SET ---------------------------

  void setRandomValues ()
  {
    location = new PVector (random (width), random (height));
    ellipseSize = random (4, 20);

    float angle = random (TWO_PI);
    direction = new PVector (cos (angle), sin (angle));

    speed = random (1, 4);
    SPEED = speed;
    
    c=lerpColor(moltitude,color(random(255),random(255),random(255)),0.1);

  }

 
  // GENEREL ------------------------------


  void update ()
  {
    {
      // speed = SPEED * 0.7;
      move();
      checkEdgesAndBounce();
    }
    disp();
  }

  void checkEdgesAndBounce ()
  {
    float radius = ellipseSize / 2;

    if (location.x < radius )
    {
      location.x = radius ;
      direction.x = direction.x * -1;
    }
    else if (location.x > width-radius )
    {
      location.x = width-radius ;
      direction.x *= -1;
    }

    if (location.y < radius )
    {
      location.y = radius ;
      direction.y *= -1;
    }
    else if (location.y > height-radius )
    {
      location.y = height-radius ;
      direction.y *= -1;
    }
  }


  // MOVE -----------------------------------------

  void move ()
  {

    PVector velocity = direction.get();
    velocity.mult (speed);
    location.add (velocity);
  }

  // DISPLAY ---------------------------------------------------------------

  void disp ()
  {
  noStroke();
    fill (c);
    ellipse (location.x, location.y, ellipseSize, ellipseSize);
  }


void interact (ArrayList <Mover> boids)
  {

    PVector other;
    float otherSize ;
    
    PVector d1 = direction.get();
    float speed1=speed;
    PVector v1 = PVector.mult (d1,speed1);
    

    for (int i = 0; i < boids.size(); i++)
    {
      other = boids.get(i).location;
      otherSize = boids.get(i).ellipseSize;
      
      if(location!=other){
      
      PVector d2 = boids.get(i).direction;
      float speed2=boids.get(i).speed;
      PVector v2 = PVector.mult (d2,speed2);
      

      float distance = PVector.dist(other, location);
      
      
      
      if (distance < 0.5*(ellipseSize+otherSize)) {
          //color a=lerpColor(c,boids.get(i).c,0.5);
          
          //c=color(distance,distance,distance);
          PVector Connection=PVector.sub(other,location);
          Connection.normalize();
          PVector scarto= new PVector;
          scarto.x=Connection.x;
          scarto.y=Connection.y;
          scarto.mult(0.5*(ellipseSize+otherSize)-distance)
          location.sub(scarto);
          float v1pm=PVector.dot(v1,Connection);
          float v2pm=PVector.dot(v2,Connection);
          PVector v1p=PVector.mult(Connection,v1pm);
          PVector v2p=PVector.mult(Connection, v2pm);
          PVector Deltav=PVector.sub(v1p,v2p);
          v1.sub(Deltav);
          v2.add(Deltav);
          speed=min(v1.mag(),10);
          speed2=v2.mag();
          d1.set(v1);
          d1.normalize();
          d2.set(v2);
          d2.normalize();   
          direction.x=d1.x;
          direction.y=d1.y;
          boids.get(i).direction.x=d2.x;
          boids.get(i).direction.y=d2.y;   
          boids.get(i).speed=min(speed2,10);   
          }
          }
      
      }
    }


}


void mouseClicked(){
  bgcolor=lerpColor(color(0,0,0),color(random(255),random(255),random(255)),0.3);
  color rcolor; 
  int s=bouncers.size();
  for (int i = 0; i < s; i++)
  {
    rcolor=color(random(255),random(255),random(255));  
    bouncers.get(i).c=lerpColor(moltitude,rcolor,0.1);
  }

  
  focus=(focus+1) % s;
  bouncers.get(focus).c=color(255,255,255);
  
  path.clear();

    }