Alec Albright – Final Project

sketch

// Alec Albright
// aalbrigh
// Section B
// Project 12 - Final Project

var video;
var nPoints = 100; // number of points used to draw curves

var previous; // previous image from camera
var threshold = 150; // used to determine if a pixel is different enough to consider it "moving"
var motionX = 0; // main coordinate of X motion
var motionY = 0; // main coordinate of Y motion
var lerpX = 0; // X coordinate for smoothing of motion
var lerpY = 0; // Y coordinate for smoothing of motion

var higherLove; // Whitney Houston's "Higher Love"
var low; // Flo Rida's "Low"
var irreplaceable; // Beyonce's "Irreplaceable"
var newBooty; // Bubba Sparxxx's "Ms. New Booty"
var higherVol; // Higher love volume
var lowVol; // low volume
var irrepVol; // irreplaceable volume
var bootyVol; // new booty volume

function preload(){
    higherLove = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Higher-Love.wav");
    low = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Low.wav");
    irreplaceable = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Irreplaceable.wav");
    newBooty = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/New-Booty.wav");
}

function soundSetup() { // setup for audio generation
    // making sine
    sine = new p5.Oscillator();
    sine.setType("sine");
    //sine.start();

    // making sawtooth
    sawtooth = new p5.Oscillator();
    sawtooth.setType("sawtooth");
    //sawtooth.start();

    // making square wave
    square = new p5.Oscillator();
    square.setType("square");
    square.freq(440);
    //square.start();
}

function setup(){
    createCanvas(480, 480);
    angleMode(RADIANS);

    video = createCapture(VIDEO);
    video.size(480, 480); // attempt to size the camera. 
    video.hide(); // this hides an unnecessary extra view.
    // prepping to copy previous frame for difference in motion
    previous = createImage(480, 480, RGB);

    useSound();

    higherLove.play();
    higherLove.setVolume(0);
    higherLove.loop();

    low.play();
    low.setVolume(0);
    low.loop();

    irreplaceable.play();
    irreplaceable.setVolume(0);
    irreplaceable.loop();

    newBooty.play();
    newBooty.setVolume(0);
    newBooty.loop();
}

function draw(){
    var count = 0; // number of pixel instances we've looped through
    var sumX = 0; // sum of motion X coordinates
    var sumY = 0; // sum of motion X coordinates

    // making camera actually mirror user
    push();
    translate(width, 0);
    scale(-1, 1);
    image(previous, 0, 0);
    pop();

    loadPixels();
    video.loadPixels(); // this must be done on each frame.
    previous.loadPixels();

    // comparing all pixels to previous image
    for (var x = 0; x < video.width; x ++) {
        for (var y = 0; y < video.height; y ++) {
            var location = (x + y * video.width) * 4;
            // finding previous and current colors
            // previous
            var red1 = previous.pixels[location]; 
            var green1 = previous.pixels[location + 1];
            var blue1 = previous.pixels[location + 2];
            // current
            var red2 = video.pixels[location];
            var green2 = video.pixels[location + 1];
            var blue2 = video.pixels[location + 2];

            var diff = distSquared(red1, green1, blue1, red2, green2, blue2);

            // checking whether they are different enough to call motion
            if (diff > threshold * threshold) {
                sumX += x;
                sumY += y;
                count ++;
            }
        }
    }
    updatePixels();

    // only count it as a different frame if more than 30 pixels have changed
    // find main X and Y coordinate of motion, this will be our control for everything
    if (count > 100) { 
        motionX = sumX / count;
        motionY = sumY / count;
    }
      
    // maintaining mirrored scale for user interface
    push();
    translate(width, 0);
    scale(-1, 1);
    // smoothing out how the point of focus is travelling
    lerpX = lerp(lerpX, motionX, 0.1); 
    lerpY = lerp(lerpY, motionY, 0.1); 

    // drawing point so user knows where the main motion point is
    stroke("black");
    fill("white");
    ellipse(lerpX, lerpY, 20, 20);
    pop();

    push();
    translate(width / 2, height / 2);
    
    // draw all the shapes
    drawHippopede();
    drawEpicycloid();
    drawHypotrochoid();

    pop();

    previous.copy(video, 0, 0, video.width, video.height, 0, 0, video.width, video.height);
    
    // creating slight boundaries for better sound isolation
    if(lerpY < 200 || lerpY > 320) {
        // letting contrast between top and bottom come through
        bootyVol = 0;
        irrepVol = 0;
        newBooty.setVolume(bootyVol);
        irreplaceable.setVolume(irrepVol);

        // as we move up, more higher love/less low
        // volume 0 to 1
        higherVol = map(lerpY, 0, width, 0, 1);
        higherLove.setVolume(1 - higherVol);
        lowVol = map(lerpY, 0, width, 0, 1);
        low.setVolume(lowVol);
    } else {
        // letting contrast between right and left come through
        higherVol = 0;
        lowVol = 0;
        higherLove.setVolume(higherVol);
        low.setVolume(lowVol);

        // as we move right, more new booty/less irreplaceable
        // volume 0 to 1
        bootyVol = map(lerpX, 0, width, 0, 1);
        newBooty.setVolume(1 - bootyVol);
        irrepVol = map(lerpX, 0, width, 0, 1);
        irreplaceable.setVolume(irrepVol);
    }
}

// draws Hippopede
function drawHippopede() {
    var x; // x coordinate of vertex
    var y; // y coordinate of vertex
    var r; // polar coordinate
    var a = lerpX / 3 // main parameter of the curve
    var b = map(a, 0, 480, 100, 200); // circle radius
    var rotation = map(lerpY, 0, 480, 0, TWO_PI); // amount of rotation

    // thickness of line proportional to the circle radius
    strokeWeight(b / 6);
    stroke(255, 255, 255, 150);
    noFill();

    // rotate shape
    push();
    rotate(rotation);

    // start drawing the shape, one point at a time
    beginShape();
    for(var i = 0; i < nPoints; i++){
        var t = map(i, 0, nPoints, 0, TWO_PI);
        
        // find r (polar equation)
        r = sqrt(4 * b * (a - b * sinSq(t)));

        // convert to x and y coordinates
        x = r * cos(t);
        y = r * sin(t);

        // draw a point at x, y
        vertex(x, y);
    }
    endShape();
    pop();
}

// draws hypotrochoid
function drawHypotrochoid() {
    var x; // x coordinate of vertex
    var y; // y coordinate of vertex
    var a = map(lerpX, 0, 480, 20, 100); // radius of the interior circle
    var b = 3; // radius of the petals
    var h = lerpX / 10; // distance from center of interior circle
    var red = map((lerpX + lerpY) / 2, 0, 480, 0, 255); // how much red
    var blue = map(lerpY, 0, 480, 0, 255); // how much blue
    var alpha = map(lerpX, 0, 480, 50, 150); // how opaque
    var rotation = map(lerpY, 100, 300, 0, TWO_PI); // amount of rotation

    strokeWeight(2)
    stroke(255, 255, 255, 150);

    // control color and opacity with mouse location
    fill(red, 0, blue, alpha);

    // control rotation with lerpY
    push();
    rotate(rotation);

    // create the shape itself
    beginShape();
    for(var i = 0; i < nPoints; i++) {
        var t = map(i, 0, nPoints, 0, TWO_PI);

        // use parametric euqations for hypotrochoid to find x and y
        x = (a - b) * cos(t) + h * cos((a - b) / b * t);
        y = (a - b) * sin(t) - h * sin((a - b) / b * t);

        // draw a point at x, y
        vertex(x, y)
    }
    endShape(CLOSE);
    pop();
}

// draws an epicycloid
function drawEpicycloid() {
    var x; // x coordinate of vertex
    var y; // y coordinate of vertex
    var a = map(lerpX, 0, 480, 20, 100); // radius of interior circle
    var b = map(lerpY, 0, 480, 5, 30); // radius of petals
    var blue = map((lerpX + lerpY) / 2, 0, 480, 0, 255); // how much blue
    var red = map(lerpY, 0, 480, 0, 255); // how much red
    var rotation = map(lerpY, 100, 300, 0, TWO_PI); // how muhc rotation

    // control color with mouse location
    strokeWeight(10)
    stroke(red, 0, blue, 150);

    // control rotation with mouse location
    push();
    rotate(rotation);

    // start drawing shape
    beginShape();
    for(var i = 0; i < nPoints; i++) {
        var t = map(i, 0, nPoints, 0, TWO_PI);

        // find coordinates using epicycloid parametric equations
        x = (a + b) * cos(t) - b * cos((a + b) / b * t);
        y = (a + b) * sin(t) - b * sin((a + b) / b * t);

        // draw a point at x, y
        vertex(x, y);
    }
    endShape();
    pop();
}

// defines sin^2 using trigonometric identities
function sinSq(x) {
    return((1 - cos(2 * x)) / 2);
}

function distSquared(x1, y1, x2, y2) {
    let dx = x2 - x1;
    let dy = y2 - y1;
    return (dx * dx) + (dy * dy);
}

For the Final Project, I wanted to do something that had to deal with music, as it is my primary focus at CMU, but I also wanted to try doing something computationally complex that I would certainly be challenged by. Thus, the idea to create a motion detection music player was born! I also wanted to keep it fun, so I decided to play music related to each quadrant: “Irreplaceable” – Beyonce for the left (to the left, to the left…), “Higher Love” – Whitney Houston for the top, “Low” – Flo Rida for the bottom, and “Ms. New Booty” – Bubba Sparxxx for the right (get it right, get it right get it tight). For better user interfacing, I also included a floating point that denotes where the program has tracked the average motion.

The process was most difficult in rendering and comparing one frame to its previous frame in order to create a successful motion detection program. It was interesting mapping the visualization to the motion detection as well, giving each song its own visual identity.

In order to run the program, you must allow the website to access your video camera. However, I have included a demo video below for those who would rather see that.

Minjae Jeong- Final Project

sketch

//Minjae Jeong
//Section B
//minjaej@andrew.cmu.edu
//Final Project

var human = []; //array to save x y position
var count = 0;
var transp = 255; //transparency

function preload() {
    //simplified world map
    worldMap = loadImage("https://i.imgur.com/Kviuun0.png");
}

function setup() {
    createCanvas(600, 348);
    textAlign(CENTER);
}

function draw() {
    background(132, 181, 229); //rgb of image's body of water
    tint(255, transp); //this makes the water to fill up as you click
    image(worldMap, 0, 30);

    //title
    textSize(24);
    fill('red');
    text("UNTIL WHEN CAN THE EARTH SUPPORT US?", width / 2, 27);//Have you thought about it

    //Draw human + CO2
    strokeWeight(1);
    for (var i = 0; i < human.length; i++) {
        xx = human[i][0];
        yy = human[i][1];
        fill('black');
        drawHuman(xx, yy);
        drawco2(xx, yy - 5);
    }

    //display global warming text
    if (count > 20 & count < 40) {
        textSize(20);
        fill("red");
        text("GLOBAL WARMING", 350, 330);
        // count = count + 1;
    }

    //display "No more penguins and polar bears." Could be very soon
    if (count > 40 & count < 60) {
        textSize(20);
        fill("red");
        text("NO MORE PENGUINS & POLAR BEARS", 320, 50);
    }

    //display "No more place to live"
    //(Elon Musk please)
    if (count > 70 & count < 100) {
        textSize(27);
        fill("red");
        text("NO MORE PLACE TO LIVE", width / 2, height / 2);
    }

    //changes background color to black
    if (count > 90 & count < 100) {
        fill("black");
        rect(0, 0, width, height);
        fill("red");
        text("NO MORE PLACE TO LIVE", width / 2, height / 2);
    }

    //"What will you do?"
    if (count >= 100){
        fill('black');
        rect(0, 0, width, height);
        fill('red');
        textSize(30);
        text("WHAT WILL YOU DO?", width / 2, height /2);
    }
}

//draw human
function drawHuman(x, y) {
    ellipse(x, y, 5);
    rect(x - 2, y + 5, 4, 11);
    line(x - 2, y + 7, x - 8, y + 2);
    line(x + 2, y + 7, x + 8 , y + 2);
}

//CO2
function drawco2(x, y) {
    textSize(9);
    text("+ CO2", x, y);
}

function mousePressed() {
    human.push([mouseX, mouseY]); //Save mouseX, mouseY
    transp = transp - 3.3; //Water fills up the land
    count += 1;
}

For the final project, I made an interactive map that I wish to deliver some message. Click to add people on the map, keep on adding as it represents human population on the Earth.

My final project is little different from the proposal, because the original idea, which was to indicate temperature rise and deforestation, did not have clear message compared to what it actually shows. So I rather made a simple interactive map that shows what is happening as we grow on the Earth.

Julia Nishizaki – Final Project

sketch

//Julia Nishizaki
//Section B
//jnishiza@andrew.cmu.edu
//Final Project - ABCs of Climate Change


//variables for climate change effects, uses true/false statements to make effects appear/disappear
var cE = {
    lakeColor: false, //algae blooms
    flowers: false, //biodiversity
    clouds: false, //carbon footprint
    trees: true, //deforestation
    gas: false, //greenhouse gases
    mtn: false, //hazardous waste
    hill: false, //invasive species
    jeopardy: false, //jeopardy
    house: false, //population growth
    sky: false, //smog
    field: false, //toxic pollutants
    building: false, //urban sprawl
    lake: false, //water levels
    deadz: false, //zones that are dead
}

//variables to help with effects of climate change
var lakeWidth = 200; //initial width of lake
var lakeHeight = 35; //height of lake
var skyHeight = 0; //height of sky for smog
var cloudX = 475; //starting x position for cloud
var gasX = 475; //starting x position for gas cloud
var jtranslu = 0; //starting opacity for "smoke screen", jeopardy

//variables for the window and its dimensions
var win = {
    ws: 125, //distance from window to right and left sides of canvas
    wt: 40, //distance from window to top of canvas
    wb: 160, //distance from window to bottom of canvas
    frm: 5, //width of window frame
    dis: 5, //displacement outside of canvas
}

//variables for colors used throughout, especially for objects that change color
var colors = {
    hill: 80, //light green hill (HSB)
    mtnb: 70, //purple mountains (HSB)
    sky: '#8ED9EF', //light blue of sky
    smogop: 80, //opacity of smog in background
    field: 'green', //green
    lakeh: 55, //hue value of lake (HSB)
    lakes: 50, //saturation value of lake (HSB)
    lakeb: 100, //brightness value of lake (HSB)
    fieldb: 60, //brightness value of field (HSB)
    wall: 230, //light gray of walls
    table: 150, //dark gray of table 
    flower: 'purple', //purple flowers
    plnflw: 'green', //green flowers
    type: '#8BC63F', //light green of type
}

//arrays that store letters and each letter's climate change info
var alphabetLetters = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
var letterInfo = [ //stores copy on climate change ABCs
    "Algae Blooms: toxic algae can poison water and create dead zones", 
    "Biodiversity: the variety of life on the planet", 
    "Carbon Footprint: the amount of carbon dioxide each of us produces", 
    "Deforestation: the reduction of trees due to natural forces or human activity", 
    "Extinctions: the death of all individuals of a species", 
    "Fossil Fuels: nonrenewable fuels that are burned for energy like coal and gas", 
    "Greenhouse Gases: gases like methane, trap heat and warm the atmosphere", 
    "Hazardous Waste: waste that pose a risk to human health and the environment", 
    "Invasive Species: any organism not native to an ecosystem that causes harm", 
    "Jeopardy: danger of loss, harm, or failure", 
    "Keystone Species: a species that is critical to the survival of other species", 
    "Landfill: a site where wastes are dumped for permanent disposal", 
    "Microplastics: very small pieces of plastic that pollute the environment", 
    "Nonrenewable: resources that can't be replenished onced used", 
    "Ozone Layer: a thin protective layer of gas above Earth that filters UV radiation", 
    "Population Growth: an increase in the total human population", 
    "Quotas Insufficient: limits and restrictions in environmental policies not met", 
    "Runoff: stormwater from cities or farms that carry pollutants into water systems", 
    "Smog: dust, smoke, or chemical fumes that pollute the air", 
    "Toxic Pollutants: contaminate areas and cause death, disease, or birth defects", 
    "Urban Sprawl: expansion of auto-dependent developments over large areas of land", 
    "Vulnerability: susceptibility to harm from exposure to stresses", 
    "Water Level Rise: rising sea levels due to global warming and melting glaciers", 
    "Xenobiotic: non-natural or man-made substances found in the environment", 
    "Yield: amount of crops produced per unit area", 
    "Zones that are Dead: dead zones are caused by hypoxia, or lack of oxygen in water",
    ];

function setup() {
    createCanvas(600, 480);
    frameRate(30);   
}

function draw() {
    background(colors.sky); //sets the background as a light blue
    
    prepEnvironEffects(); //connects each key to a variable

    drawLandscape(); //creates all elements of the landscape 
    drawRoom(); //creates all elements of the room
    
    typedLetterAlphabet(); //displays the alphabet
    typedLetterInfo(); //displays the words and definitions
}

function prepEnvironEffects() {//when a particular key is pressed, the variable associated with that key switches from false to true
    if (key == 'a') { //algae blooms
            cE.lakeColor = true;
        } 
    if (key == 'b') { //biodiversity
            cE.flowers = true;
        }
    if (key == 'c') { //carbon footprint
            cE.clouds = true;
        } 
    if (key == 'd') { //deforestation
            cE.trees = false;
        } 
    if (key == 'g') { //greenhouse gases
            cE.gas = true;
        } 
    if (key == 'h') { //hazardous waste
            cE.mtn = true;
        } 
    if (key == 'i') { //invasive species
            cE.hill = true;
        } 
    if (key == 'j') { //jeopardy
            cE.jeopardy = true;
        } 
    if (key == 'p') { //population growth
            cE.house = true;
        } 
    if (key == 's') { //smog
            cE.sky = true;
        } 
    if (key == 't') { //toxic pollutants
            cE.field = true;
        } 
    if (key == 'u') { //urban sprawl
            cE.building = true;
        } 
    if (key == 'w') { //water level rise
            cE.lake = true;
        } 
    if (key == 'z') { //zones that are dead
            cE.deadz = true;
    }
}

//Creates elements in the landscape, and calls for changes to those elements
function drawLandscape() {
    makeClouds(); //creates clouds for carbon footprint and greenhouse gas, letters c and g
    changeSky(); //creates smog screen in background, letter s
    changeMtnHill(); //changes color of mountains and hills, letters h and i

    var landscapeScale1 = 0.004; //detail in hills
    var landscapeScale2 = 0.018; //detail in mountains

    //creates mountains in the background
    colorMode(HSB, 100);
    stroke(70, 30, colors.mtnb);
    strokeWeight(1);
    for (var x = 0; x < width; x ++) {
        var l = (x * landscapeScale2);
        var y = map(noise(l), 0, 1, height * 0.2, height * 0.5); //constrains hills
        line(x, y, x, height); //creates vertical lines, forming a solid shape
    }

    colorMode(RGB);
    makeBuilding(); //creates buildings when letter u is pressed

    //creates hills in the middleground
    colorMode(HSB, 100); //switches color mode to HSB to help with color changes
    stroke(25, 50, colors.hill);
    for (var x = 0; x < width; x ++) {
        var l = (x * landscapeScale1);
        var y = map(noise(l), 0, 1, height * 0.4, height * 0.6); //constrains hills
        line(x, y, x, height); //creates vertical lines, forming a solid shape
    }

    //creates field in foreground
    noStroke();
    fill(28, 100, colors.fieldb); //field color
    rect(0, height * 0.55, width, height * 0.35);
    changeField(); //changes color of field, letter t
    
    //creates lake
    fill(colors.lakeh, colors.lakes, colors.lakeb);
    ellipse(175, 286, lakeWidth, lakeHeight);
    changeLake(); //changes color and size of lake, letters a, w, and z

    colorMode(RGB); //switches color mode back to RGB
    makeFlowers(); //makes flowers, alternating colors, becomes one color with letter b
    makeHouse(); //makes houses, letter p
    makeTrees(); //makes single yellow tree in foreground, tree disappears with letter d 
    smokeScreen(); //creates a semi-transparent grey layer with letter j
}

//makes and moves the clouds
function makeClouds() {
    if (cE.clouds == true) { //makes a cloud for carbon footprint, letter c
        drawClouds(cloudX, 120, 150, 50, 150);
        cloudX = cloudX - 2;
        if (cloudX < win.ws - 150) {
            cloudX = 475;
        }
    }
    if (cE.gas == true) { //makes a cloud for greenhouse gases, letter g
        drawClouds(gasX, 180, 220, 75, 100);
        gasX = gasX - 1;
        if (gasX < win.ws - 220) {
            gasX = 475;
        }
    }
}

//draws the clouds
function drawClouds(locationX, locationY, width, height, color) {
    push();
    fill(color);
    translate(locationX, locationY);
    rect(0, - height, width, height, 50, 50, 50, 50);
    pop();
}

//adds "smog" in background
function changeSky() {
    if (cE.sky == true) {
        fill(80, colors.smogop);
        noStroke();
        rect(0, height * 0.55 - skyHeight, width, skyHeight);
        skyHeight = constrain(skyHeight, 0, 300) + 3;
    }
}

//changes colors of mountains and hills
function changeMtnHill() {
    if (cE.mtn == true) { //changes mountain colors
        colors.mtnb = constrain(colors.mtnb, 20, 70) - 5;
    }
    if (cE.hill == true) { //changes hill colors
        colors.hill = constrain(colors.hill, 30, 80) - 5;
    }
}

//makes the buildings for urban sprawl
function makeBuilding() {
    if (cE.building == true) { //from left to right
        drawBuildings(125, 37, 130, 180);
        drawBuildings(162, 62, 110, 150);
        drawBuildings(224, 50, 120, 200);
        drawBuildings(274, 37, 100, 130);
    }
}

//draws buildings
function drawBuildings(locationX, buildW, buildH, color) {
    push();
    noStroke();
    fill(color);
    translate(locationX, height * 0.58);
    rect(0, - buildH, buildW, buildH);
    //windows in buildings
    fill(255);
    for (var x = 0; x < (buildW / 6) - 1; x ++) {
        for (var y = 0; y < 200; y ++) {
            rect(2 + x * 6, - buildH + 4 + y * 8, 3, 4);
        }
    }
    pop();
}

//changes lake size and color
function changeLake() {
    if (cE.lake == true) { //makes larger for water level
        lakeWidth = constrain(lakeWidth, 200, 350) + 5;
    }
    if (cE.lakeColor == true) { // becomes green for algae
        colors.lakeh = constrain(colors.lakeh, 30, 55) - 0.75;
    }
    if (cE.deadz == true) { //becomes dark for dead zones
        colors.lakes = constrain(colors.lakes, 50, 100) + 5;
        colors.lakeb = constrain(colors.lakeb, 35, 100) - 5;
    }
}

//changes color of field
function changeField() { 
    if (cE.field == true) {
        colors.fieldb = constrain(colors.fieldb, 20, 60) - 2;
    }
}

//makes row of flowers at base of hills
function makeFlowers() {
    for (var i = 0; i < 20; i ++) {
        strokeWeight(2);
        for (var g = 0; g < 6; g ++) {
            if (i % 2) { //alternates colors of flowers to represent biodiversity
                stroke(colors.plnflw);
                push();
                translate(win.ws + i * 25, height * 0.55);
                rotate(g * 60);
                line(0, 0, 0, 3);
                pop();   
            } else {
                stroke(colors.flower);
                push();
                translate(win.ws + i * 25, height * 0.55);
                rotate(g * 60);
                line(0, 0, 0, 3);
                pop();   
            }
        }
    }
    if (cE.flowers == true) { //changes color of flowers to single color, removal of biodiversity
        colors.flower = colors.plnflw; 
    }
}

//makes houses for population growth
function makeHouse() {
    if (cE.house == true) {
        drawHouses(320, height * 0.58, '#FCAD77', '#E8762A', 0.9); //left
        drawHouses(375, height * 0.57,'#7BE0FF', '#1CB8E8', 0.8); //right
        drawHouses(350, height * 0.59,'#B09DCC', '#9274C1', 1.0); //middle
    }
}

//draws houses
function drawHouses(locationX, locationY, colorHouse, colorDoor, houseScale) {
    push();
    noStroke();
    fill(colorHouse);
    translate(locationX, locationY);
    scale(houseScale);
    rect(0, -20, 40, 20);
    fill('white');
    triangle(-5, -20, 45, -20, 20, -30);
    rect(24, -15, 10, 10);
    fill(colorDoor);
    rect(8, -15, 8, 15);
    pop();   
}

//makes tree in foreground of landscape
function makeTrees() {
    if (cE.trees == true) { //the tree disapears when key is pressed, as key switches variable to false
        push();
        rectMode(CENTER);
        translate(440, 110);
        noStroke();
        fill(249, 176, 30); //yellow of tree
        rect(0, 0, 130, 200, 40, 40, 40, 40);
        //tree branches
        strokeWeight(15);
        stroke(124, 20, 22);
        line(0, -50, 0, 225);
        strokeWeight(10); //thinner branches
        line(0, 80, 40, 40);
        line(0, 20, -40, -20);
        pop();
    }  
}

function smokeScreen() { //creates grey screen
    if (cE.jeopardy == true) {
        noStroke();
        jtranslu = constrain(jtranslu, 0, 80) + 15;
        fill(150, jtranslu);
        rect(win.ws, win.wt, 350, 300)
    }
}

//creates all aspects of the room - window, window frame, walls, table, poster, instructions
function drawRoom() { 
    rectMode(CORNER);
    noStroke();
    
    //walls of the room
    fill(colors.wall);
    rect(-win.dis, -win.dis, win.ws + win.dis, height + win.dis * 2);
    rect(width - win.ws, -win.dis, win.ws + win.dis, height + win.dis * 2);
    rect(0, height - win.wb, width, win.wb);
    rect(0, 0, width, win.wt);
    
    //gray "table" below window where alphabet and definitions appear
    fill(colors.table); //medium gray
    rect(0, height - 130, width, 130);

    //white lines that divide window
    stroke(255);
    strokeWeight(4);
    line(width / 2, win.wt - win.frm, width / 2, height - win.wb + win.frm);
    line(win.ws - win.frm, (height - win.wb) / 2 + win.wt / 2, width - win.ws + win.frm, (height - win.wb) / 2 + win.wt / 2);
    //white border around the window
    strokeWeight(10);
    line(win.ws - win.frm, win.wt - win.frm, win.ws - win.frm, height - win.wb + win.frm);
    line(width - win.ws + win.frm, win.wt - win.frm, width - win.ws + win.frm, height - win.wb + win.frm);
    line(win.ws - win.frm, win.wt - win.frm, width - win.ws + win.frm, win.wt - win.frm);
    line(win.ws - win.frm, height - win.wb + win.frm, width - win.ws + win.frm, height - win.wb + win.frm);

    drawPoster(); //draws the poster to the left of window
    drawInstructions(); //draws instructions on the gray "table"
}

function drawPoster() { //creates poster telling you to refresh
    push();
    noStroke();
    rectMode(CENTER);
    angleMode(DEGREES);
    textAlign(CENTER);
    fill(255);
    translate(60, 165);
    rotate(-3); //rotates poster slightly
    rect(0, 0, 75, 100);
    //pin at the top of the poster
    fill(colors.table); 
    ellipse(0, -40, 5, 5);
    //writing in gray telling you to refresh
    textSize(12);
    textLeading(15); //sets leading
    var poster = "Refresh\npage\nto\nrestart"; //puts each word on a new line
    text(poster, 0, -17);
    pop();
}

function drawInstructions() { //creates instructions
    textAlign(CENTER);
    noStroke();
    fill(255);
    var textLocation = 375;
    textSize(12);
    text("Press and hold down keys to see some ABCs of climate change", width / 2, textLocation);
}

//creates alphabet
function typedLetterAlphabet() {
    for (var i = 0; i < 26; i ++) {
        textAlign(CENTER);
        textSize(20);
        noStroke();
        var alphabetLocation = 400;
        var x = map(i, 0, alphabetLetters.length, 50, width - 30);
        if (keyCode === 65 + i) { //when key is down, letter turns grey
            fill(100);
            text(alphabetLetters[i], x, alphabetLocation);
        } else { //all letters green when not pressed
            fill(colors.type);
            text(alphabetLetters[i], x, alphabetLocation);
        } 
    }
}

//creates climate change info
function typedLetterInfo() {
    textAlign(CENTER);
    textSize(15);
    fill(255);
    for (var i = 0; i < 26; i ++) {
        if (keyCode === 65 + i) {
            text(letterInfo[i], width / 2, height - 45);  
        } 
    }   
}

//when key released, already pressed letters disapear
function keyReleased() { //replaces already clicked letters and their info with spaces in the respective arrays
    for (var i = 0; i < 26; i ++) {
        if (keyCode == 65 + i) {
            alphabetLetters.splice(i, 1, " ");
            letterInfo.splice(i, 1, " ");
        }       
    }
}

For this project, I initially wanted to use sound and the typing keyboard in order to create an instrument out of sounds related to the environmental crisis. However, I decided to instead pivot towards creating an interactive and visual display of some “ABCs” of climate change. When you type and hold down a key, a word that starts with that letter will appear, along with that word’s definition. For a little less than half of the letters in the alphabet, something related to the word will happen on the landscape that is visible outside of the window. I wanted to keep the interactions fairly simple, while still conveying some of the effects of climate change, global warming, and our actions as a society.

final project – ilona altman

For my final project, I really wanted to work with text and explore alternate ways of moving through a poem. I chose to focus on one of my favorite poets, pablo neruda, and chose his poem, Ode to Things, as it has a lot of beauty to it.

sketch

// ilona altman
// final project 
// section a 
// iea @ andrew.cmu.edu 
// this is a poem showcase of 

var odetothings;
let fromHere;
let toHere;
let thefont; //allegra sans from GoogleFont 
let poemletters = []; //array of letters 
let poem = "ode to things by neruda - "; // title of the poem
let reversedpoem = reverseString(poem); // reversed
let nextimageCount; //image counter 
let imagelinks= ['https://i.imgur.com/EiIMWxn.png', 
                'https://i.imgur.com/XCmsYws.png',
                'https://i.imgur.com/fQZf2Sc.png'];
let imagesofthings = []; // image array 
let currentThingImage; 


function preload() {
    //loading the text and the poem 
    odetothings = loadStrings("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/ode-2.txt");
    //thefont = loadFont('thefont.ttf'); (cannot figure out hot to upload font for WordPress)

    //loading the images
    for (l = 0; l < imagelinks.length; l++) {
        imagesofthings[l] = loadImage(imagelinks[l]);
        }
}


function setup() {
    createCanvas(450,640);
    //initializing variables 
    fromHere = 0;
    toHere = 14;
    nextimageCount = 0;
    nextimage = 0;

    //initial placement for letters in a circle 
    for (let i = 0; i < poem.length; i ++) {
        var radius = 120;
        var angle = i * TWO_PI/poem.length;
        var inputX = radius * sin(angle);
        var inputY = radius * cos(angle);
        var inputL = reversedpoem.charAt([i]);
        poemletters[i] = makeLetters(inputL, inputX, inputY);
    }
}

function draw() {
    background(255,255,255);

    //images rotating 
    push();
    imageMode(CENTER);
    rotate(frameCount/10000);
    currentThingImage = image(imagesofthings[nextimage],width/2,height/3);
    pop();
    //updating the position of the letters
    Update();
    // making sure that there is continuous text 
    if (toHere > odetothings.length){
        fromHere = 0;
        toHere = 14;
    }
    // the text on the bottom that runs through the poem
    for (var i = fromHere; i < toHere; i++) {
        textSize(14);
        //textFont(thefont);
        fill(150,190,150);
        var placeY  = 340 + (i%14) * 20
        text(odetothings[i], width/4, placeY);
    }



}

// reversing the string so the text is easier to read
function reverseString(str) {
    var splitting = str.split("");
    var reversing = splitting.reverse();
    var joined = reversing.join(""); 
    return joined;
}

// the object of each letter
function makeLetters(inputL, inputX, inputY) {
   var ltr =  {letter: inputL, 
            px: inputX, 
            py: inputY,
            showing: showLetters}; // draw the letter
    return ltr;
}

function showLetters() {
    push();
    translate(width/2, height/3.5);
    rotate(frameCount/1000);
    //textFont(thefont);
    textSize(30);
    textAlign(CENTER);
    fill(180,100,130);
    text(''+ this.letter, this.px, this.py);
    pop();
}

function Update() {
    for (var i = 0; i < poemletters.length; i++){
        poemletters[i].showing(); 
    }

}

// when the mouse is pressed, the text cycles through
function mouseClicked() {
    fromHere  =  fromHere + 14;
    toHere = toHere + 14;
    nextimageCount = nextimageCount + 1;
    nextimage = nextimageCount%3;

}





ode

Jacky Tian’s Final Project

For this final project, I created a “Catch & and Run” game. As a player, you need to use your mouse to control the position of a thief. Your goal is to collect coins in order to earn score.

Instructions:

  1. Use you mouse to control the position of the thief.
  2. Move the thief onto the coin in order to collect it and earn score.
  3. After the coin is collected, the next one will spawn randomly elsewhere.
  4. Avoid the cops when moving towards the coins, if you get caught, it’s GG.
  5. Good luck and have fun!

sketch

//Final Project
//Yinjie Tian
//yinjiet@andrew.cmu.edu
//Section D

var theif;
var cop;
var copX = [];
var copY = [];
var dx = [];
var dy = [];
var coinX = 300;
var coinY = 300;
var coin;
var count = 0;
var carX;
var carX2;
var carY;
var carY2;
var carSpeed;
var showText = false;

function preload(){
  thief = loadImage("https://i.imgur.com/lcp6pIM.png");
  cop = loadImage("https://i.imgur.com/ndxH6Uh.png");
  coin = loadImage("https://i.imgur.com/fKFvpra.png");

}

function setup(){
 	createCanvas(600, 480);
 	imageMode(CENTER);
//creating two cars moving in opposite direction
 	carX = 200;
 	carX2 = 350;
 	carY = 0;
 	carY2 = height - 60;
 	carSpeed = random(1,5);
// Randomly select cops' starting location and speed
  for (var i = 1; i < 15; i++) { 
    copX[i] = random(30, width - 30);
    copY[i] = random(40, height - 40);
    dx[i] = random(-2, 5);
    dy[i] = random(-2, 5);
  }
}

function draw(){
	background("grey");
//street background
	fill("white");
	noStroke();
	rect(0,0,100,150);
	rect(0,330,100,150);
	rect(500,0,100,150);
	rect(500,330,100,150)
//crosswalks
	rect(110, 50, 20, 100);
	rect(150, 50, 20, 100);
	rect(190, 50, 20, 100);
	rect(230, 50, 20, 100);
	rect(270, 50, 20, 100);
	rect(310, 50, 20, 100);
	rect(350, 50, 20, 100);
	rect(390, 50, 20, 100);
	rect(430, 50, 20, 100);
	rect(470, 50, 20, 100);
	
	rect(110, 330, 20, 100);
	rect(150, 330, 20, 100);
	rect(190, 330, 20, 100);
	rect(230, 330, 20, 100);
	rect(270, 330, 20, 100);
	rect(310, 330, 20, 100);
	rect(350, 330, 20, 100);
	rect(390, 330, 20, 100);
	rect(430, 330, 20, 100);
	rect(470, 330, 20, 100);

//cars moving
	fill("red");
	rect(carX, carY, 40, 60);
	carY += carSpeed;
	if(carY > height){
		carY = -60;
	}
	fill("blue");
	rect(carX2, carY2, 40, 60);
	carY2 -= carSpeed;
	if(carY2 < -60){
		carY2 = height;
	}
// Make the cops move randomly in the canvas
 	for (var i = 1; i < 8 ; i ++){
  	image(cop, copX[i], copY[i]);
  
    copX[i] += dx[i];
    copY[i] += dy[i];

// bounce back if cops hit boundary
    if (copX[i] + 30 > width || copX[i] - 30 < 0){
      dx[i] =- dx[i];
      }
    if (copY[i] + 40 > height || copY[i] - 40 < 0){
      dy[i] =- dy[i];
      }
// if theif got caught
	 if (copX[i] > mouseX - 15  & copX[i] < mouseX + 15){
     	if (copY[i] > mouseY - 20 && copY[i] < mouseY + 20){
     		endGame();
      }      
    }
// if theif got hit by car1
	 if (carX > mouseX - 15  & copX < mouseX + 15){
     	if (carY > mouseY - 20 && carY < mouseY + 20){
     		endGame();
      }      
    }
// if theif got hit by car2
if (carX2 > mouseX - 15  & carX2 < mouseX + 15){
     	if (carY2 > mouseY - 20 && carY2 < mouseY + 20){
     		endGame();
      }      
    }
  }
   
// create theif
	image(thief, mouseX, mouseY);
	
// randomly placing coin 
	image(coin, coinX, coinY);

// scoreboard
	textSize(20);
	fill("white");	
  	text("SCORE: " + str(count), 260, 30);

// if theif gets the coin  	
	if (coinStolen()){
		coinPlace();			
  		count +=10;
	}
}

function coinPlace(){
	coinX = random(30, width - 30);
	coinY = random(30, height - 30);
}

function coinStolen(){
	var d = dist(mouseX, mouseY, coinX, coinY);
	if(d < 20){
		return true;
	}
	else {
		return false;
	}
}


function endGame(){	
	showText = true;
	fill("pink");
	textSize(50);
	textStyle(BOLD);
  	textFont('New Roman');
	text("GGWP! Please Refresh", 50, height/2);
	noLoop();
}

Danny Cho – Final Project – Shooting Stars

sketch

var renderer;
var starSize = 10;
var stars = [];
var launchSpeed = 40;
var starDuration = 1000;
var starLimit = 10;
var starGrowth = .5;
var starMoveFade = 20;
var persX = 30;
var persY = 30;
var timerMultiplier = 0.2;

var particles = [];
var particleSize = 5;
var particleSpeed = 2;
var limitZ = -7500;
var starWiggle = 4;


var bgStars = [];
var bgStarNumber = 100;

function setup() {
    renderer = createCanvas(windowWidth, windowHeight, WEBGL);
    for (var i = 0; i < 100; i++) {
        bgStars.push(makeBackgroundStars());
        bgStars[i].x = random(-15000, 16000);
    }
    frameRate = 60;
}

function draw() {
    background(0);
    fill(255);
    translate(-width / 2, -height / 2, 0);
    noCursor();
    ellipse(mouseX, mouseY, 25);
    //drawing background stars
    if (bgStars.length < bgStarNumber) {
        bgStars.push(makeBackgroundStars());
    }
    for (var i = 0; i < bgStars.length; i++) {
        bgStars[i].draw();
        bgStars[i].move();
        if (bgStars[i].x < -15000) {
            bgStars.splice(i,1);
        }
    }

    //drawing particles
    if (mouseIsPressed) {
        particles.push(makeParticle());
        for (var i = 0; i < particles.length; i++) {
            particles[i].draw();
            particles[i].move();
            particles[i].remove();
            if (particles[i].opq == 0){
                particles.splice(i,1);
            }
        }
    }
    //drawing stars
    for (var i = 0; i < stars.length; i++) {
        stars[i].draw();
        stars[i].count();
        stars[i].move();
        if (stars[i].timer > starDuration) {
            stars.shift();
        }  
        if (stars[i].x < -15000) {
            stars.splice(i,1);
        }
    }
    //removeStars
    if (stars.length > starLimit) {
        stars.shift();
    }
}

//when the mouse is pressed, it starts creating a star
function mousePressed() {
    stars.push(makeStar());
}

//as soon as the stars are done being created, they are not the newest
function mouseReleased() {
    for (var j = 0; j < stars.length; j++) {
        stars[j].newest = false;
    }
    particles = [];
}

function makeStar() {
    var star = {x: mouseX, y: mouseY, z: 0,
                size: starSize, newest: true,
                perspectiveX: width/2 - mouseX,
                perspectiveY: height/2 - mouseY,
                // evolve: evolveStar, 
                count: countTimeStar, timer: 0,
                flashX: mouseX, flashY: mouseY, flashZ: -1000,
                draw: drawStar, move: moveStar, sizeDown: 20}
    return star;
}

//drawing the star
//controls the growth of the star
function drawStar() {
    // translate(this.x, this.y, this.z);
    push();
    translate(this.x, this.y, this.z);
    strokeWeight(0);
    stroke(200);
    //radiance shown by multiple circle
    for (var i = 0; i < 3; i++) {
        fill(255, 255, 255, 40);
        sphere(this.size * (1 + (i / 2)), 15, 15);
    }
    pop();
    if (mouseIsPressed & this.newest == true) {
        this.size += starGrowth;
    }
    if (mouseReleased) {
        strokeWeight(0);
        push();
        translate(this.flashX, this.flashY, 0);
        fill(255, 255, 255, 100 - 5 * (this.timer))
        sphere(this.size * ((this.timer) ^ 2 / 10));
        // sphere((this.size * ((this.timer)/10))/2 * 10);
        pop();
    }
}

//controls the movement of the star
function moveStar() {
    //if it has been released, 
    if (this.newest == false) {
        if (this.z <= limitZ) {
            this.y += starWiggle * sin(millis()/300);
           
            this.x -= starMoveFade;
                while (this.sizeDown > 1) {
        this.size = this.size * .99;
        this.sizeDown -= 1;
        print("hi")
    }
        }
        else if (this.z > limitZ) {
            this.z -= launchSpeed * this.timer * .25;
            this.x -= this.perspectiveX / persX * (this.timer * timerMultiplier);
            this.y -= this.perspectiveY / persY * (this.timer * timerMultiplier);
        }
        else {this.y -= launchSpeed * (this.timer * .05);    
        }
    }
}

function countTimeStar() { //works!
    if (frameCount % 2 == 0 & this.newest == false) {
        this.timer++;
    }
}

//creating particles that will gather towards the touch point
function makeParticle() {
    var particle = {OriginX: mouseX, OriginY: mouseY, OriginZ: 0,
                    awayX: mouseX - random(-500, 500),
                    awayY: mouseY - random(-500, 500),
                    awayZ: 0 + random(-200, 200), opq: 20,
                    move: moveParticle, count: countTimeParticle,
                    draw: drawParticle, remove: removeParticle,
                    timer: 0}
    return particle;
}

function drawParticle() {
    
    push();
    translate(this.awayX, this.awayY, this.awayZ);
    fill(255, 255, 255, this.opq);
    sphere(particleSize);
    sphere(particleSize / 2);
    pop();
}

function removeParticle() {
    if (dist(this.OriginX, this.OriginY, this.OriginZ,
        this.awayX, this.awayY, this.awayZ) <= 50) {
        this.opq = 0;
    }
}

function moveParticle() {
    var distX = this.OriginX - this.awayX;
    var distY = this.OriginY - this.awayY;
    var distZ = this.OriginZ - this.awayZ;
    this.awayX += distX * .03;
    this.awayY += distY * .03;
    this.awayZ += distZ * .03;
    this.opq += 50 / dist(this.OriginX, this.OriginY, this.OriginZ,
                            this.awayX, this.awayY, this.awayZ);
}

function countTimeParticle() {
    if (frameCount % 2 == 0 & this.newest == false) {
        this.timer++;
    }
}

function makeBackgroundStars() {
    var bgStar = {x: 14000, y: random(-5000, 5000), z: limitZ,
                    move: moveBackgroundStars, draw: drawBackgroundStars,
                    size: random(20, 60), fluctuate: random(400, 800)}
    return bgStar;
}

function moveBackgroundStars() {
    this.x -= starMoveFade;
    this.y += 2 * sin(millis() / this.fluctuate);
}

function drawBackgroundStars() {
    push();
    translate(this.x, this.y, this.z);
    noStroke();
    sphere(this.size);
    fill(255, 255, 255, 30 * (sin(millis() / this.fluctuate) / 2));
    sphere(2 * this.size);
    pop();
}

I created an interactive star generator as a simulation for the design project, “Tesla’s Sunlit Night”. The concept is that people entering this brand pop-up shop will be able to interactive the inner walls the way this visualization allows the audience to. The only major difference in the interaction would be the clicks translated as touches.

It is meant to emphasize through experience what Tesla’s solar energy products can do. The reason this pop up is called, “Sunlit Night” is because the experience of creating stars in the dark ceiling , representing the night sky will be powered by the solar energy.

To interact, just click anywhere on the screen. The longer you hold, it will increase in size. I wanted to push further in the growth of star and how each differ in their appearance, but it was computationally too expensive, and could not be realized.

Zee Salman- Final

Directions:

Use your mouse you glide the paddle to save the ball from dropping.

colorful cubes will be dropping at the consistent timed rate, make sure to hit the brick with the ball to increase count.

When you hit the ball, you get one point count.

For a challenge, click on the screen to add more balls, but you must balance all to save the game.

Im pretty happy with how this turned out, I definetly used almost everything I knew or saw in the course. It was really fun to make a remix of brick breaker and I learned even more along the way. I was definetly fun to recreate my child hood game.

 

sketch

//Zee Salman
//SECTION E

var gravity = 0.3;   // downward force
var springy = 0.2; // velocity 
var drag = 0.0001;    // drag 
var np = 1;      // how many particles
var fp= 1;
var particles = [];
var endgame = false;
var timerValue = 3;
var startButton;
var numberBalls = 0;
var x;
var y;
var count = 0;

var block = {
    x: 200,
    y: -25,
    w: 30,
    h: 30,
    color: "blue",
}



function particleStep() {
    this.x += this.dx;
    this.y += this.dy;
    if (this.y >= height) { // bounce off bottom
        endgame = true;
    }
    if (this.x > width) { // bounce off right wall
        this.dx = -this.dx * springy;

    } else if (this.x < 0) { // bounce off left wall
        this.dx = -this.dx * springy;

    } else if (this.y < 0) { // bounce off top
        this.y = -this.y;
        this.dy = -this.dy * springy;
    } 

}

function particleDraw() {
  //draws the ball
	fill(this.colorR, this.colorG, this.colorB);
    ellipse(this.x, this.y, this.size, this.size);
}


// create a ball object 
function makeParticle(px, py, pdx, pdy) {
    p = {x: px, y: py,
         dx: pdx, dy: pdy,
         step: particleStep,
         draw: particleDraw,
         size: 20,
         colorR: randomColor(),
         colorG: randomColor(),
         colorB: randomColor(),
        
        }
    return p;
}

//randone color for each ball
function randomColor(){
	return (random(0,255));
}

function hitBlock(ball, block) {
  //ball characteristics
        const ballLeft = ball.x - ball.size/2;
        const ballRight = ball.x + ball.size/2;
        const ballTop = ball.y - ball.size/2;
        const ballBottom = ball.y + ball.size/2;
//block characteristics
        const blockLeft = block.x - block.w / 2;
        const blockRight = block.x + block.w / 2;
        const blockTop = block.y - block.h / 2;
        const blockBottom = block.y + block.h / 2;
//check for collision
        if (
            ballRight >= blockLeft &
            ballLeft <= blockRight &&
            ballBottom >= blockTop &&
            ballTop <= blockBottom

        ) {
           
            if (ballRight >= blockLeft && ballLeft <= blockLeft) {
            
                return true;
            } else if (ballLeft <= blockRight & ballRight >= blockRight) {
               
                return true;
            } else if (ballBottom >= blockTop & ballTop <= blockTop) {
                return true;
            } else if (ballTop <= blockBottom & ballBottom >= blockBottom) {
               
                return true;
            }

        }

        return false;
      }
function collide() {
    for (let i = 0; i < particles.length; i++) {
    //if the ball hits the brick, irt disappears
      if(hitBlock(particles[i], block)){
        count +=1;
        block.y = -300;
        block.color = randomColor();
      }
     
    }


  }



function setup() {
    createCanvas(600, 400);
    for (var i = 0; i < np; i++) {
        // make a particle
        var p = makeParticle(80, 20, 7,7);       
        // push the particle onto particles array
        particles.push(p);
  
    }
    setInterval(timeIt, 1000);

}


function draw() {
    //console.log(count);
    background("pink");

    
    //drawing the board
    stroke(0);
    fill('black');
    rectMode(CENTER);
    rect(mouseX,(11*height/12)+10,100, 10);
        
    //if the game is not over...
    if (endgame == false){
        //console.log("Working draw func");
        collide();
        fill(block.color);
        noStroke();
        rectMode(CENTER);
        rect(block.x, block.y, block.w, block.h);
        if (block.y >= (11*height/12)) {
          endgame = true;
                }
    // draw all particles in the particles array
        for (var i = 0; i < particles.length; i++) { // for each particle
            var p = particles[i];
            p.step();
            p.draw();
          //if the ball touches the board, 
          //it bounces at a slighlty different angle everytime
       		if (near(p.x,p.y,p.size)){
       		 	p.dx = -p.dx + (PI/3);
       		 	p.dy = -p.dy;
                springy = 1.01;
                push();
                translate(width,height);
                rotate(PI/3);
                p.draw();
                p.step();
                pop();
                if((block.y >= height)){
                  endgame = true;
                }
    		}
        }   
        //timer to display when the next ball is going to disperse
            fill("black");
            textStyle(BOLD);
            text("Count: " + count, width / 2.3, height / 3);
            textStyle(NORMAL);
            if (timerValue >= 10) {
              fill(0);
              textSize(20);
              text("0:" + timerValue, width / 2, height / 2);
            }
            if (timerValue < 10) {
              fill(0);
              textSize(20);
              text('0:0' + timerValue, width / 2, height / 2);
            }
            if (timerValue == 0) {
              if(block.y < 0){
                block.y = random(20, 350);
                block.x = random(20, 350);  
              }else{
                block.y +=20;
                fill(0);
                textSize(20);
                timerValue = 3;  
              }
              
            //}
            }
        //if the game is over...
        }else if (endgame == true){
                count = 0;
                // transperent background
                fill(0,0,0,100);
                rect(0,0,width*2, height*2);

                //Game Over display
                fill(0);
                rect(width/2, height/2, 200, 70);
                fill(255);
                textSize(32);
                text("Game Over!", width / 2.8, height / 1.9);

                //Restart button w/ a hover effect
                fill(255);
                noStroke();
                rect(width/2, height/1.5, 100, 50);
                fill(0);
                textSize(20);
                text("Restart", width / 2.25, height / 1.47);

                if ((mouseX > (width/2)-50) & (mouseY < (height/1.5)+25) &&
                 (mouseX < (width/2)+50 && (mouseY > (height/1.5) - 25))) {
                    fill("green");
                    rect(width/2, height/1.5, 100, 50);
                    rect(width/2, height/1.5, 100, 50);
                    fill(255);
                    textSize(20);
                    text("Restart", width / 2.25, height / 1.47);


            }
            
                }

    }


function timeIt() {
  //timer
  if (timerValue > 0) {
    timerValue--;
  }
}
function mouseClicked() {
    //for users that want a challenge, click.
    var newp = makeParticle(mouseX, mouseY,
                                random(4, 6), random(4, 6));
        particles.push(newp);
    if(endgame == true) {
    //if restart button clicked, reset game 
        if (mouseX > 250 & mouseX < 550 && mouseY < 291 &
                 mouseY > 241) {
            endgame = false;
            particles = [];
            var p = makeParticle(80, 20, 7,7);
            particles.push(p);
            timerValue = 3;
            block.y = -25;

        }
    }
}


function near(x,y,size) {
//constant testing to see if the ball is touching the board
      if ((block.y + block.h) >= (11*height/12)) {
        //count +=1;
        block.x = random(20,300);
        block.y = -25;
      }

    	if((y + size/2) >= (11*height/12) &
       (x >= mouseX-50 && x <= mouseX + 100)) {

    		return true;

    	}
    	else{
    		return false;

    	}

    }






Shannon Ha – Final Project

sketch

//Shannon Ha
//sha2@andrew.cmu.edu
//Section D
// Final Project
var soundLogos = [];
var amplitude; //initialize amplitude
var level; //initialize amp level
var rotatePath = 0;
var h;
var dY; // dot x position
var dX; // dot y position

function preload(){ //load sounds
    soundLogos[1] = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Apple-1-2.wav');
    soundLogos[2] = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Apple-2-text-2.wav');
    soundLogos[4] = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Intel-p2.wav');
    soundLogos[5] = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Microsoft-2-1.wav');
    soundLogos[6] = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Microsoft-3-1.wav');
    soundLogos[7] = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Netflix-1.wav')
    soundLogos[8] = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Nokia-1.wav');
    soundLogos[9] = loadSound('https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/Skype-1.wav');
}

function setup() {
  createCanvas(300, 300);
  amplitude = new p5.Amplitude(); // p5.js sound library for amplitude
}

function draw() {
  background(0);
  push();
  translate(width / 2, height / 2); // centers the epicycloid
  drawEpicy();
  pop();
  drawThreeDots();
  drawIntelEllipse();
  drawMicroGrid()
}

function keyPressed(){ // assigns the number keys to respective sound files and animations.
    if (key == '1'){
        soundLogos[1].play();
        drawEpicy();

    } else if (key == '2'){
        soundLogos[2].play();
        dY = height / 2; // makes starting position of dot center of canvas
        dX = width / 2; // makes starting position of dot center of canvas
        drawThreeDots();

    } else if (key == '3'){
        soundLogos[4].play();
        drawIntelEllipse();

    } else if (key == '4'){
        soundLogos[5].play();
        drawMicroGrid();

    } else if (key == '5'){
        soundLogos[6].play();

    } else if (key == '6'){
        soundLogos[7].play();

    } else if (key == '7'){
        soundLogos[8].play();

    } else if (key == '8'){
        soundLogos[9].play();
        }
    }

//animation for apple
function drawEpicy() {
    var a = 60; // variable that controls the size and curvature of shape
    var b = a / 2; // variable that controls the size and curvature of shape
    level = amplitude.getLevel(); //takes the value of measured amp level.
    h = map(level, 0, 3, 20, 900); // maps amplitude to appropriate value
    var ph = h / 2; // links mapped amp value as a variable that controls shape.
    fill(h * 5, h * 10, 200); //fills color according to measured amp.
    noStroke();
    beginShape();
  for (var i = 0; i < 100; i ++) { // for loop to draw vertex for epicycloid
      var t = map(i, 0, 100, 0, TWO_PI); // radian value.
      x = (a + b) * cos(t) - h * cos(ph + t * (a + b) / b);
      y = (a + b) * sin(t) - h * sin(ph + t * (a + b) / b);
        vertex(x, y); //curve line
         }
  endShape();
}

//animation for text
function drawThreeDots(){ //draws the three dots that fall
    fill(255);
    noStroke();
    print(h);
    ellipse(dX - 50, dY, 25, 25);
    ellipse(dX, dY * 1.2, 25, 25);
    ellipse(dX + 50, dY * 1.5, 25, 25);
    dY += 10; // vertical falling
}

function drawIntelEllipse(){
    level = amplitude.getLevel();
    let h = map(level, 1, 8, 5, 50);
    for (var i = 0; i < 15 ; i++){
  		var diam = rotatePath - 30 * i; // creates the spin out effect of the ellipse

      if (diam > 0){ //pushes each new ellipse to show
        noFill();
  		stroke(0, 113, 197); //intel blue
        strokeWeight(2);
        ellipseMode(CENTER)
        push();
        translate(width/8 - 90, height/4 - 10); //position of starting ellipse
        rotate(cos(2.0));// rotation angle
        ellipse(200, 200, diam / h, 40 / h); // the size of the ellipse is affected by amp.
      }
    }
    rotatePath = rotatePath + 2; // controls the speed of the spin out effect.
  }

function drawMicroGrid(){ // suppose to imitate the microsoft grid
    level = amplitude.getLevel();
    let h = map(level, 1, 8, 20, 200);
    noStroke();
    rectMode(CENTER);
    for (var y = 50; y < height + 50; y += 100) { // nested for loop for tiling
       for (var x = 50; x < width + 50; x += 100) {
           fill(x, y + 100, h * 5); // color is affected by amp
           rect(x , y, h * 3, h * 3); // size is affected by amp
       }
   }
}

How does it work:

Press all the number keys from 1 to 8 and watch the patterns move and change to familiar sound logos!

(For some reason there are problems when Safari is used to view my project so please use Chrome or Firefox!)

In my proposal, I wanted to do some sort of sound visualization either in a form of a game or something similar to patatap. Sticking to my proposal, I used some iconic sounds that can be recognized through our day to day usage of technology. I realized how easy it is to overlook the importance of how these sounds inform our usage of technology so I ended up creating a sonic art piece that creates patterns according to the amplitude measured through the sound files.

My final project does not quite achieve the level of fidelity I originally intended my sonic art to have as the visuals are a bit too noisy and I want it to have a simple yet sophisticated look. I spent quite a bit of time trying to figure out how to use sound libraries in p5.js and mapping the amplitude to each of the various patterns, so I had a bit of difficulty debugging the whole code.

Margot Gersing – Final Project

The goal of my final project was to create some interactive project that is simple but playful. When working on this project I took it very incrementally, building on the previous versions and trying to add more elements or making the previous ones better. As I worked my way through the code, I got more comfortable and became more efficient with the way I wrote it. I enjoyed working this way because I found it a lot less intimidating. I really enjoyed making this project. I think if I wanted to I could continue to add on to this. I think a logical next step could be incorporating sound.

Note: I made the canvas size larger then what wordpress can handle because I liked the look of it being a larger area. Below is a zip file of the full size files. The one on wordpress is basically the same just with a few composition adjustments.

Instructions: just use the mouse to play around with the scene. Type into the input bar and hit enter to change the type displayed on the screen.

sketch

//Margot Gersing - Final project - mgersing@andrew.cmu.edu - Section E

//for blob shapes
//object one
var xOne;
var yOne;
var dOne;
var opaCityOne = 120;
var overOne = false;
//object two
var xTwo;
var yTwo;
var dTwo;
var opaCityTwo = 120;
var overTwo = false;
//object three
var xThree;
var yThree;
var dThree;
var opaCityThree = 110;
var overThree = false;
//object four
var xFour;
var yFour;
var dFour;
var opCityFour = 110;
var overFour = false;
//object five
var xFive;
var yFive;
var dFive;
var opCityFive = 110;
var overFive = false;

//snake -- code refrenced and modified from p5js examples
//https://p5js.org/examples/interaction-follow-3.html --- link to code refrenced
var snakeX = []; //arrays for snake
var snakeY = [];
var snakeJoint = 10; //amount of joints
var snakeLength = 10; //length between

for (let i = 0; i < snakeJoint; i++) { //loading the joints and lenght into to x and y arrays
  snakeX[i] = 0;
  snakeY[i] = 0;
}

//for "pong" letters on screen
var letterString = "hello!"; //starting string
var playArray = []; //store the objects (letters and their movements)
var d = [-1, 1]; //direction of array
var input; //for typing

function setup() {
  createCanvas(800, 600);
  noStroke();
  //for type
  textFont("Courier New"); //type style
  textSize(60); //typesize
  //for input bar 
  input = createInput(); //create the bar to type into
  input.position(50, 20);
  //for bouncing type, put string into array
  for(var i = 0; i < letterString.length; i++){ //load array with objects
    var x = map(i, 0, letterString.length, 100, width - 100); //map letters to begin
    var vvx = random(1, 5) * d[round(random(0, 1))]; //random velocity in x direction
    var vvy = random(1, 5) * d[round(random(0, 1))]; //random velocity in y direction
    playArray[i] = createLetter(x, width/2, letterString.charAt(i), vvx, vvy) //call object
  }
}

function draw() {
  background(250, 120, 110);
  //call blob shapes
  thingOne(); 
  thingTwo();  
  thingThree();
  thingFour();
  thingFive();
  //for snake
  stroke(87, 156, 128);
  strokeWeight(10);
  dragSnake(0, mouseX, mouseY); //make snake move with mouse
  for (let i = 0; i < snakeX.length - 1; i++) { //create the moevment quality for the snake
    dragSnake(i + 1, snakeX[i], snakeY[i]);
  }
  //get the letters to move around
  noStroke();
  fill("black");
  for(var i = 0; i < playArray.length; i++){ 
    var t = playArray[i]; 
    if(dist(mouseX, mouseY, t.x, t.y) < 30){ //when mouse hovers over letter
       t.vx = random(1, 5) * d[round(random(0, 1))]; //get new random velocity x
       t.vy = random(1, 5) * d[round(random(0, 1))]; //get new random velocity x
       }
    if(t.x > width -30 || t.x < 30 || t.y > height - 30 || t.y < 30){ //when the letters hit the walls
       t.vx = -t.vx; //reverse the direction  
       t.vy = -t.vy;
    }
    t.x = t.x + t.vx; //update the location of the letters
    t.y = t.y + t.vy;
    text(t.letter, t.x, t.y); //display it
  }
}

function thingOne(){
  //activation circle
  xOne = 25; //location
  yOne = 100;
  dOne = 600; //diameter
  // Test if the cursor is over the box
  if(dist(mouseX, mouseY, xOne, yOne) < dOne / 2){ //if the mouse is over the activation ellipse -- var over one is true
    overOne = true;
    if (overOne == true) { //if true, then change value of opacity which chnages fill color of blob  
      opaCityOne = 200;
      fill(250, opaCityOne, 110); //changing the fill
    }
  } else { //other wise go back to orignal color
    if (opaCityOne >= 120) opaCityOne = opaCityOne - 3; //fades out 
    fill(250, opaCityOne, 110);
    overOne = false;
  }
  drawOne();
}

function drawOne(){ //location and shape of blob in top left
  noStroke();
  ellipse(25, 100, 620, 700);
  ellipse(50, 300, 450, 320);
}

function thingTwo(){ //same as function thingOne but for bottom right blob
  xTwo = 650;
  yTwo = 600;
  dTwo = 500;
  // Test if the cursor is over the box
  if(dist(mouseX, mouseY, xTwo, yTwo) < dTwo / 2){
    overTwo = true;
    if (overTwo == true) { 
      opaCityTwo = 200; 
      fill(250, opaCityTwo, 110);
    }
  } else {
    if (opaCityTwo >= 120) opaCityTwo = opaCityTwo - 5;
    fill(250, opaCityTwo, 110);
    overTwo = false;
  }
  drawTwo();
}

function drawTwo(){ //location and shape of blob in bottom right
  noStroke();
  ellipse(650, 600, 600, 500);
  ellipse(800, 450, 400, 400);
}

function thingThree(){ //same as function thingOne but for top right blob
  xThree = 700;
  yThree = -20;
  dThree = 500;
  // Test if the cursor is over the box
  if(dist(mouseX, mouseY, xThree, yThree) < dThree / 2){
    overThree = true;
    if (overThree == true) { 
      opaCityThree = 255; 
      fill(250, 120, opaCityThree);
    }
  } else {
    if (opaCityThree >= 110) opaCityThree = opaCityThree - 3;
    fill(250, 120, opaCityThree);
    overThree = false;
  }
  drawThree();
}

function drawThree(){ //location and shape of blob in top right
  noStroke();
  ellipse(700, -20, 550, 300);
}

function thingFour(){ //same as function thingOne but for center blob
  xFour = 475;
  yFour = 225;
  dFour = 200;
  // Test if the cursor is over the box
  if(dist(mouseX, mouseY, xFour, yFour) < dFour / 2){
    overFour = true;
    if (overFour == true) {
      opCityFour = 255;  
      fill(250, 120, opCityFour);
    }
  } else {
    if (opCityFour >= 110) opCityFour = opCityFour - 3;
    fill(250, 120, opCityFour);
    overFour = false;
  }
  drawFour();
}

function drawFour(){ //location and shape of blob in center
  noStroke();
  ellipse(475, 225, 225, 200);
}

function thingFive(){ //same as function thingOne but for bottom left
  xFive = 150;
  yFive = 600;
  dFive = 200;
  // Test if the cursor is over the box
  if(dist(mouseX, mouseY, xFive, yFive) < dFive / 2){
    overFive = true;
    if (overFive == true) {
      opCityFive = 255;  
      fill(250, 120, opCityFive);
    }
  } else {
    if (opCityFive >= 110) opCityFive = opCityFive - 3;
    fill(250, 120, opCityFive);
    overFive = false;
  }
  drawFive();
}

function drawFive(){ //location and shape of blob in bottom left
  noStroke();
  ellipse(150, 600, 225, 200);
}

function dragSnake(i, xin, yin) { // for snake
  const dx = xin - snakeX[i];
  const dy = yin - snakeY[i];
  const angle = atan2(dy, dx);
  snakeX[i] = xin - cos(angle) * snakeLength;
  snakeY[i] = yin - sin(angle) * snakeLength;
  joint(snakeX[i], snakeY[i], angle);
}

function joint(x, y, a) { //for snake
  push();
  translate(x, y);
  rotate(a);
  line(0, 0, snakeLength, 0);
  pop();
}

function createLetter(x, y, letter, vx, vy){ //object for each letter from the array, with loction, velocity
  return{x: x, y: y, letter: letter, vx: vx, vy: vy}
}

function keyPressed(){ //when hit enter key call word function
  if(keyCode == ENTER) word();
}

function word() { //for changing the letters on the screen
  playArray = []; //empty array that holds letters from string
  letterString = input.value(); //make the value of the input the new string (what you type)
  //print(input.value());
  //reload the newstring into the array
  for(var i = 0; i < letterString.length; i++){ //load array with objects
    var x = map(i, 0, letterString.length, 100, width - 100); //map letters to begin
    var vvx = random(1, 5) * d[round(random(0, 1))]; //random velocity 
    var vvy = random(1, 5) * d[round(random(0, 1))];
    playArray[i] = createLetter(x, width/2, letterString.charAt(i), vvx, vvy) //call object
  }
}