fractalkitty looking for math? fractalkitty.com

sound

hatching vis

#random#trig#physics#classes#color#sound#interactive#animation#music

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"
  ]
];