Project-10: Sonic Story

My Project

//Chuong Truong;
//cbtruong;
//cbtruong@andrew.cmu.edu;
//Section B;

//The Overall Story of this program is that of fall;
//Leaves are falling off of trees, the sun is getting whiter;
//The air is getting frostier;
//And the birds are seen more actively flying;
//I included no custom sound and instead wanted to portray a scene;
//That was described with a song;


//initial empty array that will hold leaf objects;
var leaves = [];
//variables for the sun's green and blue values which change;
var sunG = 238;
var sunB = 82;
//initial empty array for birds;
var birds = [];

//function of the leaf object that allows it to fall;
function leafFall (){
    //stops each leaf from falling off the canvas;
    //if it has not reached that point, it will continue to fall until it does;
    if (this.f == true){
        if (this.y > height-17){
            this.y = height-5;
        }
        else {
            this.y += random(30, 60);
        }
    }
    //if met, this condition causes the leaf to fall;
    //this randomization occurs to allow for the tree and leaves to be more lifelike;
    //as not all leaves fall off immediately;
    else if (floor(random(200)) == 25){
            this.y += random(30);
            this.x += random(-15, 15);
            this.f = true;

        }
    return this.y;
}

//function that draws the leaves;
function drawLeaf(){
    //this switch and case allows for color variance for the leaves;
    //the colors are those of fall;
    switch(this.col){
      case 0: fill(237, 164, 23); break;
      case 1: fill(167, 159, 15); break;
      case 2: fill(233, 134, 4); break;
      case 3: fill(223, 57, 8); break;
      case 4: fill(201, 30, 10); break;
    }
    rectMode(CENTER);
    push();
    translate(this.x, this.y);
    rotate(radians(45));
    rect(0, 0, 15, 15);
    pop();
}

//function that makes leaves;
function leaf(lx, ly, cPreset){
    //the leaf object constructor;
    l = {x: lx, y: ly, orgY: ly, col: cPreset, f: false, 
        drawFunction: drawLeaf, fallFunction: leafFall};
    return l;
}

function makeLeavesOnTrees (x, y){
    //for loops create the leaves on the trees themselves;
    //the leaves' x and y are dependent on the tree's x and y;
    //the first row is 17 and then decreases by 1 as the row gets closer to the tree's x;
    //as the row gets closer, the leaves' initial x and y increase;

    //this variable allows the leaves to center as each row of them becomes less;
    //it is initalized again to allow for the top row to be centered correctly;
    //like it was before the nested for loops below change it;
    var centeringX = 80;

    //the starting number of leaves for each row
    var leavesRowNum = 17;

    //these nested for loops creates the leaves and gives them their inital x and y;
    //the inner loop creates the leaves for each row, giving them the x, y, and colorPreset;
    //the outer loop controls the leaves' y, as it decreases, a new row will not only be drawn;
    //but that row's total number of leaves decreases, and the centering of them is centered;
    //the loops repeat until only 5 leaves are left and they are closest to the tree's x and y;
    for (var j = 120; j > -10; j-= 10){
        for (var i = 0; i < leavesRowNum; i++){
        var l = leaf(x-centeringX + i*10, y-j, floor(random(5)));
        leaves.push(l);
    }
    //the leaves row number decreases to make each row have less leaves;
    leavesRowNum--;
    //the centering is decreased to make sure the row, as it becomes less in number;
    //is centered correctly to the tree's x;
    centeringX -= 5;
    }
}

//this function creates bird objects;
function bird (bx, by){
    //bird object constructor;
    b = {x: bx, y: by, orgY: by, flyFunction: birdFly, drawFunction: drawBird};
    return b;
}

//function that allows the bird to fly;
function birdFly (){
    this.x -= 10;
    if (this.x < 0){
        this.x = width - 20;
    }
    if (this.y > this.orgY + 20 ){
        this.y -= 5;
    }
    else {
        this.y += 5;
    }
}

//this draws the bird;
function drawBird(){
    fill(36, 143, 190);
    circle(this.x, this.y, 20);
    fill(30);
    circle(this.x, this.y, 5);
    fill(131, 67, 51);
    triangle(this.x-15, this.y, this.x - 10, this.y - 2, this.x - 10, this.y+2);
    stroke(0);
    line(this.x - 15, this.y, this.x - 10, this.y);
    fill(16, 123, 170);
    push();
    rectMode(CORNER);
    translate(this.x, this.y);
    rotate(270);
    rect(0+5, 0 - 12, 15, 10);
    rect(0+5, 0 + 4, 15, 10);
    pop();
}


function setup() {
    createCanvas(700, 500);
    frameRate(10);
    useSound();
    frameRate(3);

    //calls the makeLeavesOnTree function to create the leaves pattern;
    //on each tree dependent on the trees' location;
    makeLeavesOnTrees(125, 390);
    makeLeavesOnTrees(350, 390);
    makeLeavesOnTrees(575, 390);

    //calls the bird function and creates the bird objects;
    for (var i = 0; i < 7; i++){
         var bD = bird(random(100, 600), random(70, 120));
         birds.push(bD);
    }
}
//I kept the same sound setup from the assignment because I liked the sounds;
function soundSetup() { 
    osc = new p5.Oscillator();
    osc.amp(0.25);
    osc.setType('sine');
    osc.start();
}


function draw() {
    //this creates the background of a blue sky and  green grass;
    background(154, 211, 222);
    noStroke();
    rectMode(CORNER);
    fill(24, 136, 39);
    rect(0, 475, 700, 5);
    fill(14, 146, 49);
    rect(0, 480, 700, 20);

    //calls the drawTree function to draw trees;
    drawTree(125, 390);
    drawTree(350, 390);
    drawTree(575, 390);
    
    //this for loop updates and draws each leaf in the leaves array;
    for (var i = 0; i < leaves.length; i++){
        var l = leaves[i];
        l.fallFunction();
        l.drawFunction();
    }
    
    //calls the clouds function to make clouds;
    drawClouds(125, 80);
    drawClouds(325, 130);
    drawClouds(525, 105);

    //draws the sun;
    //this if statement allows for the sun to slowly change colors;
    if (!(sunG == 250 & sunB == 193)){
        sunG += 1.2/5;
        sunB += 11.1/5;
    }
    noStroke();
    fill(255, sunG, sunB);
    circle(600, 75, 100);
    print(leaves.length);

    //draws the birds;
    for (var o = 0; o < birds.length; o++){
        var b = birds[o];
        b.flyFunction();
        b.drawFunction();
    }

    //I turned the code from the assignment into a function;
    musicPlayer(pitches, durations);
}

//function that draws the trees without the leaves;
function drawTree (x, y){
    fill(191, 75, 25);
    rectMode(CENTER);
    rect(x, y, 20, 205);
    push();
    translate(x - 40, y - 40);
    rotate(radians(-30));
    rect(0, 0, 10, 150);
    pop();
    push();
    translate(x + 40, y - 40);
    rotate(radians(30));
    rect(0, 0, 10, 150);
    pop();
    push();
    translate(x - 30, y - 70);
    rotate(radians(-30));
    rect(0, 0, 8, 100);
    pop();
    push();
    translate(x + 30, y - 70);
    rotate(radians(30));
    rect(0, 0, 8, 100);
    pop();
    push();
    translate(x - 20, y - 90);
    rotate(radians(-30));
    rect(0, 0, 5, 80);
    pop();
    push();
    translate(x + 20, y - 90);
    rotate(radians(30));
    rect(0, 0, 5, 80);
    pop();
    push();
    translate(x - 5, y - 100);
    rotate(radians(-30));
    rect(0, 0, 3, 60);
    pop();
    push();
    translate(x + 5, y - 100);
    rotate(radians(30));
    rect(0, 0, 3, 60);
    pop();
    rect(x, y - 105, 2, 40);
}

//this function creates the clouds and draws them;
function drawClouds (x, y){
    fill(243, 242, 231);
    ellipse(x, y, 80, 50);
    ellipse(x + 20, y + 10, 80, 40);
    ellipse(x - 40, y + 10, 80, 30);
    ellipse(x - 10, y + 20, 70, 50);
}

//I used the same code from the assignments to make the music;

//arrays for the pitches and durations;
//also count variables for the index and frameCount;
//finally, the boolean rest is added to account for rests in the music;

//I changed the pitches and went with a simple 1 beat per note;
var pitches = [ 64, 64, 62, 64, 64, 62, 0, 62, 64, 66, 65, 67, 65, 0,
  60, 60, 62, 66, 65, 64, 62, 68, 68, 65, 64, 62, 62 ];
var durations = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
var indexTracker = 0;
var frameCount = 0;
var rest = false;

//I turned the code that creates the music with different notes and beat durations into a function;
//the function takes a note array and a corresponding note duration array;
function musicPlayer (noteArray, noteDurationArray){

    //code for the piano to play;
    //this sets the frequencies of the oscillator to the MIDI pitches;
    osc.freq(midiToFreq(noteArray[indexTracker]));
    
    //checks for when the note's duration is over and acts accordingly;
    if (frameCount > noteDurationArray[indexTracker]){
        //this checks for whether the tune has been completely played;
        //if it has been, then the program and oscillator ends;
        if (indexTracker + 1 == noteArray.length) {
            //print(frameCount);
            //print(indexTracker);
            osc.stop();
            noLoop();
        }
        //if it has not been completely played, then the next note will play;
        //with the frameCount reset to 0;
        else {
        print(frameCount);
        indexTracker++;
        //after the indexTracker is increased;
        //it checks to see if the new note is a rest;
        //if it is, then it deals according;
        //it also turns on the oscillator after a rest;
        if (noteArray[indexTracker] != 0){
            if (rest == true) {
            osc.start();
            rest = false;
                }
            }
        else if (noteArray[indexTracker] == 0){
            rest = true;
            osc.stop();
            }
        }
        frameCount = 0;
    }
    else {
        frameCount++;
    }
    print(noteArray[indexTracker]);
}

Instead of making 4 sounds, I used the same code from the assignments to make a song that I felt fit what I wanted to show, a scene of Fall. That scene has birds flying, leaves falling, and a sun that becomes whiter and whiter to fit the upcoming Winter.

Leave a Reply