ammar hassonjee and lee chu – final project

sketch

// Ammar Hassonjee | lee chu
// section c
// ahassonj@andrew.cmu.edu | lrchu@andrew.cmu.edu
// final project


var mode = 0; // variable for cycling through frames

// variables for the beachBall ball scene
// choosing an initial point to launch the ball from
var ballx = 240;
var bally = 100;
var dir1 = 1; // direction of ball
var dir2 = 1; // direction of ball
var speedx = 1; // speed of the ball
var speedy = 0.5;
var size = 100; // size of the ball

// variables for rain scene
var raindrops = []; // array to store rain objects
var rainSpeed = 5; // tracking the speed of the rain
var increment = 0.01; //incrementing the rain values
var tone = 255; // the color of the lightning
var strweight = 30; // stroke weight of the lightning bolt
var cloudNumber; //
var cloudwidth;
var cloudheight;
var frame = 8; // keeping track of the frame count

var myCaptureDevice;
var px = [];
var py = [];
var theColorAtPxPy;
var theBrightnessOfTheColorAtPxPy;
var brightnessThreshold;
var darknessThreshold = 10;

// variables for determining silhouette
var borderX = [];
var borderY = [];
// variables for particles
var parties = [];
var ex = 20;
var why = 20;


function setup() {
    createCanvas(480, 360);
    myCaptureDevice = createCapture(VIDEO);
    myCaptureDevice.size(480, 360); // attempt to size the camera. 
    myCaptureDevice.hide(); // this hides an unnecessary extra view.


    // three variables declared to initialize the lighting function
    var xi = random(40, 440);
    var xii = random(30, 450);
    var xiii = random(20, 460);

    //bImage.resize(480, 360);
}


function isColor(c) {
    return (c instanceof Array);
}


//--------------------------------------------------------------------
function draw() {
    background(220);
    myCaptureDevice.loadPixels();

    image(myCaptureDevice, 0, -0, width, height);  // draw the camera at 1:1 resolution

    // ammar's code
    if (mode === 0) {
        initialScene();
    }
    if (mode === 1) {
        // varying the clouds for each time the rain scene is called
        // done before rainFall is called to ensure this code doesn't loop again
        cloudNumber = random(3, 8);
        cloudwidth = random(105, 140);
        cloudheight = random(60, 95);
        //calling the beach ball scene
        ballSlap();
    }
    if (mode === 2) {
        rainFall();
    }

    // lee's code
    findBorder(); // finding silhouette of person
    if (mode === 3) {
    	// particle effects
    	addParti();
	    updateAndDisplayParti();
	    removeParti();
    }
    if (mode === 4) {
    	// censoring effect
    	censor();
    }
}


function mousePressed() {
    mode = (mode + 1) % 5; // code to swtich between modes
}


//-------AMMAR'S CODE----------------------------------------------------------------------
// NOTE: the code works best if users are wearing dark clothing against a light background
function initialScene() { // initial scene for webcam text
    textAlign(CENTER, CENTER);
    textSize(15);
    fill(100);
    text("WELCOME TO AMMAR AND LEE'S WEBCAM MACHINE", width / 2, height / 2);
    text("Press the mouse to cycle between scenes", width / 2, height * .8);
    text("Press 'O' to increase darkness threshold", width / 2, height * .85);
    text("Press 'P' to decrease darkness threshold", width / 2, height * .9);
    text("Press 'R' to detect threshold automatically", width / 2, height * .95);
}

function ballSlap() {
  // Creating the ball and setting its movement by changing
        //  ballx and bally variables
    beachBall(ballx, bally, size);
    ballx += dir1 * speedx;
    bally += dir2 * speedy;

    // Making ball bounce off the right
    if (ballx >= width - size / 2 || ballx <= size / 2) {
        dir1 = -dir1;
      }

      // Making the ball bounce off the top and bottom
    if (bally < size / 2 || bally > height - size / 2) {
        dir2 = -dir2;
      }

    var colorAtBall = myCaptureDevice.get(ballx, (bally + size / 2));
    if (isColor(colorAtBall)) {
            // setting the brightness to a variable and testing if it meets the
            //    the threshold values
            brightnessAtBall = brightness(colorAtBall);
            // if the ball hits the user's head (darker pixel) the ball will bounce up
            if (brightnessAtBall < darknessThreshold & dir2 > 0) {
                dir2 = -dir2;
                speedy = random(0.5, 5);
                speedyx = random(-4, 2);
              }
    }
}

function beachBall(x, y, diameter) { // function for creating rendering the beach ballx
    var ballcolors = ["RED", "BLUE", "YELLOW"];
    noStroke();
    fill(255);
    ellipse(x, y, diameter, diameter);
    fill(ballcolors[0]);
    arc(x, y, diameter, diameter, radians(30), radians(90));
    fill(ballcolors[1]);
    arc(x, y, diameter, diameter, radians(150), radians(210));
    fill(ballcolors[2]);
    arc(x, y, diameter, diameter, radians(270), radians(330));
    fill(255);
    ellipse(x, y, diameter / 5, diameter / 5);
}

function keyPressed() { // allowing the user to alter the beachball size with keys
    // increasing the ball size if the a key is pressed
    if (key === 'a' || key === 'A') {
        if (size < 200) {
            size += 10;
        }
    }

    // decreasing the ball size if the d key is pressed
    if (key === 'd' || key === 'D') {
        if (size > 50) {
            size -= 5;
        }
    }

    // this code allows the user to edit the darkness threshold in order to fix bugs in the webcam
    if (key === 'o' || key === 'O') {
        if (darknessThreshold < 100) {
            darknessThreshold += 2;
        }
    }

    // decreasing the darkness threshold
    if (key === 'p' || key === 'P') {
        if (darknessThreshold > 10) {
            darknessThreshold -= 2;
        }
    }

    // finding threshold automatically
    if (key ==='r' || key === 'R') {
    	findThreshold();
    }

}

function rainFall() { // function for creating the rain scene
    clouds(cloudNumber, cloudwidth, cloudheight); // calling the cloud function
    // these lines of called call the function for the rain objects to make ensure
    //    the rain continuously falls
    updateRain();
    removeRain();
    addRain();

    // these if statements remap the speed of the rain to change as time passes
    rainSpeed += increment;
    if (rainSpeed >= 15) {
        increment = -0.01;
    }
    if (rainSpeed <= 5) {
        increment = 0.01;
    }

    // code to implement the lighting function at a random timeout
    // this first if statement sets the lighting variables to an initial value
    //      and increments the frame variable
    if (frameCount % 200 === 0) {
        frame++;
        tone = 255;
        xi = random(40, 440);
        xii = random(30, 450);
        xiii = random(20, 460);
        strweight = 30;
    }

    // a separate frame variable is used to make sure the lighning stays for multiple frames
    if (frame % 3 === 0) {
        // a random variable is used to make sure the lightning is called unpredictably
        var chance = random(0, 2);
        lightning(strweight, tone, xi, xii, xiii);
        tone -= 4; // altering the lighting render values for aesthetic effect
        strweight -= 1;
    }

}

function makeRain(xpos, ypos) { // function for making the rain objects
    var rain = {x: xpos, y: ypos, move: rainMove, display: rainDraw};
    return rain;
}

function rainDraw() { // function for drawing the rain particles
    noStroke();
    fill(0, 0, 240);
    push();
    translate(this.x, this.y);
    rotate(radians(15));
    ellipse(0, 0, 2, 10);
    pop();
}

function rainMove() { // moving the rain by the rain speed global variable
    this.y += rainSpeed;
}

function updateRain() {
  // for loop that calls train track objects and moves/displays them
    for (var i = 0; i < raindrops.length; i++) {
        var colorAtRain = myCaptureDevice.get(raindrops[i].x, raindrops[i].y);
        raindrops[i].move();
        if (isColor(colorAtRain)) {
              // setting the brightness to a variable and testing if it meets the
              //    the threshold values
              brightnessAtRain = brightness(colorAtRain);

              // this ensures the rain stops falls on top of the figure in the WEBCAM
              //    by comparing to the pixel brightness
              if (brightnessAtRain >= darknessThreshold) {
                  raindrops[i].display();
                }
              }

      }
}

function addRain() { // function for adding rain objects to raindrops array
    for (var i = 0; i < 6; i++) {
       raindrops.push(makeRain(random(0, width), 0));
    }
}

function removeRain() { // function for removing objects from the array
    var rainKeep = [];
    for (var i = 0; i < raindrops.length; i++) {
        if (raindrops[i].y < 380) {
            rainKeep.push(raindrops[i]);
        }

      }
    raindrops = rainKeep; // reassigning the raindrops array to the duplicate array
}

// this function calls the lighting from a list of values that create polylines
function lightning(weight, brightness, xpos, xpos2, xpos3) {
    noFill();
    strokeWeight(weight);
    stroke(brightness);
    var x2 = xpos + random(-10, 10);
    var x3 = xpos2 + random(-20, 25);
    var x4 = xpos3 + random (-30, 40);
    var y1 = random(height / 4, height / 3);
    var y2 = random(height / 8 * 5, height * 2 / 3);
    line(xpos, 0, x2, y1);
    line(x2, y1, x3, y2);
    line(x3, y2, x4, height);
}

// function that calls the clouds from a list of variables
function clouds(number, length, cheight) {
    noStroke();
    for (var i = 0; i < number + 1; i++) {
        fill( map(i, 0, number, 100, 150));
        var cloudx = map(i, 0, number, 0, width);
        ellipse(cloudx, 0, length, cheight + 15 * (i % 3));
    }
}


//-------LEE'S CODE----------------------------------------------------------------------

function findBorder() {
	borderX = [];
	borderY = [];
	// finds the silhouette of person based on darkness threshold in intervals of 5
	for (var i = 0; i < width; i += 5) {
		for (var j = 0; j < height; j += 5) {
			if (brightness(myCaptureDevice.get(i, j)) < darknessThreshold & 
				borderX.length < i / 5) {
					borderX.push(i);
					borderY.push(j);
			}
		}
	}
}

function findThreshold() {
	var brightest = 50;
    var darkest = 50;
    var xColors = [];
    var xx = [];
    // stores brightnesses of all colors along a line in the image displayed
    for (var j = 0; j < width; j += 5) {
        xColors.push(brightness(myCaptureDevice.get(j, height / 2)));
        xx.push(j);
    }
    // finds brightest and darkest pixels
    for (var k = 0; k < xColors.length; k ++) {
        if (xColors[k] > xColors[brightest]) {
            brightest = k;
        }
        if (xColors[k] < xColors[darkest]) {
            darkest = k;
        }
    }
    // elementary ratio to determine thresholds
    brightnessThreshold = (xColors[brightest] - xColors[darkest]) / 3 + xColors[darkest];
    darknessThreshold = (xColors[brightest] - xColors[darkest]) / 5 + xColors[darkest] - 10;
}

function addParti() {
	// creating particles along top of person
	var likelihood = 0.45;
	for (var i = 0; i < borderX.length; i ++) {
		if (random(1) < likelihood) {
			parties.push(createParticle(borderX[i], borderY[i]));
		}
	}
}

function removeParti() {
	// removes particle when size decreases below 1
	var partiesToKeep = [];
	for (var i = 0; i < parties.length; i ++) {
		if (parties[i].size > 1) {
			partiesToKeep.push(parties[i]);
		}
	}
	parties = partiesToKeep;
}

function updateAndDisplayParti() {
	for (var i = 0; i < parties.length; i ++) {
		parties[i].move();
		parties[i].display();
	}
}

function createParticle(birthX, birthY) {
	var parti = {x: birthX, y: birthY, size: round(random(5, 15)),
				speed: -5, move: partiMove, display: partiDisplay,
				color: myCaptureDevice.get(birthX, birthY)}
	return parti;
}

function partiMove() {
	// move particle and decrease size
	this.y += this.speed;
	this.size -= 1;
}

function partiDisplay() {
	strokeWeight(0);
	fill(this.color);
	push();
	translate(this.x, this.y);
	rotate(millis() / 1000 * 2 * PI);
	rectMode(CENTER);
	rect(0, 0, this.size, this.size);
	pop();
}

function censor() {
	// divides area below silhouette into 25 by 25 squares and extracts colors
	for (var i = 0; i < borderX.length; i += 5) {
		for (var j = borderY[i]; j < height; j += 25) {
			push();
			translate(borderX[i], j);
			rectMode(CENTER)
			fill(myCaptureDevice.get(borderX[i], j));
			rect(0, 0, 25, 25);
			pop();
		}
	}
}

Ammar Hassonjee and Lee Chu collaborated on this webcam machine. It consists of four scenes: a beachball headbutting game, a rainy day, snapped by Thanos, and an unnecessary censorship. Click the mouse to cycle through the scenes. Press the keys O and P to increase or decrease the darkness threshold depending on the lighting of your setting. Press the key R to automatically detect the darkness threshold, although this process may not be perfect.

Final Project – Austin Garcia – Group C

Click, hold and drag on the white circle to move it, but don’t move it too quickly or it will reset. Move it to the black circle to complete and randomize the box placement again. I intended to have collision on the white rectangles but have so-far been unsuccessful in the implementation of that.

My goal with this project was to make a quick and easy game where you moved the ball through a series of obstacles and, upon reaching the goal, the map re-set and you could do it again. I have tried to tune the boxes so that there is always a path through them to the goal, but RNG is often a difficult thing to work with and a more careful approach of creating different ‘levels’ to cycle through may have been a more effective method.

sketch

/*		Austin Garcia
		Section C
		aegarcia@andrew.cmu.edu
		Assignment or Project
*/

var ballX = 10;
var ballY = 10;
var diameter = 10;
var goalX = 380;
var goalY = 380;
var boxNum = 15;


function drawSquares() {
    noStroke();
    fill(255);
    rect(this.x, this.y, this.w, this.h);
};

function makeSquares() {
    var squares = {
      x: random(0, 200),
      y: random(15, 380),
      w: 10,
      h: random(100),
      draw: drawSquares,

    }
    return squares;
};



function drawBoxes() {
    noStroke();
    fill(255);
    rect(this.x, this.y, this.w, this.h);
};

function makeBoxes() {
    var boxes = {
      x: random(0, 350),
      y: random(15, 380),
      w: random(100, 150),
      h: 10,
      draw: drawBoxes,
    }
    return boxes;
};

var boxes = [];
var squares = [];


function setup() {
    createCanvas(400, 400);

    for(var i = 0; i < boxNum; i++) {
    var b = makeBoxes();
    var s = makeSquares();
    squares.push(s);
    boxes.push(b);
  }
}

function draw() {
    background(20, 180, 0);

    for(var i = 0; i < boxNum; i++) {
      var b = boxes[i];
      var s = squares[i];
      s.draw();
      b.draw();
   }
// mouse circle
    fill(255);
    if(dist(ballX, ballY, mouseX, mouseY)< diameter & mouseIsPressed)  {
      ballX = mouseX;
      ballY = mouseY;
  }
    //ball
    ellipse(ballX, ballY, diameter,diameter);
    //goal circle
    fill(0);
    ellipse(goalX, goalY, diameter*2, diameter*2);

    //goal circle effect
    if(dist(ballX, ballY, goalX, goalY) < 18)  {
      ballX = 10;
      ballY = 10;
      for (var i = 0; i < boxNum; i++) {
          boxes[i].x = random(0, 350);
          boxes[i].y = random(15, 380);
          boxes[i].w = random(100, 150);
          boxes[i].h = 10;

          squares[i].x = random(0, 200);
          squares[i].y = random(15, 380);
          squares[i].w = 10;
          squares[i].h = random(100);
        }
      }
      //Attempt at getting collision to work
/*    for (var i = 0; i < boxNum; i++) {
      if(dist(mouseX+5, mouseY+5, boxes[i].x, boxes[i].y) > boxes[i].w & boxes[i].h) {
        ballX = 10;
        ballY = 10;
      }
    }
      */

    }
function mouseReleased() {
   ballX = 10;
   ballY = 10;
 };

Jasmine Lee – Final Project

sing

//Jasmine Lee
//jasmine4@andrew.cmu.edu
//Section C
//Final Project

var nodes = []; //array to hold node objects
var node1c = 1; //node sound counters
var node2c = 1;
var node3c = 1;
var node4c = 1;
var node5c = 1;
var node6c = 1;
var node7c = 1;
var node8c = 1;
var node9c = 1;
var node10c = 1;
var waves; //sound variables
var windchimes;
var rain;
var campfire;
var chant;
var crickets;
var birdwhistle;
var cafe;
var church;
var stream;
var c1; //gradient colors
var c2;
var x1; //gradient controls
var inter;
var c;
var xarray = []; //arrays to hold bubble positions
var yarray = [];
var ydir = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
var r = 0; //bubble colors
var g = 0;
var b = 0;
var bubbY; //controls bubblesNC movement
var bubbY2;
var h; //time
var m;
var s;

function preload() {
    waves = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/waves.mp3")
    windchimes = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/windchimes.wav")
    rain = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/rain.wav")
    campfire = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/campfire.wav")
    chant = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/chant.mp3")
    crickets = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/crickets.wav")
    birdwhistle = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/birdwhistle.wav")
    cafe = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/cafe.m4a")
    church = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/church.wav")
    stream = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/12/stream.wav")
}

function setup() {
    createCanvas(600, 450);
    background(255);

    //creates node objects and gives them parameters
    nodes = [{x: 70, y: 70, d: 40}, //top row of nodes
             {x: 230, y: 120, d: 90},
             {x: 390, y: 75, d: 50},
             {x: 520, y: 130, d: 40},
             {x: 125, y: 235, d: 50}, //middle row of nodes
             {x: 400, y: 230, d: 80},
             {x: 550, y: 270, d: 30}, //bottom row of nodes
             {x: 80, y: 380, d: 80}, 
             {x: 250, y: 330, d: 40},
             {x: 450, y: 370, d: 50},
             ]

    //shows the nodes initially when page is refreshed
    for (var i = 0; i < nodes.length; i ++) {
        fill(200);
        noStroke();
        ellipse(nodes[i].x, nodes[i].y, nodes[i].d)
        }
}

function draw() {
    //gradient background
    c1 = color(255, 255, 255);
    c2 = color(220 + (mouseX * 0.04), 240, 255);
    setGradient(c1, c2);

    //functions that control whether the nodes are colored/white
    n1a();
    n2a();
    n3a();
    n4a();
    n5a();
    n6a();
    n7a();
    n8a();
    n9a();
    n10a();

    //bubbles that follow the mouse
    cursorP();

    //bubbles controlled by clock
    bubblesNC();

    //text
    motivationalText();
}

function mousePressed() {
    //functions that control whether the nodes play/pause sounds
    n1s();
    n2s();
    n3s();
    n4s();
    n5s();
    n6s();
    n7s();
    n8s();
    n9s();
    n10s();
}

function mouseDragged() {
    //adds mouse old coordinates into bubble arrays to create new bubbles
    xarray.push(mouseX)
    yarray.push(mouseY)
}

function setGradient(c1, c2) {
    //creates interactive background gradient
    noFill();
    for (var y = 0; y < height; y++) {
        var inter = map(mouseY, 0, height, 0, 1);
        var c = lerpColor(c1, c2, inter);
        stroke(c);
        line(0, y, width, y);
    }
}

//node 1 appearance
function n1a() { 
    noStroke();
    if (node1c % 2 == 0) {
        fill(255);
    } else {
        fill(245, 204, 240); //periwinkle
    }
    ellipse(70, 70, 40, 40);
}

//node 1 sound
function n1s() { 
    if (mouseX > 50 & mouseX < 90 && mouseY > 50 & mouseY < 90) {
        node1c = node1c + 1;
        if (node1c % 2 == 0) {
            waves.loop();
        } else {
            waves.pause();
        }
    } 
}

//node 2 appearance
function n2a() { 
    if (node2c % 2 == 0) {
        fill(255);
    } else {
        fill(233, 255, 255); //robin's egg blue
    }
    ellipse(230, 120, 90, 90);
}

//node 2 sound
function n2s() { 
    if (mouseX > 185 & mouseX < 275 && mouseY > 75 & mouseY < 165) {
        node2c = node2c + 1;
        if (node2c % 2 == 0) {
            windchimes.loop();
        } else {
            windchimes.pause();
        }
    }
}

//node 3 appearance
function n3a() {
    if (node3c % 2 == 0) {
        fill(255);
    } else {
        fill(217, 240, 255); //light blue
    }
    ellipse(390, 75, 50, 50);
}

//node 3 sound
function n3s() {
    if (mouseX > 365 & mouseX < 415 && mouseY > 50 && mouseY < 100) {
        node3c = node3c + 1;
        if (node3c % 2 == 0) {
            rain.loop();
        } else {
            rain.pause();
        }
    }
}

//node 4 appearance
function n4a() {
    if (node4c % 2 == 0) {
        fill(255);
    } else {
        fill(246, 224, 252); //light pink-purple
    }
    ellipse(520, 130, 40, 40);
}

//node 4 sound
function n4s() {
    if (mouseX > 500 & mouseX < 540 && mouseY > 110 & mouseY < 150) {
        node4c = node4c + 1;
        if (node4c % 2 == 0) {
            campfire.loop();
        } else {
            campfire.pause();
        }
    }
}

//node 5 appearance
function n5a() {
    if (node5c % 2 == 0) {
        fill(255);
    } else {
        fill(217, 195, 242); //light purple
    }
    ellipse(125, 235, 50, 50);
}

//node 5 sound
function n5s() {
    if (mouseX > 100 & mouseX < 175 && mouseY > 210 & mouseY < 260) {
        node5c = node5c + 1;
        if (node5c % 2 == 0) {
            chant.loop();
        } else {
            chant.pause();
        }
    }
}

//node 6 appearance
function n6a() {
    if (node6c % 2 == 0) {
        fill(255);
    } else {
        fill(241, 223, 242); //pale pink
    }
    ellipse(400, 230, 80, 80);
}

//node 6 sound
function n6s() {
    if (mouseX > 360 & mouseX < 440 && mouseY > 190 & mouseY < 270) {
        node6c = node6c + 1;
        if (node6c % 2 == 0) {
            crickets.loop();
        } else {
            crickets.pause();
        }
    }
}

//node 7 appearance
function n7a() {
    if (node7c % 2 == 0) {
        fill(255);
    } else {
        fill(189, 220, 255); //baby blue
    }
    ellipse(550, 270, 30, 30);
}

//node 7 sound
function n7s() {
    if (mouseX > 535 & mouseX < 565 && mouseY > 255 & mouseY < 285) {
        node7c = node7c + 1;
        if (node7c % 2 == 0) {
            birdwhistle.loop();
        } else {
            birdwhistle.pause();
        }
    }
}

//node 8 appearance
function n8a() {
    if (node8c % 2 == 0) {
        fill(255);
    } else {
        fill(238, 210, 242); //mauve
    }
    ellipse(80, 380, 80, 80);
}

//node 8 sound
function n8s() {
    if (mouseX > 40 & mouseX < 120 && mouseY > 340 & mouseY < 420) {
        node8c = node8c + 1;
        if (node8c % 2 == 0) {
            cafe.loop();
        } else {
            cafe.pause();
        }
    }
}

//node 9 appearance
function n9a() {
    if (node9c % 2 == 0) {
        fill(255);
    } else {
        fill(235, 154, 240); //light blue-purple
    }
    ellipse(250, 330, 40, 40);
}

//node 9 sound
function n9s() {
    if (mouseX > 230 & mouseX < 270 && mouseY > 310 & mouseY < 350) {
        node9c = node9c + 1;
        if (node9c % 2 == 0) {
            church.loop();
        } else {
            church.pause();
        }
    }
}

//node 10 appearance
function n10a() {
    if (node10c % 2 == 0) {
        fill(255);
    } else {
        fill(206, 228, 237); //pale blue
    }
    ellipse(450, 370, 50, 50);
}

//node 10 sound
function n10s() {
    if (mouseX > 425 & mouseX < 475 && mouseY > 345 & mouseY < 395) {
        node10c = node10c + 1;
        if (node10c % 2 == 0) {
            stream.loop();
        } else {
            stream.pause();
        }
    }
}

//controls cursor generated bubbles and their movement
function cursorP() {
    for (var i = 0; i < xarray.length; i ++) {
        //gives floating bubbles flashing colors
        r = random(220, 255);
        g = random(220, 255);
        b = random(220, 255);
        fill(r, g, b);

        //creates bubbles when mouse is dragged
        ellipse(xarray[i], yarray[i], i, i)

        //makes bubbles bounce off bottom of canvas
        if (yarray[i] > (450 - (i / 2))) {
            ydir[i] = -(ydir[i]);
            yarray[i] = (450 - (i / 2)) - 1;
        } else {
            yarray[i] = yarray[i] + ydir[i]; 
        }

        //makes bubbles bounce off top of canvas
        if (yarray[i] < (i / 2)) {
            ydir[i] = -(ydir[i]);
            yarray[i] = (i / 2) - 1;
         } else {
            yarray[i] = yarray[i] + ydir[i];
        }

        //makes bubbles bounce off nodes
        for (var j = 0; j < nodes.length; j ++) {
            if ((dist(xarray[i], yarray[i], nodes[j].x, nodes[j].y)) < (((nodes[j].d) / 2) + (i / 2))) {
                ydir[i] = -(ydir[i]);
                if (ydir[i] > 0) {
                    //lets bubbles bounce off bottom of nodes
                    yarray[i] = yarray[i] + (i / 2) + 1; 
                } else {
                    //lets bubbles bounce off top of nodes
                    yarray[i] = yarray[i] - (i / 2) - 1; 
                }
            }
        }
    }

    //deletes bubbles if there are more than 25
    if (xarray.length > 25) {
        xarray.shift();
        yarray.shift();
    }
}

function bubblesNC() {
    h = hour();
    m = minute ();
    s = second ();

    //moves 7.5 pixels down for every second that passes
    bubbY = s * 7.5;
    bubbY2 = 450 - (s * 7.5);

    noStroke();
    //white bubbles
    fill(255, 255, 255, 100);
    ellipse(70, bubbY, 200, 200);
    ellipse(200, bubbY + 20, 80, 80);
    ellipse(450, bubbY - 40, 320, 320);
    ellipse(300, bubbY2, 80, 80);
    ellipse(30, bubbY2, 130, 130);
    ellipse(520, bubbY + 5, 100, 100);
    ellipse(370, bubbY2 - 15, 220, 220);
}

function motivationalText() {
    //adds text to center of the screen
    textAlign(CENTER, CENTER);
    textSize(30);
    textStyle(BOLDITALIC);
    fill(255, 255, 255);
    text('hello', 300, 195);
    fill(255, 255, 255);
    text('hello', 300, 225);
    fill(255, 255, 255, 200);
    text('hello', 300, 255);

}

For my final project, I intended to create a dreamlike atmosphere. The sounds that the nodes play are a mystery, with the user having to click them to discover what they are. The project acts as a sort of music sampler to allow the user to play whatever tracks they’d like to hear at the same time. Once the music is on, the node disappears into the white background, with the user having to interact with the color changing background to find the node again. When the mouse is dragged, many bubbles are created that bounce around the canvas and off the music nodes to create visual interest for the user. When all the sounds are being played and the mouse is used to make the background white, an interesting “screensaver” is created with the negative space.

Sean Leo_Final Project

TEST CARD GENERATOR

The Test Card Generator (TCG) allows you to create a customizable Test pattern to use for testing outputs for a media installation. You can select HD or SD (1920×1080 or 1280×720) which will populate on your card. Then using the input fields you can type in what you’d like the card to say. Provided is a field for a title and labeling the output and input; a Projector using SDI, for example. You can also color the grid lines to further customize and is extremely helpful with multiple outputs. Un-checking the boxes will take away some of the graphic elements to further customize the look of the card. Lastly clicking save will save a PNG titled with the name and selected resolution to your downloads folder.

As a media designer, I’m often faced with ambitious projects and installations that call for multiple outputs and sources of media. In a room with wrap around projections seeing the same test pattern everywhere doesn’t help you understand how your system is working and what is media is being feed to what. A tool like TCG allows me to quickly test multiple output sources and customize the look based on version, show, or whatever I feel like I need shown.

Below are some of the customizable test cards I generated:

thisatestcard_1280x720.png
WALL1of4_1920x1080.png
TESTCARDGENERATOR_1920x1080.png
test_1920x1080.png

sleo_finalProject_20191205

//Sean B. Leo
//sleo@andrew.cmu.edu
//Section C 
//FINAL PROJECT

//TEST CARD GENERATOR___________(c) Sean B. Leo 2019
/*The TCG allows you to create a customizable Test pattern 
to use for testing outputs for a media installion. You can 
select HD or SD (1920x1080 or 1280x720) which will populate on your card.
Then using the input fields you can type in what you'd like the card to say.
Provided is a field for a title and labeling the output and input; 
a Projector using SDI for example. You can also color the grid lines to further
customize and is extremly helpful with multiple outputs. 
Un-checking the boxes will take away some of the graphic elements
to further customize the look of the card. 
Lastly clicking save will save a PNG titled with the name and selected resolution 
to your downloads folder.*/

//Global variables
//aspect ratio
var aspectX = 16;
var aspectY = 9;
// grid color variables
var colorInp1, colorInp2;
//gradient color variables
var c1, c2;
//grid slider
var gridSlider;
var spacing = 0;
//element dimensions
var colW;
var colH;
var rowW;
var rowH;
//radio varibile
var radio;


function setup() {
//radio options set for HD and SD    
radio = createRadio(); 
radio.option('1920x1080');// HD
radio.option('1280x720');// SD
//canvas sized to fit within WP window
createCanvas(600, 337.5);
colorMode(RGB);
//Color picker input for elements
colorInp1 = createColorPicker('#ffffff'); //set to white at start
colorInp1.position(360,height+30);
colorInp2 = createColorPicker('#727272'); //set to gray at start
colorInp2.position(420,height+30);
colorInp3 = createColorPicker('#ffffff'); //set to white at start
colorInp3.position(480,height+30);
//black and white gradient color  
c1 = color(0);
c2 = color(255);
//Title for test card
textInp1 = createInput('NAME YOUR TEST CARD');
textInp1.size(150, 20);
textInp1.position(0,height+30);
//label output (projector, screen, etc.)
textInp2 = createInput('OUTPUT');
textInp2.size(100, 20);
textInp2.position(150,height+30);
//label input (HDMI, DVI, SDI, etc.)
textInp3 = createInput('INPUT');
textInp3.size(100, 20);
textInp3.position(250,height+30);
//Save custom test card
button = createButton('Save Test Card');
button.position(420, height+60);
button.mousePressed(saveImage);
//graphic element sizing
colW = width/2.28/8;
colH = height/3;
barStartX = width/3.56;
barStartY = height/6;  
//turn off or on elements
toggleGrid = createCheckbox('Grid', true);//set as on from start
toggleGrid.changed(toggleSet);
toggleGrid.position(0, height+60);

toggleLines = createCheckbox('Lines', true);
toggleLines.changed(toggleSet);
toggleLines.position(60, height+60);

toggleColor = createCheckbox('Color Bars', true);
toggleColor.changed(toggleSet);
toggleColor.position(120, height+60);

toggleGrad = createCheckbox('Black and White', true);
toggleGrad.changed(toggleSet);
toggleGrad.position(210, height+60);
}
function saveImage(){    
radioXY = radio.value(); // read radio value as variable
var title = textInp1.value() +"_" + radioXY; //set file name from custom inputs
if (button.mousePressed()){
    saveCanvas(title,'png');
    }
}
function draw() {
background(0);
toggleSet();
textBlocks();
}
function toggleSet(){
//turn off or on element functions based on state of checkbox    
if (toggleGrid.checked()) {
  grid();
  }
if (toggleLines.checked()) {
  lines();
  }
if (toggleColor.checked()) {
  colorBars();
  } 
if (toggleGrad.checked()){
  gradient();
  }
}
function grid(){
//draw grid    
var gridColorTop = colorInp1.color();//set grid color based on selection
var gridColorBot = colorInp2.color();//set grid color based on selection
var gridStrokeTop = 2;
var gridStrokeBot = .5
var x = spacing;
var y = spacing;
//bottom grid loop
for (var x = 0; x < width; x += width / (aspectX*2)) {
  for (var y = 0; y < height; y += height / (aspectY*2)) {
    stroke(gridColorBot);
    strokeWeight(gridStrokeBot);
    line(x, 0, x, height);
    line(0, y, width, y);
    }
  }
//top grid
for (var x = 0; x < width; x += width / aspectX) {
  for (var y = 0; y < height; y += height / aspectY) {
    stroke(gridColorTop);
    strokeWeight(gridStrokeTop);
    line(x, 0, x, height);
    line(0, y, width, y);
    }
  }
}
function lines(){    
var lineColor = colorInp3.color();//set color based on selection
stroke(lineColor);
strokeWeight(2);
//diagonals
line(0, 0, width, height);
line(width, 0, 0, height);
noFill();
//cross lines
line(width/2, 0, width/2, height);   
line(0, height/2, width, height/2); 
//circle
ellipse(width/2, height/2, width/1.8);
}
function colorBars(){
//SMPTE color bars
noStroke();
fill('white');
rect(barStartX, barStartY, colW, colH);
fill('yellow');
rect(barStartX+colW, barStartY, colW, colH);
fill('cyan');
rect(barStartX+colW*2, barStartY, colW, colH);
fill(0, 255, 0);
rect(barStartX+colW*3, barStartY, colW, colH);
fill('magenta');
rect(barStartX+colW*4, barStartY, colW, colH);
fill('red');
rect(barStartX+colW*5, barStartY, colW, colH);
fill('blue');
rect(barStartX+colW*6, barStartY, colW, colH);
fill('black');
rect(barStartX+colW*7, barStartY, colW, colH);
}
function setGradient(x, y, w, h, c1, c2) {
//creates gradient    
noFill();
for (var i = x; i <= x + w; i++) {
  var inter = map(i, x, x + w, 0, 1);
  var c = lerpColor(c1, c2, inter);
  stroke(c);
  line(i, y, i, y + h);
  }
}
function gradient(){
//gradient block
//calls gradient and creates shape
setGradient(barStartX, height/2, colW*8, colH/4, c1, c2);
//grayscale blocks
noStroke();
fill(0);
rect(barStartX, height/1.779, colW*2, colH/6);
fill(255/4);
rect(barStartX+colW*2, height/1.779, colW*2, colH/6);
fill(255/2);
rect(barStartX+colW*4, height/1.779, colW*2, colH/6);
fill('white');
rect(barStartX+colW*6, height/1.779, colW*2, colH/6);
}
function textBlocks() {
radioXY = radio.value();
fill(255);
textSize(30);
textAlign(CENTER, CENTER);
stroke(27);
strokeWeight(5);//set against grid pattern for better legibility
//takes in first text value to display at top of canvas
text(textInp1.value(), width/2, barStartY-barStartY/4);
strokeWeight(4);
//textSize(18);
//takes in radio button value to set text on canvas
textSize(18);
text(radioXY, width/2 - colW*2.5, barStartY*4.35);
//second text value 'OUTPUT'
textSize(18);
text(textInp2.value(), width/2, barStartY*4.35);
//third text value 'INPUT
textSize(18);
text(textInp3.value(), width/2 + colW*2.5, barStartY*4.35);
//Signing my work
textSize(10);
fill('yellow');
text('(c) Sean B. Leo 2019', width-colW-20, height-10);
}

Steven Fei & Mike Jin – Final Project

Press your mouse to add planets and nebulas and use your mouse to hover around the Canvas and explore the universe!!

sketch

//Steven Fei & Fanjie Mike Jin
//Section A & C
//Final Project
//zfei@andrew.cmu.edu & fjin@andrew.cmu.edu
var starNumber = 150;//number of the stars on the background
var starsize = 1.5;//size of the stars
var sx = [];//array to define the x position of the stars
var sy = [];//array to define the y position of the stars
var sz = [];//array to define the z position of the stars
var amplitude = 3.14 * 3;//define the moving margin of the stars
var waveSpeed;//define the moving speed of the stars on the background
var theta = 0;//define the moving angle of the stars
var glowDefiner = [];//define the true false value for whether to let the star glow
var glowSize = 22;//glowing size of the stars
var newStars = [];//array for making new stars
var mouseXList = [];//arrays to store mouseX value
var mouseYList = [];//arrays to store mouseY value
var img; //load image for the earth texture mapping 
var w = 600 / 7 // devivded the canvas into seven regions and from left to right, the pitches of the piano sound will progressively become higher  
var newExplod = [];//array for making new explosion at the background
var mouseXListEx = [];//arrays to store mouseX value
var mouseYListEx = [];//arrays to store mouseY value


function setup() {
//load the background image for the texture mapping of the earth
//coded by Mike
    img = loadImage("https://i.imgur.com/lamlO83.jpg");
    createCanvas(600, 600,WEBGL);

//create values for the positions of the stars on the background
//coded by Mike
    for (var i = 0; i < starNumber; i++){
        sx.push(random(-width * 0.75, width * 0.75));
        sy.push(random(-height, height));
        sz.push(random(-width, height/2));
        var toggle = random(1.0);
        //define whether the stars on the background will glow
        if(toggle < 0.9){
            glowDefiner.push(false);
        }else{
            glowDefiner.push(true);
        }
    }
    for(var j = 0; j < glowDefiner.length; j++){
    print(glowDefiner[j]);
    }
}

function draw(){
    background(0);
    noStroke();
    normalMaterial();
    centerCube();//create a center star to give a sense of what perspective we are looking at
    makeCamera();//use the makeCamera function to change the viewport angle
    makeearth();
    push();
    //draw the stars on the background
    for(var i = 0; i < starNumber; i++){
        //coded by Mike
        push();
        waveSpeed = map(sz[i], -width, height/2, 15000, 60000);//define the moving speed of the stars
        theta += (TWO_PI / waveSpeed);//define the moving angle of the stars
        if(theta > amplitude){
            theta = -theta;//set the moving margins of the stars
        }
        sy[i] += sin(theta);//set the moving value to the positions
        sx[i] += cos(theta);//set the moving value to the positions
        translate(sx[i], sy[i], sz[i]);
        if(glowDefiner[i]){
            fill(255, 200, 130, 4);
            sphere(glowSize);//draw glow light of the sphere
        }
        fill("white");
        smooth();
        sphere(starsize);//draw the stars
        pop();
    }
    pop();
    //draw some new stars
    //coded by Steven
    if (mouseXList.length != 0){
        for(var k = 0; k < newStars.length; k++){
            newStars[k].updateStar();//animate the expansion of the stars
            push();
            translate(newStars[k].x, newStars[k].y,0);
            rotateX(frameCount * 0.05 + k*2);//rotate the new star
            rotateY(frameCount * 0.05 + k*2);//rotate the new star
            newStars[k].draw();//animate the emergence of the stars
            pop();
        } 
    }
    if(newStars.length > 4){
        newStars.shift();
    }

    push();
    //make the planet
    if (mouseXListEx.length != 0){
        for(var k = 0; k < newExplod.length; k++){
            newExplod[k].updateExplo();//animate the expansion of the stars
            push();
            translate(newExplod[k].x, newExplod[k].y,0);
            rotateX(frameCount * 0.05 + k*2);//rotate the new star
            rotateY(frameCount * 0.05 + k*2);//rotate the new star
            newExplod[k].draw();//animate the emergence of the stars
            pop();
        } 
    }
    if(newExplod.length > 2){
        newExplod.shift();
    }
    pop();

    
}

function makeCamera(){
//coded by Steven
    camX = map(mouseX, 0, width, -width/2, width/2);//changing camera position x
    camY = map(mouseY, 0, height, -height/2, height/2);//changing camera position y
    camZ = height/2;//changing camera position z
    camera(camX, camY, camZ,0,0,0,1,1,0);//allow the viewport angle to change
}
//make object to create new stars
function makeNewStar(x, y, radius){
//coded by Mike
    var newstar = {x: x,
                    y: y,
                    r: radius,
                    updateStar: updateStar,
                    draw: drawNewStar};
    return newstar;
}

function makeNewExplo(x, y, radius){
//coded by Mike
    var newExplo = {x: x,
                    y: y,
                    r: radius,
                    updateExplo: updateExplo,
                    draw: drawNewExplo};
    return newExplo;
}

//function to draw new star
function drawNewStar(){
//coded by Mike
    var color1 = random(150, 255);
    var color2 = random(100,180);
    var color3 = random(100,200);
    var density = random(14,20);//allow different numbers of the spheres to appear on the star
    for(var i = 0; i < density; i++){
        var lengthValue = map(i, 0, density, -PI, PI); //set longitudinal value
        for(var j = 0; j< density; j++){
            var widthValue = map(j, 0, density, -PI/2, PI/2);// set horizontal value
            var pX = this.r * sin(lengthValue) * cos(widthValue);
            var pY = this.r * sin(lengthValue) * sin(widthValue);
            var pZ = this.r * cos(lengthValue);
            push();
            fill(color1, color2, color3);
            translate(pX, pY, pZ);
            sphere(1.6);
            pop();
        }
    }
}

function drawNewExplo(){
//coded by Mike
    var color4 = random(100, 255);
    var color5 = random(100,180);
    var color6 = random(100,200);
    var density = random(12, 15);//allow different numbers of the spheres to appear for the explosion
    for(var i = 0; i < density; i++){
        var lengthValue = map(i, 0, density, -PI, PI); //set longitudinal value
        for(var j = 0; j< density; j++){
            var widthValue = map(j, 0, density, -PI/2, PI/2);// set horizontal value
            var pX1 = this.r * sin(lengthValue) * cos(widthValue * 0.5) * 0.5;
            var pY1 = this.r * sin(lengthValue * 0.5) * sin(widthValue) * 0.5;
            var pZ1 = this.r * cos(lengthValue);
            push();
            fill(color4, color5, color6);
            translate(pX1, pY1, pZ1);
            box(2, 2, 2);
            pop();
        }
    }
}

function updateStar(){
//coded by Mike
    this.r += random(0.5,2);//allow the new star to expand
}

function updateExplo(){
//coded by Mike
    this.r += random(1,2);//allow the new explosion to expand
}


function mousePressed(){
//coded by Steven
    var newStarMaking = [];
    var newMouseXList = [];
    var newMouseYList = [];
    var newExploMaking = [];
    var newmouseXListEx = [];
    var newmouseYListEx = [];
    var clickEx;//check whether there is existing new stars
    var click;//check whether there is existing new stars
    
    if(mouseXList.length == 0){
        click = 0;
        newStarMaking.push(newStars[0]);
        newMouseXList.push(mouseXList[0]);
        newMouseYList.push(mouseYList[0]);
    }
    else{
        for(var l = 0; l < newStars.length; l++){
            var distance = dist(mouseX - width/3, mouseY - height/3, newStars[l].x, newStars[l].y);
            if(distance <= 30){
                click = 1;
            }else{
                click = 0;
                newStarMaking.push(newStars[l]);
                newMouseXList.push(mouseXList[l]);
                newMouseYList.push(mouseYList[l]);
            }
        }
        newStars = newStarMaking;
        mouseXList = newMouseXList;
        mouseYList = newMouseYList;
    }
    if(click == 0){
        mouseXList.push(mouseX - width/3);
        mouseYList.push(mouseY - width/3);
        var newStar = makeNewStar(mouseX - width/3, mouseY-width/3, 30);
        newStars.push(newStar);
    }

    //add value to empty list
    if(mouseXListEx.length == 0){
        clickEx = 0;
        newExploMaking.push(newExplod[0]);
        newmouseXListEx.push(mouseXListEx[0]);
        newmouseYListEx.push(mouseYListEx[0]);
    }
    else{
    //assign initiating position according to the mouse postion
        for(var w = 0; w < newExplod.length; w++){
            var distance = dist(mouseX - width/3, mouseY - height/3, newExplod[w].x, newExplod[w].y);
            if(distance <= 30){
                clickEx = 1;
            }else{
                clickEx = 0;
                newExploMaking.push(newExplod[w]);
                newmouseXListEx.push(mouseXListEx[w]);
                newmouseYListEx.push(mouseYListEx[w]);
            }
        }
        //assign values back to the list
        newExplod = newExploMaking;
        mouseXListEx = newmouseXListEx;
        mouseYListEx = newmouseYListEx;
    }
    //avoid invalid value
    if(clickEx == 0){
        mouseXListEx.push(mouseX - width/3);
        mouseYListEx.push(mouseY - width/3);
        var newExplo = makeNewExplo(mouseX - width/3, mouseY-width/3, 300);
        newExplod.push(newExplo);
    }
}


//function to make a center planet to have some understanding of the perspective
//coded by Mike
function centerCube(){
    //make sure the location of the center planet is always at the center of the canvas
    push();
    var locX = mouseX - height / 2;
    var locY = mouseY - width / 2;
    ambientLight(50);
    directionalLight(255, 0, 0, 0.25, 0.25, 0);
    pointLight(0, 0, 255, locX, locY, 250);
    ambientMaterial(100);
    strokeWeight(0.5);
    stroke(255);
    smooth();
    sphere(40);
    pop();
    //first ring surronding the planet
    push();
    rotateZ(frameCount * 0.01);
    rotateX(frameCount * 0.01);
    rotateY(frameCount * 0.01);
    strokeWeight(0.5);
    smooth();
    stroke(255);
    torus(60, 0.5);
    pop();
    //second ring surronding the planet
    push();
    rotateZ((100+ frameCount) * 0.01);
    rotateX((100 + frameCount) * 0.01);
    rotateY((100+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(70, 0.5);
    pop();
    //third ring surronding the planet
    push();
    rotateZ((200+ frameCount) * 0.01);
    rotateX((200 + frameCount) * 0.01);
    rotateY((200+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(80, 0.5);
    pop();
    //fourth ring surronding the planet
    push();
    rotateZ((300+ frameCount) * 0.01);
    rotateX((300 + frameCount) * 0.01);
    rotateY((300+ frameCount) * 0.01);
    smooth();
    strokeWeight(0.5);
    stroke(255);
    torus(90, 1);
    pop();
}
//function to make a earth adjacent to the center planet 
//coded by Mike
function makeearth(){
    push();
    translate(width / 2, height / 3, -150);
    rotateX(frameCount * 0.05);
    rotateY(frameCount * 0.05);
    texture(img);
    sphere(20);
    pop();
}

 

In this project, we aim to establish an interactive universe made possible by using the P5 3D geometry and 3D lighting. When you are hovering around in this universe, the stars and planets will move according to your mouse position. When you lower the mouse position, the screen will be zoomed out and when you higher the mouse, the screen will zoom in more.  When the mouse is pressed, new “stars” which look like the colorful spheres composed of smaller spheres with galaxy-like explosion will happen randomly on the screen and would expand further until they can be seen no more. However, once you click on the screen, you will be able to see them again. The small spheres are glowing on the background to have an interstellar appearance. The center spindle-like sphere and an “Earth” like sphere are created to give us a general understanding of what perspective we are looking at the canvas. 

Chelsea Fan & Katrina Hu – Final Project

Final copy

/* Chelsea Fan and Katrina Hu
Section 1B and Section 1C
chelseaf@andrew.cmu.edu and kfh@andrew.cmu.edu
Project-15
*/

//important variables
var killCount = 0;
var score = 0;
var yCoord = 0;
var snow = [];
var bear = [];
var c1;
var c2;

function setup() {
    createCanvas(600, 480);
    frameRate(60);
    //initial collection of bears
    for (i = 0; i < 1; i++) {
        var bearY = -40;
        bear[i] = makeBear(bearY);
    }
    //setting color of background
    c1 = color(106, 197, 252);
    c2 = color(126, 127, 207);
    //initial collection of snows
    for (i = 0; i < 60; i++) {
        var snowx = random(width);
        var snowy = random(0, height);
        snow[i] = makeSnow(snowx, snowy);
    }
}

function draw() {
    setGradient(c1, c2);
///////// BY CHELSEA
    //draw Sun
    noStroke();
    fill(255, 252, 227, 120);
    ellipse(80, 250, 85, 85);
    fill(255, 246, 179, 140);
    ellipse(80, 250, 70, 70);
    fill(255, 238, 112, 200);
    ellipse(80, 250, 50, 50);
    //draw background
    drawMountains2();
    drawMountains();
    //bears
    updateBear();
    removeBearFromView();
    addBear();
    drawKill();
    //more scenery things
    drawWater();
    drawIce();
    snows();
    //end of game
    endGame();
}

///////// BY KATRINA
function drawKill() {
    //printing score and number of bears killed
    fill(255);
    textSize(20);
    textAlign(RIGHT);
    noStroke();
    text("Kill Count = " + killCount, width - 70, 50);
    text("Score = " + score, width - 70, 75);
}

///////// BY CHELSEA
function endGame() {
    //end screen if five bears killed 
    //and restart game button
    if(killCount == 5) {
        textSize(50);
        fill(255);
        textAlign(CENTER);
        text("GAME OVER", width/2, height/2-100);
        for (var i = 0; i < bear.length; i++) {
            bear[i].speed = 0;
        }
        textSize(25);
        fill(255, 150);
        noStroke();
        rect(width/2 - 80, height/2 - 40, 160, 60);
        fill(50);
        text("RESTART", width/2, height/2);
    }
}

///////// BY KATRINA
function mouseClicked() {
    //if restart button clicked, reset game 
    if(killCount == 5) {
        if (mouseX > 220 & mouseX < 380 && mouseY > 200 && mouseY < 260) {
            bear = [];
            killCount = 0;
            score = 0;
            for (var i = 0; i < bear.length; i++) {
                bear[i].speed = 2;
            }
        }
    }
}

///////// BY KATRINA
function setGradient(c1, c2) {
    //gradient color sky background
    noFill();
    for (var y = 0; y < height; y++) {
        var inter = map(y, 0, height, 0, 1);
        var c = lerpColor(c1, c2, inter);
        stroke(c);
        line(0, y, width, y);
    }
}

///////// BY CHELSEA
function drawWater() {
    //water color and transparency
    fill(0, 107, 214, 100);
    noStroke();
    //water level 
    rect(0, height - (96 * killCount) - 20, width, height + 30)
}

///////// BY KATRINA
function drawIce() {
    fill(245, 68, 59);
    rect(mouseX + 8, height - (96 * killCount) - 100, 55, 30); //sign
    textSize(10);
    textFont('Georgia');
    fill(255);
    rect(mouseX + 8, height - (96 * killCount) - 100, 8, 75); //pole
    text('NORTH', mouseX + 55, height - (96 * killCount) - 90); //words
    text('POLE', mouseX + 50, height - (96 * killCount) - 75);
    fill(162, 232, 250)
    rect(mouseX, height - (96 * killCount) - 15, 100, 4); //ice
    fill(255);
    rect(mouseX, height - (96 * killCount) - 25, 100, 10); //ice
    fill(245, 68, 59);
    for(lines = 0; lines < 4; lines++) { //stripes
        rect(mouseX + 8, height - (96 * killCount) - lines * 20 - 33, 8, 7);
    }
    fill(255, 242, 145);
    ellipse(mouseX + 12, height - (96 * killCount) - 106, 15, 15) //top of pole
}

///////// BY CHELSEA
function drawSnow() {
    noStroke();
    fill(255, 255, 255, 170); ///snow color and transparency
    push();
    translate(this.x2, this.y2); //draw snow at x2, y2
    ellipse(10, 10, 5, 5); //snow shape
    pop();
}

///////// BY CHELSEA
function makeSnow(xlocation, ylocation) {
    //snow object
    var makeS = {x2: xlocation, 
                y2: ylocation, 
                snowx: random(0, width), 
                snowy: 0,
                speed: random(1, 2),
                move: moveSnow,
                draw: drawSnow}
    return makeS;
}

///////// BY CHELSEA
function moveSnow() {
    this.y2 += this.speed; //speed of snow moving
    if (this.y2 >= height - (96 * killCount) - 30) { //restart snow on top
        this.y2 -= height;
    }
}

///////// BY CHELSEA
function snows() {
    //move and draw all individual snows
    for(i = 0; i < snow.length; i++) {
        snow[i].move();
        snow[i].draw();
    }
}

///////// BY CHELSEA
function drawMountains(){
    noStroke();
    fill(192, 200, 207); //mountain color
    beginShape(); 
    for (i = 0; i < width; i++) {
        var mountainSpeed = .0005; //speed of mountains moving
        var mountainDetail = 0.009; //smoothness of mountains
        var t = (i * mountainDetail) + (millis() * mountainSpeed);
        //mountain y coord
        var y = map(noise(t), 0, 1.2, height/2, height);
        //keep drawing mountain
        vertex(i, y);
    }
    //height constriant of mountains
    vertex(width, height);
    //restart mountains at left side 
    vertex(0, height);
    endShape();
}

///////// BY CHELSEA
function drawMountains2(){
    noStroke();
    fill(245); //mountain color
    beginShape(); 
    for (i = 0; i < width; i++) {
        var mountainSpeed = .0003; //speed of mountains moving
        var mountainDetail = 0.007; //smoothness of mountains
        var t = (i * mountainDetail) + (millis() * mountainSpeed);
        //mountain y coord
        var y = map(noise(t), 0, 2, height/2, height);
        //keep drawing mountain
        vertex(i, y);
    }
    //height constriant of mountains
    vertex(width, height);
    //restart mountains at left side 
    vertex(0, height);
    endShape();
}

///////// BY KATRINA
function updateBear() {
    //move and draw all individual bears
    for (var i = 0; i < bear.length; i++) {
        bear[i].move();
        bear[i].display();
    }
}

///////// BY KATRINA
function removeBearFromView() {
    //if bear lands on ice, delete bear
    for(var i = 0; i < bear.length; i++) {
        if (bear[i].x > mouseX & bear[i].x < mouseX + 100 && (bear[i].y > height - (96 * killCount) - 50 && bear[i].y < height - (96 * killCount) - 40)) {
            bear.splice(i, 1);
            score += 1;
        }
        //if bear leaves screen, remove from array
        else if (bear[i].y > height + 40) {
            bear.splice(i, 1);
            killCount += 1;
        }
    }
}

///////// BY KATRINA
function makeBear(startY) {
    //bear object
    var myBear = {x: random(30, 570),
                y: startY,
                speed: 2,        
                move: bearMove,
                display: bearDisplay}
    return myBear;
}

///////// BY KATRINA
function bearMove() {
    //to move bear
    this.y += this.speed;
}

///////// BY KATRINA
function bearDisplay() {
    //drawing bear shape
    noStroke();
    fill(255);
    ellipse(this.x, this.y, 43, 60); //body
    ellipse(this.x + 14, this.y + 25, 12, 20); //right leg
    ellipse(this.x - 14, this.y + 25, 12, 20); //left leg
    ellipse(this.x, this.y - 30, 27, 32); //head
    ellipse(this.x + 9, this.y - 42, 8, 8); //right ear
    ellipse(this.x - 9, this.y - 42, 8, 8); //left ear
    fill(240);
    ellipse(this.x, this.y, 30, 36); //body
    fill(210);
    ellipse(this.x + 9, this.y - 42, 5, 5); //right inner ear
    ellipse(this.x - 9, this.y - 42, 5, 5); //left inner ear
    ellipse(this.x, this.y - 31, 9, 9); //snout
    fill(0);
    ellipse(this.x + 5, this.y - 37, 4, 4); //right eye
    ellipse(this.x - 5, this.y - 37, 4, 4); //left eye
    ellipse(this.x, this.y - 32, 6, 3); //nose
    fill(255);
    ellipse(this.x + 5.5, this.y - 35.5, 2, 2); //right inner eye
    ellipse(this.x - 5.5, this.y - 35.5, 2, 2); //left inner eye
    stroke(0);
    line(this.x, this.y - 32, this.x1, this.y - 29) //line from nose
}

///////// BY KATRINA
function addBear() {
    //add new bears to array with small probability
    var newBearProb = 0.005;
    if(random(0,1) < newBearProb) {
        bear.push(makeBear(-40));
    }
}

Instructions: Move the ice block with mouse to catch the falling bears. If you miss the bears, they will drown and the water level rises. If you miss 5 bears, the game ends. Press Restart to play again!

This was a fun project to make. Collaborating together was very helpful as we could learn from each other’s mistakes. However, it is difficult to code on two computers. We really enjoyed this experience and hope you enjoy the game!

Sean Meng-Final Project

hmeng-final project

//Sean Meng
//hmeng@andrew.cmu.edu
//Section C
//Final Project

var mySoundA;
var amp;
var vol = [];

function preload() {
    //Load music Love Lockdown
    mySoundA = loadSound("https://courses.ideate.cmu.edu/15-104/f2019/wp-content/uploads/2019/11/Love_Lockdown-online-audio-converter.com.wav");
    mySoundA.setVolume(2);
}

function setup() {
    createCanvas(500, 500);
    //define amplitude and frequency to visualize
    amplitude = new p5.Amplitude();
    fft = new p5.FFT();
    mySoundA.amp(0.2);    
    frameRate(200);
}

function draw() {
    //size of the button
    var bSize = 20;
    background(218, 227, 226);
    noStroke();

//Album art background
    fill(250);
    rect(0, 0, 100, 500);

    fill(128, 15, 120);
    rect(85, 0, 15, 45);
    
    fill(34, 32, 99);
    rect(85, 45, 15, 45);  
    
    fill(242, 235, 97);
    rect(85, 90, 15, 45);   

    fill(141, 214, 204);
    rect(85, 135, 15, 45); 

    fill(92, 182, 224);
    rect(85, 180, 15, 45); 

    fill(53, 156, 120);
    rect(85, 225, 15, 45); 

    fill(242, 182, 241);
    rect(85, 270, 15, 45); 
    
    fill(197, 204, 124);
    rect(85, 315, 15, 45); 

    fill(181, 103, 180);
    rect(85, 360, 15, 45); 

    fill(184, 44, 116);
    rect(85, 405, 15, 45);  
    
    fill(49, 6, 92);
    rect(85, 450, 15, 50);      

//PAUSE button
    fill(0);
    rect(10, height - 30, bSize, bSize);

//PLAY button
    fill(0);
    triangle(10, height - 60, 10, height - 40, 30, height - 50);

//Spectrum represents amplitude
    let spectrum = fft.analyze();
    noStroke();
    fill(255); 
    for (var i = 0; i< spectrum.length; i++){
        let x4 = map(i, 0, spectrum.length, 100, width * 3.5);
        let h4 = -height + map(spectrum[i], 0, 255, height * 0.95, 0);
        rect(x4, height, width / spectrum.length, h4 )
    }

//Beating heart graphic represents amplitude
    let level = amplitude.getLevel();
    let offset = map(level, 0, 1, 0, 80);

//draw first half of the heart    
    strokeWeight(2);
    stroke(220, 30, 30);
    fill(220, 30, 30);
    beginShape();
    vertex(240 - offset, 180 - offset);
    vertex(270 - offset, 165 - offset);
    vertex(300, 180 - offset);
    vertex(330 + offset, 160 - offset);
    vertex(355 + offset, 170 - offset);   
    vertex(375 + offset, 200);
    vertex(355 + offset, 240);
    vertex(330 + offset, 270);
    vertex(290, 335 + offset);
    vertex(275 - offset, 280);
    vertex(240 - offset, 240);    
    vertex(220 - offset, 210);
    vertex(240 - offset, 180 - offset);
    endShape();

//Draw second half of the heart
    strokeWeight(2);    
    stroke(115, 20, 15);
    fill(115, 20, 15);
    beginShape();
    vertex(300, 180 - offset);
    vertex(330 + offset, 160 - offset);
    vertex(355 + offset, 170 - offset);   
    vertex(375 + offset, 200);
    vertex(355 + offset, 240);
    vertex(330 + offset, 270);
    vertex(290, 335 + offset);
    vertex(305 + offset, 270);
    vertex(290 - offset, 245); 
    vertex(300 + offset, 215);        
    vertex(275 - offset, 200);
    vertex(300, 180 - offset);
    endShape();

//Five waveform that visualzie frequency
    //wave A
    let waveform = fft.waveform();
    noFill();
    beginShape(POINTS);
    stroke(150, 10, 10);
    strokeWeight(2);
    for(var i = 0; i < waveform.length; i++){
        let x0 = map(i, 0, waveform.length, 100, width);
        let y0 = map(waveform[i], - 3, 3, 0, height);
        vertex(x0, y0);
    }
    endShape();

    //wave B
    beginShape(POINTS);
    stroke(180, 10, 10);
    strokeWeight(2);
    for(var i = 0; i < waveform.length; i++){
        let x0 = map(i, 0, waveform.length, 100, width);
        let y0 = map(waveform[i], - 1.5, 1.5, 0, height);
        vertex(x0, y0);
    }
    endShape();
    
    //Wave C
    beginShape(POINTS);
    stroke(220, 30, 30);
    strokeWeight(2);
    for(var i = 0; i < waveform.length; i++){
        let x1 = map(i, 0, waveform.length, 100, width);
        let y1 = map(waveform[i], - 0.7, 0.7, 0, height);
        vertex(x1, y1);
    }
    endShape();

    //Wave D
    beginShape(POINTS);
    stroke(230, 50, 50);
    strokeWeight(1);
    for(var i = 0; i < waveform.length; i++){
        let x2 = map(i, 0, waveform.length, 100, width);
        let y2 = map(waveform[i], - 0.4, 0.4, 0, height);
        vertex(x2, y2);
    }
    endShape();

    //Wave E
    beginShape(POINTS);
    stroke(230, 90, 90);
    strokeWeight(0.5);
    for(var i = 0; i < waveform.length; i++){
        let x2 = map(i, 0, waveform.length, 100, width);
        let y2 = map(waveform[i], - 0.2, 0.2, 0, height);
        vertex(x2, y2);
    }
    endShape();

    //Title of the album
    push();
    translate(75, 250);
    rotate(- PI / 2);
    stroke(65);
    fill(65);
    textStyle(BOLDITALIC);
    textSize(25);
    text('808s & Heartbreaks', 0, 0);
    pop();
}

function mousePressed() {
    //play the song when buttonA is clicked
    if(mouseX > 10 & mouseX < 30 && mouseY > height - 60 && mouseY < height - 40){
        mySoundA.play();
    } 
    //pause the song when buttonB is clicked
    if(mouseX > 10 & mouseX < 30 && mouseY > height - 30 && mouseY < height - 10){
        mySoundA.pause();
    }     
}    

In this project, I intend to homage to my favorite artist of all time Kanye West. The project represents a visualization of his song Love Lockdown from his renowned album 808’s & Heartbreaks. The representation and graphic elements are inspired by the original album cover that designed by artist Kaws. While the beating heart visualizes the amplitude of the music, the waveforms which has a gradient of both color and stroke weight visualizes the frequency of the song. As the song goes, the frequency gets increasingly complicated and generates intriguing pattern.

The original album cover by Kaws
Visualization at 02:37
Concept sketches

Nawon Choi— Looking Outward 12

“Strength” by Field for Deutsche Bank

I was really inspired by a studio called Field. They are a creative studio that creates immersive artistic experiences using technology. In particular, a project called “Evolving Environments” was very interesting to me. I really admire the beautiful motion graphics combined with and auditory component that creates a truly immersive and captivating experience. They used real-time code that reflects something happening in nature.

Light and motion graphics for a project for the car company Infinity

I was also inspired by the works of a studio called Nand. For this project, they tried to capture the experience of driving through data, light, and motion. I love the idea of taking data points such as speed, acceleration, heart rate, etc to incorporate into the visualization. I also like how they tried to evoke or emulate emotion through an abstract visualization.

Both projects take data points from “real life” and abstract them in a way to visualize motion and emotion. I really like this idea of creating computational art by incorporating data.

Austin Garcia – Project 12 – Final Project Proposal – Group C

I am and have always been interested in games, and have found myself understanding concepts in this class most easily though drawing connections to fundamental functions of various games I have played throughout my life. The particular strengths of P5.js that I have learned about clearly can work nicely toward creating a simple browser game, and that is what I intend to make. I would like to make a puzzle game, utilizing a geometry centered on the mouse that the player must move through a shifting maze in order to beat the game. I got the idea from an indie game that came out a while ago called ‘PUSS’. This game is remarkable both in its puzzle mechanics as well as visuals. I would love to explore both puzzle mechanics and visual style as it relates to a puzzle through this project and hopefully make something that is enjoyable to play.