sjahania – final project

sjahania-final-project

My project is a simple, interactive keyboard. They keys light up when you press them, and I included harmonics to make it sound more like a real piano.

Press on a key and the note will sound! You can click and drag in order to play more than one note quickly.

To run:
1. Download the file “sjahania-final-project”
2. Open “index.html” in your browser
3. Play away!

sijings-Final Project

For this project, I want to visualize a set of data from NASA about temperature change and Antarctic mass loss. Instead of just looking at statistical graphs, I chose to investigate from a image perspective that the audience may get a better connection. I found out that although we all know what global warming is, we don’t really connect them to ourselves, thus, I create a direct connection between our daily necessities (food and water) and the changes. The project is divided to two parts, one is to visualize the relationship between the loss of wheat and increasing temperature, the second part is to visualize the relationship between the loss of water and the decreasing antarctic mass. For our knowledge,  there are applications of recursion, use of objects, for loops, etc. The data are all transformed with equations calculated from certain patterns and unit comparison. The project on wordpress is not displayed correctly and very slow, for the full project, please download the linked zip file (below are both the original and the scaled) and see it chrome. 

The introduction
The help page
The second part displaying the relationship between wheat and temperature
The first part between water and Antarctic mass

sijings-termP-original

sijings-termP-scaled

sijings-termP-scaled

//Clair(sijing) Sun
//session C
//sijings@andrew.cmu.edu
//sijings-11-B

///////////global vriables///////////
var wheatX = 50;
var wheatY = 50;
var wheatL = 20;
var frames = [];
var backgroundR = 204;
var backgroundG = 229;
var backgroundB = 237;
var TemperatureMode = false;
var startMode = true;
var iceMode = false;
var helpMode = false;
var img;
var animateW = 200;
var animateH = 50;

///////////global value for ice mass///////////

//all data from NASA.com: URL: https://climate.nasa.gov/vital-signs/land-ice/
var dateRecorded = ["2002.4.16", "2002.5.8", "2002.8.15", "2002.9.17", "2002.10.16", "2002.11.14", 
 "2002.12.17", "2003.1.15", "2003.2.13", "2003.3.15", "2003.4.16", "2003.5.12",
 "2003.7.17",  "2003.8.15", "2003.9.17", "2003.10.16", "2003.11.14", "2003.12.17",
 "2004.1.08", "2004.2.17",  "2004.3.17", "2004.4.16", "2004.5.15", "2004.6.17", "2004.7.16", "2004.8.14",     
 "2004.9.16", "2004.10.16", "2004.11.14", "2004.12.17","2005.1.15","2005.2.13", "2005.3.15", "2005.4.16", 
 "2005.5.16", "2005.6.17", "2005.7.16", "2005.8.14","2005.9.16", "2005.10.16", "2005.11.14", "2005.12.17", 
 "2006.1.15", "2006.2.13", "2006.3.15", "2006.4.16", "2006.5.16", "2006.6.14", "2006.7.17", "2006.8.15", 
 "2006.9.17", "2006.10.16", "2006.11.14", "2006.12.17", "2007.1.15", "2007.2.13", "2007.3.15", 
 "2007.4.16", "2007.5.16", "2007.6.14", "2007.7.17", "2007.8.15", "2007.9.17", 
 "2007.10.16", "2007.11.14", "2007.12.17", "2008.1.15", "2008.2.13", "2008.3.15", 
 "2008.4.16", "2008.5.15", "2008.6.17", "2008.7.16", "2008.8.14", "2008.9.16", "2008.10.16",     
 "2008.11.14", "2008.12.17", "2009.1.15", "2009.2.13", "2009.3.15", "2009.4.16", "2009.5.16",   
 "2009.6.17", "2009.7.17", "2009.8.14", "2009.9.16", "2009.10.16", "2009.11.14", "2009.12.17",    
 "2010.1.15", "2010.2.13", "2010.3.15", "2010.4.16", "2010.5.15", "2010.6.17",  "2010.7.16",
 "2010.8.14", "2010.9.16", "2010.10.16", "2010.11.14", "2010.12.17", "2011.2.17", 
 "2011.3.15", "2011.4.16", "2011.5.16", "2011.7.20", "2011.8.15", "2011.9.17", "2011.10.16",
 "2011.10.30", "2011.10.30", "2012.1.1", "2012.2.13", "2012.3.17", "2012.4.8", "2012.6.17",
 "2012.7.16", "2012.8.14", "2012.9.13", "2012.11.21", "2012.12.17", "2013.1.15", "2013.2.13",
 "2013.4.20", "2013.5.16", "2013.6.17", "2013.7.17", "2013.10.16", "2013.11.14", "2013.12.17",
 "2014.1.8", "2014.3.18", "2014.4.16", "2014.5.16", "2014.6.14", "2014.8.15", "2014.9.17", 
 "2014.10.16", "2014.11.18", "2015.1.22", "2015.2.13", "2015.3.15", "2015.4.16", "2015.4.27",
 "2015.7.13", "2015.8.15", "2015.9.13", "2015.12.21", "2016.1.15", "2016.2.13", "2016.3.17",
 "2016.5.19", "2016.6.17", "2016.7.16", "2016.8.22", "2016.11.29", "2016.12.24", "2017.1.22"]  

var iceMassL = [  0.00, 62.12, -176.07, 170.09, 33.71, -81.62, -51.14, -249.68, -168.66, 
                -238.74, -143.83, -29.82, -139.58,  -118.44, -48.72, -84.84, -107.17, 
                -83.32, -218.59, -604.75, -322.73, -412.72, -98.40, -99.73, -331.48, 
                -361.87, -287.24, 78.00, -181.62, -229.19, -323.17, -379.81, -362.53, 
                -276.68, -285.66, -196.75, -128.12, -342.36, -109.54, -121.62, -97.43, 
                -137.23, -315.63, -340.25, -296.39, -307.18, -178.31, -154.18, -196.17, 
                2.39, -10.96, -74.55, -162.59, -244.63, -451.67, -427.09, -453.85, 
                -356.27, -70.24, -269.10, -295.85, -222.92, -196.99, -374.88, -467.93, 
                -469.47, -715, -676.06, -660.57, -515.51, -518.89, -484.19, -764.67, 
                -821.51, -540.05, -536.66, -476.17, -572.55, -682.62, -641.78, -592.27, 
                -577.59, -572.47, -570.43, -546.31, -550.68, -544.09, -548.48, -587.92, 
                -587.78, -846.48, -671.72, -621.76, -706.68, -727.68, -809.36, -1071.51, 
                -953.83, -841.41, -935.26, -928.85, -789.81, -1033.29, -1086.26, -1138.23, 
                -1017.76, -1035.13, -951.88, -827.31, -914.18, -611.65, -948.14, -1066.81, 
                -1088.57, -1025.66, -1043.95, -1028.25, -1196.57, -987.23, -734.95, -807.52, 
                -996.11, -1220.58, -1329.47, -1116.96, -994.06, -989.43, -1085.24, -1066.72, 
                -1215.76, -1162.48, -1424.32, -1606.66, -1386.24, -1253.63, -1480.57, 
                -1531.72, -1252.97, -1383.92, -1321.53, -1687.98, -1697.55, -1808.10, 
                -1825.73, -1735.62, -1862.28, -1934.24, -1778.25, -1637.34, -1604.18, 
                -1679.21, -1516.72, -1755.32, -1611.07, -1750.97, -1808.04, -1438.70, 
                -1840.86, -1933.91]; 

var cupW = 300;
var cupH = 400;
var top1H = 30;
var top3H = 10;
var xspacing = 0.5;    // Distance between each horizontal location
var w;                // Width of entire wave
var theta = 0.0;      // Start angle at 0
var amplitude = 5.0; // Height of wave
var period = 150.0;   // How many pixels before the wave repeats
var dxWave;               // Value for incrementing x
var yvalues;  // Using an array to store height values for the wave
var beginAnimate = false;
var beginChanges = false;
var iceCount = 0; //to represent framerate

var instruct1; //two images in help
var instruct2;

/////////preloading images////////////

function preload(){
    //loading mountains on page 1
    img = loadImage("https://i.imgur.com/BIk36Rs.png");
    //loading mouth
    var filenames = [];
    filenames[0] = "https://i.imgur.com/fDCS6G3.png";
    filenames[1] = "https://i.imgur.com/XqYcfeX.png";
    filenames[2] = "https://i.imgur.com/vOOvd64.png";
    filenames[3] = "https://i.imgur.com/XqYcfeX.png";
    filenames[4] = "https://i.imgur.com/tmTBJXg.png";
    filenames[5] = "https://i.imgur.com/XqYcfeX.png";
    for (var i = 0; i < filenames.length; i++){//create a new arrary for humans
        frames.push(loadImage(filenames[i]));
    }
    //load instructural images
    instruct1 = loadImage("https://i.imgur.com/yXqSt39.png");
    instruct2 = loadImage("https://i.imgur.com/8KBVWZK.png");
}

//////////setting moving particles///////// Some ideas are inspired by TA's leadinglecture

var gravity = 0.01;   // downward acceleration
var springy = 1.2; // how much velocity is retained after bounce
var drag = 0.0001;    // drag causes particles to slow down
var np = 100;      // how many particles


function particleStep() {
    var forceX = (mouseX / 0.4 - this.x) / dist(this.x,this.y,mouseX / 0.4 ,mouseY / 0.4) * 0.1;
    var forceY = (mouseY / 0.4 - this.y) / dist(this.x,this.y,mouseX / 0.4 ,mouseY / 0.4) * 0.1;
    this.dx -= forceX;
    this.dy -= forceY;
    this.x += this.dx;
    this.y += this.dy;
    if (this.x > width) { // bounce off right wall
        this.x = width - (this.x - width);
        this.dx = -this.dx * springy;
    } else if (this.x < 0) { // bounce off left wall
        this.x = -this.x;
        this.dx = -this.dx * springy;
    }
    if (this.y > height) { // bounce off bottom
        this.y = height - (this.y - height);
        this.dy = -this.dy * springy;
    } else if (this.y < 0) { // bounce off top
        this.y = -this.y;
        this.dy = -this.dy * springy;
    }
    var vs = Math.pow(this.dx, 2) + Math.pow(this.dy, 2);
    // d is the ratio of old velocty to new velocity
    var d = vs * drag;
    d = min(d, 1);
    this.dx *= (1 - d);
    this.dy *= (1 - d);
}


function particleDraw() {
    fill(this.randomR,this.randomG,207,this.randomOpacity);
    ellipse(this.x, this.y,this.scaleS,this.scaleS);

}

function makeParticle(px, py, pdx, pdy) {
    p = {x: px, y: py,
        dx: pdx, dy: pdy,
        step: particleStep,
        render: particleDraw,
        scaleS: random(10,55), //because of the color gradiation on the background
        randomR: map(mouseY,0,height,250,100),//the foreground color also needs a transition
        randomG: random(150,200),
        randomOpacity: random(70,100)
        }
    return p;
}

var particles = [];

/////////basic setup//////////
function setup() {//2.6,x       1.875,y
    createCanvas(1250, 900);
    //loading moving circles on the front page
    for (var i = 0; i < np; i++) {
        particles.push(makeParticle(200, 200,random(-0.25, 0.25), random(-0.25, 0.25)));
    }
    w = width/2+cupW/2-3;
    dxWave = (TWO_PI / period) * xspacing;
    yvalues = new Array(floor(w/xspacing));
}

////////////draw function is divided to different modes as each will lead to a differect part of 
////////////the project

function draw() {
    scale(0.4,0.4);
    background(backgroundR, backgroundG, backgroundB); //set as variables for later changes
    ///////////////call of temperature mode////////////////
    if (TemperatureMode == true){
        fill(252,235,198);
        draWheats();
        fill(255,150);
        rect(150,height - 80,300,50);
        textSize(18);
        fill(103, 114, 175);
        text("Click me to the start",190,height - 50);
    }
    ///////////////call of start mode////////////////
    if (startMode == true){
        //using recursion for drawing a transitional background
        push();
        translate(200, 350);
        colorLayer1(0, 2);
        pop();
        push();
        scale(0.25,0.25);
        image(img,width / 2 - 700,height / 2 - 100);
        pop();

        //activate boxes & introduction behind & around the text 1
        var higherx = width / 2 - 50;
        var lowerx = width/2 - 450;
        if (mouseX / 0.4 < higherx & mouseX / 0.4 > lowerx && mouseY / 0.4 > height/2 - 60 && mouseY / 0.4 < height/2 + 50){
            push();
            strokeWeight(1);
            noFill();
            stroke(255);
            var quadx1 = width/2 - 400;
            var quadx2 = width/2 - 50;
            var quadx3 = width/2 - 100;
            var quadx4 = width/2 - 450;
            quad(quadx1, height/2 - 60, quadx2, height/2 - 60, quadx3, height/2 + 50, quadx4, height/2 + 50);
            pop();
            textSize(15);
            fill(0, 102, 153);
            text("Click to see the relationship between Antarctica ice mass and our primary drink source", width/2-400, 280, 200, 300);
        }

        //activate boxes & introduction behind & around the text 2
        if (mouseX / 0.4 < width/2+420 && mouseX / 0.4 > width/2+70 && mouseY / 0.4 < height/2+50 && mouseY / 0.4 > height/2-60){
            push();
            strokeWeight(1);
            noFill();
            stroke(255);
            quad(width/2+70, height/2-60, width/2+420, height/2-60, width/2+370, height/2+50, width/2+20, height/2+50);
            pop();
            textSize(15);
            fill(0, 102, 153);
            text("Click to see the relationship between temperature and our primary food source: wheat", width/2+70, 280, 200, 300);
        }

        //writing the text
        textSize(28);
        fill(0, 102, 153);
        textFont("Courier New");
        text("Antarctica Mass", width/2-400, height/2);
        text("Temperature Change", width/2+100,height/2);
        text("HELP",width-100,height-20);
        
        //loading the particles
        push();
        noStroke();
        for (var i = 0; i < particles.length; i++) { // for each particle
            var p = particles[i];
            p.step();
            p.render();
        }
        if (mouseIsPressed) {
            particles.push(makeParticle(mouseX/0.4, mouseY/0.4,random(-0.5, 0.5), random(-0.5, 0.5)));
        }
        pop();
    }

    if (iceMode == true){
        noFill();
        drawIce();
    } 

    if (helpMode == true){
        backgroundR=192;
        backgroundG=213;
        backgroundB=247;
        textSize(18);
        fill(0, 102, 153);
        textFont("Courier New");
        text("We are all familiar with the idea 'GLOBAL WARMING',",width/2-400, 100); 
        text("however, do we really connect ourselves with it? ", width/2-400, 120);
        text("Human are not always sensitive to numerical values. Therefore, what we understand",width/2-400, 160);
        text("as 'GLOBAL WARMING' may not be what actually happened. Here, statistical graphs", width/2-400, 180);
        text("are transformed to animations that demonstrate the changes. By connecting our", width/2-400, 200);
        text("primary needs with the changes, a tight relationship is shown.",width/2-400, 220);
        
        text("The second part, Temperature Change, is a interactive data", width/2-120, 660);
        text("visualization, by having the audience able to use up-arrow", width/2-120, 680);
        text("and down-arrow key on their keyboard, they are able to see", width/2-120, 700);
        text("the changes of temperature from its influence on wheat from",width/2-120,720);
        text("1880 to 2016",width/2-120,740);
        
        text("The first part is a animation where the audience will follow the",width/2-120, 350); 
        text("instructions, and by few clicks see the changes in the amount", width/2-120, 370);
        text("of our drinkable water from 2003 to 2017", width/2-120, 390);
        push();
        scale(0.17,0.17);
        image(instruct1,width/2+140,height/2+3000);
        image(instruct2,width/2+140,height/2+1200);
        pop();
        textSize(28);
        fill(0, 102, 153);
        text("BACK",width-100,height-20);

    }
}
function mousePressed() {
    if (startMode == true){
        if ((mouseX / 0.4) < width/2-50 & (mouseX / 0.4) > width/2-450 && (mouseY / 0.4) > height/2-60 && (mouseY / 0.4) < height/2+50){
            iceMode = true;
            startMode = false;
        }
        if (mouseX / 0.4 < width/2+420 & mouseX / 0.4 > width/2+70 && mouseY / 0.4 < height/2+50 && mouseY / 0.4 > height/2-60){
            TemperatureMode = true;
            startMode = false;
        }
        if (mouseX / 0.4 > width - 100 & mouseX / 0.4 < width - 30 && mouseY / 0.4 > height - 40 && mouseY / 0.4 < height - 10){
            helpMode = true;
            startMode = false;
        }
    }
    else if (TemperatureMode == true){
        if (mouseX / 0.4 > width/2-60 & mouseX / 0.4 < width/2-60+150 && mouseY / 0.4 > height-80 && mouseY / 0.4 < height-80+50){
            yearCount=2016;
        }
        if (mouseX / 0.4 < 450 & mouseX / 0.4 > 150 && mouseY / 0.4 < height-30 && mouseY / 0.4 > height-80){
            startMode = true;
            TemperatureMode = false;
        }
    }
    else if (iceMode == true){
        rect(width/2-animateW/2,height-animateH*3.5,animateW,animateH);
        if (beginAnimate == true & mouseX / 0.4 >width/2-animateW/2 && mouseX / 0.4 height-animateH*3.5 && mouseY / 0.4  width/2-animateW*1.8 && mouseX / 0.4 < width/2-animateW*1.8+210 && mouseY / 0.4 > height/2+275 && mouseY / 0.4 < height/2+275+50){
            startMode = true;
            iceMode = false;
            iceCount = 0;
            beginChanges = false;
            beginAnimate = false;

        }
    }
    
    else if (helpMode == true){
        if (mouseX / 0.4 > width - 100){
            helpMode = false;
            startMode = true;
        }
    }
}

/////////////recursion for background transition//////////////////
var colorR=215;
var colorG=112;
var colorB=106;
function colorLayer1(depth, len) {
    noStroke();
    fill(colorR+depth/3,colorG+depth/3,colorB+depth/3);
    rect(-200,-400,width,2);
    push();
    translate(0, len);
    colorLayer2(depth + 1, len);
    pop();
}

function colorLayer2(depth, len) {
    if (depth < 400) {
        colorLayer1(depth, len);
    }
}

/////////////data for wheat//////////////////
var wheatCounter=0;
var yearCount=1880;
var averTemp = [-0.20, -0.12 , -0.10, -0.21, -0.28, -0.32, -0.31, -0.33, -0.20, -0.12, -0.37, -0.24, -0.27,
                -0.30, -0.31, -0.21, -0.15, -0.11, -0.28, -0.16, -0.09, -0.15, -0.27, -0.35, -0.44, -0.28, 
                -0.23, -0.40, -0.43, -0.47, -0.42, -0.44, -0.35, -0.34, -0.16, -0.11, -0.34, -0.40, -0.26,
                -0.22, -0.27, -0.21, -0.28, -0.24, -0.28, -0.21, -0.10, -0.21, -0.21, -0.36, -0.15, -0.09,
                -0.17, -0.28, -0.14, -0.20, -0.15, -0.03, -0.03, -0.03, 0.08, 0.12, 0.09, 0.13, 0.25, 0.12,
                -0.04, -0.05, -0.09, -0.09, -0.18, -0.07, 0.01, 0.08, -0.13,-0.15,-0.20, 0.04, 0.07, 0.03,
                -0.02, 0.05, 0.03, 0.06, -0.20, -0.10, -0.05, -0.02, -0.07, 0.07, 0.02, -0.09, 0.01, 0.15,
                -0.07, -0.02, -0.11, 0.18, 0.07, 0.17, 0.27, 0.33, 0.13, 0.30, 0.15, 0.12, 0.19, 0.33, 0.41,
                0.28, 0.44, 0.43, 0.23, 0.24, 0.32, 0.46, 0.35, 0.48, 0.64, 0.42, 0.42, 0.55, 0.63, 0.62, 0.55, 
                0.69, 0.63, 0.66, 0.54, 0.64, 0.71, 0.60, 0.63, 0.65, 0.74, 0.87, 0.99]

var wheat;
var leaf;
var levelofO;
var lowestTemp = -0.47;//data from NASA
var convertionRate = 0.16
//calculated by 1 temperature will effect 6 wheats to disappear, then one corresponds to 0.16 degree

function convertion(){//this convert the averTemp to the desired value for display
    var currentTemp;
    currentTemp = averTemp[yearCount - 1880] - lowestTemp;
    wheat = floor(currentTemp / convertionRate);
    leaf = floor((currentTemp / convertionRate * 10) % 10);
    levelofO = (currentTemp / convertionRate * 10) % 10 - leaf;
}


function draWheats(){
    convertion();
    var numofL;
    wheatCounter += 0.1;
    backgroundR = 103;
    backgroundG = 114;
    backgroundB = 175;
    noStroke();
    angleMode(DEGREES);
    
    //draw background years
    textSize(100);
    fill(255,100);
    textFont("Courier New");
    text("YEAR " + yearCount, width/2 - 270, height/2);
    
    //draw wheats and mouths
    fill(252,235,198);
    for (var y = 0; y < 10; y ++){
        wheatX = 50 + y * 120;
        for (var i = 0; i < 10; i ++){//top part
            numofL = 0;
            if (i <= wheat & i >= 1 && y < 1){//4 is the number of 麦子
                fill(252,235,198,20);

            }else{fill(252,235,198)}
            
            numofL += 1;
            if (i == wheat + 1 & y < 1){
                if (numofL <= leaf) {
                    fill(252,235,198,20);
                }else{fill(252,235,198)}
            }
            arc(wheatX, wheatY, wheatL, wheatL, 85, 190,CHORD);

            numofL += 1;
            if (i == wheat + 1 & y < 1){
                if (numofL <= leaf) {
                    fill(252,235,198,20);
                }else{fill(252,235,198)}
            }
            arc(wheatX - 9, wheatY + 8, wheatL, wheatL, 265, 10, CHORD);

            push();//left part1
            translate(0,8);
            numofL += 1;
            if (i == wheat + 1 & y < 1){
                if (numofL <= leaf) {
                    fill(252,235,198,20);
                }else{fill(252,235,198)}
            }
            arc(wheatX, wheatY, wheatL, wheatL, 60, 160,CHORD);
    
            ////determine if filling the leaves
            numofL+=1;
            if (i == wheat + 1 & y < 1){
                if (numofL <= leaf) {
                    fill(252,235,198,20);
                }else{fill(252,235,198)}
            }
            arc(wheatX - 4, wheatY + 10, wheatL - 3, wheatL - 3, 230, 355, CHORD);
            translate(7,8);//left part2

            numofL += 1;
            if (i == wheat + 1 & y < 1){
                if (numofL <= leaf) {
                    fill(252,235,198,20);
                }else{fill(252,235,198)}
            }
            arc(wheatX, wheatY, wheatL, wheatL, 60, 160, CHORD);
            
            numofL += 1;
            if (i == wheat + 1 & y < 1){
                if (numofL <= leaf) {
                    fill(252,235,198,20);
                }else{fill(252,235,198)}
            }
            arc(wheatX - 4, wheatY + 10, wheatL - 3, wheatL - 3, 230, 355, CHORD);
            pop();

            push();//right part1
            numofL += 1;
            if (i == wheat + 1 & y < 1){
                if (numofL <= leaf) {
                    fill(252,235,198,20);
                }else{fill(252,235,198)}
            }
            translate(10,6);
            arc(wheatX, wheatY, wheatL, wheatL, 110, 220, CHORD);

            numofL += 1;
            if (i == wheat + 1 & y < 1){
                if (numofL <= leaf) {
                    fill(252,235,198,20);
                }else{fill(252,235,198)}
            }
            arc(wheatX - 11, wheatY + 3, wheatL, wheatL, 290, 40, CHORD);
            
            numofL += 1;
            if (i == wheat + 1 & y < 1){
                if (numofL <= leaf) {
                    fill(252,235,198,20);
                }else{fill(252,235,198)}
            }
            translate(7,8);//right part2
            arc(wheatX, wheatY, wheatL, wheatL, 110, 220, CHORD);
            
            numofL += 1;
            if (i == wheat + 1 & y < 1){
                if (numofL <= leaf) {
                    fill(252,235,198,20);
                }else{fill(252,235,198)}
            }
            arc(wheatX - 11, wheatY + 3, wheatL, wheatL, 290, 40,CHORD);
        
            pop();
            wheatY=50 + i * 80;//for listing all the ys
            push();
            strokeWeight(0.4);
            stroke(252,235,198);
            translate(-9, -1);
            line(wheatX - 5, wheatY - 5, wheatX, wheatY);//top
            line(wheatX - 5, wheatY + 10, wheatX, wheatY + 13);//left1
            line(wheatX + 10, wheatY - 5, wheatX + 12,wheatY + 1);//right1
            line(wheatX, wheatY + 18, wheatX+7, wheatY + 21);//left2
            line(wheatX + 19, wheatY + 10, wheatX + 17, wheatY + 1);//right2
            strokeWeight(1);//root
            line(wheatX + 2, wheatY + 5, wheatX + 29, wheatY + 32);
            pop();
            push();
            var framesC = round(frameCount/6);
            scale(0.1,0.1);
            image(frames[framesC % 6], wheatX * 10, wheatY * 10);
            pop();
        }
    }
    
    fill(255,150);
    if (mouseX / 0.4 > width/30 & mouseX / 0.4 < width/30 + 50 && mouseY / 0.4 > height/18 && mouseY / 0.4 < height/18+50){
        textSize(12);
        fill(173, 129, 225);
        text("1880 -0.2",mouseX / 0.4 +50,mouseY+50);
    }

    rect(width/2-60,height-80,150,50);
    textSize(18);
    fill(103, 114, 175);
    text("Jump to 2016",width/2-50,height-50);
}

function drawIce(){
    iceCount += 1;
    backgroundR = 103;
    backgroundG = 114;
    backgroundB = 175;
    noFill();
    strokeWeight(4);
    stroke(230);
    rect(width / 2 + cupW / 3 - 10, height / 2 - cupH / 2 - top3H, cupW / 6 + 10, -top1H);
    rect(width / 2 + cupW / 3, height / 2 - cupH / 2 - top3H, cupW / 8, top3H);
    rect(width / 2 - cupW / 2, height / 2-cupH / 2, cupW, cupH);

    calcWave();
    renderWave();
    fill(255,200);
    rect(width/2 - 130, height/2 - 190, 65, 25, 20);
    animation();
    
    push();
    var increaseCount = frameCount/3;
    fill(255,190);
    rect(width/2 - animateW * 1.8,height / 2 + 275, 210, 50);
    strokeWeight(0.8 + 0.08 * (increaseCount % 10));
    fill(103,114,175);
    stroke(18);
    textSize(14);
    textFont("Courier New"); 
    text("Click me to the start", width/2 - animateW * 1.7, height / 2 + 295, 350, 100);
    pop();

    if (beginAnimate == true){
        noFill();
        var increaseCount = frameCount/3;
        strokeWeight(0.8 + 0.1 * (increaseCount % 10));
        stroke(230);
        rect(width / 2 - animateW / 2, height - animateH * 3.5, animateW, animateH);
        textSize(12);
        textFont("Courier New"); 
        text("See the changes 2002~2017", width / 2 - animateW / 4 - 40, height - animateH * 3);
        noStroke();
        fill(194,211,231);
        textSize(100);
        textFont("Courier New"); 
        fill(255,100);
        text("X 100", width / 2 + cupW / 1.5, 250, 200, 280);
    }
}


function animation(){
    if (iceCount <= 80){
        textSize(18);
        textFont("Courier New"); 
        fill(255);
        text("Since 2002, there are about 127.0 gigatones loss On antarctica mass every year", width / 2 + cupW / 1.5, 210, 200, 280);
    }
    else if (iceCount > 80 & iceCount <= 160){
        textSize(18);
        textFont("Courier New"); 
        fill(255);
        text("Through the numerical data, we may not see the changes clearly", width / 2 + cupW / 1.5, 210, 200, 280);
    }
    else if (iceCount > 160 & iceCount <= 240){
        textSize(18);
        textFont("Courier New"); 
        fill(255);
        text("However, what we do relate the this place counts 68% of the fresh water for the entire earth", width / 2 + cupW / 1.5, 210, 200, 280);
    }
    else if (iceCount > 240 & iceCount <= 320){
        textSize(18);
        textFont("Courier New"); 
        fill(255);
        text("What if we transform the loss of ice into the loss of our drinkable water?", width/2+cupW/1.5,210,200,280);
    }
    else if (iceCount > 320 & iceCount <= 400){
        textSize(18);
        textFont("Courier New"); 
        fill(255);
        text("Here, I show what happen to 1 bottle of water if we devide this water source into 100 bottles of water", width/2 + cupW/1.5, 210, 200, 280);
    }
    else{beginAnimate=true;}
}
function calcWave() {
    // Increment theta (try different values for 
    // 'angular velocity' here)
    theta += 0.02;

    // For every x value, calculate a y value with sine function
    var x = theta;
    for (var i = 0; i < yvalues.length; i++) {
        yvalues[i] = sin(x)*amplitude;
        x += dxWave;
    }
}
var inputwaterL;
var currentwaterL;
var waterR=255;
var waterG=255;
var waterB=255;
var dateCount=0;
var converticeM=1.091*(10**3);
var totaliceM=2.65*(10**9);
var currentSum;
var changeT=0;

function convertwaterL(){
    if (frameCount % 7 == 0 & changeT < (iceMassL.length - 1) && beginChanges == true){
        changeT += 1;
    }  
    inputwaterL = ((totaliceM - ((-1 * (iceMassL[changeT] - 170.1)) * converticeM)) / (totaliceM));
    inputwaterL = inputwaterL * 100 - 99;
}

function renderWave() {
    convertwaterL();
    currentwaterL = height - (inputwaterL * height);
    currentwaterL = map(currentwaterL, 0, height, height / 2 - cupH / 2, height / 2 + cupH / 2);
    textSize(100);
    fill(255,100);
    textFont("Courier New"); 
    text(dateRecorded[changeT], width / 2 - 270, 100);
    noStroke();
    fill(194,211,231);
    rect(width / 2 - cupW / 2 + 2, currentwaterL + 20, cupW - 4,(height / 2 + cupH / 2 - (currentwaterL + 20)));

    // A simple way to draw the wave with an ellipse at each location
    for (var i = 0; i < 10;i ++){
        waterR = 255 - i * 6.1;
        waterG = 255 - i * 4.4;
        waterB = 255 - i * 2.5;
        for (var x = 955; x < yvalues.length; x++) {
            fill(waterR,waterG,waterB);
            ellipse(x * xspacing, currentwaterL + yvalues[x], 5, 5);
        }
        currentwaterL += 5;
    }
}

function keyPressed() {
    if (keyCode == UP_ARROW & yearCount <= 2015) {
        yearCount += 1;
    }
    else if (keyCode == DOWN_ARROW) {
        if (yearCount > 1880){
            yearCount -= 1;
        }
    }

}

selinal-FinalProject

sketch

//Selina Lee
//Section C
//selinal@andrew.cmu.edu
//Final Project

var mapPic;//variable for image of map
var backPic; //background picture (collage of running in Pittsburgh)
var skiboStart; //turtle functions at different start poitns
//this one starts in front of skibo
var ovalStart; //this one occurs after reaching the schenley oval
var scaleX = 0.4; //scale down width wise from original canvas which is
// 480 / 1200
var scaleY = 0.6; //scale down height wise from original canvas whic is
// 480 / 800 

//arrays containing the points to draw run routes with turtle functions
//route titled beechwood (x and y points placed into arrays)
var beechX = [760, 789, 778, 808, 859, 895, 968, 980, 1014, 984, 1024, 950,
809, 737, 733];
var beechY = [277, 262, 244, 225, 221, 242, 242, 325, 324, 175, 111, 125, 189,
195, 237];
//route titled the point
var pointX = [740, 726, 719, 697, 687, 695, 677, 632, 592, 568, 560, 464, 402, 
268, 219, 35, 38, 61, 104, 148, 154, 201, 162, 183, 234, 418, 463, 502, 602, 
672, 695, 732, 722, 735, 733, 745];
var pointY = [295, 298, 312, 315, 327, 353, 372, 378, 365, 389, 418, 361, 356, 
379, 370, 279, 262, 258, 242, 226, 255, 244, 314, 328, 327, 338, 352, 355, 261,
235, 236, 234, 258, 261, 270, 275];
//route titled trader joe's
var traderX = [760, 789, 778, 808, 859, 859, 968, 1059, 1064, 1062, 1098, 964, 
943, 718, 731, 737, 733, 744, 734];
var traderY = [277, 262, 244, 225, 221, 242, 242, 221, 212, 204, 138, 24, 12, 
103, 147, 194, 234, 239, 270];
//route titled tranquil
var tranquilX = [760, 789, 778, 808, 859, 895, 968, 980, 1049, 1087, 1089, 1111,
1126, 1138, 1161, 1174, 1169, 1178, 1170, 1178, 1160, 1159, 1139, 1068, 1060, 
1059, 1139, 1068, 1060, 1059, 968, 895, 859, 808, 778];
var tranquilY = [277, 262, 244, 225, 221, 242, 242, 325, 324, 338, 345, 343, 
354, 346, 362, 350, 339, 322, 301, 287, 260, 234, 217, 191, 208, 218, 245, 242,
221, 225, 244];
//warmup route to work out location titled one-eight
var eightX = [743, 732, 715, 700, 686, 695, 687, 678, 687, 674, 673, 677, 671, 
683, 683, 692, 759, 782, 787, 778, 761, 721];
var eightY = [291, 295, 310, 315, 328, 349, 365, 379, 394, 397, 406, 411, 421, 
436, 444, 449, 403, 398, 392, 385, 391, 417];
//schenley oval route
var ovalX = [714, 720, 737, 746, 757, 764, 760, 751, 741, 720, 715];
var ovalY = [411, 415, 407, 396, 393, 389, 381, 379, 379, 395, 406];
//regular cool down route from oval
var coolX = [737, 778, 789, 794, 801, 789, 776, 733, 719, 709, 709, 713, 714, 
723, 740, 746];
var coolY = [408, 387, 387, 392, 386, 378, 374, 358, 355, 342, 328, 321, 311, 
308, 296, 274];
//other cool down route from oval called ten minute
var tenX = [724, 696, 684, 689, 688, 704, 690, 712, 707, 693, 696, 690, 694, 
724, 731, 741];
var tenY = [420, 439, 426, 416, 407, 404, 385, 379, 372, 363, 351, 326, 318, 
306, 294, 293];
//run titled southside
var southX = [745, 730, 740, 727, 673, 602, 499, 465, 418, 407, 409, 431, 477, 
486, 496, 523, 576, 602, 632, 680, 675, 682, 686, 699, 761, 782, 795, 784, 733, 
712, 694, 691, 694, 724, 731, 739];
var southY = [274, 271, 235, 233, 236, 262, 352, 354, 335, 417, 454, 460, 472, 
463, 455, 477, 437, 460, 469, 460, 443, 435, 448, 448, 400, 395, 382, 376, 357, 
350, 340, 323, 315, 304, 293, 293];

var counter = 0;// counter variable to count down differet routes shown
var backColR = 0; //background R value variable
var backColG = 0; //background G value variable
var backColB = 0; //background B value variable
var backColT = 270; //background opacity value

var colorArr = []; //empty array to contain color and placement creations
//see function fillInColorArray
var colors = ["black", "yellow"]; //colors to take


function preload() {
    mapPic = loadImage("https://i.imgur.com/zIVTSXM.jpg"); //map preload
    backPic = loadImage("https://i.imgur.com/vzuo6YG.jpg"); //background image
    //preload
}

function setup() {
    createCanvas(480, 480);
    image(backPic, 0, 0, map.width, map.height);//drawing map picture
    
    //used early on in project to find array points
    /*if(mouseIsPressed) {
     print(mouseX, mouseY); 
    }*/

    skiboStart = makeTurtle(747 * scaleX, 274 * scaleY); //draws turtles that 
    //start and end at Skibo
    ovalStart = makeTurtle(712 * scaleX, 410 * scaleY); // turtles that start at 
    //Schenley Oval 
    
    //I missed the criteria to scale the canvas to 480, so I used the scale 
    //variable to reduce the size of my points
    for(var i = 0; i < beechX.length; i++) {
        beechX[i] *= scaleX;
        beechY[i] *= scaleY;
    }
    for(var i = 0; i < pointX.length; i++) {
        pointX[i] *= scaleX;
        pointY[i] *= scaleY;
    }
    for(var i = 0; i < traderX.length; i++) {
        traderX[i] *= scaleX;
        traderY[i] *= scaleY;
    }
    for(var i = 0; i < tranquilX.length; i++) {
        tranquilX[i] *= scaleX;
        tranquilY[i] *= scaleY;
    }
    for(var i = 0; i < ovalX.length; i++) {
        ovalX[i] *= scaleX;
        ovalY[i] *= scaleY;
    }
    for(var i = 0; i < eightX.length; i++) {
        eightX[i] *= scaleX;
        eightY[i] *= scaleY;
    }
    for(var i = 0; i < coolX.length; i++) {
        coolX[i] *= scaleX;
        coolY[i] *= scaleY;
    }
    for(var i = 0; i < tenX.length; i++) {
        tenX[i] *= scaleX;
        tenY[i] *= scaleY;
    }
    for(var i = 0; i < southX.length; i++) {
        southX[i] *= scaleX;
        southY[i] *= scaleY;
    }
}

function mouseClicked() {
    counter++; //when mouse is clicked, create a counter to increment
    //every time 
    backColT = backColT - 20; //with every mouse click, the background
    //transparency gets more opaque
}


function draw() {
 image(backPic, 0, 0, map.width, map.height);//underlying image to be
 //revealed
 background(backColR, backColG, backColB, backColT); //background color
 //based on variable values

 fill(255); //prints directions on how to interact with piece ==>
 //continuous clicking reveals the different routes and visuals and black 
 //and white background
 text("Click on the canvas to reveal my running log in Pittsburgh!", 30, 
  30);

 if(mouseIsPressed) {
     print(mouseX, mouseY); //helps find position of mouse on map to draw 
     //turtle before translation
    }

    translate(-8, 50); //center the marks with these units
    
    //BEECHWOOD ROUTE: 5 MILES
    if (counter == 0 || counter >= 9) { //the start of the counter and when
    	//the mouse clicks through all slides, this will be shown
        for(var i = 0; i < beechX.length; i++) { //iterate through route 
            //arrays to get points. The array length should be the same for
        	//X and Y because I manually clicked on the screen to get place
        	//numbers
            skiboStart.setColor(color(255, 0, 255)); //magenta turtle
            skiboStart.penDown(); //start drawing
            skiboStart.goto(beechX[i], beechY[i]); //drawing beechwood route 
            //based on points in beechX and beechY array
            skiboStart.penUp();//stop drawing
            
            noStroke(); 
            fill(150, 0, 255, 80); //light, see-through, purple rectangles
            //these rectangles are drawn based on the values of the points
            //and the differences of the points on the path
            rect(beechX[i - 1], beechY[i - 1], beechX[i - 1] - beechX[i], 
             beechY[i - 1] - beechY[i]);
            rect(beechX[i], beechY[i], beechX[i] - beechX[i], 
             beechY[i - 1] - beechY[i]);
            rect(beechX[i - 1], beechY[i], beechX[i] - beechX[i - 1], 
             beechY[i] - beechY[i - 1]);
            rect(beechX[i], beechY[i], beechX[i] - beechX[i - 1], 
             beechY[i] - beechY[i - 1]);
        }
    }

    //THE POINT: 9.25 MILES
    fillInColorArr(0); //see function fillInColorArr 
    //this starts the function at place 0
    if (counter == 1 || counter >= 9) { //next shown visual from counter
    	//(all visuals are shown at the end of the list)
        for(var i = 0; i < pointX.length; i++) {
             backColB = 255; //background will be light blue
             backColG = 200;
             backColR = 100;

             skiboStart.setColor(colorArr[i]); //the color of each 
             //turtle move is based on fillInColorArr (while it 
             //iterates, a value is placed into the color function out
             //of the colorArr array)
             skiboStart.setWeight(5); //thicker line
             skiboStart.penDown();
             skiboStart.goto(pointX[i], pointY[i]);
             skiboStart.penUp();

             noFill();
             stroke(255, 255, 0); //yellow thin lines
             strokeWeight(1);
             beginShape(); //curves based off of Pittsburgh bridges
             //and the curve vertex control points are based on
             //position between selected points so that some
             //abstraction is visualized from the data
             curveVertex(pointX[i], pointY[i] + 30);
             curveVertex(pointX[i], pointY[i] + 30);
             curveVertex((pointX[i] + pointX[i - 1]) / 2, 
              (pointY[i - 1] + pointY[i]) / 4);
             curveVertex((pointX[i - 1] + pointX[i]) / 2, 
              (pointY[i - 1] + pointY[i]) / 4);
             curveVertex(pointX[i - 1], pointY[i - 1] + 30);
             curveVertex(pointX[i - 1], pointY[i - 1] + 30);
             endShape();
        }
    }

    //TRADER JOE'S: 5.5 MILES
    if(counter == 2  || counter >= 9) {
        for(var i = 0; i < traderX.length; i++) {
            backColR = 255; //light purple background
            backColG = 120;
            backColB = 200;

            skiboStart.setColor(color(200, 255, 0)); //green-yellow 
            skiboStart.setWeight(1)
            skiboStart.penDown();
            skiboStart.goto(traderX[i], traderY[i]);
            skiboStart.penUp();

            for(var j = 0; j < 5; j++) { //make 5 of this command
                 noFill();
                 strokeWeight(2); 
                 stroke(255, 200, 0); //orange bullseye design at 
                 //each turtle point
                 ellipse(traderX[i], traderY[i], 10 * j, 10 * j);
            }
        }
    }

    //TRANQUIL: 6.3 MILES
    if(counter == 3 || counter >= 9) { 
        for(var i = 0; i < tranquilX.length; i++) {
            backColB = 75; //dark blu background
            backColG = 0;
            backColR = 0;

            skiboStart.setColor(color(200, 255, 0)); //green-yellow
            skiboStart.setWeight(1);
            skiboStart.goto(tranquilX[i], tranquilY[i]);
            skiboStart.penUp();

            fill(255, 230, 0, 60); //see-through orange-yellow
            //circles drawn at each tranquil turtle point
            //one on top of the other like an eye
            ellipse(tranquilX[i], tranquilY[i], 20, 20); 
            ellipse(tranquilX[i], tranquilY[i], 8, 8);

            fill(150, 255, 100, 100); //see-through green
            noStroke();
            //these ellipses were drawn towards the top right of the turtle
            //route as a conglomeration
            ellipse(tranquilX[i] + 60, tranquilY[i] - 20, 50, 50);     
            fill(100, 255, 220, 100); //see-through blue-green
            ellipse(tranquilX[i] + 50, tranquilY[i] - 40, 40, 40); 
        }
    }

    //ONE EIGHT- WARMUP ROUTE TO SCHENLEY OVAL VIA THE BRIDAL PATH: 1.8 MILES
    if(counter == 4 || counter >= 9) {
        for(var i = 0; i < eightX.length; i++) {
         backColR = 255; //yellow background
         backColG = 255;
         backColB = 0;

            skiboStart.setColor(color(255, 0, 0)); //red turtle
            skiboStart.setWeight(1);
            skiboStart.penDown();
            skiboStart.goto(eightX[i], eightY[i]);
            skiboStart.penUp();

            fill(255, 50, 75, 20); //fill transparent red
            var maxX = max(eightX); //maximum value in x value array
            var minX = min(eightX); //minimum value in x value array
            var midX = (maxX + minX) / 2; //average of max and min value in 
            //x array

            var maxY = max(eightY); //maximum value in y array
            var minY = min(eightY); //minimum value in y array
            var midY = (maxY + minY) / 2; //avverage of max and min value in 
            //y array
            var curveX1; //first control x value point 
            var curveY1; //first control y value point
            var curveX2; //control two x value point
            var curveY2; //control two y value point

            if(eightX[i] < midX) { //if the turtle point is to the left of the 
             //"center"
             curveX1 = eightX[i] + 10; //if using bezier curve function, the 
             //first control point goes towards the middle 
             curveX2 = eightX[i] - 10; //then the second control point goes 
             //away from the center
            } else { //to the right of "center"
             curveX1 = eightX[i] - 10; //towards middle
             curveX2 = eightX[i] + 10; //away from center
            }

            if(eightY[i] < midY) { //if the turtle point is to the top of the 
             //middle of the route loop
             curveY1 = eightY[i] + 10; //the first control point goes down 
             //towards the center
             curveY2 = eightY[i] - 10; //second goes away from
            } else { //to bottom of route
             curveY1 = eightY[i] - 10; //first control point towards middle
             curveY2 = eightY[i] + 10; //away from middle
            }

            stroke(255, 100, 100, 200); //red
            strokeWeight(0.5);
            //the curves meet at a midpoint
            bezier(eightX[i], eightY[i], curveX1, curveY1, curveX2, curveY2, 
             midX, midY);
            bezier(eightX[i], eightY[i], curveX2, curveY2, curveX1, curveY1, 
             midX, midY);
        }
    }

    //OVAL LOOP = .625 MILES
    if(counter == 5 || counter >= 9) {
        for(var i = 0; i < ovalX.length; i++) {
            stroke(255, 100, 255, 70); //light magenta
            strokeWeight(40); //very thick line
            //used a line so the turtle function does not get confused 
            //and hide the movement created visually.
            //this line makes the same route as the turtle function
            line(ovalX[i], ovalY[i], ovalX[i - 1], ovalY[i - 1]);

            stroke(100, 150, 255, 120); //overlapping light blue lines
            //on top of oval lap so you can still see the purple underneath
            strokeWeight(15);
            line(ovalX[i - 1], ovalY[i - 1], ovalX[i], ovalY[i]);

            stroke(255, 200, 0); //orange turtle on top of laps
            strokeWeight(3);
            line(ovalX[i], ovalY[i], ovalX[i - 1], ovalY[i - 1]);
        }
    }

    //COOL DOWN ROUTE FROM SCHENLEY OVAL VIA PANTHER HOLLOW TRAIL: 1.3 MILES
    if(counter == 6 || counter >= 9) {
        for(var i = 0; i < coolX.length; i++) {
            ovalStart.setColor(color(0, 100, 255)); 
            ovalStart.setWeight(1);
            ovalStart.penDown();
            ovalStart.goto(coolX[i], coolY[i]);
            ovalStart.penUp();

            fill(100, 150, 255, 30);
            var maxX = max(coolX); //maximum value in x value array
            var minX = min(coolX); //minimum value in x value array
            var midX = (maxX + minX) / 2; //average of max and min value in 
            //x array

            var maxY = max(coolY); //maximum value in y array
            var minY = min(coolY); //minimum value in y array
            var midY = (maxY + minY) / 2; //avverage of max and min value in 
            //y array
            var curveX1; //first control x value point 
            var curveY1; //first control y value point
            var curveX2; //control two x value point
            var curveY2; //control two y value point

            if(coolX[i] < midX) { //if the turtle point is to the left of the 
                //"center"
                curveX1 = coolX[i] + 10; //if using bezier curve function, the 
                //first control point goes towards the middle 
                curveX2 = coolX[i] - 10; //then the second control point goes 
                //away from the center
            } else { //to the right of "center"
                 curveX1 = coolX[i] - 10; //towards middle
                 curveX2 = coolX[i] + 10; //away from center
            }

            if(coolY[i] < midY) { //if the turtle point is to the top of the 
                //middle of the route loop
                curveY1 = coolY[i] + 10; //the first control point goes down 
                //towards the center
                curveY2 = coolY[i] - 10; //second goes away from
            } else { //to bottom of route
                curveY1 = coolY[i] - 10; //first control point towards middle
                curveY2 = coolY[i] + 10; //away from middle
            }

            stroke(0, 200, 255, 200);
            strokeWeight(.5);
            bezier(coolX[i], coolY[i], curveX1, curveY1, curveX2, curveY2, midX,
             midY);
            bezier(coolX[i], coolY[i], curveX2, curveY2, curveX1, curveY1, midX, 
             midY);
        }
    }

    //TEN MINUTE COOL DOWN: 1.1 MILES
   if(counter == 7 || counter >= 9) {
       for(var i = 0; i < tenX.length; i++) {
           ovalStart.setColor(color(0, 150, 255));
           ovalStart.penDown();
           ovalStart.goto(tenX[i], tenY[i]);
           ovalStart.penUp();

           fill(20, 20, 255, 30);
           var maxX = max(tenX); //maximum value in x value array
           var minX = min(tenX); //minimum value in x value array
           var midX = (maxX + minX) / 2; //average of max and min value in 
           //x array

           var maxY = max(tenY); //maximum value in y array
           var minY = min(tenY); //minimum value in y array
           var midY = (maxY + minY) / 2; //avverage of max and min value in 
           //y array
           var curveX1; //first control x value point 
           var curveY1; //first control y value point
           var curveX2; //control two x value point
           var curveY2; //control two y value point

           if(tenX[i] < midX) { //if the turtle point is to the left of the 
               //"center"
               curveX1 = tenX[i] + 10; //if using bezier curve function, the 
               //first control point goes towards the middle 
               curveX2 = tenX[i] - 10; //then the second control point goes 
               //away from the center
            } else { //to the right of "center"
               curveX1 = tenX[i] - 10; //towards middle
               curveX2 = tenX[i] + 10; //away from center
            }

            if(tenY[i] < midY) { //if the turtle point is to the top of the 
                //middle of the route loop
                curveY1 = tenY[i] + 10; //the first control point goes down 
                //towards the center
                curveY2 = tenY[i] - 10; //second goes away from
            } else { //to bottom of route
                curveY1 = tenY[i] - 10; //first control point towards middle
                curveY2 = tenY[i] + 10; //away from middle
            }

            stroke(0, 150, 255, 200);
            strokeWeight(0.5);
            bezier(tenX[i], tenY[i], curveX1, curveY1, curveX2, curveY2, midX, 
             midY);
            bezier(tenX[i], tenY[i], curveX2, curveY2, curveX1, curveY1, midX, 
             midY);
     }
  }

  //SOUTHSIDE: 6.6 MILES
  if(counter == 8 || counter >= 9) {
      for(var i = 0; i < southX.length; i++) {
      	  backColG = 255; //green background
      	  backColR = 50;
      	  backColB = 100;

          skiboStart.setColor(color(255, 0, 255)); 
          skiboStart.penDown();
          skiboStart.goto(southX[i], southY[i]);
          skiboStart.penUp();

          stroke(255, 50, 100); //red
          fill(255, 120, 50, 50); //transparent red orange
          //lines drawn to create turtle skeleton
          line(southX[i], southY[i], southX[i] * 0.9, southY[i] + 20);
          line(southX[i] * 0.9, southY[i] + 20, southX[i - 1] * 0.9, 
          southY[i - 1] + 20); 
          line(southX[i - 1] * 0.9, southY[i - 1] + 20, southX[i] * 0.85, 
          southY[i] - 30);
          line(southX[i] * 0.85, southY[i] - 30, southX[i - 1] * 0.85, 
          southY[i - 1] - 30);
          line(southX[i] * 0.85, southY[i] - 30, 180, 330);

          noStroke();
          //triangles based off of parameters to create line skeleton
          triangle(southX[i], southY[i], southX[i] * 0.9, southY[i] + 20,
          southX[i - 1] * 0.9, southY[i - 1] + 20);
          triangle(southX[i - 1] * 0.9, southY[i - 1] + 20, 
          southX[i] * 0.85, southY[i] - 30, 180, 330)
       }
  }
}

function fillInColorArr(filledSoFar) { //recursive function to change color
	//every action of the turtle 
    if(filledSoFar == 0) { //if nothing has been drawn yet, leave the array 
        colorArr = []; 
        colorArr.push(colors[0]); //push the colors from colors array into
        //colorArr so that they can be used and start from 0 which is "black"
        var currentFillNumber = filledSoFar + 1; //counts which property has
        //recieved a color to use
        fillInColorArr(currentFillNumber); //fill in this area with the color
        //corresponding to the placement of the turtle in its start point in 
        //its array
    } else if(filledSoFar >= pointX.length) {
        return;
    } else { //if the paremeters that have been filled so far do not exceed 
    	//the length of the point array, do the same as if nothing has been
    	//drawn yet and give the parameter a color to use
        colorArr.push(colors[filledSoFar % colors.length]);
        var currentFillNumber = filledSoFar + 1;
        fillInColorArr(currentFillNumber);
    }
}

function turtleLeft(d) {
    this.angle -= d;
}


function turtleRight(d) {
    this.angle += d;
}


function turtleForward(p) {
    var rad = radians(this.angle);
    var newx = this.x + cos(rad) * p;
    var newy = this.y + sin(rad) * p;
    this.goto(newx, newy);
}


function turtleBack(p) {
    this.forward(-p);
}


function turtlePenDown() {
    this.penIsDown = true;
}


function turtlePenUp() {
    this.penIsDown = false;
}


function turtleGoTo(x, y) {
    if (this.penIsDown) {
      stroke(this.color);
      strokeWeight(this.weight);
      line(this.x, this.y, x, y);
    }
    this.x = x;
    this.y = y;
}


function turtleDistTo(x, y) {
    return sqrt(sq(this.x - x) + sq(this.y - y));
}


function turtleAngleTo(x, y) {
    var absAngle = degrees(atan2(y - this.y, x - this.x));
    var angle = ((absAngle - this.angle) + 360) % 360.0;
    return angle;
}


function turtleTurnToward(x, y, d) {
    var angle = this.angleTo(x, y);
    if (angle < 180) {
        this.angle += d;
    } else {
        this.angle -= d;
    }
}


function turtleSetColor(c) {
    this.color = c;
}


function turtleSetWeight(w) {
    this.weight = w;
}


function turtleFace(angle) {
    this.angle = angle;
}


function makeTurtle(tx, ty) {
    var turtle = {x: tx, y: ty,
                  angle: 0.0, 
                  penIsDown: true,
                  color: color(128),
                  weight: 1,
                  left: turtleLeft, right: turtleRight,
                  forward: turtleForward, back: turtleBack,
                  penDown: turtlePenDown, penUp: turtlePenUp,
                  goto: turtleGoTo, angleto: turtleAngleTo,
                  turnToward: turtleTurnToward,
                  distanceTo: turtleDistTo, angleTo: turtleAngleTo,
                  setColor: turtleSetColor, setWeight: turtleSetWeight,
                  face: turtleFace};
    return turtle;
}

abradbur – Final Project – Section C

sketch


var aSlider;
var frames = [];//stores crow images

function preload(){
  //crow cycle images uploaded to imgur
  var crowCycles = [];
  crowCycles[0] = "https://i.imgur.com/kFSBiWN.png"
  crowCycles[1] = "https://i.imgur.com/WLXwnwq.png"
  crowCycles[2] = "https://i.imgur.com/PGafnLp.png"
  crowCycles[3] = "https://i.imgur.com/kFSBiWN.png"
  crowCycles[4] = "https://i.imgur.com/WLXwnwq.png"
  crowCycles[5] = "https://i.imgur.com/PGafnLp.png"
  crowCycles[6] = "https://i.imgur.com/kFSBiWN.png"
  crowCycles[7] = "https://i.imgur.com/PrhO9gc.png"
  crowCycles[8] = "https://i.imgur.com/wIi9Q1O.png"
  crowCycles[9] = "https://i.imgur.com/ddJaFA1.png"
  crowCycles[10] = "https://i.imgur.com/PrhO9gc.png"
  crowCycles[11] = "https://i.imgur.com/wIi9Q1O.png"
  crowCycles[12] = "https://i.imgur.com/ddJaFA1.png"
  crowCycles[13] = "https://i.imgur.com/PrhO9gc.png"

  //load images into the frames array
  for (i = 0; i < crowCycles.length; i ++){
    frames[i] = loadImage(crowCycles[i]);
  }
}

function setup(){
  createCanvas(480, 480);
  //slider controls the height of the grass
  aSlider = createSlider(0, 400, 400, 0);
  aSlider.position(200, 440);
  frameRate(5);
}

function draw(){

  //the sky will change color depending on the seconds
  var s = second();
  var skyR = map(s, 0, 60, 110, 248);
  var skyG = map(s, 0, 60, 210, 105);
  var skyB = map(s, 0, 60, 230, 32);
  background(skyR, skyG, skyB);

  //create the text box + slider-button area
  var v = aSlider.value()
  fill(255);
  rect(0, 400, 479, 79);
  line(160, 400, 160, 480);
  fill(0);
  textSize(15);
  text("The time flows differently here.", 10, 410, 150, 75);
  
  //button
  fill(206, 78, 58);
  ellipse(440, 440, 70);
  fill(237, 89, 81);
  ellipse(440, 440, 60);
  
  //hills
  fill(167, 118, 59);
  arc(448, 128, 208, 84, PI, TWO_PI);
  fill(211, 164, 98);
  arc(384, 240, 416, 264, PI, TWO_PI);
  arc(72, 240, 416, 200, PI, TWO_PI);

  //farmhouse
  fill(111, 16, 29);
  rect(152, 144, 176, 96);
  fill(38, 0, 2); 
  triangle(152, 144, 240, 64, 328, 144);
  for (var i = 0; i < 4; i ++){
    line(152, 168 + (i * 12), 328, 168 + (i *12));
    i += 1;
  }
  line(152, 144 + (24 *3), 328, 144 + (24 *3));
  rect(230, 200, 20, 40);
  fill(255);
  rect(170, 200, 30, 20);
  rect(278, 200, 30, 20);
  fill(0);

  //first window crack
  beginShape();
  vertex(171, 200);
  vertex(180, 210);
  vertex(200, 210);
  vertex(190, 220);
  vertex(171, 205);
  endShape();

  //second window crack
  beginShape();
  vertex(278, 220);
  vertex(308, 210);
  vertex(298, 210);
  vertex(290, 203);
  vertex(300, 220);
  vertex(284, 200);
  endShape();

  //field
  fill(242, 224, 159);
  rect(0, 240, 480, 160);

  //tree with tire swing
  push();
  translate(448, 100);
  drawBranch(0, 10);
  pop();
  line(430, 51, 430, 80);
  noFill();
  ellipse(430, 85, 10);

  //the well
  fill(138);
  rect(364, 100, 25, 25);
  line(364, 100, 364, 80);
  line(389, 100, 389, 80);
  line(377, 90, 377, 80);
  line(377, 100, 377, 125);
  line(364, 106, 389, 106);
  line(364, 115, 389, 115);
  fill(80, 40, 50);
  beginShape();
  vertex(373, 90);
  vertex(381, 90);
  vertex(379, 95);
  vertex(375, 95);
  vertex(373, 90);
  endShape();
  triangle(364, 80, 377, 75, 389, 80);

  //grave
  fill(138);
  rect(72, 125, 12, 15, 15, 15, 2, 2);
  
  //border trees
  push();
  translate(20, 240);
  drawBranch(0, 15);
  pop();
  push();
  translate(120, 240);
  drawBranch(0, 15);
  pop();
  push();
  translate(70, 245);
  drawBranch(0, 10);
  pop();
  push();
  translate(448, 240);
  drawBranch(0, 10);
  pop();
  push();
  translate(468, 240);
  drawBranch(0, 15);
  pop();
  push();
  translate(418, 245);
  drawBranch(0, 13);
  pop();
  push();
  translate(358, 240);
  drawBranch(0, 15);
  pop();

  //path
  fill(187, 113, 59);
  rect(230, 240, 20, 160);

  //log 
  fill(112, 68, 38);
  rect(50, 246, 40, 27, 10);
  ellipse(70, 250, 40, 10);
  fill(171, 117, 79);
  ellipse(70, 250, 35, 8);
  fill(220, 182, 151);
  ellipse(70, 250, 25, 6);
  fill(112, 68, 38);
  ellipse(70, 250, 10, 3);
  
  //fence
  fill(112, 68, 38);
  rect(0, 260, 30, 140);
  rect(450, 260, 30, 140);
  rect(0, 300, 480, 30);

  //crow animation
  image(frames[frameCount % 13],320, 228, 80, 80);
  
  //overgrowth
  fill(243, 205, 127);
  var val = aSlider.value();
  for (i = 0; i < 160; i ++){
    rect(i * 10, 400, 10, -val);
    i += 1;
  }
  
}

//create trees
function drawBranch(depth, len) {
    line(0, 0, 0, -len);
    push();
    translate(0, -len);
    drawTree(depth + 1, len);
    pop();
}

function drawTree(depth, len) {
    if (depth < 8) {
        rotate(radians(-10));
        drawBranch(depth, len);
        rotate(radians(20));
        drawBranch(depth, len);
    }
}

//if you push the red button
function mouseInsideRedButton(){
  return mouseX > 410 & mouseX < x + 60 && mouseY > 410 && mouseY < 470;
}
function mousePressed(){
  if (mouseInsideRedButton){
    fill(205, 90, 85);
    ellipse(440, 440, 60);
    text("Congrats you found the button.", 310, 350, 150, 75);
  }

}

For my project I ended up focusing on the feeling of finding an abandoned place (in this case an old barn). You push aside the overgrown weeds and use the odds and ends in that location to construct a story of your own. I drew the little crow myself, and the sky changes with every second in a way that I intended to be a little unsettling.

afukuda-FinalProject

sketch

/*  Name | Ai Fukuda 
 * Course Section | C 
 * Email | afukuda@andrew.cmu.edu
 * Project | Final Project
 */ 


// ---- VARIABLES FOR FERRIS WHEEL ---- 
  // ferris wheel color
  var structureColor = 255;  // white
  var supportColor = 90;     // grey 
  
  // speed
  var speed = 160;
  
  // ferris wheel dimensions
  // note: counting circles from most inner to outermost 
  var centerX;        // center of ferris wheel (x-coordinate)
  var centerY;        // center of ferris wheel (y-coordinate)
  var radiusC1;       // radius of circle 1  
  var radiusC2;       // radius of circle 2 
  var radiusC3;       // radius of circle 3 (carrying the passenger cars)
  var radiusC3R;      // radius of circle 3 (passenger cars rotate on it)
  var radiusCar;      // radius of passenger car 
  var radiusBolt;     // radius of bolt on passenger car (detail)
  
  var base;           // base of ferris wheel 
  var baseW;          // width of base of ferris wheel 
  var baseH;          // height of base of ferris wheel 

// ---- END OF VARIABLES FOR FERRIS WHEEL ---- 

// ---- VARIABLES FOR FIREWORK ---- 
var fireworks = []; 
var particles = [];
var gravity = 0.7;
// ---- END OF VARIABLES FOR FIREWORK ---- 


function setup() {
	createCanvas(480, 480); 
  	frameRate(10);
	strokeWeight(1);
	stroke(255);

    // ---- FERRIS WHEEL ---- 
    // define ferris wheel dimensions
  
    var h = height/1.75;   // scaling ferris wheel (overall)

    centerX = h/2.2;  
    centerY = h - h/10; 
    radiusC1 = h/11; 
    radiusC2 = h/2.8; 
    radiusC3 = h/1.3; 
    radiusC3R = h/1.4; 
    radiusCar = h/10;
    radiusBolt = h/60;

    base = h/90;
    baseW = h/6.5;
    baseH = 1.35*h;

    // ---- FIREWORK ---- 
	fireworks.push(new Firework());
}

function draw() {
    background(36, 69, 140);
	background('rgba(0,0,0, 0.1)');

    // ---- FERRIS WHEEL ---- 
    
    // ---- ROTATIONAL ----
    // draw grey beam
    push();
    strokeWeight(1.1);
    stroke(supportColor);
    noFill();
    translate(centerX,centerY);
    rotate(frameCount/speed);
    for (k = PI/8; k < 2*PI; k += PI/4) {
      arc(0, 0, radiusC3, radiusC3, k, k + PI/4, PIE);
    } 
    pop();

    // draw white beam & circle 
    push();
    strokeWeight(1);
    stroke(structureColor);
    noFill();
    translate(centerX,centerY);
    rotate(frameCount/speed);
    for( i=0; i < 2*PI; i += PI/4) {
      arc(0, 0, radiusC3, radiusC3, i, i + PI/4, PIE);
    }
    pop();
  
    // draw passenger car 
    push();
    for (k=0; k<8; k++) {
        fill(72,157,206);
        arc(radiusC3R/1.85*cos(frameCount/speed + (PI/4*k)) + centerX, radiusC3R/1.85*sin(frameCount/speed + (PI/4*k)) + centerY, radiusCar, radiusCar, 0, PI);
    }
    fill(supportColor);
    translate(centerX,centerY);
    rotate(frameCount/speed);
    for (j=0; j < 2*PI; j += PI/4) {
        ellipse(radiusC3R/1.85*cos(j), radiusC3R/1.85*sin(j), radiusBolt, radiusBolt);
    }
    pop();
  
    // ---- STATIONARY ---- 
    // circle 1 
    push();
    strokeWeight(1.2);
    stroke(structureColor);
    fill(supportColor);         
    ellipse(centerX,centerY,radiusC1,radiusC1);
    pop();

    // circle 2 
    push();
    strokeWeight(1.2); 
    stroke(structureColor);     
    noFill();
    ellipse(centerX,centerY,radiusC2,radiusC2);
    pop();
  
    // support beam (base & passenger car)
    push();
    strokeWeight(1);
    stroke(structureColor);
    fill(0,0,0,0);
    for(a=0; a<base; a++) {
    triangle(centerX, centerY + a, centerX - baseW + a, baseH, centerX + baseW - a, baseH);
    } 
    pop();

    // ---- PIER ---- 
    push();
    strokeWeight(5);
    stroke(102,51,0);
    line(0,baseH, centerX*1.5, baseH);
    line(centerX*1.5-10, baseH, centerX*1.5-10, height);
    line((centerX*1.5-10)*2/3, baseH, (centerX*1.5-10)*2/3, height);
    line((centerX*1.5-10)/3, baseH, (centerX*1.5-10)/3, height);
    line(10, baseH, 10, height);
    pop();

    // ---- OCEAN ---- 
    push();
    drawWaveDistant(); // calling wave draw function    (foreground)
    drawWaveClose();   // calling wave draw function    (foreground)
    pop();

    // ---- FIREWORK ---- 
    push();
    translate(width / 2, height);

    if (random(1) < 0.10) {            // probability of firework release
        fireworks.push(new Firework())
    }

    for (var i = fireworks.length - 1; i >= 0; i--) {
        if(fireworks[i].type == "Exploded") {
            fireworks.splice(i,1);
            }
        else {
        fireworks[i].draw();
        }
    }

    for (var i = particles.length - 1; i >= 0; i--) { 
        if(particles[i].position.y > 0 || particles[i].brt <= 0) {
            particles.splice(i,1);
        }
    else {
        particles[i].draw();
    }
    }
    pop();

}   // ---- END OF DRAW FUNCTION ------- 

function Firework() {
    push();
    this.position = createVector(int(random(0, 0+width/3)), 0);
    this.speed = createVector(random(-1,1), -random(20,24));
    this.sparkler = round(random(0,1)) == 0;
    this.fuse = random(-1,1);
    fireworkType = int(random (0,6));
    
    switch (fireworkType) {
        case 0:
        this.type = "simple";
        break;
        case 1:
        this.type = "simple"; // used to be crackle but transformation was messing up geometry
        break;
        case 2:
        this.type = "sparkle";
        break;
        case 3:
        this.type = "double";
        break;
        case 4:
        this.type = "finale";
        break;
        case 5:
        this.type = "shooter";
        break;
    }

    this.draw = function() {      // FUNCTION 1 
        stroke(255);
        
        if (this.fuse < this.speed.y) {
            this.explode();
        }

        if (this.sparkler) {
            sparkleDir = random(0, TWO_PI);
            sparkleVel = random(0,1);
            sparkleSpd = createVector(sparkleVel * cos(sparkleDir), sparkleVel * sin(sparkleDir))
            thisSparkle = new Particle(createVector(this.position.x+sparkleSpd.x, this.position.y+sparkleSpd.y), sparkleSpd.copy(),random(3,8), random(255), random(255), random(255));
            particles.push(thisSparkle);
        }
        strokeWeight(2);
        stroke(random(255), random(255), random(255));
        point(this.position.x,this.position.y);

        this.position.add(this.speed);
        this.speed.y = this.speed.y + gravity;
    }                            // END OF FUNCTION 1 

    this.explode = function() {  // FUNCTION 2 
        switch (this.type) {
        case "sparkle":
        if (this.type == "sparkle") {
            for (var i = 0; i < 60; i++) {
                sparkleDir = random(0, TWO_PI);
                sparkleVel = random(0,3) + random(0,3);
                sparkleSpd = createVector(this.speed.x + sparkleVel * cos(sparkleDir), this.speed.y + sparkleVel * sin(sparkleDir))
                thisSparkle = new Particle(this.position.copy(), sparkleSpd.copy(), random(3,8), random(255), random(255), random(255), "sparkle");
                particles.push(thisSparkle);
            }
                this.type = "Exploded";
        }

        break;

        case "double": {
            for (var i = 0; i < 90; i++) {
                sparkleDir = random(0, TWO_PI);
                sparkleVel = random(3,5);
                sparkleSpd = createVector(this.speed.x + sparkleVel * cos(sparkleDir), this.speed.y + sparkleVel * sin(sparkleDir))
                thisSparkle = new Particle(this.position.copy(), sparkleSpd.copy(), random(2,4), random(255), random(255), random(255));
                particles.push(thisSparkle);
            }
            for (var i = 0; i < 10; i++) {
                sparkleDir = random(0, TWO_PI);
                sparkleVel = random(0,.5);
                sparkleSpd = createVector(this.speed.x + sparkleVel * cos(sparkleDir), this.speed.y + sparkleVel * sin(sparkleDir))
                thisSparkle = new Particle(this.position.copy(), sparkleSpd.copy(), random(2,4), random(255), random(255), random(255));
                particles.push(thisSparkle);
            }
                this.type = "Exploded";
        }
        
        break;

        case "finale": {
            for (var i = 0; i < 500; i++) {
                sparkleDir = random(0, TWO_PI);
                sparkleVel = random(0,4)+random(0,4);
                sparkleSpd = createVector(this.speed.x + sparkleVel * cos(sparkleDir), this.speed.y + sparkleVel * sin(sparkleDir))
                thisSparkle = new Particle(this.position.copy(), sparkleSpd.copy(), random(3,6), random(255), random(255), random(255));
                particles.push(thisSparkle);
            }
            this.type = "Exploded";
        }
        
        break;

        case "shooter": {
            for (var i = 0; i < 100; i++) {
                sparkleDir = random(0, TWO_PI);
                sparkleVel = random(0,2)+random(0,3);
                sparkleSpd = createVector(this.speed.x + sparkleVel * cos(sparkleDir), this.speed.y + sparkleVel * sin(sparkleDir))
                thisSparkle = new Particle(this.position.copy(), sparkleSpd.copy(), random(1,3), random(255), random(255), random(255),"shooter");
                particles.push(thisSparkle);
            }
            this.type = "Exploded";
        }
        
        break;

        case "crackle": {
            for (var i = 0; i < 60; i++) {
                sparkleDir = random(0, TWO_PI);
                sparkleVel = random(0,3) + random(0,3);
                sparkleSpd = createVector(this.speed.x + sparkleVel * cos(sparkleDir), this.speed.y + sparkleVel * sin(sparkleDir))
                thisSparkle = new Particle(this.position.copy(), sparkleSpd.copy(), random(7,10), random(255), random(255), random(255),"crackle");
                    particles.push(thisSparkle);
            }
            this.type = "Exploded";

        }
        
        break;

        default: {
            for (var i = 0; i < 100; i++) {
                sparkleDir = random(0, TWO_PI);
                sparkleVel = random(0,5);
                sparkleSpd = createVector(this.speed.x + sparkleVel * cos(sparkleDir), this.speed.y + sparkleVel * sin(sparkleDir))
                thisSparkle = new Particle(this.position.copy(), sparkleSpd.copy(), random(1,3), random(255), random(255), random(255));
                particles.push(thisSparkle);
            }
            this.type = "Exploded";
        }
        }
    }            // ---- END OF FUNCTION 2 
    pop();
}  


function Particle(position, speed, fade, r, g, b, type) { 
	this.position = position.copy();
	this.speed = speed.copy(); 
	this.fade = (fade == undefined ? 5 : fade);
	this.r = r
    this.g = g
    this.b = b
    this.type = type;

	this.brt = 70;

	this.burntime=0;

	this.draw = function() {
		stroke(this.r, this.g, this.b);
		newPositionX = this.position.x + log(this.burntime) * 8 * this.speed.x;
		newPositionY = this.position.y + log(this.burntime) * 8 * this.speed.y + this.burntime * gravity;

		point(newPositionX, newPositionY);

		if (this.type == "shooter" & this.burntime > 1) {
			line(newPositionX, newPositionY, this.position.x + log(this.burntime-2) * 8 * this.speed.x, this.position.y + log(this.burntime-2) * 8 * this.speed.y + this.burntime * gravity);

(note: I uploaded my final project before the midnight deadline on Friday, however, I noticed that the visuals was not showing up on my post so I tried editing it. It is still not showing up on WordPress when it was originally.)

I changed my idea from my Final Project proposal; initially I wanted to create a storyboard that incorporated fireworks as the final landscape. But I thought a storyboard wasn’t “computational” enough and I wanted to incorporate more concepts learned in class. So that’s why I maintained creating a code for fireworks and incorporated a generative landscape of a ferris wheel. I wrote the fireworks to be multi-colored, and at random fire different styles of fireworks. One thing I struggled with is putting the ferris wheel code and the fireworks code together; the codes would affect the other and therefore I had to use push() and pop() to maintain the stylistic elements of the two components of my final project.

ikrsek– Final Project – Section C

 

Instructions:
You can click your mouse to move your character, (which changes from dream to dream) – and you change dreams by pressing 1,2,3,4 or 5 on your keyboard. When you’re in dreams you can hover over certain notes to see what that dream is about – (for the green woman you hover over her mouth since there is no note).

sketch

//Isadora Krsek 
//Ikrsek@andrew.cmu.edu
//Section C
//Final Project(Project 12): "Dreamscape"

var DreamTracker = (0);

//vars scenery 
var morningStars = [];

//dream5
var clouds;
var daSky;
var daGround;
var stillMan;
var message5;
var message5X = (145.5);
var message5Y = (298);

//dream4
var bed;
var woman;
var message4;
var message4X = (401);
var message4Y = (75);

//dream3
var building;
var tree;
var moon; 
var dirt;
var groundRipples;
var message3;
var message3X = (453);
var message3Y = (330);

//dream2
var spinnyThing;
var lamp;
var touchyGuy;
var LadyWithEyes;
var weirdKid; 
var note;
var message2;
var message2X = (405);
var message2Y = (311);

//dream1
var ripples;
var girl;
var papers;
var trees;
var message1;
var message1X = (155);
var message1Y = (252);

//vars for moveable character in dream 5
var kidFramez = []; // An array to store the images
var kidPreX; // The last X location of the character
var kidPreY; // The last Y location of the character
var kidTrack = (0); //to keep kidTrack fo index in array "kidFramez"
var kidX; //the current x location of character
var kidY = 360; //the current y location of character

//vars for moveable fly
var flyFramez = []; // An array to store the images
var flyPreX; // The last X location of the character
var flyPreY; // The last Y location of the character
var flyTrack = (0); //to keep flyTrack fo index in array "flyFramez"
var flyX; //the current x location of character
var flyY; //the current y location of character

//vars for main character
var mainCharFramez = []; // An array to store the images
var mainCharPreX; // The last X location of the character
var mainCharPreY; // The last Y location of the character
var trackMain = (0); //to keep trackMain fo index in array "mainCharFramez"
var mainCharX; //the current x location of character
var mainCharY = 300; //the current y location of character

var targetX; // The X goal, from the user's click
var targetY; // The Y goal, from the user's click 

//------let the code begin------------------------------------------

function preload(){
    //These URLs are for main character's walk cycle images
    var filenames = [];
    filenames[0] = "https://i.imgur.com/hi7fjid.png" 
    filenames[1] = "https://i.imgur.com/DlkJlK6.png" 
    filenames[2] = "https://i.imgur.com/KQcAqSF.png" 
    filenames[3] = "https://i.imgur.com/PgWS8Ek.png" 
    filenames[4] = "https://i.imgur.com/S7T2PoJ.png"  
    filenames[5] = "https://i.imgur.com/lNmB0Sh.png" 
    filenames[6] = "https://i.imgur.com/6rRh9JS.png" 
    filenames[7] = "https://i.imgur.com/lNmB0Sh.png" 
    //array for the walking cycle
    for(var i=0; i < filenames.length; i++) {
        mainCharFramez.push(loadImage(filenames[i]));
    }
    
    //dream 5 load-ins
    clouds = loadImage("https://i.imgur.com/K0WuYlD.png");
    daSky = loadImage("https://i.imgur.com/xtFA8AG.png");
    daGround = loadImage("https://i.imgur.com/KVhbWTf.png");
    stillMan = loadImage("https://i.imgur.com/JRbHrTk.png");
    message5 = loadImage("https://i.imgur.com/BuNkluX.png");
    //for the walking kid
    var filenames2 = [];
    filenames2[0] = "https://i.imgur.com/8IEaEQz.png" 
    filenames2[1] = "https://i.imgur.com/eSKype2.png" 
    filenames2[2] = "https://i.imgur.com/3Jc1SAO.png" 
    filenames2[3] = "https://i.imgur.com/xD4OH72.png" 
    filenames2[4] = "https://i.imgur.com/IT7FXKF.png"  
    filenames2[5] = "https://i.imgur.com/Syn95Ib.png" 
    filenames2[6] = "https://i.imgur.com/OHlPsCf.png" 
    filenames2[7] = "https://i.imgur.com/mJMmHXz.png"
    //array for walking
    for(var z=0; z < filenames2.length; z++) {
    kidFramez.push(loadImage(filenames2[z]));
    }
    
    //dream 4 load-ins
    bed = loadImage("https://i.imgur.com/0Lc8iQs.png");
    woman = loadImage("https://i.imgur.com/bINLqta.png");
    message4 = loadImage("https://i.imgur.com/HzVhpA1.png");
    
    //dream 3 load-ins
    building = loadImage("https://i.imgur.com/rNIfdQ5.png");
    tree = loadImage("https://i.imgur.com/hgvQQsn.png");
    moon = loadImage("https://i.imgur.com/b2JY2gV.png"); 
    groundRipples = loadImage("https://i.imgur.com/12PrKWt.png");
    dirt = loadImage("https://i.imgur.com/SIdPvf1.png");
    message3 = loadImage("https://i.imgur.com/ZqzLPma.png");
    
    //dream 2 load-ins
    spinnyThing = loadImage("https://i.imgur.com/VLWV1Ri.png");
    lamp  = loadImage("https://i.imgur.com/cfaSffr.png");
    touchyGuy = loadImage("https://i.imgur.com/bcEIg2B.png");
    LadyWithEyes = loadImage("https://i.imgur.com/AHm0VMD.png");
    weirdKid = loadImage("https://i.imgur.com/AkoodGn.png");
    note = loadImage("https://i.imgur.com/PP7U6Rg.png");
    message2 = loadImage("https://i.imgur.com/hbIgCMR.png");
    
    //dream 1 load-ins
    trees = loadImage("https://i.imgur.com/WXXHuxn.png");
    girl = loadImage("https://i.imgur.com/vI3RID0.png");
    papers = loadImage("https://i.imgur.com/gdNlDPK.png");
    ripples = loadImage("https://i.imgur.com/DpPYeiP.png");
    message1 = loadImage("https://i.imgur.com/VKZcrYA.png");
    
    //These URLs are for fly's cycle
    var filenames3 = [];
    filenames3[0] = "https://i.imgur.com/MSyp1iw.png" 
    filenames3[1] = "https://i.imgur.com/lVJeXAA.png" 
    filenames3[2] = "https://i.imgur.com/GENXp9g.png"
    filenames3[3] = "https://i.imgur.com/Th6Ckap.png" 
    //fly man 
    for(var q=0; q < filenames3.length; q++) {
      flyFramez.push(loadImage(filenames3[q]));
    }
    
}
 
function setup(){
    createCanvas(480, 375);
    background(30);
    imageMode(CENTER);
    frameRate(10);
    //Initialize main character postition & target
    mainCharPreX = 50; 
    mainCharPreY = height/2; 
    targetX = mainCharPreX;
    targetY = mainCharPreY;    
    //initialize fly's position & target
    flyPreX = 50;
    flyPreY = height/2;
    targetX = flyPreX;
    targetY = flyPreY;
        //initialize fly's position & target
    flyPreX = width/2;
    flyPreY = height/2;
    targetX = flyPreX;
    targetY = flyPreY;
    //initialize child's position & target
    kidPreX = width-50;
    kidPreY = 360;
    targetX = kidPreX;
    targetY = kidPreY;   
    
    //stars
    //# which allows for new star to appear
    StarProb = 30; 
    //morningStars inital amount 
    for (var i = 0; i < 22; i++) {
      morningStars[i] = new Star(random(width));
    } 
} 
 
function draw(){
  //cycle through dreams by pressing 1,2,3,4, or 5
    if (DreamTracker === 0){
      Dream1();  
    } else if (DreamTracker == 1){
      Dream2();
    } else if (DreamTracker == 2){
      Dream3();
    } else if (DreamTracker == 3){
      Dream4();
    } else if (DreamTracker == 4){
      Dream5();
    }
}

function Dream1(){
    push();
    scale(.81);
    noStroke();
    fill(224,196,195);
    rect(0,0,width+120,height-100); //sky
    drawStars();
    noStroke();
    fill(192,198,210);
    rect(0,height-124,width+120,height); //ground
    image(trees,302,215,trees.width*1.2,trees.height*1.2);
    image(girl,312,265,girl.width*1.1,girl.height*1.1);
    image(ripples,312,219,ripples.width*1.3,ripples.height*1.1);
    image(papers,312,255,papers.width*1.2,papers.height*1.2);
    pop();
    fly();
    //hover over note to see message
    if(dist(mouseX,mouseY,message1X,message1Y)<10){
      image(message1,width/2,height/2);
    }
}

function Dream2(){
    push();
    scale(.81);
    noStroke();
    mainCharY = 305;
    fill(223,212,119);
    rect(0,0,width+120,170); //sky
    noStroke();
    fill(252,207,185);
    rect(0,170,width+120,height); //ground
    image(spinnyThing,312,225,spinnyThing.width*1.2,spinnyThing.height*1.2);
    image(lamp,300,225,lamp.width*1.2,lamp.height*1.2);
    image(touchyGuy,312,225,touchyGuy.width*1.2,touchyGuy.height*1.2);
    image(LadyWithEyes,312,225, LadyWithEyes.width*1.2, LadyWithEyes.height*1.2);
    mainCharWalks();
    image(weirdKid,312,225,weirdKid.width*1.2,weirdKid.height*1.2); 
    image(note,312,225,note.width*1.2,note.height*1.2);
    pop();
    
    //hover over note to see message
    if(dist(mouseX,mouseY,message2X,message2Y)<15){
      image(message2,width/2,height/2);
    }
}

function Dream3(){
    push();
    scale(.75);
    mainCharY = 405;
    noStroke();
    fill(179,132,13);
    rect(0,0,width+180,height*2); //sky
    fill(51,45,29);
    rect(0,height+20,width+180,height*2); //ground
    drawStars();
    image(dirt,312,235,dirt.width*1.3,dirt.height*1.3);
    image(moon,310,250,moon.width*1.3,moon.height*1.3);
    image(tree,312,235,tree.width*1.3,tree.height*1.3);
    image(groundRipples,312,235,groundRipples.width*1.3,groundRipples.height*1.3);
    image(building,312,235,building.width*1.3,building.height*1.3);
    image(note,500,352,note.width/1.5,note.height/1.5);
    mainCharWalks();
    pop();

    //hover over note to see message
    if(dist(mouseX,mouseY,message3X,message3Y)<10){
      image(message3,width/2,height/2);
    }
}

function Dream4(){
    push();
    scale(.75);
    noStroke();
    fill(32,34,26);
    rect(0,0,width,height); //sky
    image(bed,320,250,bed.width*1.3,bed.height*1.4)
    image(woman,320,250,woman.width*1.3,woman.height*1.4)
    pop();
    fly();
    //hover over note to see message
    if(dist(mouseX,mouseY,message4X,message4Y)<10){
      image(message4,width/2,height/2);
    }
}

function Dream5(){
    push();
    scale(.75);
    //the sky is is comprised of two images
    image(daSky,320,210,daSky.width*1.6,daSky.height*1.2)
    drawStars();
    image(clouds,320,250,clouds.width*1.3,clouds.height*1.4)
    image(daGround,320,250,daGround.width*1.3,daGround.height*1.4)
    image(stillMan,585,345,stillMan.width*1.05,stillMan.height*1.05)
    image(note,90,309,note.width/1.5,note.height/1.5);
    image(mainCharFramez[5],40,412)
    pop();
    push();
    scale(.75)
    kidWalks();
    pop();
    
    //hover over note to see message
    if(dist(mouseX,mouseY,message5X,message5Y)<10){
      image(message5,width/2,height/2);
    }
    
  
}

//all of the moveable characters
function fly(){
  //--------flying conditions...
    var dx = targetX - flyPreX;
    var dy = targetY - flyPreY;
    var distanceFromCharacterToTarget = sqrt(dx*dx + dy*dy);
    //control how fly moves toward target 
    flyX = lerp(flyPreX,targetX,0.15);
    flyY = lerp(flyPreY,targetY,0.15);
    //keep looping through the images seamlessly 
    if (flyTrack >= flyFramez.length){
      flyTrack = 0; 
    }
  //--------the actual flying part & more conditions...
    if (flyX < flyPreX){
      push();
      scale(-1,1);//flip image 
      image(flyFramez[flyTrack],flyX*-1,flyY); //you multiply the X-coordinate by -1 so it walks in the right direction 
      pop();
    }
    //otherwise if it's larger, it will be flying right
    else if (flyX >= flyPreX){
      image(flyFramez[flyTrack],flyX,flyY);
    }
  //------------------Refresh values...
    flyPreX = flyX;
    flyPreY = flyY;
    //cycle through the walking images 
    flyTrack = flyTrack + 1
}    

function kidWalks(){
  //--------walking conditions...
    var dx = targetX - kidPreX;
    var dy = targetY - kidPreY;
    var distanceFromCharacterToTarget = sqrt(dx*dx);
    //control how character moves toward target 
    kidX = lerp(kidPreX,targetX,.15);
    //keep looping through the images seamlessly 
    if (kidTrack >= kidFramez.length){
      kidTrack = 0; 
    }
  //--------the actual walking part & more conditions...
  //if the current x location is smaller than last x location, walk left
    if (distanceFromCharacterToTarget < 15 && kidX < kidPreX){
      push();
      scale(-1,1);//flip image 
      image(kidFramez[2],kidX*-1,kidY);
      pop();
    } 
    else if(distanceFromCharacterToTarget < 15){
      image(kidFramez[2],kidX,kidY);
    } 
    else if(kidX < kidPreX){
      push();
      scale(-1,1);//flip image 
      image(kidFramez[kidTrack],kidX*-1,kidY); 
      pop();
    }
    //otherwise if larger, walk right
    else if(kidX >= kidPreX){
      image(kidFramez[kidTrack],kidX,kidY);
    }
  //------------------Refresh values...
    kidPreX = kidX;
    kidTrack = kidTrack + 1;
}

function mainCharWalks(){
  //--------walking conditions...
    var dx = targetX - mainCharPreX;
    var dy = targetY - mainCharPreY;
    var distanceFromCharacterToTarget = sqrt(dx*dx );
    //control how character moves toward target 
    mainCharX = lerp(mainCharPreX,targetX,.15);
    theY = lerp(mainCharPreY,targetY,.15);
    //keep looping through the images continuously/seamlessly 
    if (trackMain >= mainCharFramez.length){
      trackMain = 0; 
    }
  //--------the actual walking part & more conditions...
    //if the current x location is smaller than last x location, walk left
    if(distanceFromCharacterToTarget < 15 && mainCharX < mainCharPreX){
      push();
      scale(-1,1);//flip image 
      image(mainCharFramez[7],mainCharX*-1,mainCharY);
      pop();
    } 
    else if(distanceFromCharacterToTarget < 15){
      image(mainCharFramez[7],mainCharX,mainCharY);
    } 
    else if (mainCharX < mainCharPreX){
      push();
      scale(-1,1);//flip image 
      image(mainCharFramez[trackMain],mainCharX*-1,mainCharY); 
      pop();
    }
    //otherwise if larger, walk right
    else if (mainCharX > mainCharPreX){
      image(mainCharFramez[trackMain],mainCharX,mainCharY);
    }
  //------------------Refresh values...
    mainCharPreX = mainCharX;
    mainCharPreY = theY;
    trackMain = trackMain + 1;
}

//other stuff
function mousePressed(){
    targetX = mouseX;
    targetY = mouseY;
}

function keyPressed(){
    if (key == "1"){
      DreamTracker = (0);
    } else if (key == "2"){
      DreamTracker = (1);
    } else if (key == "3"){
      DreamTracker = (2);
    } else if (key == "4"){
      DreamTracker = (3);
    } else if (key == "5"){
      DreamTracker = (4);
    }
}    

function drawStars(){
  //when random # is smaller than probability then new start occurs  
  if (StarProb > random(0,100)) {
    morningStars.push(new Star(width));
  }
  for (var i = 0; i < morningStars.length; i++) {
    morningStars[i].move(); //update star array
    morningStars[i].display(); 
  //if star goes out of boundary, remove it
    if (morningStars[i].x < 0) { 
      morningStars.splice(i, 1);
    }    
  }
}

//generate morningStars
function Star(xLocation){
    var randoOpa = random(80,180); //have the brightness of stars vary 
    var randoSize = random(0.5,2); //have star size vary 
    strokeWeight(randoSize);
    this.x = xLocation;//controlled above by random width 
    this.y = random(1,380); //range for stars to appear
    this.speed = (-1.5); //speed       
    this.move = function() {
      this.x += this.speed; //move the stars
    }
    this.display = function() {
	  //draw the stars here 
	    stroke(202,195,232,80);
      fill(202,195,232,randoOpa);
	    ellipse(this.x, this.y,randoSize,randoSize);
    }
}

Conclusion:
Overall this project was exhausting to complete – but I’m pleased with the way it looks. Each image was hand drawn in photoshop with a one pixel brush so as to have the utmost control over my vision.  I spent all of my free-time working on this, trying to bring it to life as best I could. There is still much more I would’ve liked to do with it, such as adding smoother transitions between dream sequences or adding more notes but overall it really sticks close to how I envision it in my head. In terms of the notes, I intended for them to be difficult to read to act as a parallel to the ambiguity and hazy quality of dreams – how things can seem so fuzzy and vague but you still can understand what’s going on perfectly.

Here’s a video of a play through with all the actions:

 

 

Here are some photos of each scene and the corresponding note:

If you want to know what each of the notes say, here is a quick copy of each of them:

Note from dream 1:
“I remember a young girl desparately searching for something… she was wading through papers in a clear blue body of water. There were pathetic and skinny little trees that grew around and behind her directly from the water which was a bit of an odditiy… I remeber trying to call out to her – ask her what she was looking for or if I could help… but she ignored me. The more I tried to screm the less I seemed to make a sound and I was quickly becoming panicked – it was at that point that I realized thtat I was just a fly. She couldn’t hear or understand me no matter how hard I would try and I was nothing more than a buzzing nuisance. I resigned to watch after realizing this and was surprised by the fact that she was so involved in her task – that she was completely unbothered by the annoying buzzing coming from me.”

Note from dream 2:
“There were three people all standing or sitting around, it was outside – but I’m not exactly sure where – mostly because we were in the grass but there was also a lamp plugged in outside? I tried to turn it on, but the lamp was broken. The sky in combination with the color of the ground reminded me of an anemic watermelon – maybe this is summer then? Anywho I remember seeing a girl sitting down and a gentlemen beside her -only he wasn’t much of a gentleman… his hands were crawling up her leg and I could see her whole face go black (well, everything but her eyes which remained a piercing white color). There was also a strange you child – just watching. Everyone had eyes but the only one with a mouth was Mr.Touchy feely.. I still don’t understand this.”

Note from dream 3:
“This dream I don’t remember all too well – all I remember is how it looked and felt to be there, the way the stars moved across the sky (as they always do in my dreams for some reason) and the odd abandoned structure sitting still beneath a blossomig tree – It looked so rickety, like it could’nt possibly hold anyone up inside of it… but somehow in that absence of another person – you could feel them there… I don’t know who exactly, just that there was supposed to be someone there. There is some presence in absence here…”

Note from dream 4:
“I remember this dream so vividly – it was beautiful – the plush bed reminded me of the way that cloth is rendered in paintings of Vesnus by TItian or other great artsists who inspired the classical period – the colors were off though – the women, although supple and lush was a gastly shade of green and somehow upon looking at her I knew she was dead. Dead people aren’t usually green – I know, but it was that weird “dreamer’s intuition” where you know nothing makes sense but somehow you are able to piece things together and just know things somehow. What didn’t know was why or how. Maybe there’se something to be said for the fact that I appeared asa fly in this dream as well…”

Note from dream 5:
“It was dark – like time was moving backward . The sky shifted from a deep red to dark blue – almost like a sunset? But not quite. The clouds draped down the sky and had an overwhleming presence – they were almost too big – and I remember the way the stars moved behind the clouds – like they were being projected in motion across the sky – but the strangest part were the two people I saw – one not even moving, but entranced by the sky – the other walked backwards and refused to make eye-contct. I couldn’t move at all – I was trapped like the one looking to the sky and I only remember the fear that filled my body at the younger one moved closer – I was unsure of what they would do”

Final Project Thomas Wrabetz / Anna Boyle

sketch

//Anna Boyle and Thomas Wrabetz
//Main functions

//Thomas' code
function setup() {
    createCanvas(480, 480);
    rectMode( CENTER );
    player = makePlayer( width / 2, height / 2 );
    level = makeLevel();
    var sec=second();
}

function draw() {
    background(200);
    player.draw();
    player.step();
    level.draw();

//Anna's code
    fill(0);
    txt=width/2
    fill(255);
    noStroke();
    if (drawBubble==1){
//triangle for speech bubble
    triangle(width/2-20, txtH+20, bubbleX, bubbleY, width/2+20, txtH+20)
//if the player is on the top half, make the bubble on the bottom half
    if (player.y<height/2){
      txtH=440;
      rect(width/2, 470, width, bubbleHeight);
//adjust the line height when there is only one line
      singleLineHeight=465;
//if the player is on the bottom half, make the bubble on the top half
    }if (player.y>=height/2){
      txtH=30;
      rect(width/2, 20, width, bubbleHeight);
//adjust the line height when there is only one line
      singleLineHeight=30;
  }
    fill(0);
//makes the quote
    textSize(17);
    textAlign(CENTER);
    printQuote( whichQuote );
  }
    rectMode(CORNER);
//draws the inspiration meter red bar
    fill(188, 64, 64);
    rect(width-20, 0, 20, height);
//draws the inspiration meter's variable green bar
    fill(64, 188, 64);
    rect(width-20, height-inspiroMeter, 20, height);
    rectMode(CENTER);
//if the player gets enough quotes, they will win and see this screen
    if (inspiroMeter>480){
      fill(255);
      rect(width/2, height/2, width, height)
      fill(0);
      textSize(32)
      text("CONGRATULATIONS!", width/2, height/2-25);
      text("YOU ARE INSPIRED", width/2, height/2+25);
      noLoop();
    }
}

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Player object

//-----PLAYER OBJECT-----//

var PSIZE = 30;
var PCOLOR = [ 25, 150, 25, 255 ];
var PSPEED = 3;
var keyArray = [];

//Updates the player's position based on keyboard input
function stepPlayer()
{
    //Variables to track the player's movement in each direction
    var yStep = 0;
    var xStep = 0;
    if( keyIsPressed )
    {
        for( var i = 0; i < keyArray.length; i++ )
        {
            switch( keyArray[i] )
            {
                case 'W':
                    yStep -= PSPEED;
                    break;
                case 'S':
                    yStep += PSPEED;
                    break;
                case 'A':
                    xStep -= PSPEED;
                    break;
                case 'D':
                    xStep += PSPEED;
                    break;
            }
        }
        //Adjust speed for diagonal movement
        if( xStep != 0 & yStep != 0 )
        {
            xStep *= 0.7071
            yStep *= 0.7071
        }
        //Check if the player will collide with a wall in the x-direction
        //and move the player if not
        if( !level.collisionSearch( this.x + xStep, this.y, PSIZE ) )
        {
            //If the player is too close to the edges of the screen,
            //move the level instead of the player
            if( ( this.x < width * 4/5 || xStep < 0 ) 
                && ( this.x > width * 1/5 || xStep > 0 ) ) this.x += xStep;
            else level.xOffset -= xStep;
        }
        //Check if the player will collide with a wall in the y-direction
        //and move the player if not
        if( !level.collisionSearch( this.x, this.y + yStep, PSIZE ) )
        {
            //If the player is too close to the edges of the screen,
            //move the level instead of the player
            if( ( this.y < height * 4/5 || yStep < 0 ) 
                & ( this.y > height * 1/5 || yStep > 0 ) ) this.y += yStep;
            else level.yOffset -= yStep;
        }
        //If the player collides with a figure, update the bubble
        var figure = level.figureCollisionSearch( this.x + xStep, 
                                                  this.y + yStep, PSIZE );
        if( figure != -1 )
        {
            if( !drawBubble )
            {
                drawBubble = true;
                //Only update to a new quote if this is a different figure
                if( bubbleID != level.figures[ figure ].ID )
                {
                    bubbleID = level.figures[ figure ].ID;
                    updateBubble();
                }
            }
            bubbleX = level.figures[ figure ].x + level.xOffset;
            bubbleY = level.figures[ figure ].y + level.yOffset;
        }
        else if( drawBubble )
            drawBubble = false;
        level.step();
    }
}

//Draw the player
function drawPlayer()
{
    fill( PCOLOR );
    rect( this.x, this.y, PSIZE, PSIZE );
}

function makePlayer( px, py )
{
    player = { x: px, y: py, draw: drawPlayer, step: stepPlayer };
    return player;
}

//-----KEY TRACKING-----//

//Each key pressed is stored in the key array
function keyPressed()
{
    keyArray.push( key );
}

//Keys are removed from the key array when released
function keyReleased()
{
    for( var i = 0; i < keyArray.length; i++ )
    {
        if( keyArray[i] == key ) keyArray.splice( i, 1 );
    }
}

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Walls and level and figures

//-----INSPIRATIONAL FIGURE OBJECT-----//

figureColorArray = [ "Red", "Blue", "Green", "Yellow",
                     "Purple", "Orange", "Brown" ];
//Counter to give the figures unique IDs
figureIDCounter = 0;
//Counter that keeps track of how many open spaces have been created
figureCounter = 0;
//Each time figureCounter reaches FIGUREFREQ, a new figure is created
FIGUREFREQ = 10;
//Size of a figure
FIGUREWIDTH = 30;

function makeFigure( xPos, yPos )
{
    figure = { x: xPos, y: yPos, figureColor: random(figureColorArray),
               ID: figureIDCounter };
    figureIDCounter++;
    return figure;
}


//-----WALL OBJECT-----//

//Size of a wall
var WALLWIDTH = 80;
var WALLCOLOR = [ 116, 18, 229, 255 ];
var WALLCOLORDARK = [ 39, 7, 76, 255 ];

function makeWall( wx, wy )
{
    var wall = { x: wx, y: wy, pattern: makePattern() };
    return wall;
}

//-----LEVEL OBJECT-----//

//Add a row to the level. The parameters indicate which side
function levelAddRow( xRef, yRef )
{
    //Variables to track whether the new row is an empty row
    //and whether it has intersected an existing corridor
    var before = false;
    var after = false;
    var passed = false;
    var justPassed = false;
    //Left Side
    if( xRef == 1 ) 
    {
        //Clear out old row on opposite side
        this.walls.unshift( [] );
        this.walls.splice( this.walls.length - 1, 1 );
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls[1].length-2; i++ )
        {
            if( this.walls[1][i] == 0 & this.walls[1][i+1] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls[1].length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[1][i] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[1][i] == 0 & i != 0 && this.walls[1][i-1] != 0 &&
                  i != this.walls[1].length - 1 && this.walls[1][i+1] != 0 ) ||
                ( before && ( !passed || justPassed ) ) || ( after && passed ))
            {
                this.walls[0][i] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( -1 * WALLWIDTH,
                                       (i - 1) * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else this.walls[0][i] = makeWall( -1 * WALLWIDTH, 
                                              (i - 1) * WALLWIDTH );
            justPassed = false;
        }
    }
    //Right Side
    if( xRef == -1 ) 
    {
        //Clear out old row on opposite side
        this.walls.push( [] );
        this.walls.shift( 1 );
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls[1].length-2; i++ )
        {
            if( this.walls[this.walls.length-2][i] == 0 
                & this.walls[this.walls.length-2][i+1] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls[this.walls.length-2].length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[this.walls.length-2][i] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[this.walls.length-2][i] == 0 & i != 0 &&
                this.walls[this.walls.length-2][i-1] != 0 && 
                i != this.walls[this.walls.length-2].length - 1 &&
                this.walls[this.walls.length-2][i+1] != 0 ) ||
                ( before && (!passed || justPassed) ) || ( after && passed ) )
            {
                this.walls[this.walls.length-1][i] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( (this.walls.length-2) 
                                                   * WALLWIDTH, 
                                                   (i-1) * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else this.walls[this.walls.length-1][i] = 
                 makeWall( (this.walls.length-2) 
                           * WALLWIDTH, (i-1) * WALLWIDTH );
            justPassed = false;
        }
    }
    //Top
    if( yRef == 1 )
    {
        //Clear out old row on opposite side
        for( i = 0; i < this.walls.length; i++ )
        {
            this.walls[i].unshift( -1 );
            this.walls[i].splice( this.walls[i].length - 1, 1 );
        }
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls.length-2; i++ )
        {
            if( this.walls[i][1] == 0 & this.walls[i+1][1] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls.length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[i][1] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[i][1] == 0 & i != 0 && this.walls[i-1][1] != 0 
                  && i != this.walls.length - 1 
                  && this.walls[i+1][1] != 0 ) 
                  || (before && (!passed || justPassed)) || (after && passed))
            {
                this.walls[i][0] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( (i-1) * WALLWIDTH,
                                       -1 * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else 
                this.walls[i][0] = makeWall((i-1) * WALLWIDTH, -1 * WALLWIDTH);
            justPassed = false;
        }
    }
    //Bottom
    if( yRef == -1 )
    {
        //Clear out old row on opposite side
        for( i = 0; i < this.walls.length; i++ )
        {
            this.walls[i].push( -1 );
            this.walls[i].shift( 1 );
        }
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls.length-2; i++ )
        {
            if( this.walls[i][this.walls.length-2] == 0 
                & this.walls[i+1][this.walls.length-2] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls.length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[i][this.walls[0].length-2] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[i][this.walls[0].length-2] == 0 & i != 0 
                  && this.walls[i-1][this.walls[0].length-2] != 0 
                  && i != this.walls.length - 1 
                  && this.walls[i+1][this.walls[0].length-2] != 0 ) 
                  || (before && (!passed || justPassed)) || (after && passed)) 
            {
                this.walls[i][this.walls[0].length-1] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( (i-1) * WALLWIDTH,
                                      (this.walls[0].length-2) * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else 
                this.walls[i][this.walls[0].length-1] = 
                makeWall( (i-1) * WALLWIDTH,
                          (this.walls[0].length-2) * WALLWIDTH );
            justPassed = false;
        }
    }
}

//Update the level, moving objects inside and adding new rows if needed
function levelStep()
{
    //If the offset for the walls is greater than the width of a wall,
    //Shift the array of walls and add a new row
    if( abs( this.xOffset ) >= WALLWIDTH )
    {
        //Incorporate offset into walls' basic x-positions
        for( var j = 0; j < this.walls.length; j++ )
        {
            for( var k = 0; k < this.walls[j].length; k++ )
            {
                if( this.xOffset > 0 )
                {
                    this.walls[j][k].x += WALLWIDTH;
                }
                if( this.xOffset < 0 )
                {
                    this.walls[j][k].x -= WALLWIDTH;
                }
            }
        }
        //Incorporate offset into figures' basic x-positions
        for( var j = 0; j < this.figures.length; j++ )
        {
            if( this.xOffset > 0 )
            {
                this.figures[j].x += WALLWIDTH;
            }
            if( this.xOffset < 0 )
            {
                this.figures[j].x -= WALLWIDTH;
            }
            //Remove figures that are off the screen
            if( this.figures[j].x > width + FIGUREWIDTH / 2 
                || this.figures[j].x < 0 - FIGUREWIDTH / 2 )
            {
                this.figures.splice( j, 1 );
                j--;
            }
        }
        //Reset the offset and add a new row
        if( this.xOffset > 0 )
        {
            this.xOffset -= WALLWIDTH;
            this.addRow( 1, 0 );
        }
        if( this.xOffset < 0 )
        {
            this.xOffset += WALLWIDTH;
            this.addRow( -1, 0 );
        }
    }
    if( abs( this.yOffset ) >= WALLWIDTH )
    {
        //Incorporate offset into walls' basic y-positions
        for( var j = 0; j < this.walls.length; j++ )
        {
            for( var k = 0; k < this.walls[j].length; k++ )
            {
                if( this.yOffset > 0 )
                {
                    this.walls[j][k].y += WALLWIDTH;
                }
                if( this.yOffset < 0 )
                {
                    this.walls[j][k].y -= WALLWIDTH;
                }
            }
        }
        //Incorporate offset into figures' basic y-positions
        for( var j = 0; j < this.figures.length; j++ )
        {
            if( this.yOffset > 0 )
            {
                this.figures[j].y += WALLWIDTH;
            }
            if( this.yOffset < 0 )
            {
                this.figures[j].y -= WALLWIDTH;
            }
            //Remove figures that are off the screen
            if( this.figures[j].y > height + FIGUREWIDTH / 2 
                || this.figures[j].y < 0 - FIGUREWIDTH / 2 )
            {
                this.figures.splice( j, 1 );
                j--;
            }
        }
        //Reset the offset and add a new row
        if( this.yOffset > 0 )
        {
            this.yOffset -= WALLWIDTH;
            this.addRow( 0, 1 );
        }
        if( this.yOffset < 0 )
        {
            this.yOffset += WALLWIDTH;
            this.addRow( 0, -1 );
        }
    }
}

//Checks if a square at x,y with size size would collide with the wall
//at index a,b of the array of walls
function levelWallCollision( x, y, size, a, b )
{
    var wall = this.walls[a][b];
    if( wall == 0 ) return false;
    return abs( x - ( wall.x + this.xOffset ) ) < size / 2 + WALLWIDTH / 2 
           & abs( y - ( wall.y + this.yOffset ) ) < size / 2 + WALLWIDTH / 2;
}

//Check collision for all the walls
function levelCollisionSearch( x, y, size )
{
    for( i = 0; i < this.walls.length; i++ )
    {
        for( j = 0; j < this.walls[i].length; j++ )
        {
            if( this.wallCollision( x, y, size, i, j ) ) return true;
        }
    }
    return false;
}

//Draw the wall at index a,b of the wall array
function levelDrawWall( a, b )
{
    var wall = this.walls[a][b];
    if( wall == 0 ) return;
    push();
    stroke( WALLCOLORDARK );
    fill( WALLCOLOR );
    rect( wall.x + this.xOffset, wall.y + this.yOffset, WALLWIDTH, WALLWIDTH );
    wall.pattern.draw( wall.x + this.xOffset, wall.y + this.yOffset );
    pop();
}

//Checks if a square at x,y with size size would collide with a figure
//at index a of the figure array
function levelFigureCollision( x, y, size, a )
{
    if( a >= this.figures.length ) return false;
    var figure = this.figures[a];
    return abs( x - ( figure.x + this.xOffset ) ) < size / 2 + FIGUREWIDTH / 2
                & abs( y - ( figure.y + this.yOffset ) ) 
                   < size / 2 + FIGUREWIDTH / 2;
}

//Check collision for all the figures. If found, returns the index of
//the colliding figure in the figure array. If not, returns -1.
function levelFigureCollisionSearch( x, y, size )
{
    for( i = 0; i < this.figures.length; i++ )
    {
        if( this.figureCollision( x, y, size, i ) ) return i;
    }
    return -1;
}

//Draw the figure at index a of the figure array
function levelDrawFigure( a )
{
    var figure = this.figures[a];
    if( figure == 0 ) return;
    push();
    stroke( 0 );
    fill( figure.figureColor );
    ellipse( figure.x + this.xOffset, figure.y + this.yOffset,
             FIGUREWIDTH, FIGUREWIDTH );
    pop();
}

//Draw all the walls and figures
function levelDraw()
{
    for( i = 0; i < this.walls.length; i++ )
    {
        for( j = 0; j < this.walls[i].length; j++ )
        {
            this.drawWall( i, j );
        }
    }
    for( i = 0; i < this.figures.length; i++ )
    {
        this.drawFigure( i );
    }
}

//Make a level, which contains arrays of walls and figures as well as a shared
//x and y offet which applies to every object in the level
function makeLevel()
{
    var wallsArray = [];
    var figuresArray = [];
    for( i = 0; (i - 1) * WALLWIDTH <= width + WALLWIDTH; i++ )
    {
        wallsArray.push( [] );
        for( j = 0; (j - 1) * WALLWIDTH <= height + WALLWIDTH; j++ )
        {
            if( i == 4 || j == 4 ) wallsArray[i].push( 0 );
            else 
                wallsArray[i].push( makeWall( (i - 1) * WALLWIDTH,
                                    (j - 1) * WALLWIDTH ) );
        }
    }
    level = { walls: wallsArray, figures: figuresArray, xOffset: 0, yOffset: 0,
              draw: levelDraw, drawWall: levelDrawWall,
              wallCollision: levelWallCollision,
              collisionSearch: levelCollisionSearch,
              step: levelStep, addRow: levelAddRow,
              drawFigure: levelDrawFigure, 
              figureCollision: levelFigureCollision,
              figureCollisionSearch: levelFigureCollisionSearch };
    return level;
}

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Pattern object for wall blocks

var DOTSIZE = 3;
var colors = [ [66,134,234,255], [23,216,213,255],
               [23,216,236,255], [68,216,23,255], [228,242,42,255] ];

function makePattern() {
    var angle;
    var newPattern={c: random(colors), arms: int( random( 4 ) ) + 2, 
                    a: random(2*PI), draw: drawPattern, dotPositionArray: [] };
    for( var i = 0; i < newPattern.arms; i++ )
    {
        for( var j = 0; j < WALLWIDTH / 2 - 5; j+= DOTSIZE * 2 )
        {
            angle = newPattern.a + i * (2 * PI / newPattern.arms);
            newPattern.dotPositionArray.push( j * cos( angle ) + 
                     ( sin( j ) * 20 * cos( angle + PI / 2 ) ) );
            newPattern.dotPositionArray.push( j * sin( angle ) + 
                     ( sin( j ) * 20 * sin( angle + PI / 2 ) ) );
        }
    }
    return newPattern;
}

function drawPattern( x, y ){
    fill(this.c)
    push();
    noStroke();
    var currentX;
    var currentY;
    for( var i = 0; i < this.dotPositionArray.length - 1; i+= 2 )
    {
            ellipse( x + this.dotPositionArray[i], y + this.dotPositionArray[i+1],
                     DOTSIZE, DOTSIZE );
    }
    pop();
}

//Anna Boyle
//Section D
//aboyle@andrew.cmu.edu
//Quote generator

var abstractNouns = ["Rebellion", "Curiosity", "Jealousy", "Friendship",
"Family", "Evil", "Life", "Hope", "Grace", "Love", "Faith", "Opportunity",
"Dedication", "Insanity", "Fortune", "Luck", "Hatred", "Knowledge", "Pain",
 "Heaven"];
var inspireNouns = ["rainbow", "cloud", "light", "star", "candle", "child",
"dream", "building", "hero", "breeze", "eye", "moon", "snowflake", "apple",
"tree", "flower", "butterfly", "mirror", "door", "heart"];
var inspireNounsPlural = ["rainbows", "clouds", "lights", "stars", "candles",
"children", "kisses", "buildings", "hands", "brothers", "sisters", 
"snowflakes", "dreams", "apples", "trees", "flowers", "butterflies", "mirrors",
"doors", "hearts"];
var strangeNouns=["peach cobbler", "deodorant", "used tissue", "conch shell",
"toaster", "pasta strainer", "blade of grass", "grandma's house", "unicycle",
"weed whacker", "shampoo bottle", "corpse", "snickerdoodle",
"ten gallon hat", "toupee", "colony of termites", "mother-in-law",
"sexy firemen calendar", "underground bunker", "angry baboon"];
var strangeNounsPlural = ["alien invasions", "clowns", "podiatrists",
"belly dancers", "cacti", "voodoo dolls", "raspberries", "dust bunnies",
"distant relatives", "kentucky fried chicken", "rotten eggs", "nudists",
"nunchuks", "toenail clippings", "rocket scientists", "green beans", "nuns",
"croissants", "drunk ballerinas", "shoelaces" ];
var inspireVerbs= ["flies", "moves", "shines", "waits", "stands", "goes",
"sleeps", "thinks", "cries", "laughs", "yells", "watches", "jumps"];
var inspireVerbsObj = ["hold", "hug", "love", "hate", "grab", "accept",
"support", "look at", "want", "sacrifice", "kiss", "pray for", "abandon"];
var inspireVerbsGerund= ["flying", "moving", "doing", "waiting", "standing",
"going", "saying", "thinking", "crying", "laughing", "yelling", "watching",
"jumping"];
var inspireVerbsObjGerund = ["holding", "hugging", "loving", "hating",
"grabbing", "accepting", "supporting", "seeing", "wanting", "finding",
"kissing", "praying for", "abandoning"];
var strangeVerbs=["dances", "dies", "melts", "yodels", "sneezes", "does yoga",
"crawls", "beatboxes", "undresses", "vomits", "whistles", "rollerblades",
"explodes"];
var strangeVerbsObj=["stab", "fight", "smack", "bury", "kick", "exorcise",
"kidnap", "high five", "sniff", "smuggle", "tickle", "cuddle", "nibble"];
var strangeVerbsGerund=["dancing", "dying", "melting", "yodeling", "sneezing",
"doing yoga","crawling", "sleeping", "undressing", "vomiting", "whistling",
"rollerblading", "exploding"];
var strangeVerbsObjGerund=["stabbing", "fighting", "smacking", "burying",
"kicking", "exorcising", "kidnapping", "high fiving", "sniffing", "smuggling",
"tickling", "cuddling", "nibbling"];
var locationWords=["behind", "in front of", "next to", "inside of", "below",
"on top of", "above", "under", "among", "beside", "over", "far away from",
"underneath"];
var comparison=["darker", "sadder", "bigger", "smaller", "harder", "softer",
"better", "worse", "faster", "slower", "stronger", "weaker", "happier", 
"drunker", "older", "younger", "smarter", "dumber", "hotter", "colder"];
var personQuote=["Albert Einstein", "Mahatma Gandhi", "Oprah Winfrey",
"George Washington", "Nelson Mandela", "Jesus Christ", "Benjamin Franklin",
"Plato", "Mother Teresa", "My mom", "Beyonce", "Martin Luther King Jr.",
"Santa Claus"]

//variable for the quote templates
var whichQuote;

/*nCh=nineteen choices, tCh=twelve choices
There are multiple variables to prevent parts of speech with same amount of
choices don't get constantly paired with each other */

var nCh1;
var nCh2;
var nCh3;
var nCh4;
var tCh1;
var tCh2;
var tCh3;
var tCh4;

//Variables related to drawing the speech bubble
var txt;
var txtH;
var bubbleHeight;
var singleLineHeight;
var bubbleX = 0;
var bubbleY = 0;
var drawBubble = false;
var bubbleID = -1;
var inspiroMeter=0;

function updateBubble(){
//randomizes which number in the array will be chosen for the parts of speech
    nCh1=int(random(20));
    nCh2=int(random(20));
    nCh3=int(random(20));
    nCh4=int(random(20));
    tCh1=int(random(13));
    tCh2=int(random(13));
    tCh3=int(random(13));
    tCh4=int(random(13));
//randomzies which quote template will be chosen
    whichQuote=int(random(14));
    inspiroMeter=inspiroMeter+20;

}

//Chooses which quote template will be chosen based on the random number
//between 0 and 13

function printQuote( num )
{

    switch(num)
  {
      case 0:
      worthTwo();
      break;
    case 1:
      tryToBe();
      break;
    case 2:
      whenYouHave();
      break;
    case 3:
      judgeEach();
      break;
    case 4:
      ifYouMiss();
      break;
    case 5:
      theBest();
      break;
    case 6:
      duringOurMoments();
      break;
    case 7:
      letUs();
      break;
    case 8:
      palesInComparison();
      break;
    case 9:
      haveSeen();
      break;
    case 10:
      inSeason();
      break;
    case 11:
      combination();
      break;
    case 12:
      onlyICan();
      break;
    case 13:
      jokeQuote();
     break;
  }
}

//Below are all the quote template functions
//bubbleHeight changes the size of bubble when there are different amounts of text

function tryToBe(){
    text("Try to be a "+inspireNouns[nCh1]+" in someone's "
    +strangeNouns[nCh2], txt, singleLineHeight);
    bubbleHeight=75;
}

function worthTwo(){
    text("One "+inspireNouns[nCh1]+" is worth two "+
    strangeNounsPlural[nCh2], txt, singleLineHeight);
    bubbleHeight=75;
}

function whenYouHave(){
    text("When you have a "+strangeNouns[nCh1]+", you've got to ", txt, txtH);
    text(inspireVerbsObj[tCh1]+" it and never "+strangeVerbsObj[tCh2]+
    " it", txt, txtH+25);
    bubbleHeight=130;
}

function judgeEach(){
    text("Don't judge each day by the "+inspireNounsPlural[nCh1],
    txt, txtH);
    text(" you "+inspireVerbsObj[tCh1]+", but by the "+strangeNounsPlural[nCh1]
    +" you "+strangeVerbsObj[tCh1], txt, txtH+25);
    bubbleHeight=130;
}

function ifYouMiss(){
    text("Shoot for the "+inspireNouns[nCh1]+", and if you miss", txt, txtH);
    text(" you will still be "+locationWords[tCh1]+" the "
    +strangeNounsPlural[nCh2], txt, txtH+25);
    bubbleHeight=130;
}

function theBest(){
    text("The best preparation for tomorrow is", txt, txtH);
    text(strangeVerbsObjGerund[tCh1]+" your "+
    strangeNouns[nCh1]+" today", txt, txtH+25);
    bubbleHeight=130;
}

function duringOurMoments(){
    text("It is during our "+comparison[nCh1]+" moments that we must", txt, txtH);
    text("focus to "+strangeVerbsObj[tCh1]+" the "+
    strangeNounsPlural[nCh2], txt, txtH+25);
    bubbleHeight=130;
}

function letUs(){
    text("Let us sacrifice our "+inspireNounsPlural[nCh1]
    +" so that", txt, txtH);
    text("our children can "+strangeVerbsObj[tCh1]+" a "+
    comparison[nCh2]+" "+strangeNouns[nCh3], txt, txtH+25);
    bubbleHeight=130;
}

function palesInComparison(){
    text("What "+inspireVerbs[tCh1]+" behind you and what "+
    inspireVerbs[tCh2]+" in front of you,", txt, txtH);
    text("pales in comparison to what "+strangeVerbs[tCh3]+" "+
    locationWords[tCh4]+" you", txt, txtH+25)
    bubbleHeight=130;
}

function haveSeen(){
    text("If I have seen further than others, it is", txt, txtH);
    text("by "+strangeVerbsGerund[tCh1]+" "+locationWords[tCh2]+" "
    +strangeNounsPlural[nCh1], txt, txtH+25)
    bubbleHeight=130;
}

function inSeason(){
    text(abstractNouns[nCh1]+" is a fruit in season at all times,", txt, txtH);
    text("and within reach of every "+strangeNouns[nCh2], txt, txtH+25);
    bubbleHeight=130;

}
function combination(){
    text(abstractNouns[nCh1]+" and "+strangeNounsPlural[nCh2]+
    " are a powerful combination", txt, singleLineHeight);
    bubbleHeight=75;
}


function onlyICan(){
    text("Only you can "+strangeVerbsObj[tCh1]+" your "+strangeNouns[nCh1]+".",
    txt, txtH);
    text("No one else can do it for you.", txt, txtH+25);
    bubbleHeight=130;
}

function jokeQuote(){
    text("This project definitely deserves an A", txt, txtH);
    text("-- "+personQuote[tCh1], txt+15, txtH+25);
    bubbleHeight=130;
}

For our final project, we made an Inspirational Quote Maze. The player moves a small square around in a randomly generated maze using the WASD keys. The dots in the maze tell the player inspirational quotes when they collide. For every quote the character receives, they gain a couple points in their “InspiroMeter.” Once they hear enough quotes, the game is over and they are congratulated for being inspired.
            Thomas mainly worked in the wall, player, and patterns files. He made the player movements and randomly generated the maze and the dots found within. He made it so the player can’t receive a different quote from the same dot twice in a row. He also created patterns to make the blocks look more exciting. 
            Anna mainly worked in the main and quotes files. She decided on the quote templates, made arrays filled with parts of speech, and randomized both of them for unique quotes. She made the speech bubble that appears when a character is talking. She also made the “InspiroMeter” and made the game end after a certain number of quotes. 
            Overall, we think that our project turned out well and we are proud of our efforts!

rfarn and ziningy1- final project

Audio embedded, please turn up volume. Vimeo recording also included at bottom.

In our final project, we made a music video and explored the relationship between geometric motion and rhythm. We divided the video into four sections of movements, interacting with the rhythm and mood of the music.

Motion section 1: Morphing blob

Motion section 2: Droplets

Motion section 3: Interacting Balls

 

Motion section 4: Splitting /Pulsing Balls

sketch

//stores music
var song;

//intro blob variables
var dx1;
var dy1;
var v0x;
var v0y;
var v1x;
var v1y;
var v2x;
var v2y;
var v3x;
var v3y;
var v4x;
var v4y;
var v5x;
var v5y;
var vcolor = 100;
var vopac = 255; 

//circle droplet variables
var diam1 = 30;
var diam2 = 30;
var diam3 = 30;
var diam4 = 30;
var opac = 200;
var drate = 6;

//interacting balls variables
var IBdiam = 30;
var IBxpos1 = 20;
var IBypos1 = 20;
var IBxpos2 = 20;
var IBypos2 = 20;
var IBxpos3 = 20;
var IBypos3 = 20;
var IBxpos4 = 20;
var IBypos4 = 20;
var IBxpos5 = 20;
var IBypos5 = 20;
var triangleOpac = 255;

//red bars variables
var bwidth1 =  15; 
var bheight = 15;
var bwidth2 = 15;
var barOpac = 255;
var bspeed = 4;
var rectx1 = 200;
var rectx2 = 230;

//splitting balls variables
var SBypos = -15;
var SBxpos1 = 300;
var SBxpos2 = 300;
var ball3y = 200;
var ball4y = 200; 


function preload() {
    song = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/music.mp3");
    song.setVolume(0.5);
}

function setup() {
    createCanvas(600, 400);
    frameRate(10);
    song.play();

    //set values to intro blob vertexes
    v0x = width/2 - 70;
    v0y = height/2;
    v1x = width/2;
    v1y = height/2 - 70;
    v2x = width/2 + 70 ;
    v2y = height/2 ;
    v3x = width/2;
    v3y = height/2 + 70;
    v4x = width/2 - 70;
    v4y = height/2;
    v5x = width/2;
    v5y = height/2 - 70;
    v6x = width/2 + 70;
    v6y = height/2;
}

function draw() {
        angleMode(DEGREES);
        background(150);
        noStroke();

        fill(vcolor);
        vcolor += 2;
        drawintroDrop(); //larger intro blob
        fill(130, 130, 130, vopac);
        push();
        scale(0.4);
        translate(2 * width/3 + 20, 2 * height/3);
        drawintroDrop(); //smaller intro blob
        pop();
        vopac -= 10;
    
        drawDroplets();
        drawInteractballs();
        pulsingBalls();
}

function interactingBalls(op, xpos, ypos) { //make interacting ball
    fill(132, 190, 160, op);
    ellipse(xpos, ypos, 30, 30);     
}

function makeDrop(r, g, b, x, y, diam) { //make droplet
    fill(r,g,b,opac);
    ellipse(x, y, diam, diam);
}

function drawintroDrop(){ //intro blob 
    angleMode(DEGREES);
    beginShape();
    curveVertex(v0x, v0y);
    v0x -= 2;
    v0y += 4;
    curveVertex(v1x, v1y);
    v1x -= 2;
    v1y += 6;
    curveVertex(v2x, v2y);
    v2x -= 8;
    v2y -= 4;
    curveVertex(v3x,v3y);
    v3x += 2;
    v3y -= 4;
    curveVertex(v4x,v4y);
    v4x += 8;
    v4y += 4;
    curveVertex(v5x, v5y);
    v5x -= 2;
    v5y += 6;
    curveVertex(v6x, v6y);
    v6x -= 2; 
    v6y += 4;
    endShape();
} 

function drawDroplets(){ //circle droplets
    if(frameCount > 52){ //first droplet
        makeDrop(108,163,140,width/4, height/4, diam1);
        diam1 += drate;
        opac -= 3;
    }

    if(frameCount > 62){ //second droplet
        makeDrop(108,123,140,width/2, height/2 + 60, diam2);
        diam2 += drate;
    }

    if(frameCount > 73){ //third droplet
        makeDrop(178,160,140,width - 100, height - 100, diam3);
        diam3 += drate;
    }

    if(frameCount > 88){ //fourth droplet
        makeDrop(200,163,140,width - 140, height - 270, diam4);
        diam4 += drate;
    }

    if(frameCount > 120 & frameCount % 3 == 0 ){ //flashing background
        fill(252, 252, 240);
        rect(0, 0, width, height);
    }
}

function drawInteractballs(){ //interacting balls
    if(frameCount > 120 & frameCount < 172 ){ //red triangle
        fill(210, 65, 65, triangleOpac);
        triangle(30, 45, 30, 135, 165,135);
    }

    //balls movement
    if(frameCount > 120){ //ball one
        interactingBalls(250, IBxpos1, IBypos1);
        IBxpos1 += 6;
        IBypos1 += 4;
        if(IBxpos1 > 165 + IBdiam/3){
            IBxpos1 -= 3;
            IBypos1 += 10;
        } 
        if(IBypos1 > 350 - IBdiam/2 || frameCount > 161){
            IBxpos1 -= 1;
            IBypos1 -= 20;
        }
        if(frameCount > 185){
            IBypos1 += 12;
        }
        if(frameCount > 211){
            IBypos1 -= 12;
        }
        if(frameCount > 237){
            IBypos1 += 18;
        }
    }

    if(frameCount>126.5){ //ball two
        interactingBalls(180, IBxpos2, IBypos2);
        IBxpos2 += 6;
        IBypos2 += 4;
        if(IBxpos2 > 165 + IBdiam/3){
            IBxpos2 -= 3;
            IBypos2 += 10;
        }
        if(IBypos2 > 350 - IBdiam/2 || frameCount > 167.5){
            IBxpos2 -= 1;
            IBypos2 -= 20;        
        }
        if(frameCount > 191.5){
            IBypos2 += 12;
        }
        if(frameCount > 217.5){
            IBypos2 -= 12;
        }
        if(frameCount > 244.5){
            IBypos2 += 18;
        }
    }

    if(frameCount > 133){ //ball three
        interactingBalls(130, IBxpos3, IBypos3);
        IBxpos3 += 6;
        IBypos3 += 4;
        if(IBxpos3 > 165 + IBdiam/3){
            IBxpos3 -= 3;
            IBypos3 += 10;
            triangleOpac -= 17; //triangle opacity decreases when third ball falls
        }
        if(IBypos3 > 350 - IBdiam/2 || frameCount > 174){
            IBxpos3 -= 1;
            IBypos3 -= 20;
        }
        if(frameCount > 198){
            IBypos3 += 12;
        }
        if(frameCount > 224){
            IBypos3 -= 12;
        }
        if(frameCount > 251){
            IBypos3 += 18;
        }
    }

    if(frameCount>139.5){ //ball four
        interactingBalls(80, IBxpos4, IBypos4);
        IBxpos4 += 6;
        IBypos4 += 4;
        if(IBxpos4 > 165 + IBdiam/3){
            IBxpos4 -= 3;
            IBypos4 += 10;
        }
        if(IBypos4 > 350 - IBdiam/2 || frameCount > 180.5){
            IBxpos4 -= 1;
            IBypos4 -= 20;
        }
        if(frameCount > 204.5){
            IBypos4 += 12;
        }
        if(frameCount > 230.5){
            IBypos4 -= 12;
        }
        if(frameCount > 257.5){
            IBypos4 += 18;
        }
    }

    if(frameCount>146.5){ //ball five
        interactingBalls(40, IBxpos5, IBypos5);
        IBxpos5 += 6;
        IBypos5 += 4;
        if(IBxpos5 > 165 + IBdiam/3){
            IBxpos5 -= 3;
            IBypos5 += 10;
        }
        if(IBypos5 > 350 - IBdiam/2 || frameCount > 186.5){
            IBxpos5 -= 1;
            IBypos5 -= 20;
        }
        if(frameCount > 211){
            IBypos5 += 12;
        }
        if(frameCount > 237){
            IBypos5 -= 12;
            barOpac -= 7; //red bars opacity decreases on fifth balls second to last bounce
        }
        if(frameCount > 264){
            IBypos5 += 18;
        }
    }

    //red bars
    if(frameCount > 159){ //bottom bar
        fill(210, 65, 65, barOpac);
        rect(rectx1,345,bwidth1,bheight);
        bwidth1+= bspeed;
    }

    if(frameCount > 175){ //top bar
        fill(210, 65, 65, barOpac);
        rect(rectx2,155,bwidth2,bheight);
        bwidth2 += bspeed;
    }

    if(bwidth1 > 350  || frameCount > 212){ //bars moving right
        rectx1 += 7;
        rectx2 += 2;
    }
}

function pulsingBalls(){ //splitting and pulsing balls
    //constraining variables
    var SBy1 = constrain(SBypos, -IBdiam/2, height/2);
    var SBx1 = constrain(SBxpos1, width/3 - 25, width);
    var SBx2 = constrain(SBxpos2, 0, width * (2/3) + 25);
    
    if(frameCount > 287){ //first circle moving
        fill(132, 190, 160);
        SBypos += 10;
        ellipse(SBx1, SBy1, IBdiam, IBdiam);
        ellipse(SBx2, SBy1, IBdiam, IBdiam);
        if(SBy1 > 160 & SBy1 < 200){ //diam increases
            IBdiam += 5;
        }
        if(SBy1 == 200){ //split to two circles
            SBxpos1 -= 5;
            SBxpos2 += 5;
            if(frameCount>330){ //split to six circles
                var SBy2 = constrain(ball3y, height/4, height/2);
                var SBy3 = constrain(ball4y, height/2, height * (3/4));
                ellipse(SBx1, SBy2, IBdiam, IBdiam); 
                ellipse(SBx1, SBy3, IBdiam, IBdiam);
                ellipse(SBx2, SBy2, IBdiam, IBdiam); 
                ellipse(SBx2, SBy3, IBdiam, IBdiam);
                ball3y -= 10; 
                ball4y += 10;
                if(SBy2 > 130 & SBy2 < 170){ //diam increases
                    IBdiam += 3; 
                }
            }
        }
    }

    //pulsing balls 
    if(frameCount > 350 & frameCount % 2 == 0){
        IBdiam += 16;
    }

    if(frameCount > 360 & frameCount % 3 == 0){
        IBdiam -= 20;
    }
}

 

 

aerubin-Final Project

KEY – NOTE NAME

A STRING:
1 – A
2 – B
3 – C#
4 – D
5 – E

D STRING:
Q – D
W – E
E – F#
R – G
T – A

G STRING:
A – G
S – A
D – B
F – C
G – D

C STRING:
Z – C
X – D
C – E
V – F
B – G

My final project is a playable viola that creates art in the background based on the notes played and length of the notes played. I drew the viola utilizing arcs, triangles, lines, and other 2D shapes. Then I added sounds to the notes played and ellipses that move with the music.

Each note is connected to a key, that when pressed, plays a note and a visual representation of the sound as a green dot showing the placement of the note on the fingerboard. In addition, there are 20 uniquely colored balls hiding behind the viola that are connected to 20 notes that can be played with the keyboard. Each ball will move at its individual vertical and horizontal velocities when the key is pressed. When the key is lifted, the sound will stop and ball will stop in place. When the performer is finished playing, it will leave a pattern of balls in the background. With the end of each unique composition, the background will look unique, linking each unique piece of music with a unique piece of art.

Functioning Code Showing Moving Ellipses

Note: WordPress does not display the audio correctly, so here is a zip file with the audio files and functioning code. In order to run this code, you access it in the terminal and type “python -m SimpleHTTPServer” and the code will run properly. Above is a screenshot of the completely functioning code.

aerubin_Final_Project

Make sure to turn the volume up!

Angela Rubin – Final Project

//Angela Rubin
//Section C
//aerubin@andrew.cmu.edu
//Final Project

//Initial Placement of Balls in Background
var x = 300;
var y = 175;
//Speed of Balls in both x and y directions
var dx = -1;
var dy = 2;

var x1 = 300;
var y1 = 175;
var dx1 = 2;
var dy1 = 1;

var x2 = 300;
var y2 = 175;
var dx2 = -1;
var dy2 = 1;

var x3 = 300;
var y3 = 175;
var dx3 = 2;
var dy3 = -2;

var x4 = 300;
var y4 = 175;
var dx4 = 2;
var dy4 = 3;

var x5 = 300;
var y5 = 175;
var dx5 = -3;
var dy5 = 2;

var x6 = 300;
var y6 = 175;
var dx6 = 3;
var dy6 = -3;

var x7 = 300;
var y7 = 175;
var dx7 = -3;
var dy7 = 4;

var x8 = 300;
var y8 = 175;
var dx8 = 4;
var dy8 = 3;

var x9 = 300;
var y9 = 175;
var dx9 = -4;
var dy9 = 4;

var x10 = 300;
var y10 = 175;
var dx10 = -1;
var dy10 = -2;

var x11 = 300;
var y11 = 175;
var dx11 = -2;
var dy11 = -1;

var x12 = 300;
var y12 = 175;
var dx12 = -2;
var dy12 = -2;

var x13 = 300;
var y13 = 175;
var dx13 = -2;
var dy13 = -3;

var x14 = 300;
var y14 = 175;
var dx14 = -3;
var dy14 = -2;

var x15 = 300;
var y15 = 175;
var dx15 = -3;
var dy15 = -4;

var x16 = 300;
var y16 = 175;
var dx16 = -4;
var dy16 = -3;

var x17 = 300;
var y17 = 175;
var dx17 = -1;
var dy17 = 2;

var x18 = 300;
var y18 = 175;
var dx18 = -2;
var dy18 = 3;

var x19 = 300;
var y19 = 175;
var dx19 = 3;
var dy19 = -2;

//Sound Names
var EonAString;
var DonAString;
var ConAString;
var BonAString;
var AonString;
var AonString2;
var GonDString;
var FonDString;
var EonDString;
var DonString;
var DonString2;
var ConGString;
var BonGString;
var AonGString;
var GonString;
var GonString2;
var FonCString;
var EonCString;
var DonCString;
var ConString;

//Background Pattern Variables
var diameter = 15; // diameter of the circles
var horizSpace = diameter; // horizontal spacing of the circles
var verSpace; // vertical spacing of the circles

function setup() {
    createCanvas(450, 350);
    verSpace = horizSpace * sqrt(0.75);   
}


function preload() {
    //Preloads each sound for each note
    EonAString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/E-A_String.m4a");
    DonAString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/D-A_String.m4a");
    ConAString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/C-A_String.m4a");
    BonAString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/B-A_String.m4a");
    AonString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/A-String.m4a");
    AonString2 = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/A-String2.m4a");
    GonDString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/G-D_String.m4a");
    FonDString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/F-D_String.m4a");
    EonDString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/E-D_String.m4a");
    DonString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/D-String.m4a");
    DonString2 = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/D-String2.m4a");
    ConGString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/C-G_String.m4a");
    BonGString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/B-G_String.m4a");
    AonGString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/A-G_String.m4a");
    GonString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/G-String.m4a");
    GonString2 = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/G-String2.m4a");
    FonCString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/F-C_String.m4a");
    EonCString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/E-C_String.m4a");
    DonCString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/D-C_String.m4a");
    ConString = loadSound("https://courses.ideate.cmu.edu/15-104/f2017/wp-content/uploads/2017/12/C-String.m4a");
}

function draw() {
    background(255);

    noStroke();
    for(var i = 0; i < 30; i++) {
        if (i%2==1) {var c = -1;}
        if (i%2==0) {c = 0;}
        for(var n = 0; n < 35+c; n++) {
            fill(i*10, n*10, 255-(i*4));
            ellipse(horizSpace*n+(-7.5*c), verSpace*i, diameter, diameter);
        }
    }

    //Drawing the Balls in Background
    fill(248, 179, 147);
    ellipse(x, y, 50, 50);

    fill(239, 117, 129);
    ellipse(x1, y1, 50, 50);

    fill(191, 109, 135);
    ellipse(x2, y2, 50, 50);

    fill(109, 93, 128);
    ellipse(x3, y3, 50, 50);

    fill(53, 94, 128);
    ellipse(x4, y4, 50, 50);

    fill(156, 196, 176);
    ellipse(x5, y5, 50, 50);

    fill(176, 221, 202);
    ellipse(x6, y6, 50, 50);

    fill(218, 237, 197);
    ellipse(x7, y7, 50, 50);

    fill(246, 166, 168);
    ellipse(x8, y8, 50, 50);

    fill(150, 89, 91);
    ellipse(x9, y9, 50, 50);

    fill(163, 128, 129);
    ellipse(x10, y10, 50, 50);

    fill(170, 210, 189);
    ellipse(x11, y11, 50, 50);

    fill(218, 255, 253);
    ellipse(x12, y12, 50, 50);

    fill(208, 163, 171);
    ellipse(x13, y13, 50, 50);

    fill(247, 193, 172);
    ellipse(x14, y14, 50, 50);

    fill(72, 158, 151);
    ellipse(x15, y15, 50, 50);

    fill(235, 180, 166);
    ellipse(x16, y16, 50, 50);

    fill(211, 200, 215);
    ellipse(x17, y17, 50, 50);

    fill(250, 162, 134);
    ellipse(x18, y18, 50, 50);

    fill(179, 179, 163);
    ellipse(x19, y19, 50, 50);

    //Viola Function to Draw Viola
    makeViola();

    //Color of Dots on Fingerboard
    fill(0, 255, 0);
    noStroke();

    //B Natural, A String, KEY = 2
    if (keyIsDown(50)) {
        BonAString.play();
        ellipse(86, (height/2)-6.7, 4, 4);
        y+=dy;
        x+=dx;
        if(y>height-25 || y<25) {
            dy=-dy;
        }
        if(x>width-25 || x<25) {
            dx=-dx;
        }
    }
    else {BonAString.stop();}

    //C#, A String, KEY = 3
    if (keyIsDown(51)) {
        ConAString.play();
        ellipse(105, (height/2)-7, 4, 4);
        y1+=dy1;
        x1+=dx1;
        if(y1>height-25 || y1<25) {
            dy1=-dy1;
        }
        if(x1>width-25 || x1<25) {
            dx1=-dx1;
        }
    }
    else {ConAString.stop();}

    //D Natural, A String, KEY = 4
    if (keyIsDown(52)) {
        DonAString.play();
        ellipse(114, (height/2)-7.3, 4, 4);
        y2+=dy2;
        x2+=dx2;
        if(y2>height-25 || y2<25) {
            dy2=-dy2;
        }
        if(x2>width-25 || x2<25) {
            dx2=-dx2;
        }
    }
    else {DonAString.stop();}

    //E Natural, A String, KEY = 5
    if (keyIsDown(53)) {
        EonAString.play();
        ellipse(130, (height/2)-7.8, 4, 4);
        y3+=dy3;
        x3+=dx3;
        if(y3>height-25 || y3<25) {
            dy3=-dy3;
        }
        if(x3>width-25 || x3<25) {
            dx3=-dx3;
        }
    }
    else {EonAString.stop();}

    //E Natural, D String, KEY = W
    if (keyIsDown(87)) {
        EonDString.play();
        ellipse(86, (height/2)-2.2, 4, 4);
        y4+=dy4;
        x4+=dx4;
        if(y4>height-25 || y4<25) {
            dy4=-dy4;
        }
        if(x4>width-25 || x4<25) {
            dx4=-dx4;
        }
    }
    else {EonDString.stop();}

    //F#, D String, KEY = E
    if (keyIsDown(69)) {
        FonDString.play();
        ellipse(105, (height/2)-2.3, 4, 4);
        y5+=dy5;
        x5+=dx5;
        if(y5>height-25 || y5<25) {
            dy5=-dy5;
        }
        if(x5>width-25 || x5<25) {
            dx5=-dx5;
        }
    }
    else {FonDString.stop();}

    //G Natural, D String, KEY = R
    if (keyIsDown(82)) {
        GonDString.play();
        ellipse(114, (height/2)-2.5, 4, 4);
        y6+=dy6;
        x6+=dx6;
        if(y6>height-25 || y6<25) {
            dy6=-dy6;
        }
        if(x6>width-25 || x6<25) {
            dx6=-dx6;
        }
    }
    else {GonDString.stop();}

    //A Natural, D String, KEY = T
    if (keyIsDown(84)) {
        AonString.play();
        ellipse(130, (height/2)-2.9, 4, 4);
        y7+=dy7;
        x7+=dx7;
        if(y7>height-25 || y7<25) {
            dy7=-dy7;
        }
        if(x7>width-25 || x7<25) {
            dx7=-dx7;
        }
    }
    else {AonString.stop();}

    //A Natural, A String, KEY = 1
    if (keyIsDown(49)) {
        AonString2.play();
        y16+=dy16;
        x16+=dx16;
        if(y16>height-25 || y16<25) {
            dy16=-dy16;
        }
        if(x16>width-25 || x16<25) {
            dx16=-dx16;
        }
    }
    else {AonString2.stop();}


    //A Natural, G String, KEY = S
    if (keyIsDown(83)) {
        AonGString.play();
        ellipse(86, (height/2)+2.2, 4, 4);
        y8+=dy8;
        x8+=dx8;
        if(y8>height-25 || y8<25) {
            dy8=-dy8;
        }
        if(x8>width-25 || x8<25) {
            dx8=-dx8;
        }
    }
    else {AonGString.stop();}


    //B Natural, G String, KEY = D
    if (keyIsDown(68)) {
        BonGString.play();
        ellipse(105, (height/2)+2.3, 4, 4);
        y9+=dy9;
        x9+=dx9;
        if(y9>height-25 || y9<25) {
            dy9=-dy9;
        }
        if(x9>width-25 || x9<25) {
            dx9=-dx9;
        }
    }
    else {BonGString.stop();}

    //C Natural, G String, KEY = F
    if (keyIsDown(70)) {
        ConGString.play();
        ellipse(114, (height/2)+2.5, 4, 4);
        y10+=dy10;
        x10+=dx10;
        if(y10>height-25 || y10<25) {
            dy10=-dy10;
        }
        if(x10>width-25 || x10<25) {
            dx10=-dx10;
        }
    }
    else {ConGString.stop();}

    //D Natural, G String, KEY = G
    if (keyIsDown(71)) {
        DonString.play();
        ellipse(130, (height/2)+2.9, 4, 4);
        y11+=dy11;
        x11+=dx11;
        if(y11>height-25 || y11<25) {
            dy11=-dy11;
        }
        if(x11>width-25 || x11<25) {
            dx11=-dx11;
        }
    }
    else {DonString.stop();}

    //D Natural, D String, KEY = Q
    if (keyIsDown(81)) {
        DonString2.play();
        y17+=dy17;
        x17+=dx17;
        if(y17>height-25 || y17<25) {
            dy17=-dy17;
        }
        if(x17>width-25 || x17<25) {
            dx17=-dx17;
        }
    }
    else {DonString2.stop();}

    //D Natural, C String, KEY = X
    if (keyIsDown(88)) {
        DonCString.play();
        ellipse(86, (height/2)+6.3, 4, 4);
        y12+=dy12;
        x12+=dx12;
        if(y12>height-25 || y12<25) {
            dy12=-dy12;
        }
        if(x12>width-25 || x12<25) {
            dx12=-dx12;
        }
    }
    else {DonCString.stop();}

    //E Natural, C String, KEY = C
    if (keyIsDown(67)) {
        EonCString.play();
        ellipse(105, (height/2)+6.7, 4, 4);
        y13+=dy13;
        x13+=dx13;
        if(y13>height-25 || y13<25) {
            dy13=-dy13;
        }
        if(x13>width-25 || x13<25) {
            dx13=-dx13;
        }
    }
    else {EonCString.stop();}

    //F Natural, C String, KEY = V
    if (keyIsDown(86)) {
        FonCString.play();
        ellipse(114, (height/2)+7, 4, 4);
        y14+=dy14;
        x14+=dx14;
        if(y14>height-25 || y14<25) {
            dy14=-dy14;
        }
        if(x14>width-25 || x14<25) {
            dx14=-dx14;
        }
    }
    else {FonCString.stop();}
    
    //G Natural, C String, KEY = B
    if (keyIsDown(66)) {
        GonString.play();
        ellipse(130, (height/2)+7.5, 4, 4);
        y15+=dy15;
        x15+=dx15;
        if(y15>height-25 || y15<25) {
            dy15=-dy15;
        }
        if(x15>width-25 || x15<25) {
            dx15=-dx15;
        }
    }
    else {GonString.stop();}

    //G Natural, G String, KEY = A
    if (keyIsDown(65)) {
        GonString2.play();
        y18+=dy18;
        x18+=dx18;
        if(y18>height-25 || y18<25) {
            dy18=-dy18;
        }
        if(x18>width-25 || x18<25) {
            dx18=-dx18;
        }
    }
    else {GonString2.stop();}

    //C Natural, C String, KEY = Z
    if (keyIsDown(90)) {
        ConString.play();
        y19+=dy19;
        x19+=dx19;
        if(y19>height-25 || y19<25) {
            dy19=-dy19;
        }
        if(x19>width-25 || x19<25) {
            dx19=-dx19;
        }
    }
    else {ConString.stop();}
}

function makeViola() {
    stroke(255);
    strokeWeight(.4);

    push();
    noStroke();
    strokeWeight(1);
    fill(187, 74, 28);
    //Upper Bout
    arc(205, (height/2)+.5, 100, 120, 1.5, 4.81, CHORD);
    //Lower Bout
    arc(358, (height/2)+.5, 110, 125, 4.6, 8, CHORD);

    quad(210, (height/2)-59, 208, (height/2)+60.5, 255, (height/2)+52, 255, (height/2)-52);

    noFill();
    strokeWeight(4);
    stroke(187, 74, 28);
    //little curve
    arc(254, (height/2)-55, 11, 10, -.2, 2);
    arc(254, (height/2)+55, 11, 10, 4.3, 6.2);

    //Waist of Viola
    arc(285, (height/2)-55, 50, 30, -.2, 3);
    arc(285, (height/2)+55, 50, 30, 3, 6.6);

    //lower bout
    arc(328.5, (height/2)-62, 48, 14, .12, 2.9);
    arc(329, (height/2)+64, 48, 14, 3.3, 6.1);

    fill(187, 74, 28);
    //filling in sparce areas
    quad(252, (height/2)-48, 252, (height/2)+48, 260, (height/2)+51, 260, (height/2)-51);
    quad(260, (height/2)-45, 260, (height/2)+47, 280, (height/2)+38, 280, (height/2)-36);
    quad(279, (height/2)-38, 279, (height/2)+38, 307, (height/2)+44, 306, (height/2)-43);
    quad(305, (height/2)-44, 306, (height/2)+46, 313, (height/2)+52, 313, (height/2)-52);
    quad(312, (height/2)-53, 312, (height/2)+55, 333, (height/2)+53, 333, (height/2)-52);
    quad(332, (height/2)-53, 332, (height/2)+53, 352, (height/2)+58, 352, (height/2)-58);

    //Black Outline of Body
    strokeWeight(1);
    stroke(0);
    noFill();
    arc(205, (height/2)+.5, 100-7, 120-7, 1.5, 4.81);
    arc(358, (height/2)+.5, 110-7, 125-7, 4.6, 8);
    line(209, (height/2)-59+3, 254, (height/2)-52+3);
    line(209, (height/2)+59-3, 254, (height/2)+52-3);
    arc(254, (height/2)-55+1.6, 11, 10, -.2, 1.7);
    arc(254, (height/2)+55, 11, 10, 4.5, 6.2);
    arc(285, (height/2)-54, 50, 30, -.2, 3.1);
    arc(285, (height/2)+54, 50, 30, 3, 6.6);
    arc(328.5, (height/2)-62, 52, 15, .17, 2.88);
    arc(329.5, (height/2)+64-.5, 49, 16, 3.3, 6.05);
    pop();

    //finger board
    fill(0);
    quad(80-10, (height/2)-10, 80-10, (height/2)+10, 250+26, (height/2)+18, 250+26, (height/2)-18);

    //Pegs
    stroke(0);
    quad(38, (height/2)+9, 38+5-1, (height/2)+9, 38+5-1, (height/2)-17, 38, (height/2)-17);
    quad(38+8, (height/2)+9+8, 38+5+8-1, (height/2)+9+8, 38+5+8-1, (height/2)-17+8, 38+8, (height/2)-17+8);
    quad(38+16, (height/2)+9+1, 38+5+16-1, (height/2)+9+1, 38+5+16-1, (height/2)-17+1, 38+16, (height/2)-17+1);
    quad(38+24, (height/2)+9+7, 38+5+24-1, (height/2)+9+7, 38+5+24-1, (height/2)-17+7, 38+24, (height/2)-17+7);

    //Peg Ends
    fill(0);
    arc(40, (height/2)-20+1, 12, 12, 2.5, 6.9, CHORD);
    arc(40+16, (height/2)-20, 12, 12, 2.5, 6.9, CHORD);
    arc(40+8, (height/2)+20-1, 12, 12, 4+3-1.3, 3+.85, CHORD);
    arc(40+24, (height/2)+20, 12, 12, 4+3-1.3, 3+.85, CHORD);

    //Peg Dots
    ellipse(40, (height/2)-26, 2, 2);
    ellipse(40+16, (height/2)-26-1, 2, 2);
    ellipse(40+8, (height/2)+26, 2, 2);
    ellipse(40+24, (height/2)+26+1, 2, 2);

    //Peg Triangles
    triangle(36, (height/2)-13.5, 44, (height/2)-13.5, 40, (height/2)-23);
    triangle(36+16, (height/2)-13.5-1, 44+16, (height/2)-13.5-1, 40+16, (height/2)-23-1);
    triangle(36+8, (height/2)+13.5, 44+8, (height/2)+13.5, 40+8, (height/2)+23);
    triangle(36+24, (height/2)+13.5+1, 44+24, (height/2)+13.5+1, 40+24, (height/2)+23+1);

    stroke(255);
    //peg box
    fill(187, 74, 28);
    quad(70, (height/2)-10, 70, (height/2)+10, 30, (height/2)+7, 30, (height/2)-7);
    stroke(252, 185, 91);

    //Black Section of Peg Box
    fill(0);
    quad(35, (height/2)-3.5, 35, (height/2)+3.5, 70, (height/2)+6.5, 70, (height/2)-6.5);
    line(35, (height/2)-3.5, 70, (height/2)-6.5);
    line(35, (height/2)+3.5, 70, (height/2)+6.5);

    push();
    //String colors in peg box
    stroke(250, 127, 164); //pink
    line(37.5, (height/2)-3, 42.5, (height/2)-3);
    line(37.5, (height/2)-1.5, 42.5, (height/2)-1.5);
    line(37.5, (height/2), 42.5, (height/2));

    stroke(180, 101, 40); //brown
    line(37.5+8, (height/2)-3+3, 42.5+8, (height/2)-3+3);
    line(37.5+8, (height/2)-1.5+3, 42.5+8, (height/2)-1.5+3);
    line(37.5+8, (height/2)+3, 42.5+8, (height/2)+3);

    stroke(255, 0, 0); //red
    line(37.5+16, (height/2)-3-1, 42.5+16, (height/2)-3-1);
    line(37.5+16, (height/2)-1.5-1, 42.5+16, (height/2)-1.5-1);
    line(37.5+16, (height/2)-1, 42.5+16, (height/2)-1);

    stroke(216, 154, 253); //purple
    line(37.5+8+16, (height/2)-3+3+1, 42.5+8+16, (height/2)-3+3+1);
    line(37.5+8+16, (height/2)-1.5+3+1, 42.5+8+16, (height/2)-1.5+3+1);
    line(37.5+8+16, (height/2)+3+1, 42.5+8+16, (height/2)+3+1);
    pop();

    fill(187, 74, 28);
    //Inner Most Scroll Piece
    quad(15, (height/2)-18+1, 15, (height/2), 43-18-3.5, (height/2), 43-18-3.5, (height/2)-18+1);
    quad(15, (height/2)+18-1, 15, (height/2), 43-18-3.5, (height/2), 43-18-3.5, (height/2)+18-1);

    //Middle Scroll Piece
    quad(13-2, (height/2)-13+1, 13-2, (height/2), 43-18+2, (height/2), 43-18+2, (height/2)-16+1);
    quad(13-2, (height/2)+13-1, 13-2, (height/2), 43-18+2, (height/2), 43-18+2, (height/2)+16-1);
    
    //Outer Most Scroll Piece
    quad(14-9, (height/2)-6, 14-9, height/2, 43-10, height/2, 43-10, (height/2)-11);
    quad(14-9, (height/2)+6, 14-9, height/2, 43-10, height/2, 43-10, (height/2)+11);

    //Bridge
    stroke(223, 210, 194);
    strokeWeight(3);
    line(311, (height/2)-16, 311, (height/2)+16);
    stroke(30);
    strokeWeight(1);
    //Tail piece
    fill(0);
    triangle(345, (height/2)-18, 345, (height/2)+18, 410, (height/2));

    //Chin rest
    push();
    rotate(radians(19));
    ellipse(437, (height/2)-118, 40, 60);
    pop();

    push();
    stroke(251, 198, 212);
    strokeWeight(2.5);
    line(86, (height/2)-9.5, 86, (height/2)+9.5);
    line(105, (height/2)-10, 105, (height/2)+10);
    line(114, (height/2)-10.5, 114, (height/2)+10.5);
    line(130, (height/2)-11, 130, (height/2)+11);
    pop();

    //Strings
    stroke(240);
    strokeWeight(.7);
    line(58, (height/2)-4.5, 70, (height/2)-6); //Upper A String
    line(70, (height/2)-6, 311, (height/2)-14); //A String
    line(43, (height/2)-2, 311, (height/2)-5); //D String
    line(51, (height/2)+2, 311, (height/2)+4); //G String
    line(70, (height/2)+5.7, 311, (height/2)+13); //C String
    line(66, (height/2)+4.5, 70, (height/2)+5.5); //Upper C String

    line(311, (height/2)-14, 348, (height/2)-11); //Lower A String
    line(311, (height/2)-5, 348, (height/2)-4); //Lower D String
    line(311, (height/2)+4, 348, (height/2)+3.5); //Lower G String
    line(311, (height/2)+13, 348, (height/2)+11); //Lower C String

    stroke(255, 0, 0); //Red String Ends
    strokeWeight(1.3);
    line(330, (height/2)-12.6, 348, (height/2)-11);
    stroke(11, 85, 25); //Green String Ends
    line(330, (height/2)-4.5, 348, (height/2)-4);
    line(330, (height/2)+3.8, 348, (height/2)+3.5);
    line(330, (height/2)+12, 348, (height/2)+11);

    //Fine Tuner
    strokeWeight(1);
    stroke(255, 206, 79);
    fill(255, 220, 123);
    ellipse(349, (height/2)-11, 4, 4);

    stroke(0);
    strokeWeight(3);
    noFill();
    //Upper F Hole
    arc(296, (height/2)-25, 30, 12, 2.7, 4);
    line(291, (height/2)-31, 315, (height/2)-34.6);
    arc(310, (height/2)-40, 30, 12, 5.7, 7);
    
    //Lower F Hole
    arc(296, (height/2)+25.5, 30, 12, 2.3, 3.65);
    line(291, (height/2)+31, 315, (height/2)+34.6);
    arc(310, (height/2)+40.6, 30, 12, 5.5, 6.8);

    //little lines on F Holes
    strokeWeight(.8);
    line(305, (height/2)-30, 304, (height/2)-35);
    line(305, (height/2)+31, 304, (height/2)+36);

    //Dots on F Holes
    fill(0);
    ellipse(287, (height/2)-21.5, 4.3, 4.3);
    ellipse(287.2, (height/2)+21.9, 4.3, 4.3);

    ellipse(316.5, (height/2)-43.5, 5, 5);
    ellipse(317, (height/2)+44, 5, 5);
}