> show canvas only <


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

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



/**
 * Linked Balls (v3.2)
 * by  NatashaGunaratna (2014/Feb)
 * mod Quark & GoToLoop
 *
 * forum.processing.org/two/discussion/3087/
 * how-to-draw-lines-between-my-circles-where-they-overlap
 *
 * studio.processingtogether.com/sp/pad/export/ro.989GaZC5t7EkE/latest
 */

static final int QUALITY = 2, FPS = 60, BG = -1;
static final int NUM = 0100, MIN = 020, MAX = 0100;
final Bubble[] balls = new Bubble[NUM];

static final String ENGINE = JAVA2D;
//static final String ENGINE = P2D;

boolean isLooping = true;

void setup() {
  size(800, 600, ENGINE);
  frameRate(FPS);
  smooth(QUALITY);

  noFill();
  stroke(Bubble.STROKE);
  strokeWeight(Bubble.WEIGHT);
  ellipseMode(CENTER);

  online = 1/2 == 1/2.;

  for ( int i = 0; i != NUM; balls[i++] = new Bubble(
    random(MAX>>1, width - MAX), random(MAX>>1, height>>1), 
    (int) random(MIN, MAX)) );
}

void draw() {
  background(BG);

  if (!online)  frame.setTitle("FPS: " + round(frameRate));

  for (int j, i = 0; i != NUM; stroke(Bubble.STROKE)) {
    Bubble p, b = balls[j = i++].script();
    stroke(Bubble.LINK);

    while (++j != NUM)
      if (b.isIntersecting(p = balls[j]))  b.linkToBubble(p);
  }
}

void mousePressed() {
  if (isLooping ^= true)  loop();
  else                    noLoop();
}

void keyPressed() {
  mousePressed();
}

class Bubble {
  static final color LINK = #FF4040, STROKE = 0;
  static final float GRAV = .15, WEIGHT = 2.;

  float x, y;
  final short d, r;
  float sx = random(.3, 1.5), sy = random(.1, .5);

  Bubble(float xx, float yy, int dd) {
    x = xx;
    y = yy;
    d = (short) dd;
    r = (short) (dd>>1);
  }

  Bubble script() {
    move();
    bounce();
    gravity();
    display();

    return this;
  }

  void move() {
    x += sx;
    y += sy;
  }

  void bounce() {
    if (x > width  - r | x < r) {
      sx *= -1.;
      move();
    }

    if (y > height - r | y < r) {
      sy *= -1.;
      move();
    }
  }

  void gravity() {
    sy += GRAV;
  }

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

  void linkToBubble(Bubble b) {
    line(x, y, b.x, b.y);
  }

  boolean isIntersecting(Bubble b) {
    return sq(b.x - x) + sq(b.y - y) < sq(b.r + r);
  }
}