> show canvas only <


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

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



/**
 * Clickable Spawning Balls (v3.1.1)
 * by  drov.fr  (2013/Jun)
 * mod GoToLoop (2013/Dec)
 * refactor ver (2016/Nov/30)
 *
 * forum.Processing.org/two/discussion/19200/
 * create-10-instances-of-an-object-python#Item_8
 *
 * forum.Processing.org/one/topic/nullpointerexeption-with-an-arraylist
 * forum.Processing.org/two/discussion/2171/effect-in-processing#Item_3
 *
 * p5js.SketchPad.cc/sp/pad/view/ro.CwHWpJ$SP1EN8i/latest
 * studio.ProcessingTogether.com/sp/pad/export/ro.9oyKfI9kOIa77/latest
 */
 
"use strict";

const balls = [];
let bg;

function setup() {
  createCanvas(600, 400).mousePressed(() => {
    if (mouseButton != CENTER)  balls.push( new Ball );
    else balls.length && --balls.length;
  });

  frameRate(60).ellipseMode(CENTER).colorMode(RGB);
  fill(Ball.COLOUR).noStroke();

  bg = color(0);
}

function draw() {
  background(bg);
  for (let b of balls)  b.script();
  document.title = '# Balls: ' + balls.length;
}

class Ball {
  constructor() {
    this.x = mouseX, this.y = mouseY;

    this.spX = ~~random( Ball.MIN_SPD, Ball.MAX_SPD );
    random(1) < .5 && (this.spX *= -1);
 
    this.spY = ( ~~random( Ball.MIN_SPD, Ball.MAX_SPD ) *
               ( random(1) < .5 && -1 || 1 ) );
  }

  script() {
    this.bump(), this.show();
  }

  bump() {
    (this.x += this.spX)<Ball.RAD | this.x>width-Ball.RAD && (this.spX *= -1);
    this.y += this.spY *= this.y<Ball.RAD | this.y>height-Ball.RAD && -1 || 1;
  }

  show() {
    ellipse(this.x, this.y, Ball.DIAM, Ball.DIAM);
  }
}

Ball.DIAM = 20, Ball.RAD = Ball.DIAM >> 1;
Ball.MIN_SPD = 1, Ball.MAX_SPD = 5 + 1;
Ball.COLOUR = 'yellow';