xxxxxxxxxx
// Inspired by Steve's Makerspace - Rectangle Packing in a Perlin Flow Field
// https://www.youtube.com/watch?v=oKwi8h_yTsY&t=697s
let ball;
let history = [];
let isBackgroundBlack = true;
let hexCurve = false;
const minRadius = 3;
const maxRadius = 100;
class Ball {
constructor() {
this.x = random(width);
this.y = random(height);
this.radius = random(minRadius, maxRadius);
fill(random(256), random(256), random(256));
}
show(){
ellipse(this.x,this.y,this.radius*2);
}
update() {
const n = noise(this.x / width, this.y / height);
const angle = hexCurve ? (int(n * 10) * PI) / 3 : n * 10;
this.x += cos(angle) * this.radius * 2;
this.y += sin(angle) * this.radius * 2;
}
isFrameOut() {
if (
this.x < -this.radius ||
this.y < -this.radius ||
this.x > width + this.radius ||
this.y > height + this.radius
)
return true;
return false;
}
isOverlapped() {
return history.some((h) => {
const d = dist(this.x, this.y, h.x, h.y);
if (d + 1e-10 > h.radius + this.radius) return false;
if (d < h.radius - this.radius) return false;
return true;
});
}
}
function setup() {
createCanvas(windowWidth, windowHeight);
background(isBackgroundBlack ? "black" : "white");
isBackgroundBlack = !isBackgroundBlack;
noStroke();
noiseSeed();
history.length = 0;
}
function draw() {
for (let i = 100; i--; ) drawOneBall();
}
function drawOneBall() {
if (!ball) ball = new Ball();
ball.update();
if (ball.isFrameOut() || ball.isOverlapped()) {
ball = null;
} else {
copyOfThisBall = Object.assign({}, ball)
history.push(copyOfThisBall);
ball.show();
}
}
mousePressed = () => {
hexCurve = random(2) < 1 ? true : false;
setup();
};