var circles;
function setup() {
createCanvas(windowWidth, windowHeight);
circles = [];
for (var i = 0; i < 30; i++) {
circles.push(new Circle());
}
}
function draw() {
background(255);
var interPoints = [];
noFill();
stroke(210);
for (var i = 0; i < circles.length; i++) {
var c1 = circles[i];
c1.render();
for (var j = i + 1; j < circles.length; j++) {
var c2 = circles[j];
Array.prototype.push.apply(interPoints, c1.getIntersectionPoints(c2));
}
}
for (var i = 0; i < interPoints.length; i++) {
var p = interPoints[i];
noStroke();
fill(167, 117, 160);
ellipse(p.x, p.y, 4, 4);
}
for (var i = 0; i < circles.length; i++) {
var circle = circles[i];
circle.update();
}
}
function Circle() {
this.radius = random(20, 150);
this.loc = createVector(random(this.radius, width - this.radius), random(this.radius, height - this.radius));
var velSize = random(0.2, 2);
var velAng = random(TWO_PI);
this.vel = createVector(velSize * cos(velAng), velSize * sin(velAng));
}
Circle.prototype = {
render: function() {
ellipse(this.loc.x, this.loc.y, this.radius * 2, this. radius * 2);
},
update: function() {
this.loc.add(this.vel);
if (this.loc.x < this.radius) {
this.vel.x *= -1;
this.loc.x += this.vel.x;
}
if (this.loc.x > width - this.radius) {
this.vel.x *= -1;
this.loc.x += this.vel.x;
}
if (this.loc.y < this.radius) {
this.vel.y *= -1;
this.loc.y += this.vel.y;
}
if (this.loc.y > height - this.radius) {
this.vel.y *= -1;
this.loc.y += this.vel.y;
}
},
getIntersectionPoints: function(c) {
var relLoc = p5.Vector.sub(c.loc, this.loc);
var a = (relLoc.magSq() + sq(this.radius) - sq(c.radius)) / 2.0;
var v2sq = relLoc.magSq() * sq(this.radius) - sq(a);
if (v2sq > 0) {
var v1 = relLoc.magSq();
var v2 = sqrt(v2sq);
var p1 = createVector(this.loc.x + (a * relLoc.x + relLoc.y * v2) / v1, this.loc.y + (a * relLoc.y - relLoc.x * v2) / v1);
var p2 = createVector(this.loc.x + (a * relLoc.x - relLoc.y * v2) / v1, this.loc.y + (a * relLoc.y + relLoc.x * v2) / v1);
return [p1, p2];
} else {
return [];
}
}
}