> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.x-kDyRWoY9j/rev.16
 * 
 * authors: 
 *   GoToLoop

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



// http://forum.processing.org/topic/bouncing-ball-app-can-anyone-help-me-implement-vectors
// http://forum.processing.org/topic/collision-detection-29-4-2013

// http://studio.processingtogether.com/sp/pad/export/ro.91xkuWl51J$Vp/latest

final static short NUM_BALLS = 4, DIM = 0200, FPS = 50;
final static Ball[] balls = new Ball[NUM_BALLS];

final static String ENGINE = P2D; // use JAVA2D on Processing 2+

void setup() {
  size (800, 600, ENGINE);
  frameRate(FPS);
  smooth();
  noCursor();
  noStroke();
  fill(Ball.COLOUR);

  balls[0] = new Ball(DIM >> 1, 0);

  for ( int i=1; i!=NUM_BALLS; balls[i] = new Ball(DIM, i++) );
}

void draw() {
  background(0);
  for (Ball b: balls)  b.script();
}

final class Ball {
  float x, y, vx, vy;
  final int diam, rad, id;

  final static float SPRING = .2, FRICTION = -.4;

  final static color TRANSLUCENT = 0xCC << 030;
  final static color COLOUR = 0xFFFFFF | TRANSLUCENT;

  Ball(int d, int ident) {
    diam = d;
    rad  = d >> 1;
    id   = ident;
  }

  void script() {
    update();
    collide();
    display();
  }

  void display() {
    ellipse(x, y, diam, diam);
  }

  void collide() {
    int i = id;
    while (++i != NUM_BALLS) {
      final Ball b = balls[i];

      final float xx = b.x, yy = b.y;
      final float dx = xx - x, dy = yy - y;

      final float distance = sqrt(dx*dx + dy*dy);
      final float minDist  = b.rad + rad;

      if (distance >= minDist)    continue;
      
      final float ang = atan2(dy, dx);
      final float tx = x + cos(ang)*minDist;
      final float ty = y + sin(ang)*minDist;
      final float ax = (tx - xx)*SPRING, ay = (ty - yy)*SPRING;

      vx -= ax;
      vy -= ay;

      b.vx += ax;
      b.vy += ay;
    }
  }

  void update() {
    if (id == 0) {
      x = mouseX;
      y = mouseY;
      return;
    }

    if ( (x += vx) + rad > width ) {
      x = width - rad;
      vx *= FRICTION;
    }
    else if (x - rad < 0) {
      x = rad;
      vx *= FRICTION;
    }

    if ( (y += vy) + rad > height ) {
      y = height - rad;
      vy *= FRICTION;
    }
    else if (y - rad < 0) {
      y = rad;
      vy *= FRICTION;
    }
  }
}