When picking a project, I really wanted to do something music based. After picking one of my favorite songs, I decided I wanted to play with the bass and frequency. After I made all the lyrics respond to the frequency, I realized I could've just done that in After Effects. I had to brainstorm and add other features to make my project more interesting and interactive. I added a feature where you can change between fonts using the 1, 2, and 3 keys. Following the theme of the song, I added randomly generated flowers that also respond to the frequency of the song. I followed a tutorial for the flowers on happycoding.io. During this time, I also added an animated ghost I found from a tutorial on that same website. Then I coded the ghost to follow the mouse and made it able to eat the flowers. To make it more interesting, I added a scroll feature. When scrolling all the way up the page, the flowers turned into bone shapes that the ghost could also eat. Finally, I painstakingly coded all the lyrics to be on the screen for the same time and duration as the song. This is when I added the rewind and forward function to quicken up the process. You can then pause the song with a play/pause feature in the top right corner. 
Here is my progress below...
https://happycoding.io/tutorials/p5js/animation/ghost
Code

const tailLength = 30;
const ghostSize = 100;
const wiggliness = 10;
const floatiness = 7;
let ghostX;
let ghostY;
const tail = [];
function setup() {
  createCanvas(400, 400);
  ghostX = width / 2;
  ghostY = height / 2;
}
function draw() {
  // The cos() function gives us a value that bounces between -1 and 1.
  // We can use that to create animations!
  ghostX += cos(frameCount / 10) * wiggliness;
  ghostY -= floatiness;
  // If the ghost goes above the top of the canvas, move it back to the bottom.
  if (ghostY < -ghostSize) {
    ghostY = height + ghostSize;
  }
  // Add a point to the beginning of the array.
  tail.unshift({x: ghostX, y: ghostY});
  // If the array is too big, remove the last point.
  if (tail.length > tailLength) {
    tail.pop();
  }
  background(64, 0, 32);
  noStroke();
  // Loop over the tail and draw the points.
  for (var index = 0; index < tail.length; index++) {
    const tailPoint = tail[index];
    // Tail gets smaller and more transparent.
    const pointSize = ghostSize * (tail.length - index) / tail.length;
    const pointAlpha = 255 * (tail.length - index) / tail.length;
    fill(255, pointAlpha);
    ellipse(tailPoint.x, tailPoint.y, pointSize);
  }
  // Draw the ghost's face.
  fill(32);
  ellipse(ghostX - ghostSize * .2, ghostY - ghostSize * .1, ghostSize * .2);
  ellipse(ghostX + ghostSize * .2, ghostY - ghostSize * .1, ghostSize * .2);
  ellipse(ghostX, ghostY + ghostSize * .2, ghostSize * .2);
}
https://happycoding.io/tutorials/p5js/creating-functions
Code
function setup()
 { createCanvas(300, 300); background(0, 200, 0);} 
 function draw()
 { let flowerX = 150; 
 let flowerY = 150; 
 let petalSize = 100;
 let petalDistance = petalSize / 2; fill(255, 128, 0); 
 // upper-left petal circle(flowerX - petalDistance, flowerY - petalDistance, petalSize); 
 // upper-right petal circle(flowerX + petalDistance, flowerY - petalDistance, petalSize); 
 // lower-left petal circle(flowerX - petalDistance, flowerY + petalDistance, petalSize);
 // lower-right petal circle(flowerX + petalDistance, flowerY + petalDistance, petalSize );
 // center petal fill(255, 0, 0); circle(flowerX, flowerY, petalSize);}
The bones I made myself with a rectangles and ellipses.
https://www.youtube.com/watch?v=2O3nm0Nvbi4
Professor Miller suggested to watch The Coding Train with Danny Shiftman. This man got me through all of my frequency code even if it didn't matter that much in the end :(. 
That being said, I had a lot of trial and error with this.
Frequency experimentations.
The original frequency graph with the text looked like this.
I had a lot of issues with this....
My Project originally looked like this, but I wanted to make it on theme with the album. The artist Phoebe Bridgers uses a lot of skeletons and ghosts in the themes of her work, so I wanted to integrate those and use similar colors.
See the code in action here:
https://editor.p5js.org/natkam/sketches/qX2GPWzUJ

All the code is down below.
const tailLength = 30;
const ghostSize = 100;
const wiggliness = 10;
const floatiness = 7;
var maxFlowers = 1000;
let ghostX;
let ghostY;
let tail = [];
const boneHeight = 30;
const boneWidth = 5;
var song;
var fft;
var button;
var font1, font2, font3;
var currentFont;
let flowers = [];
let sensitivity = 90;
let colorChangeSpeed = 0.1;
var backgroundColor, flowerColor;
var groundDepth = 400;
var skyColor;
var lyrics = [
  { time: 0, text: "Garden Song", displayed: true, duration: 10 },
  { time: 10, text: "By Phoebe Bridgers", displayed: true, duration: 9 },
  {
    time: 19.6,
    text: "Someday I'm gonna live",
    displayed: true,
    duration: 4.0,
  },
  { time: 23.6, text: "In your house", displayed: true, duration: 1.3 },
  { time: 25, text: "up on the hill", displayed: true, duration: 2.6 },
  {
    time: 28.0,
    text: "And when your skinhead",
    displayed: true,
    duration: 2.25,
  },
  {
    time: 30.6,
    text: "neighbor goes missing",
    displayed: true,
    duration: 2.25,
  },
  { time: 33.4, text: "I'll plant a garden", displayed: true, duration: 2.4 },
  { time: 36, text: "in the yard then", displayed: true, duration: 3 },
  { time: 39.0, text: "They're gluing roses", displayed: true, duration: 2 },
  { time: 41.3, text: "on a flatbed", displayed: true, duration: 3 },
  { time: 44.5, text: "You should see it", displayed: true, duration: 2.4 },
  { time: 47.0, text: "I mean thousands", displayed: true, duration: 1.5 },
  { time: 48.5, text: "I grew up here", displayed: true, duration: 1.5 },
  {
    time: 51,
    text: "'til it all went up in flames",
    displayed: true,
    duration: 3.0,
  },
  { time: 54.4, text: "Except the notches", displayed: true, duration: 1.8 },
  { time: 56.6, text: "in the door frame", displayed: true, duration: 3 },
  { time: 60.1, text: "I dont know when", displayed: true, duration: 2 },
  { time: 62.2, text: "you got taller", displayed: true, duration: 2.0 },
  { time: 65.6, text: "See our reflection", displayed: true, duration: 1.5 },
  { time: 67.3, text: "in the water", displayed: true, duration: 3.0 },
  { time: 70.6, text: "Off a bridge", displayed: true, duration: 2.0 },
  { time: 72.6, text: "at the huntington", displayed: true, duration: 2.0 },
  { time: 74.6, text: "I hoped the fence", displayed: true, duration: 2.0 },
  { time: 76.6, text: "when I was seventeen", displayed: true, duration: 3.0 },
  { time: 79.6, text: "Then I knew", displayed: true, duration: 3.0 },
  { time: 82.6, text: "what I wanted", displayed: true, duration: 3.0 },
  { time: 94.6, text: "And when I grow up", displayed: true, duration: 2.5 },
  { time: 97.6, text: "I'm gonna look up", displayed: true, duration: 2 },
  { time: 99.6, text: "From my phone", displayed: true, duration: 1 },
  { time: 101.6, text: "and see my life", displayed: true, duration: 2.1 },
  { time: 103.8, text: "And it's gonna be", displayed: true, duration: 1.5 },
  {
    time: 105.3,
    text: "just like my reoccurring",
    displayed: true,
    duration: 3.0,
  },
  {
    time: 108.6,
    text: "dream, I'm at the movies",
    displayed: true,
    duration: 3.0,
  },
  { time: 111.6, text: "I don't remember", displayed: true, duration: 2.0 },
  { time: 113.6, text: "what I'm seeing", displayed: true, duration: 2.0 },
  { time: 116.6, text: "The screen turns", displayed: true, duration: 2 },
  { time: 118.6, text: "into a tidal wave", displayed: true, duration: 3.4 },
  {

    time: 123.6,
    text: "Then it's a dorm room ",
    displayed: true,
    duration: 2.8,
  },
  {
    time: 126.5,
    text: "like a hedge maze",
    displayed: true,
    duration: 2.7,
  },
  { time: 129.6, text: "And when I find you", displayed: true, duration: 3.0 },
  { time: 132.6, text: "You touch my leg", displayed: true, duration: 3.0 },
  { time: 136.6, text: "and I insist", displayed: true, duration: 2.0 },
  { time: 138.6, text: "But I wake up", displayed: true, duration: 3.0 },
  { time: 141.6, text: "before we do it", displayed: true, duration: 3.0 },
  { time: 147.6, text: "I don't know how", displayed: true, duration: 3.0 },
  { time: 150.6, text: "but I'm taller", displayed: true, duration: 3.0 },
  { time: 153.6, text: "It must be something", displayed: true, duration: 1 },
  { time: 154.6, text: "in the water", displayed: true, duration: 2.0 },
  {
    time: 158.6,
    text: "Everything's growing in",
    displayed: true,
    duration: 1.5,
  },
  { time: 160.6, text: "our garden", displayed: true, duration: 2.0 },
  { time: 162.6, text: "You don't have", displayed: true, duration: 1 },
  { time: 163.6, text: "to know that", displayed: true, duration: 1 },
  { time: 164.6, text: "it's haunted", displayed: true, duration: 1.5 },
  { time: 167.3, text: "The doctor put", displayed: true, duration: 1 },
  {
    time: 168.6,
    text: "her hands over my liver",
    displayed: true,
    duration: 4.0,
  },
  { time: 172.6, text: "She told me my", displayed: true, duration: 1 },
  {
    time: 173.6,
    text: "resentment's",
    displayed: true,
    duration: 0.9,
  },
  {
    time: 174.6,
    text: "getting smaller",
    displayed: true,
    duration: 2.0,
  },
  { time: 176.6, text: "No, I'm not", displayed: true, duration: 2.0 },
  { time: 178.6, text: "afraid of hard work", displayed: true, duration: 3.0 },
  { time: 181.6, text: "I get everything", displayed: true, duration: 3.0 },
  { time: 184.6, text: "I want", displayed: true, duration: 3.0 },
  { time: 187.6, text: "I have everything", displayed: true, duration: 3.0 },
  { time: 191.6, text: "I wanted", displayed: true, duration: 3.0 },
];
var currentLyricIndex = -1;
var maxFlowers = 1000;
var flowerIncrement = 0.01;
var depthSpeed = 1;
var skyColor;
v
ar groundColor;
function preload() {
  song = loadSound("gardensong.mp3");
  font1 = loadFont("bone.ttf");
  font2 = loadFont("branch.ttf");
  font3 = loadFont("eater.ttf");
  currentFont = font1;
}
function setup() {
  // createCanvas(1920, 1080);
  createCanvas(1000, 1000);
  // 1920 x1080
  angleMode(DEGREES);
  button = createButton("play/Pause");
  button.mousePressed(toggleSong);
  button.position(10, 10);
  button.style("background-color", "white");
  button.style("padding", "20px");
  button.style("border", "none");
  button.style("border-radius", "50px");
  button.style("font-family", font1);
  button.style("font-size", "8px");
  fft = new p5.FFT(0.9, 256);
  song.play();
  ghostX = width / 2;
  ghostY = height - 50;
}
function draw() {
  background(skyColor || "#135572");
  fill("#042737"); 
  noStroke();
  
  triangle(
    0,
    height - groundDepth,
    200,
    height - groundDepth - 200,
    400,
    height - groundDepth
  );
 
  triangle(
    200,
    height - groundDepth,
    500,
    height - groundDepth - 300,
    800,
    height - groundDepth
  );
  
  
   triangle(
    400,
    height - groundDepth,
    800,
    height - groundDepth - 400,
    1200,
    height - groundDepth
  );
  
    triangle(
    800,
    height - groundDepth,
    1200,
    height - groundDepth - 500,
    1600,
    height - groundDepth
  );
  
  
  
  
  
  
  var spectrum = fft.analyze();
  var frequency = findPeakFrequency(spectrum);
  var totalAmplitude = spectrum.reduce((acc, val) => acc + val, 0);
  var avgAmplitude = totalAmplitude / spectrum.length;
  let currentTime = song.currentTime();
  
  

  if (flowers.length < maxFlowers && frameCount % 5 === 0) {
    maxFlowers += flowerIncrement;
    let flower = {
      x: random(width),
      initialY: random(height),
      y: groundDepth,
      frequency: random(0.005, 0.01),
      hue: random(360),
    };
    flowers.push(flower);
  }
  fill(groundColor || "#9A0404");
  // stroke(noStroke);
  rect(0, height - groundDepth, width, groundDepth);
  ghostX = mouseX;
  ghostY = mouseY;
  if (ghostY > window.innerHeight - 20) {
    window.scrollBy(0, 10);
  }
  depthSpeed = map(ghostY, 0, height, 1, 10);
  tail.unshift({ x: ghostX, y: ghostY });
  if (tail.length > tailLength) {
    tail.pop();
  }
  noStroke();
  for (var index = 0; index < tail.length; index++) {
    const tailPoint = tail[index];
    const pointSize = (ghostSize * (tail.length - index)) / tail.length;
    const pointAlpha = (255 * (tail.length - index)) / tail.length;
    fill(255, pointAlpha);
    ellipse(tailPoint.x, tailPoint.y, pointSize);
  }
  fill(32);
  ellipse(ghostX - ghostSize * 0.2, ghostY - ghostSize * 0.1, ghostSize * 0.2);
  ellipse(ghostX + ghostSize * 0.2, ghostY - ghostSize * 0.1, ghostSize * 0.2);
  ellipse(ghostX, ghostY + ghostSize * 0.2, ghostSize * 0.2);
  for (let i = 0; i < flowers.length; i++) {
    let flower = flowers[i];
    flower.y =
      flower.initialY + sensitivity * sin(frameCount * flower.frequency);
    flower.y += depthSpeed;
    flower.hue += colorChangeSpeed;
    drawFlower(flower.x, flower.y, 20, flower.hue);
  }
   for (var i = 0; i < lyrics.length; i++) {
    var lyric = lyrics[i];
    if (
      currentTime >= lyric.time &&
      currentTime <= lyric.time + lyric.duration
    ) {
      let hue = map(frequency, 0, spectrum.length / 2, 0, 360);
      let textColor = color(hue, 80, 80);
      fill("white");
      textSize(87);
      textAlign(CENTER, CENTER);
      textFont(currentFont);
      var targetX = width / 2;
      var targetY = map(avgAmplitude, 0, 256, height / 2, height / 1.5); // Adjusted targetY value
      targetY = constrain(targetY, 50, height - 50);
      text(lyric.text, targetX, targetY);
    }
  }
  for (let i = flowers.length - 1; i >= 0; i--) {
    const flower = flowers[i];
    const d = dist(ghostX, ghostY, flower.x, flower.y);
    if (d < ghostSize / 2 + 20) {
      flowers.splice(i, 1);
    }
  }
}
function toggleSong() {
  if (song.isPlaying()) {
    song.pause();
  } else {
    song.play();
  }
}
function keyTyped() {
  switch (key) {
    case "1":
      currentFont = font1;
      break;
    case "2":
      currentFont = font2;
      break;
    case "3":
      currentFont = font3;
      break;
  }
}
function keyPressed() {
  if (keyCode === DOWN_ARROW) {
    groundDepth += 10;
  }
  if (keyCode === UP_ARROW && groundDepth > 0) {
    groundDepth -= 10;
  }
  // Check for continuous arrow key presses
  if (keyIsDown(LEFT_ARROW)) {

    let currentTime = song.currentTime();
    song.jump(currentTime - 5);
  }
  if (keyIsDown(RIGHT_ARROW)) {
    let currentTime = song.currentTime();
    song.jump(currentTime + 5);
  }
}
function findPeakFrequency(spectrum) {
  var peakIndex = 0;
  var peakValue = 0;
  for (var i = 0; i < spectrum.length / 2; i++) {
    if (spectrum[i] > peakValue) {
      peakValue = spectrum[i];
      peakIndex = i;
    }
  }
  return peakIndex;
}
function drawFlower(x, y, size, hue, thickness) {
  const flowerSize = random(size * 0.5, size * 0.95);
  const petalSize = flowerSize / 2;
  const spacing = petalSize / 2;
  if (groundDepth >= height) {
    fill("##F3DFA6");
    rect(x - boneWidth / 2, y - boneHeight / 2, boneWidth, boneHeight, 10);
    ellipse(x - boneWidth / 2, y - boneHeight / 2, boneWidth, boneWidth);
    ellipse(x + boneWidth / 2, y - boneHeight / 2, boneWidth, boneWidth);
    ellipse(x - boneWidth / 2, y + boneHeight / 2, boneWidth, boneWidth);

    ellipse(x + boneWidth / 2, y + boneHeight / 2, boneWidth, boneWidth);
  } else {
    // Draw flowers
    // fill(hue % 360, 80, 80);
    circle(x - spacing, y - spacing, petalSize);
    circle(x + spacing, y - spacing, petalSize);
    circle(x - spacing, y + spacing, petalSize);
    circle(x + spacing, y + spacing, petalSize);
    fill((hue + 180) % 360, 80, 80);
    circle(x, y, petalSize);
  }
}
function mouseWheel(event) {
  groundDepth += event.delta;
  groundDepth = max(groundDepth, 0);
}
Creative Code
Published:

Owner

Creative Code

Published:

Tools

Creative Fields