Instructions: Use arrow keys to zoom in/out and rotate
let spheres = [];
const sphereRadius = 150;
const minSize = 5;
const maxSize = 20;
const numSpheres = 3500;
let camZ = 0;
let camY = 0;
const colors = ['#618C20', '#F2C029', '#F2CA7E', '#F28627', '#D94B18'];
let zoomAmount;
let rotationAmount;
// Creepy motion variables
let angleOffset;
let offsetChange;
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
noiseDetail(4, 0.4);
zoomAmount = 20;
rotationAmount = PI / 36;
angleOffset = 0;
offsetChange = PI / 180;
for (let i = 0; i < numSpheres; i++) {
addSphere();
}
noStroke();
}
function draw() {
background(200);
translate(0, 0, camZ);
rotateX(frameCount * 0.005);
rotateY(frameCount * 0.005 + camY);
// Smooth rotation and zooming
if (keyIsDown(UP_ARROW)) {
camZ -= zoomAmount;
}
if (keyIsDown(DOWN_ARROW)) {
camZ += zoomAmount;
}
if (keyIsDown(LEFT_ARROW)) {
camY -= rotationAmount;
}
if (keyIsDown(RIGHT_ARROW)) {
camY += rotationAmount;
}
// Create a creepy motion for the bulge
let bulgeX = cos(angleOffset) * 200;
let bulgeY = sin(angleOffset) * 200;
let bulgeVec = createVector(bulgeX, bulgeY, 0);
angleOffset += offsetChange;
for (const sphere of spheres) {
let dX = bulgeVec.x - sphere.x;
let dY = bulgeVec.y - sphere.y;
let distance = sqrt(dX * dX + dY * dY);
let bulgeSize = map(distance, 0, 100, maxSize * 3, sphere.size);
bulgeSize = constrain(bulgeSize, sphere.size, maxSize * 2);
push();
translate(sphere.x, sphere.y, sphere.z);
fill(sphere.sphereColor);
sphere.sphereShape(bulgeSize);
pop();
}
}
function addSphere() {
const size = random(minSize, maxSize);
const theta = random(TWO_PI);
const phi = random(PI);
const x = sphereRadius * sin(phi) * cos(theta);
const y = sphereRadius * sin(phi) * sin(theta);
const z = sphereRadius * cos(phi);
const sphereColor = color(random(colors));
spheres.push({ x, y, z, size, sphereColor, sphereShape: (size) => sphere(size) });
}