How to open up and run the file:
- download and unzip the files below.
- nahyunk1-yugyeonl-final project
- songs
- extract “sound1”, “sound2”, and “sound3” music files from the songs folder and put them into the “assets” folder inside the final project folder.
- turn on terminal or node and run local server.
- access the sketch.js inside the final project folder.
- play and enjoy the songs by entering either 1, 2, 3 on your keyboard.
The project file was too large so we had to upload the songs separately in another folder along with the zip file of our code. Our project was based on the idea of generating animation with the kiwi bird and creating its walkthrough with the incorporation of music affecting the background of the landscape. There are three parts to the scenes: pressing 1 on your keyboard will affect your current scene to an urban landscape. Similarly, when either 2 or 3 is pressed, different scenes and music replace the current scene with different parts of the landscape responding to the beat, frequency, and the amplitude of the music assigned. The parts of the landscapes were drawn with the incorporation of the FFT(); function and the p5.Amplitude(); function which analyzes the frequency and the volume of the music when it is played. Some of the interesting factors that our animation consisted was the sun beam which would draw itself in an ellipse in a form of measured frequency and the stars and the moon which brightens and glistens depending on the beat of the music played at night. Throughout, we put a lot of effort learning and incorporating the p5.sound materials, creating a variety of landscapes with music chosen according to the mood of our scenes, and generally coding different functions and figuring out ways for our code to understand the switching of the scenes and the play of different music files.
**scene 2 consists of a song that is relatively louder than the other scenes that contain music files. We’ve put code for the sound of the song to be reduced, but the song still plays comparatively loud. Please be careful with the volume of your headphones.
var kiwi;
var kiwiX = 200; //kiwi locationX
var kiwiY = 310; //kiwi locationY
var tree = []; //array of trees
var treeAssets = [];
var shell = []; //array of shells
var shellAssets = [];
var coin = []; //array of coins
var coinAssets = [];
var gem = []; //array of gems
var gemAssets = [];
var buildings = []; //array of buildings
var ocean = []; //array of mountain
var mountain = []; //array of ocean
var stars = []; //array of stars
var clouds = []; //array of clouds
var sound1;
var sound2;
var sound3;
var amplitude;
var volArray = []; //array that stores volume
var timeState = "morning"; //determines initial state of time
function preload() {
sound1 = loadSound("assets/sound1.mp3");
sound2 = loadSound("assets/sound2.mp3");
sound3 = loadSound("assets/sound3.mp4");
var treeLinks = ["assets/palmtree0.png", "assets/palmtree1.png",
"assets/palmtree2.png", "assets/palmtree3.png"];
//load tree images
for (var t = 0; t < treeLinks.length; t++) {
treeAssets[t] = loadImage(treeLinks[t]);
}
//load shell images
for (var i = 0; i < 1; i++){
shellAssets[i] = loadImage("assets/shell.png");
}
//load coin images
for (var i = 0; i < 1; i++){
coinAssets[i] = loadImage("assets/coin.png");
}
//load gem images
for (var i = 0; i < 1; i++){
gemAssets[i] = loadImage("assets/gem.png");
}
}
function setup() {
createCanvas(1000, 700);
imageMode(CENTER);
//load amplitude
amplitude = new p5.Amplitude();
//load fft
fft = new p5.FFT();
sound1.setVolume(1);
sound2.setVolume(0.00000001);
sound3.setVolume(1);
//create initial set of trees
for (var i = 0; i < 4; i ++) {
var treeX = random(width);
tree[i] = makeTrees(treeX);
}
//create initial set of shells
for (var i = 0; i < 5; i ++) {
var shellX = random(360, width);
shell[i] = makeShells(shellX);
}
//create initial set of coins
for (var i = 0; i < 5; i ++) {
var coinX = random(360, width);
coin[i] = makeCoins(coinX);
}
//create initial set of gems
for (var i = 0; i < 5; i ++) {
var gemX = random(360, width);
gem[i] = makeGems(gemX);
}
//create initial set of buildings
for (var i = 0; i < 10; i++){
var rx = random(width);
buildings[i] = makeBuilding(rx);
}
//create initial set of clouds
for (var i = 0; i < 10; i++) {
var cloudX = random(width);
var cloudY = random(height/2);
clouds[i] = makeClouds(cloudX, cloudY);
}
//create kiwi animation
createKiwi(kiwiX, kiwiY);
//ocean
makeOcean(height - 220, 30, 0.00005, 0.0005, color(197, 227, 234));
makeOcean(height - 180, 80, 0.00005, 0.001, color(225, 211, 185));
//mountain
makeMountain(height - 400, 200, 0.00005, 0.0025, color(15));
makeMountain(height - 350, 300, 0.00015, 0.006, color(0));
}
function draw() {
if (timeState == "morning") {
morning();
if (sound1.isPlaying() == false){
sound1.play();
} else if (sound2.isPlaying() == true){
sound2.stop();
} else if (sound3.isPlaying() == true){
sound3.stop();
}
} if (timeState == "afternoon") {
afternoon();
if (sound2.isPlaying() == false){
sound2.play();
}
else if (sound1.isPlaying() == true){
sound1.stop();
} else if (sound3.isPlaying() == true){
sound3.stop();
}
} if (timeState == "night") {
night();
if (sound3.isPlaying() == false){
sound3.play();
} if (sound1.isPlaying() == true){
sound1.stop();
} else if (sound2.isPlaying() == true){
sound2.stop();
}
}
}
function keyPressed() {
if (key == '1') {
timeState = "morning";
} if (key == '2') {
timeState = "afternoon";
} else if (key == '3') {
timeState = "night";
}
}
function morning() {
//gradient background color
var from = color(125, 133, 216);
var to = color(220, 224, 251);
setGradient(0, from, to, 3.5 * height / 5);
//lines in the background showing frequency
skyFreq(0, 125);
//sun
makeSun(width / 4 - 100, 550, 236, 191, 113, 300);
//ground
noStroke();
fill(96, 91, 103);
rect(0, 3.5 * height / 5 - 10, width, 0.5 * height / 5);
fill(127, 109, 123);
rect(0, 4 * height / 5 - 10, width, height / 4);
//clouds
updateAndDisplayClouds();
addClouds();
//buildings
updateAndDisplayBuildings();
addBuildings();
//kiwi
drawKiwi();
//coins
updateAndDisplayCoins();
addCoins();
}
function afternoon() {
//gradient background color
var from = color(20, 140, 172);
var to = color(209, 255, 249);
setGradient(0, from, to, 3.5 * height / 5);
//lines in the background showing frequency
skyFreq(100, 48);
//ocean & sand
noStroke();
moveOcean();
//sun
makeSun(3 * width / 4, 90, 243, 229, 202, 150);
//sun outline based on frequency
sunFreq();
//trees
updateAndDisplayTrees();
addTrees();
//kiwi
drawKiwi();
//shells
updateAndDisplayShells();
addShells();
}
function night() {
//gradient background color
var from = color(25, 0, 51);
var to = color(51, 0, 102);
setGradient(0, from, to, 3.5 * height / 5);
//stars
updateAndDisplayStars();
removeStars();
addStars();
drawStars();
//moon
makeMoon();
//mountain
strokeWeight(random(0.2, 0.4));
stroke(random(0,255), random(0,255), random(0,255));
moveMountain();
//ground
noStroke();
fill(18, 13, 17);
rect(0, 3.5 * height / 5, width, 1.5 * height / 5);
//kiwi
drawKiwi();
//gems
updateAndDisplayGems();
addGems();
//sound
}
function setGradient (y, from, to, length) {
//top to bottom gradient (background)
for (var i = y; i <= length; i++) {
var inter = map(i, y, width, 0, 1);
var c = lerpColor(from, to, inter);
stroke(c);
strokeWeight(2);
line(0, i, width, i);
}
}
function makeSun(sunX, sunY, r, g, b, diam) {
noStroke();
//glowing gradient sunlight
for (var i = 0; i < 30; i++) {
var value = random(7, 8);
var transparency = 100 - value * i;
fill(r + 2 * i / 3, g + 7 * i / 3, b + i, transparency);
ellipse(sunX, sunY, diam + 20 * i, diam + 20 * i);
}
//sun
fill(r, g, b, 100);
ellipse(sunX, sunY, diam, diam);
}
function sunFreq() { //sun outline
angleMode(DEGREES);
//analyze level of the amplitude
var vol = amplitude.getLevel();
//array that pushes the volume in the array
volArray.push(vol);
stroke(255);
strokeWeight(.5);
noFill();
push();
translate(width - 240, 90);
scale(2.5);
//shape that represent the range of the frequency
beginShape();
for (var i = 0; i < 360; i ++){
var r = map(volArray[i], 0, 1, 10, 100);
var x = r * cos(i);
var y = r * sin(i);
vertex(x ,y);
}
endShape();
pop();
//360 because the reperesentation draws in an ellipse
if (volArray.length > 360){
volArray.splice(0, 1);
}
}
function skyFreq(offset, spacingX) { //background lines
var w = width / spacingX;
//anaylze the fft
var spectrum = fft.analyze();
push();
translate(0, offset);
beginShape();
//draws the frequency level as lines behind the ocean
for (var i = 0; i < spectrum.length; i++){
var angle = map(i, 0, spectrum.length, 0, 360);
var amp = spectrum[i];
var r = map(amp, 0, 256, 40, 200);
var y = map(amp, 0, 256, height, 0);
stroke(255);
strokeWeight(0.5);
line(i * w, height, i * w, y);
}
endShape();
pop();
}
function cityFreq() {
}
function makeMoon() {
//size of moonlight depends on the amplitude
for (var c = 0; c < 30; c++){
var level = amplitude.getLevel();
noStroke();
fill(217, 154, 100, (10 - c) * level * 50);
ellipse(850, 150, 90 + (10 * c) + level, 90 + (10 * c) + level);
stroke(255, 223, 181);
fill(255, 223, 181);
ellipse(850, 150, 100, 100);
fill(252, 240, 224);
ellipse(858, 150, 85, 85);
}
}
function drawKiwi() { //create kiwi
push();
translate(kiwiX, kiwiY);
scale(0.6, 0.6);
drawSprites();
pop();
}
function createKiwi(x, y) { //create sprite at a random position
kiwi = createSprite(x, y);
kiwi.addAnimation("assets/kiwi0.png","assets/kiwi1.png",
"assets/kiwi2.png","assets/kiwi3.png","assets/kiwi4.png","assets/kiwi5.png","assets/kiwi6.png",
"assets/kiwi7.png","assets/kiwi8.png","assets/kiwi9.png","assets/kiwi10.png",
"assets/kiwi11.png","assets/kiwi12.png","assets/kiwi13.png","assets/kiwi14.png");
}
function makeOcean(landscapeY, landscapeR, landscapeS, landscapeD, landscapeC) {
var landscape = {ly: landscapeY, //locationY
range: landscapeR, //range of how far landscape goes up
speed: landscapeS, //speed of the landscape
detail: landscapeD, //detail (how round/sharp)
color: landscapeC, //color of the landscape
draw: drawLandscape}
ocean.push(landscape);
}
function makeMountain(landscapeY, landscapeR, landscapeS, landscapeD, landscapeC) {
var landscape = {ly: landscapeY, //locationY
range: landscapeR, //range of how far landscape goes up
speed: landscapeS, //speed of the landscape
detail: landscapeD, //detail (how round/sharp)
color: landscapeC, //color of the landscape
draw: drawLandscape}
mountain.push(landscape);
}
function drawLandscape() { //generating landscape from code provided
fill(this.color);
beginShape();
vertex(0, height);
for (var i = 0; i < width; i++) {
var t = (i * this.detail) + (millis() * this.speed);
var y = map(noise(t), 0, 1, this.ly - this.range / 2, this.ly + this.range / 2);
vertex(i, y);
}
vertex(width, height);
endShape(CLOSE);
}
function moveOcean() { //move the landscape
for (var i = 0; i < ocean.length; i++)
ocean[i].draw();
}
function moveMountain() { //move the landscape
for (var i = 0; i < mountain.length; i++)
mountain[i].draw();
}
//palm trees
function updateAndDisplayTrees() {
//keeps the trees moving along the x-axis
for (var i = 0; i < tree.length; i++) {
tree[i].moveTree();
tree[i].drawTree();
}
}
function drawTrees() { //draws the trees
image(treeAssets[this.nFloor], this.x + 200, this.y - 100);
}
function moveTrees() { //move the trees
this.x -= this.speed;
}
function addTrees() { //places in more trees into the array
var newTreesProbability = 0.0015;
if (random(0, 1) < newTreesProbability) {
tree.push(makeTrees(width));
}
}
function makeTrees(originX) {
var palmtrees = {
x: originX,
y: random(400, 420),
speed: 0.55,
nFloor: floor(random(0, 3)),
moveTree: moveTrees,
drawTree: drawTrees}
return palmtrees;
}
//shells
function updateAndDisplayShells() {
//keeps the shells moving along the x-axis
for (var i = 0; i < shell.length; i++) {
shell[i].moveShell();
shell[i].drawShell();
}
}
function drawShells() { //draws the shells
push();
translate(this.x + 100, this.y);
scale(0.25, 0.25);
image(shellAssets[0], 0, 0);
pop();
}
function moveShells() { //move the shells
this.x -= this.speed;
}
function addShells() { //places in more trees into the array
var newTreesProbability = 0.0035;
if (random(0, 1) < newTreesProbability) {
shell.push(makeShells(width));
}
}
function makeShells(shellX) {
var shells = {
x: shellX,
y: 610,
speed: 1,
moveShell: moveShells,
drawShell: drawShells}
return shells;
}
//budilings
function updateAndDisplayBuildings(){
//keeps the buildings moving along the x-axis
for (var i = 0; i < buildings.length; i++) {
buildings[i].move();
buildings[i].display();
}
}
function addBuildings() { //places in more buildings into the array
var newBuilding = 0.006;
if (random(0,1) < newBuilding) {
buildings.push(makeBuilding(width));
}
}
function moveBuildings() { //move the buildings
this.x -= this.speed;
}
function drawBuildings() { //draws the buildings
var floorHeight = 45;
var bHeight = this.nFloors * floorHeight;
push();
noStroke();
fill(this.buildingC);
translate(this.x, height - 180);
rect(0, -bHeight, this.breadth, bHeight);
for (var y = 0; y < this.nFloors; y++) {
for (var x = 0; x < 6; x++){
noStroke();
fill(255, 221, random(100, 150));
rect(x * (this.breadth / 7) + 10, -25 - (y * floorHeight), this.breadth / 12, 20);
}
}
pop();
}
function makeBuilding(buildingX) {
var building = {x: buildingX,
breadth: random(100, 125),
speed: 0.55,
buildingC: color(random(150, 225), random(100, 175), random(100, 175)),
nFloors: round(random(4, 10)),
move: moveBuildings,
display: drawBuildings}
return building;
}
//coins
function updateAndDisplayCoins() {
//keeps the coins moving along the x-axis
for (var i = 0; i < coin.length; i++) {
coin[i].moveCoins();
coin[i].drawCoins();
}
}
function drawCoins() { //draws the coins
push();
translate(this.x + 100, this.y);
scale(0.3, 0.3);
image(coinAssets[0], 0, 0);
pop();
}
function moveCoins() { //move the coins
this.x -= this.speed;
}
function addCoins() { //places in more coins into the array
var newTreesProbability = 0.0035;
if (random(0, 1) < newTreesProbability) {
coin.push(makeCoins(width));
}
}
function makeCoins(coinX) {
var coins = {
x: coinX,
y: 610,
speed: 1,
moveCoins: moveCoins,
drawCoins: drawCoins}
return coins;
}
//gems
function updateAndDisplayGems() {
//keeps the gems moving along the x-axis
for (var i = 0; i < gem.length; i++) {
gem[i].moveGems();
gem[i].drawGems();
}
}
function drawGems() { //draws the gems
push();
translate(this.x + 100, this.y);
scale(0.3, 0.3);
image(gemAssets[0], 0, 0);
pop();
}
function moveGems() { //move the gems
this.x -= this.speed;
}
function addGems() { //places in more gems into the array
var newTreesProbability = 0.0035;
if (random(0, 1) < newTreesProbability) {
gem.push(makeGems(width));
}
}
function makeGems(gemX) {
var gems = {
x: gemX,
y: 610,
speed: 1,
moveGems: moveGems,
drawGems: drawGems}
return gems;
}
//stars
function updateAndDisplayStars() {
//keeps the stars moving along the x-axis
for (var i = 0; i < stars.length; i++){
stars[i].move();
stars[i].display();
}
}
function removeStars() { //remove stars out of canvas
var starsKeep = [];
for (var i = 0; i < stars.length; i++){
if (stars[i].x + stars[i].breadth > 0) {
starsKeep.push(stars[i]);
}
}
stars = starsKeep; //remaining stars
}
function addStars() { //places in more trees into the array
var newTreesProbability = 0.0075;
if (random(0,1) < newTreesProbability) {
stars.push(makeStars(width));
}
}
function moveStars() { //move the stars
this.x -= this.speed;
}
function drawStars() { //draws the coins
strokeWeight(random(0.5, 3));
stroke(random(0, 255), (0, 255), (0, 255));
push();
translate(this.x, 20);
// the size of the stars depends on the amplitude
for (var i = 0; i < stars.length; i++) {
var level = amplitude.getLevel();
var size = map(level, 0, 1, 0, 1);
fill(random(0, size), (0, size), (0, size));
ellipse(random(10, 3.5 * height / 5), random(10, 3.5 * height / 5), size, size);
}
pop();
}
function makeStars(birthLocationX) {
var star = {
x: birthLocationX,
breadth: 50,
speed: 1,
move: moveStars,
display: drawStars}
return star;
}
//clouds
function updateAndDisplayClouds() {
//update the clouds' position & draw them
for (var i = 0; i < clouds.length; i++) {
clouds[i].move();
clouds[i].draw();
}
}
function makeClouds(cloudX, cloudY) {
var cloud = {x: cloudX, //locationX of cloud
y: cloudY, //locationY of the cloud
offsetX: random(30, 100),
offsetY: random(100, 175),
breadth: random(300, 400), //width of the cloud
speedC: -random(1, 2), //speed of the cloud
nFloors: round(random(2, 8)), //multiplier that determines the height of the cloud
transparency: random(20, 60), //transparency of the cloud
move: moveClouds,
draw: drawClouds}
return cloud;
}
function drawClouds() {
var multiplier = 5; //multiplier that determines the height of the cloud
var cloudHeight = this.nFloors * multiplier;
ellipseMode(CENTER);
noStroke();
fill(255, this.transparency);
//cloud height reacts to the amplitude
var level = amplitude.getLevel();
push();
translate(this.x, height / 2 - this.offsetY);
ellipse(this.breadth/2, -cloudHeight, this.breadth, cloudHeight + 500 * level);
pop();
push();
translate(this.x, height / 2 - this.offsetY - 50);
ellipse(this.breadth/2 + this.offsetX, -cloudHeight, this.breadth, cloudHeight + 500 * level);
pop();
}
function moveClouds() {
//move clouds by updating its x position
this.x += this.speedC;
}
function addClouds() {
//new clouds from the right edge of the canvas
var newCloudsProbability = 0.0075;
//likliness of new clouds
if (random(0, 1) < newCloudsProbability) {
var cloudX = width;
var cloudY = random(height / 2);
clouds.push(makeClouds(cloudX, cloudY));
}
}