hatching vis
Click to start music. Press space or "c" to play with colors. Click the mouse to change the flocking cohesion.
bArraycrowdDistcohDistmdistxdistydistrandomnessdistArraysoundsum1sum2crowFactorcohFactordirFactorbirdiesgetDistancenewVproSoundportHoleclc
let bArray = [];
let crowdDist = 10;
let cohDist = 100;
let mdist, xdist, ydist;
let randomness = 0.2;
let n = 100;
let distArray;
let sound;
let cn = 0;
let sum1 = 0,
sum2 = 0;
let crowFactor = 0.09,
cohFactor = 0.1,
dirFactor = 0.03;
function preload() {
sound = loadSound(
"/assets/Fall%20Whirlwind%20-%20Draft.mp3"
);
}
function setup() {
userStartAudio();
c = min(windowWidth, windowHeight);
createCanvas(c, c);
for (let i = 0; i < n; i++) {
bArray.push(
new birdies(random(-width / 2, width / 2), random(-width / 2, width / 2))
);
}
angleMode(DEGREES);
noStroke();
sound.amp(0.4);
fft = new p5.FFT();
spectrum = fft.analyze();
}
function draw() {
cohFactor = sum1 / 1000;
t = frameCount;
n = bArray.length;
translate(width / 2, height / 2);
rotate(t / 10);
proSound();
p = color(clc[cn][3]);
p.setAlpha(10);
background(p);
noStroke();
for (let i = 0; i < n; i++) {
fill(i / 2 + 100, i / 2 + 100, 150 + i / 5);
bArray[i].display();
newV(i);
}
portHole();
}
class birdies {
constructor(x, y) {
this.x = x;
this.y = y;
this.vx = random(-1, 1);
this.vy = random(-1, 1);
this.col1 = clc[cn][int(random(1, clc[cn].length))];
this.col2 = clc[cn][int(random(1, clc[cn].length))];
}
display() {
fill(this.col1);
circle(this.x, this.y, 1 + sum1 / 20);
fill(this.col2);
circle(-this.x, this.y, 1 + sum1 / 20);
circle(-this.x, -this.y, 1 + sum1 / 20);
circle(this.x, -this.y, 1 + sum1 / 20);
}
}
function getDistance(x1, y1, x2, y2) {
mdist = dist(x1, y1, x2, y2);
xdist = x1 - x2;
ydist = y1 - y2;
}
function newV(p) {
cArray = [];
cntCrow = 1;
cntCoh = 1;
sumxA = 0;
sumyA = 0;
sumxB = 0;
sumyB = 0;
sumvx = 0;
sumvy = 0;
crow = 0;
coh = 0;
if (bArray[p].x > width / 2) {
bArray[p].x = bArray[p].x - width;
}
if (bArray[p].x < -width / 2) {
bArray[p].x = bArray[p].x + width;
}
if (bArray[p].y > height / 2) {
bArray[p].y = bArray[p].y - height;
}
if (bArray[p].y < -height / 2) {
bArray[p].y = bArray[p].y + height;
}
if (abs(bArray[p].vx) > 2) {
bArray[p].vx = bArray[p].vx / 1.5;
}
if (abs(bArray[p].vy) > 2) {
bArray[p].vy = bArray[p].vy / 1.5;
}
for (let i = 0; i < n; i++) {
if (i !== p) {
getDistance(bArray[p].x, bArray[p].y, bArray[i].x, bArray[i].y);
if (mdist <= crowdDist) {
cArray.push(bArray[i]);
distArray = [{ i, mdist, xdist, ydist }];
sumxA += xdist;
sumyA += ydist;
cntCrow++;
}
if (mdist <= cohDist && mdist > crowdDist) {
cArray.push(bArray[i]);
sumxB += xdist;
sumyB += ydist;
sumvx += bArray[i].vx;
sumvy += bArray[i].vy;
cntCoh++;
}
}
}
avgXcrowd = sumxA / cntCrow;
avgYcrowd = sumxA / cntCrow;
deltaXcrowd = avgXcrowd / crowdDist;
deltaYcrowd = avgYcrowd / crowdDist;
avgXcoh = sumxB / cntCoh;
avgYcoh = sumxB / cntCoh;
deltaXcoh = avgXcoh / cohDist;
deltaYcoh = avgYcoh / cohDist;
avgVx = sumvx / cntCoh;
avgVy = sumvy / cntCoh;
bArray[p].vx =
bArray[p].vx +
deltaXcrowd * crowFactor +
deltaXcoh * cohFactor +
avgVx * dirFactor +
random(-randomness, randomness);
bArray[p].vy =
bArray[p].vy +
deltaYcrowd * crowFactor +
deltaYcoh * cohFactor +
avgVy * dirFactor +
random(-randomness, randomness);
bArray[p].x = bArray[p].x + bArray[p].vx + sum2 / 10;
bArray[p].y = bArray[p].y + bArray[p].vy + sum1 / 50;
}
function mousePressed() {
crowFactor = random(-0.1, 0.1);
cohFactor = random(-0.5, 0.5);
dirFactor = random(-0.2, 0.2);
randomness = random(0, 0.3);
}
function keyPressed() {
if (keyCode === 32) {
cn = int(random(0, clc.length));
}
if (keyCode === 67) {
for (let i = 0; i < bArray.length; i++) {
bArray[i].col1 = clc[cn][int(random(1, clc[cn].length))];
bArray[i].col2 = clc[cn][int(random(1, clc[cn].length))];
}
}
}
function proSound() {
if (sound.isPlaying()) {
} else {
sound.loop();
}
spectrum = fft.analyze();
noStroke();
fill(255, 0, 255);
waves = fft.waveform();
push();
beginShape();
sum1 = 0;
sum2 = 0;
for (let i = 0; i < spectrum.length; i++) {
let x = map(i, 0, spectrum.length, -c / 2, c / 2);
let h = map(spectrum[i], 0, 50, 0, 360);
let x2 = map(i, 0, waves.length, 0, 50);
let y2 = map(waves[i], 0, 1, 0, 360);
stroke(0);
sum1 += spectrum[i];
sum2 += waves[i];
}
sum1 = sum1 / 100;
}
function portHole() {
p.setAlpha(50);
fill(p);
rd = min(width, height) / 2.2;
beginShape();
for (let i = 0; i <= 180; i++) {
x = rd * cos(i);
y = rd * sin(i);
vertex(x, y);
}
vertex(-width, 0);
vertex(-width, height);
vertex(width, height);
vertex(width, 0);
endShape(CLOSE);
beginShape();
for (let i = 179; i <= 361; i++) {
x = rd * cos(i);
y = rd * sin(i);
vertex(x, y);
}
vertex(width, 0);
vertex(width, -height);
vertex(-width, -height);
vertex(-width, 0);
endShape(CLOSE);
stroke(clc[cn][3]);
strokeWeight(1);
noFill();
circle(0, 0, 2 * rd + 50);
}
let clc = [
[
"#04172c",
"#051c34",
"#06223c",
"#082844",
"#092d4c",
"#0b3354",
"#0d395d",
"#0e3f65",
"#10466e",
"#124c77"
],
[
"#1e3a49",
"#2c4655",
"#3b5260",
"#495e6c",
"#576b79",
"#667885",
"#748692",
"#83939f",
"#93a1ac",
"#a2afb9"
],
[
"#523a3b",
"#624a4c",
"#735b5d",
"#856d6f",
"#967f81",
"#a89194",
"#baa4a8",
"#cdb7bb",
"#e0cbcf",
"#f3dfe4"
],
[
"#2c1913",
"#371b13",
"#421c13",
"#4d1d13",
"#581e13",
"#672114",
"#7a2615",
"#8e2c16",
"#a23117",
"#b63718"
],
[
"#412f44",
"#503951",
"#60445e",
"#704f6c",
"#815a7a",
"#8f607c",
"#9b6173",
"#a7616a",
"#b16261",
"#bb6257"
],
[
"#aaa95b",
"#b3b26c",
"#bdba7d",
"#c6c38f",
"#cfcca0",
"#d7d5b1",
"#e0dec3",
"#e8e7d5",
"#f1f0e7",
"#f9f9f9"
],
[
"#0e0e0f",
"#1f1f20",
"#2f3030",
"#404241",
"#525453",
"#656866",
"#787c7a",
"#8c908e",
"#a0a5a2",
"#b5bbb7"
],
[
"#111311",
"#171a16",
"#1d221b",
"#22291f",
"#283124",
"#384030",
"#545745",
"#716f5c",
"#8f8773",
"#afa18b"
],
[
"#2b3032",
"#3e4243",
"#525455",
"#676768",
"#7c7b7b",
"#918e8d",
"#a6a19d",
"#bbb4ad",
"#d0c8bd",
"#e6dcce"
]
];