SooA Kim – Final Project

sketch

/* SooA Kim
sookim@andrew.cmu.edu
Final Project
Section C
*/


//webcam and image texture variables 
var myCaptureDevice;
var img = [];
var frames = [];
var framelist = 0;
var link1= [];
var link2 = [];
var link3 = [];

//particle variables
var gravity = 0.1;   // downward acceleration
var springy = 0.9; // how much velocity is retained after bounce
var drag = 0.0001;    // drag causes particles to slow down
var np = 50;
var particles = [];

var Image1 = [];
var Image2 = [];
var Image3 = [];


var link1 = [
    "https://i.imgur.com/qAayMED.png",
    "https://i.imgur.com/86biLWe.png",
    "https://i.imgur.com/r5UE5kg.png",
    "https://i.imgur.com/I1BBRfH.png",
    "https://i.imgur.com/D1l3aXi.png",
    "https://i.imgur.com/NAHr7yB.png",
    "https://i.imgur.com/F0SB9GM.png",
    "https://i.imgur.com/B1kvNaM.png",
    "https://i.imgur.com/Th9sahL.png",
    "https://i.imgur.com/c9cuj2k.png"
  ]

var link2 = [ 
    "https://i.imgur.com/z7BAFyp.png",
    "https://i.imgur.com/8Ww7Vuo.png",
    "https://i.imgur.com/QFjlLr2.png",
    "https://i.imgur.com/0sdtErd.png",
]

var link3 = [ 
    "https://i.imgur.com/ZD7IoUP.png"
]


var textures = [link1, link2, link3];

var textureIndex = 0;

function preload() {
    for (var z = 0; z < link1.length; z++){
      link1[z] = loadImage(link1[z]);
    }
    
    for (var z = 0; z < link2.length; z++){
      link2[z] = loadImage(link2[z]);
    }
  
    for (var z = 0; z < link3.length; z++){
      link3[z] = loadImage(link3[z]);
    }
  }

function setup() {
    createCanvas(600, 480);
    myCaptureDevice = createCapture(VIDEO);
    myCaptureDevice.size(600, 480); // attempt to size the camera. 
    myCaptureDevice.hide(); // this hides an extra view.
}
  
function mousePressed(){
    textureNew = floor(random(textures.length)); //to prevent from same number(texture) that's selected again,
      while(textureNew == textureIndex){
        textureNew = floor(random(textures.length));
      } 
      textureIndex = textureNew;
    }
    
function particleStep() {
    this.age++;
    this.x += this.dx;
    this.y += this.dy;
    this.dy = this.dy + gravity; // force of gravity
    var vs = Math.pow(this.dx, 2) + Math.pow(this.dy, 2);
    // d is the ratio of old velocty to new velocity
    var d = vs * drag; 
    d = min(d, 1);
    // scale dx and dy to include drag effect
    this.dx *= (1 - d);
    this.dy *= (1 - d);
}
 
function makeParticle(px, py, pdx, pdy, imglink) {
    p = {x: px, y: py,
       dx: pdx, dy: pdy,
       age: 0,
       step: particleStep,
       draw: particleDraw,
       image: imglink  //making image as a parameter 
      }
  return p;
}

function particleDraw() {
    //tint(255, map(this.age, 0, 30, 200, 0)); //fade out image particles at the end
    image(this.image, this.x, this.y);
}

function isColor(c) {
    return (c instanceof Array);
  } 
  
function draw() {
    tint(255, 255);
    background(220);
    imageMode(CORNER);
    myCaptureDevice.loadPixels(); // this must be done on each frame.
    image(myCaptureDevice, 0, 0);
    framelist += 1;
    imageMode(CENTER);
    // get the color value of every 20 pixels of webcam output
    for (var i = 0; i < width; i += 20) {
      for (var j = 0; j < height; j+= 20) {
          var currentColor = myCaptureDevice.get(i, j);

          var rd = red(currentColor);
          var gr = green(currentColor);
          var bl = blue(currentColor);
           // targetColor: green 
           if (rd < 90 & gr > 100 && bl < 80){
             for (var s = 0; s < textures[textureIndex].length; s++) { 
                var pImage = makeParticle(i, j, random(-10, 10), random (-10, 10),textures[textureIndex][s]); //replaced position with i and j that tracks green pixels
                if (particles.length < 10000) {
                  particles.push(pImage);
                }
              }
            }
          }
        }
        newParticles = [];
        for (var i = 0; i < particles.length; i++) { // for each particle
          var p = particles[i];
          p.step();
          p.draw();
          if (p.age < 20) { //to last good amount of particle (due to laggy actions)
            newParticles.push(p);
          }
        }
        particles = newParticles;
      }

// moving frames 
function framePush(){
    framelist += 1;
    image(frames[framelist % frames.length], 0, 0);
  }

Mouse click the screen!

For this final project, I created a variety of sprite textures to apply into a particle effect animation that replaces the green pixels in the webcam screen. The sprite texture changes when the mouse is clicked.  I approached this project with the basis of environmental concern. I wanted to convey a message on what happens with climate change with the imagery of air pollution covered by these sprite texture that imitates dusts and smokes.
I tried to be be playful in terms of this project as well by providing different textures. I started this code by tracking the green pixels first, then I moved onto figuring out how to replace the image texture to the particle effect.

The coding process was very challenging, but I am really happy with the outcome.

sprite textures

first try on getting the sprite texture to the image

William Su – Final Project –

sketch

// William Su
// Section E
// wsu1@andrew.cmu.edu
// Final Project

var timer = 0;

let x = 0; //person position x
let x1 = 0;
let ender = 0; //variable used to end a scene.
let years;  //calculate random years.
let miles; //calculate random miles.

function setup() {
    createCanvas(windowWidth, 750); //Full window
    textSize(14);
    frameRate(60);

    //preload images
    Store = loadImage('https://i.imgur.com/L4qngWN.png');

    walkin = loadImage('https://i.imgur.com/W2fK1A3.png');
    walkout = loadImage('https://i.imgur.com/C5LA4S1.png');
    broken = loadImage('https://i.imgur.com/aebY3Uk.png');

    iphone = loadImage('https://i.imgur.com/iI6LMAU.png');
    iphoneInside = loadImage('https://i.imgur.com/pL2oAbJ.png');
    battery = loadImage('https://i.imgur.com/9oZjkzY.png');

    numberGen(); //Generate random years and miles.
}

function draw() {
    background(255);

    //timer starts and 0 and increments every frame of draw. 
    if (timer > 0) {
        background(255);
        image(Store, 500, windowHeight/2 - 100, Store.width / 2, Store.height / 2);

        image(walkin, 800 - x, windowHeight/2 - 8, 20, 30);

        if(x <= 240) {
            x += 2;
        } else {
            x = 590;
        }
    }

    if (timer > 110) {
        push();
        strokeWeight(2);
        fill(255);
        beginShape();
        vertex(558, windowHeight/2 - 8);
        vertex(565, windowHeight/2 - 12);
        vertex(565, windowHeight/2 + 24);
        vertex(558, windowHeight/2 + 20);
        endShape(CLOSE);
        pop();
    }

    if (timer > 130) {
        background(255);
        image(Store, 500, windowHeight/2 - 100, Store.width / 2, Store.height / 2);
    }

    if (timer > 140) {
        background(255);
        image(Store, 500, windowHeight/2 - 100, Store.width / 2, Store.height / 2);
        push();
        fill(100);
        text("Billions of smartphones are sold every year...", windowWidth/2 - 150, windowHeight/2 + 50);
        pop();
    }

    if (timer > 340) {
        background(255);
        image(Store, 500, windowHeight/2 - 100, Store.width / 2, Store.height / 2);
        push();
        fill(100);
        text("But how far can one get...", windowWidth/2 - 150, windowHeight/2 + 50);
        pop();
    }

    if (timer > 480) {
        background(255);
        image(Store, 500, windowHeight/2 - 100, Store.width / 2, Store.height / 2);
        push();
        fill(100);
        text("before needing to get a new one?", windowWidth/2 - 150, windowHeight/2 + 50);
        pop();
    }

    if (timer > 620) {
        background(255);
        image(Store, 500, windowHeight/2 - 100, Store.width / 2, Store.height / 2);
        push();
        fill(100);
        text("Lets find out >\n(Right Arrow Key)", windowWidth/2 - 150, windowHeight/2 + 50);
        pop();
    }

    if (timer > 620 & x1 > 0) {
        background(255);
        image(Store, 500 - x1, windowHeight/2 - 100, Store.width / 2, Store.height / 2);
        push();
        fill(100);
        text(x1.toString(), windowWidth/2 - 35, windowHeight/2 + 50);
        pop();

        image(walkout, 590, windowHeight/2 - 8, 20, 30);
        if (keyIsDown(RIGHT_ARROW)) {
            x1 += 10;
        }
    }

    if (x1 >= totalMiles) {
        background(255);
        //image(Store, 500, windowHeight/2 - 100, Store.width / 2, Store.height / 2);
        image(broken, 590, windowHeight/2 - 11, 20, 30);
        push();
        fill(100);
        text("This person has traveled " + totalMiles.toString() + " miles.", windowWidth/2 - 150, windowHeight/2 + 50);
        text("Their phone lasted " + years.toString() + " years.", windowWidth/2 - 150, windowHeight/2 + 65);
        text("What makes them fail and\nwhy do companies design it that way?", windowWidth/2 - 150, windowHeight/2 + 95);
        pop();

        ender += 1;
    }

    //Landscape Line
    push();
    strokeWeight(3);
    line(0, windowHeight/2 + 20, windowWidth, windowHeight/2 + 20);
    pop();

    //Borders
    push();
    noStroke();
    fill(255);
    rect(0,0, windowWidth/2 - 200, windowHeight);
    pop();

    push();
    noStroke();
    fill(255);
    rect(windowWidth/2 + 200,0, windowWidth, windowHeight);
    pop();

    if (ender > 450) { //End scene and move to parts of a phone.
        background(255);
        //image(Store, 500, windowHeight/2 - 100, Store.width / 2, Store.height / 2);
        image(iphone, windowWidth/2 - 150, windowHeight/2 - 200, 300,400);
        image(iphoneInside, windowWidth/2 + 50, windowHeight/2 - 200, 300,400);
        image(battery, windowWidth/4, windowHeight/2 - 200, 300,400);


        push();
        noStroke();
        fill(255);
        rect(windowWidth/2 + 100, windowHeight/2 - 60, 110,250);
        pop();

        if (mouseX >= windowWidth/4 + 70 & mouseX <= windowWidth/4 + 70 + 115) {
            push();
            noFill();
            stroke(255,0,0);
            strokeWeight(4);
            rect(windowWidth/4 + 70, windowHeight/2 - 95, 115,270);
            pop();

            text("Lithium-Ion Battery | Lifespan: 3-5 years\nOne of the most common areas of failure.\nThese also contain many of toxic substances that make it difficult to recycle.", windowWidth/2 - 250, windowHeight/2 +200);
        }

        if (mouseX >= windowWidth/2 - 90 & mouseX <= windowWidth/2 + 90) {
            push();
            noFill();
            stroke(0,255,0);
            strokeWeight(4);
            rect(windowWidth/2 - 90, windowHeight/2 - 180, 180, 360);
            pop();

            text("Screen / Outer Hardware | Lifespan: Varies\nThe most common failure point.\nNowadays, if a screen is cracked, its often cheaper to buy a new phone.", windowWidth/2 - 250, windowHeight/2 +200);
        }

        if (mouseX >= windowWidth/2 + 120 & mouseX <= windowWidth/2 + 160 + 115) {
            push();
            noFill();
            stroke(0, 0, 255);
            strokeWeight(4);
            rect(windowWidth/2 + 120, windowHeight/2 - 180, 160, 360);
            pop();

            text("Circuitboard / Chips | Obsolete: 2 years\nNot common to fail, in fact chips are designed to work for 20-30 years.\nHowever, the technology quickly becomes obsolete due to newer, more powerful chipsets being developed.", windowWidth/2 - 250, windowHeight/2 +200);
        }
    }
    
    timer += 1; //increment timer per call of draw.
}

function keyPressed() { //Detect right arrow key press.
    if (keyCode === RIGHT_ARROW) {
        x1 += 1;
  }
}

function numberGen() { //Generate numbers.
    let years1 = random(1, 4);
    years = nf(years1, 1, 2);
    miles1 = int(random(1300, 1500));
    miles = nf(miles1, 4, 2);

    totalMile1 = (miles * years);
    totalMiles = nf(totalMile1, 4, 2);
}

function mousePressed() { //Detect mouse press. 
    return true;
}

For my project, I wanted to highlight the issue of planned obsolescence in our everyday electronics through a simple interactive “scene”. Basically I wanted to show the briefness with which our phones are usable relate it to approximately how many miles we could walk before they utterly fail or become obsolete. At the end, the scene changes and shows some of the places where a phone is designed to fail in 2-3 years.

This project was made to fit the full view width of a window so it might not be completely viewable on wp.

Final_Project copy

Video Link: https://youtu.be/2isZoRcILBk

Nadia Susanto – Final Project

sketch

// Nadia Susanto
// nsusanto@andrew.cmu.edu
// Section B
// Final Project

var terrainSpeed = 0.0005;
var terrainDetail = 0.003;
var clouds = [];
var pipes = [];
var birdY = 300;
var birdX = 65;
var birdGravity = 0.75;
var birdVelocity = 0;
var birdUpForce = -18;
var secs = 0;


function setup() {
    createCanvas(600, 600);
    background(135,235,250);
    pipes.push(makePipe());
    //initalizing clouds
    for (var x = 0; x < 5; x++) {
        var cx = random(width);
        clouds[x] = makeClouds(cx);
    }

    frameRate(60);

}

function draw() {
    //blue sky
    background(135,235,250);
    //show mountains and waves
    makeMountains();
    makeWaves();
    //show clouds
    addNewClouds();
    updateAndDisplayClouds();
    removeCloudsOutofView();
    //pipes
    addNewPipes();
    updateAndDisplayPipes();
    //bird
    drawBird();
    updateBird();
    //collision detection for bird with pipe
    topCollision();
    bottomCollision();
    if (frameCount % 60 == 0) {
        secs += 1;
    }
    //score
    fill("black");
    textSize(30);
    textAlign(LEFT);
    text("TIME = " + secs, 5, 50);

}

//collision for bird with top pipe
function topCollision() {
    for (var i = 0; i < pipes.length; i++) {
        if ((birdY < pipes[i].top + 30) & (birdX > pipes[i].x && (birdX < pipes[i].x + pipes[i].w))) {
            gameOver();
          }
      }
}

//collision for bird with bottom pipe
function bottomCollision() {
    for (var i = 0; i < pipes.length; i++) {
        if ((birdY > pipes[i].top + 150) & (birdX > pipes[i].x && (birdX < pipes[i].x + pipes[i].w))) {
            gameOver();
          }
      }
}

//game over function that stops the game when triggered
function gameOver() {
    fill("red");
    textAlign(CENTER);
    textSize(60);
    text("GAME OVER", width/2, height/2);
    noLoop();
}

//constantly calling the pipes
function updateAndDisplayPipes() {
  for (var i = 0; i < pipes.length; i++) {
      pipes[i].move();
      pipes[i].draw();
    }
  }

function addNewPipes() {
    if (frameCount % 150 == 0) {
        pipes.push(makePipe());
    }
}

//moving the pipes right to left
function movePipe() {
    this.x -= this.speed;
}

function drawPipe() {
  noStroke();
  //top pipe
  fill(112,186,45);
  rect(this.x, 0, this.w, this.top);
  rect(this.x - 5, this.top - 2, this.w + 10, 20, 10);
  //bottom pipe
  rect(this.x, height, this.w, this.top - height + 150);
  rect(this.x - 5, this.top + 135, this.w + 10, 20, 10);
}

//object for pipe
function makePipe() {
    var pipe = {x: width,
                w: 50,
                top: random(50, height/2),
                speed: 1.5,
                move: movePipe,
                draw: drawPipe
                }
    return pipe;
}

//drawing the bird
function drawBird() {
    //legs
    fill(0);
    ellipse(birdX - 10, birdY + 15, 3, 10);
    ellipse(birdX + 10, birdY + 15, 3, 10);
    //halo
    noFill();
    stroke("gold");
    ellipse(birdX, birdY - 20, 40, 5);
    //body
    fill("yellow");
    ellipse(birdX, birdY, 35, 35);
    //eye
    fill(0);
    ellipse(birdX + 5, birdY - 5, 5);
    //beak
    fill("orange");
    triangle(birdX + 18, birdY - 4, birdX + 23, birdY, birdX + 18, birdY + 4);

}

//implementing velocity and gravity
function updateBird() {
  birdVelocity += birdGravity;
  //air resistance
  birdVelocity *= 0.9;
  birdY += birdVelocity;
  //making sure it doesnt go beyond top and bottom of canvas
  if (birdY > height) {
      birdY = height;
      birdVelocity = 0;
    }
  if (birdY < 0) {
      birdY = 0;
      birdVelocity = 0;
  }
}

//adding up force to bird velocity
function birdUp() {
    birdVelocity += birdUpForce;
}

//if space bar pressed, trigger the bird to go up
function keyPressed() {
    if (key == ' ') {
        birdUp();
    }
}

//constantly calling the clouds
function updateAndDisplayClouds() {
    for (var x = 0; x < clouds.length; x++){
        clouds[x].move();
        clouds[x].draw();
    }
}

function removeCloudsOutofView() {
    var cloudsKeep = [];
    for (var x = 0; x < clouds.length; x++) {
        if (clouds[x].x > 0) {
            cloudsKeep.push(clouds[x]);
        }
    }
    clouds = cloudsKeep; //remember the clouds
}

function addNewClouds() {
    var cloudProb = 0.01;
    //if random number less than probability then a new cloud is shown
    if (random(0, 1) < cloudProb) {
        clouds.push(makeClouds(width));
    }
}

function cloudsMove() {
    //move the clouds from right to left
    this.x -= this.speed;
}

function drawClouds() {
    //draw the white clouds
    fill("white");
    ellipse(this.x, this.y, this.width, 10);
    ellipse(this.x - 25, this.y - 10, 35, 30);
    ellipse(this.x + 25, this.y - 10, 30, 30);
    ellipse(this.x + 5, this.y - 15, 40, 25);
}

function makeClouds(cloudX) {
  //creating object for cloud
  var cloud = {x: cloudX,
              y: 50,
              width: random(50, 100),
              speed: 0.50,
              move: cloudsMove,
              draw: drawClouds}
  return cloud;
}

//adopted the terrain starter code to make mountains in background
function makeMountains() {
    noStroke();
    fill(127,221,136);
    beginShape();
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail*3) + (millis() * terrainSpeed);
        var y = map(noise(t), 0, 1, height/4, height/3);
        vertex(x, y);
      }
    vertex(width, height);
    vertex(0, height);
    endShape(CLOSE);
}

//adopted the terrain starter code to make ocean waves
function makeWaves() {
    noStroke();
    fill(1, 108, 194);
    beginShape();
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail/3) + (millis() * terrainSpeed/2);
        var y = map(noise(t), 0, 1, height/2, height);
        vertex(x, y);
      }
    vertex(width, height);
    vertex(0, height);
    endShape(CLOSE);
}

For my final project I made angel bird! I have always been a gamer at heart and love competition whether it be beating my peers or my personal bests. Originally for my proposal I wanted to do scream go hero but had difficulties with voice recognition. Flappy bird was my backup and I am really happy with the way it turned out. I used my knowledge of objects to create the generative backgrounds and the pipes, and I believe my angel bird with a halo is pretty cute.

How the game works:

The game automatically starts and all you have to do is press the space bar to make the bird go up. Instead of scoring, you want to beat your personal best times as you want to see how long you can go without the dreaded “GAME OVER.” Enjoy!

Final Project — Yoshi Torralva

sketch

//Yoshi Torralva
//yrt@andrew.cmu.edu
//Final Project 
//Section E

//storefront mockup
var mockup;
//input of camera variable
var cameraData;
//points for the hypotrochoid
var pixelPoints = 1000;
//location of hypotrochoid x position array
var placeCurvesX = [];
//location of hypotrochoid y position array
var placeCurvesY = [];
// array to store list of colors at 16 points
var getColors = [];
// array to store brightness of pixels at 16 points
var getBrightness =[];
// varible to move the 16 hypotrochoid's in indivudal rotation
var hypotrochoidsRotate = -1;
// scaled canvas for the interaction in the mockup
var SquareW = 154;

//lading the storefront mockup image
//vector image created by me with Adobe Illustrator 
function preload() {
    mockup = loadImage("https://i.imgur.com/pTMuI2T.png");
}
//connecting cameraData variable to createCapture
function setup() {
    createCanvas(600, 480);
    cameraData = createCapture(VIDEO);
    cameraData.hide();
    noStroke();
}

function draw() {
    background(172, 34, 104);
    //loading pixels into the canvas
    cameraData.loadPixels();
    //reflecting and scaling the camera data
    //when visitors move to the right/left, it properly reflects  movements
    push();
    translate(150, 0);
    scale(-1, 1);
    //sizing cameraData to the screen
    image(cameraData, 0,0, 154, 154);
    pop();
    //calling the hypotrochoids function to draw 16 hypotrochoids
    hypotrochoids(); 
    //scaling the image from imgur
    //placing it above hypotrochoids so that hypotrochoids dont go over the screen
    push();
    scale(0.24);
    image(mockup, 0, 0);
    pop();
}
//creating a function to draw a singular hypotrochoid
//setting four parameters for x position, y position, the curves color at one of the 16 points
//and the brightness of one of the 16 points
function drawCurve(x,y, curveColor, curveBrightness) {
    push();
    //translating with x and y for call parameters
    translate(x, y);
    //using the brightness in the map() of h and a to adjust size based on camera
    var h = map(curveBrightness - 100, 0, height, 0, curveBrightness + 100);
    var a = map(curveBrightness - 50, 0 , width, 0, curveBrightness + 50);
    //adding curveBrightness with 50 for more detail
    curveBrightness = curveBrightness + 50;
    var b = a / curveBrightness;
    //a small strokeWeight for clarity between curveBrightness
    strokeWeight(0.05);
    noFill();
    //using the curveColor parameter 
    //adding red and blue to display the hypotrochoids as pink/red
    stroke(curveColor + 200, 0, curveColor + 30);
    //calling all the variables in a nested for loop to draw the hypotrochoid
    beginShape();
    // adding 5 extra points to close the hypotrochoid
    for(var i = 0; i < pixelPoints + 5; i++) {
        var t = map(i, 0, pixelPoints, 0, TWO_PI); {
        x = (a-b) * cos(t) + h * cos(((a-b)/ b) * t)
        y = (a-b) * sin(t) - h * sin(((a-b) / b) * t)
        rotate(hypotrochoidsRotate);
        //slight rotation implemented
        hypotrochoidsRotate = hypotrochoidsRotate + 0.0001;
        //scale of hypotrochoids set to normal
        vertex(x, y);
    }
}
    endShape();
    pop();
}
// using nested for loops to place replicate hypotrochoid into 16 hypotrochoids
function hypotrochoids(){
//translating hypotrochoids function to fit into the square screen
push();
translate(302, 185);
    //4 in the width of the screen
    for(var i = 0; i < 4; i++) {
        //4 in the height of the screen
        for(var t = 0; t < 4; t++) {
            //locationofLoopi and LocationofLoopt space out the hypotrochoids
            var locationofLoopi = i * SquareW/4 + 10;
            var locationofLoopt = t * SquareW/4 + 10;
            //getting the color of locationofLoopi and LocationofLoop 2
            var colorLoop = get(locationofLoopi, locationofLoopt);
            //getting the brightness of the colors
            var sizeLoop = brightness(colorLoop);
            rectMode(CENTER);
            //implementing spacing into 16 hypotrochoids
            drawCurve(locationofLoopi, locationofLoopt, sizeLoop + 20, sizeLoop + 20);
            //pushing list into the arrays of location, color, and brightness of hypotrochoids
            placeCurvesX.push(locationofLoopi);
            placeCurvesY.push(locationofLoopt);
            getColors.push(colorLoop);
            getBrightness.push(sizeLoop);
        }
    }
//loop to call the length of the 16 points and implement the parameters from draw curve
    for(var a = 0; a < locationofLoopi.length; a++) {
        drawCurve(locationofLoopi[a], locationofLoopt[a], getColors[a], getBrightness[a]);
    }
pop();
}

For my final project, I wanted to explore the opportunities in which I can apply computational practices into a physical space. I decided to focus on creating a reactive storefront using a camera to show the movement of visitors in a visually intriguing way. To inspire a creative direction for the storefront, I created an Athletic Clothing brand called ové. Ové derives from the french word of l’oeuvre meaning work. Additionally, Ové is the shared characters of Move and Woven. To make the hypotrochoid curves reactive to the camera’s data, I used 16 specific points of pixel brightness and color. Through this, I create an interactive storefront that reacts to traffic and ultimately would entice people to enter the store.

Gretchen Kupferschmid & Sarah Choi – Final Project: Pittsburgh Ambience

final project: pittsburgh ambience

Our project’s canvas is too big for wordpress, so we are uploading the zip file and instructions to acess it. 

Click the link to the google drive to find the zip file. Download the zip file to find the sketch.js file “finalproject.js”  as well as the html file “finalproject.html” and the sound files. Because the project is outside of wordpress and there is a sound aspect, the project needs to be opened on the local host from your server, so the instructions must be followed bellow…

  1.  Open a Terminal in OS X or a command window (cmd) in Windows.
  2. Change your current directory to the directory you want to serve: Type cd path-to-your-directory (ex. cd Desktop/104final )
  3. Type in Terminal:
    python -m SimpleHTTPServerOr if you are using Python 3, type:
    python -m http.server
  4. Visit the URL http://localhost:8000 in your browser to test your sketch.

How it works:

Using your mouse, scroll through the four different neighborhoods presented in illustrations. 

Click on the music button to hear the song we chose to represent the ambience of the area and click on the pause button to stop the song.

Click on the different buttons for the cafes and restaurants shown to see a photo of the location, a description, and a link to the website. 

For our final project, we wanted to portray the distinct atmospheres of different neighborhoods in Pittsburgh. As two students who weren’t familiar with Pittsburgh before Carnegie Mellon, we took the initiative to venture out and explore the different areas and what Pittsburgh has to offer. As people who are interested in immersing and inspiring ourselves through our surroundings, we wanted to introduce our favorite places to other students. Because music is also a very big part of our everyday lives, we wanted to complete the Pittsburgh ambiance by selecting specific songs that we felt captured in each area the best. 

We really enjoyed the interactive visual aspect of this project. In the beginning, we brainstormed ways to depict our shared interests and goals through a project, and we felt that this achieved exactly what we envisioned. Making 2D objects into an interactive platform, we saw the potential to incorporate layers of our project into future uses. Our favorite part of the project was probably the music and design aspect of it. We had a lot of fun planning and collaborating together.  Below, we have attached a video and screenshots of each different area included in our project.

Shariq M. Shah | Paul Greenway – Final Project


This project functions as a Climate Change Visualizer, where the user is able to understand the extents of their environmental impact in a game like exaggeration of excessive consumption. The user’s actions to increase their ecological footprint, are translated to an increased rate of change in the number of tonnes of CO2 emitted. Each aspect of the Anthropocene (transport, fossil fuels, and agriculture) are represented by icons and are associated with facts that are cycled through in an array. At the end of the clicking cycle, there is a sarcastic game-like “YOU WIN!” message that points to the absurdity of excessive human consumption that ultimately leads to the degradation of the planet. The hope is that this climate change visualizer helps people to understand the gravity and severity of their impact relative to climate change.  Part of the user’s involvement makes it necessary to refresh the page in order to restart the game. The squares that change in size and movement based on mouse location are indicative of icecaps that get smaller in size as “ecological footprint” increases. 

shariqs-pgreenwa

// Shariq Shah | Paul Greenway
// shariqs | pgreenwa
// shariqs@andrew.cmu.edu | pgreenwa@andrew.cmu.edu

// Project-12-Final Project
// Climate Change Visualizer

//Variables


//Ice movement intensity variable
let movementIntensity = 0;


// Environmental impacts multipliers
var impactSize = [6,9,12,400];

//Step Variable
var n = 0;

//Starting C02 Value
var co2 = 2332947388070;

//Images


//Impact Icon Links
var impactImageLinks = [
"https://i.imgur.com/BQBpdiv.png", "https://i.imgur.com/De2zFwf.png", "https://i.imgur.com/a0ab0DC.png", 'https://i.imgur.com/SRVUOkn.png'
  ]
//Impact Facts
var impactFacts = [ "","                               Livestock contributes nearly 2/3 of agriculture's greenhouse & 78% of its methane emissions", "                       In total, the US transportation sector produces nearly thirty percent of all US global warming emissions", "The consumption of fossil fuel by the United States has been 80%. Fossil fuels are the most dangerous contributors to global warming"
  ]
//Impact Tags
var impactNames = [
  "agriculture", "transportation", "fossil        fuels", "you win"];

var impactImages;

//Images Preload

function preload() {
    impactImages =         loadImage(impactImageLinks[n]);
    currentImpactImageIndex = 0;
}

//Setup, Load in Images
function setup() {
  createCanvas(600, 600);
 
  currentImpactImage = impactImages;
  currentImpactImage.loadPixels();
 
  strokeWeight(0.25);
  stroke(dist(width/2, height/2, mouseX, mouseY), 10, 200);
  noFill();
}
 
 
function draw() {
 
  //Background color + opacity setup  
  background(255,0,0,10);
  tint(500, 20);

  //Dynamic ice grid setup 
  for (let x = 0; x <= width; x = x + 50) {
    for (let y = 0; y <= height; y = y + 50) {

      const xAngle = map(45, 0, width, -4 *         PI* 3, 4 * PI * 3, true);
      const yAngle = map(45, 0, height, -4 *         PI, 4 * PI, true);

      const angle = xAngle * (x / width) +           yAngle * (y / height);


      const myX = x + 20 * cos(2 * PI/4 *           movementIntensity + angle/10);
      const myY = y + 20 * sin(2 * PI/2 *           movementIntensity + angle/10);     
      stroke(0,255,255,200);
      strokeWeight(n);
      fill('white');
      rectMode(CENTER);
     
      rect(myX, myY, dist(myX, myY, mouseX,         mouseY)/impactSize[n],dist(myX, myY,           mouseX, mouseY)/impactSize[n]); // draw       particle5
    }
  }
 
  //Impact Icons Config + draw
  imageMode(CENTER);
  currentImpactImage.resize(100, 100);
  image(currentImpactImage, mouseX, mouseY);
 

  
  textFont('Helvetica');
  
  noStroke();
  
  fill('white');
  
  rect (width/2, 500, width, 60);
  
  fill('black');
  
  textSize(25);
  
  //C02 Emmited updating Text

  text('TONNES OF CO2 EMITTED : ' + co2, 40, 509);
  fill(255);
  //C02 emmision text backdrop

  rect(width/2, 100, width, 40);
  fill(0);
  textSize(10);
  text(impactFacts[n], width/2 - 295, 105);
  
  //C02 Count Multiplier
  co2 = co2 + 10 * n * 20;
  
  textSize(32);
    
  
  //game over text
  if (n == 4) {
    fill(0);
    text('YOU WIN! ICE CAPS MELTED.', mouseX - 200,           mouseY + 100);
  
    textFont('Helvetica');
    }
  
    else {
    
    textSize(6 * n);
    text('PRESS TO INCREASE YOUR ECOLOGICAL FOOTPRINT!',       mouseX - 120 * n, mouseY + 100);
  
  }
  
  //Ice Movement Intensity Multiplier
  movementIntensity = movementIntensity + 0.01 +n/150;

}

//Mouse Click functions

function mousePressed(){
   
    //change impact icons on click
    impactImages = loadImage(impactImageLinks[n]);
    currentImpactImage = impactImages;

    currentImpactImage.loadPixels();
    //increase step on click
    n = n + 1;
   
    if (n > 4) {
        n = 0;
    }

}

CJ Walsh – Final Project

sketch

// CJ Walsh
// cjwalsh@andrew.cmu.edu
// Section D
// Final Project

// creating variables for turtles
var trl;
var trl2;
var trl3;
var trl4;
var trl5;

function setup() {
 createCanvas(600, 600);
 frameRate(4); // giving a speed to the movement of the lines
 
}

function draw() {
	background(0);

	
	// drawing the three lines and looping them 
	for (var y = 20; y < height + 10; y += 50) {
		for (var x = 10; x < width + 10; x += 50) {

			
			trl = makeTurtle(x, y -5);
			trl.setColor('red');
			trl.forward(random(2, 15)); // random lengths to create texture
			trl.penUp(); // pulling pen up to move without mark making 
			trl.forward(10);
			trl.penDown();
			trl.forward(random(4, 10));

			
			trl2 = makeTurtle(x, y);
			trl2.setColor('red');
			trl2.forward(random(2, 20));
			trl2.penUp();
			trl2.forward(10);
			trl2.penDown();
			trl2.forward(random(4, 10));

			trl3 = makeTurtle(x, y + 5);
			trl3.setColor('red');
			trl3.forward(random(2, 20));
			trl3.penUp();
			trl3.forward(10);
			trl3.penDown();
			trl3.forward(random(4, 10));


			
		}
	}
	
	//noLoop();

}

function turtleLeft(d){this.angle-=d;}function turtleRight(d){this.angle+=d;}
function turtleForward(p){var rad=radians(this.angle);var newx=this.x+cos(rad)*p;
var newy=this.y+sin(rad)*p;this.goto(newx,newy);}function turtleBack(p){
this.forward(-p);}function turtlePenDown(){this.penIsDown=true;}
function turtlePenUp(){this.penIsDown = false;}function turtleGoTo(x,y){
if(this.penIsDown){stroke(this.color);strokeWeight(this.weight);
line(this.x,this.y,x,y);}this.x = x;this.y = y;}function turtleDistTo(x,y){
return sqrt(sq(this.x-x)+sq(this.y-y));}function turtleAngleTo(x,y){
var absAngle=degrees(atan2(y-this.y,x-this.x));
var angle=((absAngle-this.angle)+360)%360.0;return angle;}
function turtleTurnToward(x,y,d){var angle = this.angleTo(x,y);if(angle< 180){
this.angle+=d;}else{this.angle-=d;}}function turtleSetColor(c){this.color=c;}
function turtleSetWeight(w){this.weight=w;}function turtleFace(angle){
this.angle = angle;}function makeTurtle(tx,ty){var turtle={x:tx,y:ty,
angle:0.0,penIsDown:true,color:color(128),weight:1,left:turtleLeft,
right:turtleRight,forward:turtleForward, back:turtleBack,penDown:turtlePenDown,
penUp:turtlePenUp,goto:turtleGoTo, angleto:turtleAngleTo,
turnToward:turtleTurnToward,distanceTo:turtleDistTo, angleTo:turtleAngleTo,
setColor:turtleSetColor, setWeight:turtleSetWeight,face:turtleFace};
return turtle;}

For my project I wanted to create a series of generated textiles using loops and turtles. Each piece is an experiment with shape, repetition, color, placement and movement. Three are static pieces and three have movement. I really enjoyed creating each one, and they range in work time and difficulty of production. Even though some of them seem simple, each is carefully considered and planned out to get the effect that I wanted. Textile #6 is one of my favorites because it is a version of a precedent project that I wrote about in a Looking Outwards post. In my randomness post, I really enjoyed Georg Nees piece so #6 is my own version using randomness and movement to create a fun generative sketch. Overall I am happy with the outcome and look forward to using what I learned in this class to continue to generate fun imagery. A zip file is attached below containing all of the code for the 6 images.

Final Project

sketch

// CJ Walsh
// cjwalsh@andrew.cmu.edu
// Section D
// Final Project

var trl; // variable for turtle

function setup() {
    createCanvas(600, 600);
    
    frameRate(8);
    
}

function draw() {
	background(220);

	//grid of turtles
	for (var y = 10; y < height + 10; y += 50) {
		for (var x = 10; x < width + 10; x += 50) {
			trl = makeTurtle(x, y); // make turtle

			// random generate to create fun sketch movement quality
			trl.right(random(2, 60));
			trl.forward(random(4, 16));
			trl.left(random(20, 120));
			trl.forward(random(4, 10));
			trl.right(random(60, 145));
			trl.forward(10);
			trl.right(random(40, 227));
			trl.forward(random(5, 15));
			
		}
	}
	
	


}

function turtleLeft(d){this.angle-=d;}function turtleRight(d){this.angle+=d;}
function turtleForward(p){var rad=radians(this.angle);var newx=this.x+cos(rad)*p;
var newy=this.y+sin(rad)*p;this.goto(newx,newy);}function turtleBack(p){
this.forward(-p);}function turtlePenDown(){this.penIsDown=true;}
function turtlePenUp(){this.penIsDown = false;}function turtleGoTo(x,y){
if(this.penIsDown){stroke(this.color);strokeWeight(this.weight);
line(this.x,this.y,x,y);}this.x = x;this.y = y;}function turtleDistTo(x,y){
return sqrt(sq(this.x-x)+sq(this.y-y));}function turtleAngleTo(x,y){
var absAngle=degrees(atan2(y-this.y,x-this.x));
var angle=((absAngle-this.angle)+360)%360.0;return angle;}
function turtleTurnToward(x,y,d){var angle = this.angleTo(x,y);if(angle< 180){
this.angle+=d;}else{this.angle-=d;}}function turtleSetColor(c){this.color=c;}
function turtleSetWeight(w){this.weight=w;}function turtleFace(angle){
this.angle = angle;}function makeTurtle(tx,ty){var turtle={x:tx,y:ty,
angle:0.0,penIsDown:true,color:color(128),weight:1,left:turtleLeft,
right:turtleRight,forward:turtleForward, back:turtleBack,penDown:turtlePenDown,
penUp:turtlePenUp,goto:turtleGoTo, angleto:turtleAngleTo,
turnToward:turtleTurnToward,distanceTo:turtleDistTo, angleTo:turtleAngleTo,
setColor:turtleSetColor, setWeight:turtleSetWeight,face:turtleFace};
return turtle;}

Included below are some process shots of playing with color and pattern:

Jina Lee – Final Project


Here is a video to see how the maze works. 

Word Press doesn’t show you the camera screen so it is difficult to navigate the dots because of the file being so big.  Please download this html to play the maze with the camera if you want to see where your tracker is: jinal2-final project. It works best on Chrome. Thank you!

What is it? I know that we did not have much experience with using our webcam into our code, but I really wanted to implement an interactive game that used it. For my project, I wanted to create a camera censored maze game that was moved through your pupils. Before creating the final result, I researched how to sensor your pupils so that the dots follow wherever you look when you are playing the game. However, that was way too ambitious as I struggled to understand how to implement that concept into my code. In the end, I made the camera sensor for any objects that are red so that it will create dots on them.

Due to me not being able to make the game restart when you hit the maze lines, I made the dots go back to the start position when the red tracker is out of the webcam frame. I know that this class is over now, but there are things that I would like to add to my project.  Because it took so much longer to try to get the pupil sensors to work, I did not get to work more on other things that I wanted to get to. First, I want to make an “ERROR” sign when the dots hit the white lines of the maze. In addition, I would want to create an intro that would help people calibrate their red object with the screen so that it is easier to control. I had a lot of fun with this project while also pushing myself to try to create something that was way out of my comfort zone.

sketch

// Jina Lee
// jinal2@andrew.cmu.edu
// Section E
// 15-104 Final Project

// This codes uses the webcam to create red dots that will
// follow any red color on the camera.

var myCaptureDevice;
// This array stores the x value of the red positions
var xarray = [];
// This array stores the y value of the red positions
var yarray = [];
// Limits of x and y arrays
var sizeLimit = 10;
var redCircle = 1;

function setup() {
    createCanvas(500, 500);
    // Camera
    myCaptureDevice = createCapture(VIDEO);
    myCaptureDevice.size(500, 500);
}

function isColor(c) {
    // Tests the colors
    return (c instanceof Array);
}


function draw() {
    // Background
    fill(0);
    rect(0, 0, 500, 500);
    // Maze
    stroke(255);
    strokeWeight(10);
    line(250, 250, 250, 320);
    line(250, 250, 250, 320);
    line(250, 320, 320, 320);
    line(320, 320, 320, 190);
    line(320, 320, 320, 180);
    line(320, 180, 180, 180);
    line(180, 180, 180, 370);
    line(180, 370, 380, 370);
    line(380, 370, 380, 130);
    line(380, 130, 135, 130);
    line(135, 130, 135, 420);
    line(135, 420, 430, 420);
    line(430, 420, 430, 70);
    line(430, 70, 70, 70);
    //boxes
    fill(255);
    noStroke();
    rect(65, 65, 50, 50, 10);
    rect(-5, 150, 100, 100, 10);
    rect(60, 300, 80, 80, 10);
    rect(-10, 430, 70, 70, 10);
    // Starting Spot
    fill(255);
    rect(225, 230, 50, 50, 10);
    textSize(10);
    textFont('Helvetica');
    fill('green');
    text("START", 235, 260);
    // Exit Spot
    fill(255);
    rect(440, 470, 50, 50, 10);
    textSize(10);
    textFont('Helvetica');
    fill('red');
    text("END", 455, 495);

    // Red dots are created because of camera sensor
    var xMin = 0;
    var xMax = 500;
    var yMin = 0;
    var yMax = 500;
    // For loop that draws the dots
    for (var a = 0; a < xarray.length; a++){
        // Ellipse
        if (redCircle === 1){
            noStroke();
            fill('red');
            ellipse(xarray[a], yarray[a], 5, 5);
        }
    }
    for (var i = 0; i < width; i += 5){
        for (var q = 0; q < height; q += 5) {
            var currentColor = myCaptureDevice.get(i, q);
            var r = red(currentColor) - 255;
            var g = green(currentColor) - 0;
            var b =  blue(currentColor) - 0;
            // If rbg matches criteria
            // than get the center point of the red area
            // and put it in an array
            if (isColor(currentColor)){
                var dist = sqrt(sq(r) + sq(g) + sq(b));
                if (dist < 120) {
                    // Finds the location of the red areas on the web cam
                    // Finds the smallest x location
                    if (i > xMin){
                        xMin = i;
                    }
                    // Find the biggest x location
                    if (i < xMax){
                        xMax = i;
                    }
                    // Finds the smallest y loctaion
                    if (q > yMin){
                        yMin = q;
                    }
                    // Finds the biggest y location
                    if (q < yMax){
                        yMax = q;
                    }
                }
    		    }
    	  }
    }
    // Push the new x of red from camera into the array
    xarray.push((xMin + xMax) / 1.9);
    // Push the new y of red from camera into the array
    yarray.push((yMin + yMax) / 1.7);
    // When array is full, it will pop something out from the beginning
    while (xarray.length > sizeLimit) {
        xarray.shift();
        yarray.shift();
    }
}

Final Project – Alice Cai

sketch

//Alice Cai
//Section E
//alcai@andrew.cmu.edu
//Final Project

//global variables for letter A
//starting point of angles for turning
var angleA = 0; 
var angleA2 = 0;
//starting velocity of turning
var velA2 = -1;
//starting location
var y = 0; 
//color variables
var r;
var g;
var b;

//global variables for letter B
var angleC = 70;
var angleC2 = 90;
var cVel1 = 0;
var cVel2 = 0;
//varying starting sizes of circles
var size1 = 1;
var size = 0;
var rC;
var gC;
var bC;

function setup() {
  createCanvas(600, 300);
  frameRate(10); //slow down framerate
}

function draw() {
    //background is random color
    background(g, r, r);
    //constrain black circle to height of canvas
    let cc = constrain(mouseX, 0, height);
    //keep ellipse concentric to either center of A or the entire A
    if (mouseX > width / 5) {
        var cy = height / 2;
    } else {
        cy = height / 2 + 30;
    }
    fill(0);
    ellipse(width /4, cy, cc,cc);

    //draw A cap/serif. Made up of  a varying amount of circles controlled by mouseX
    for (var i = 0; i <= mouseX; i ++) {
        noStroke();
        push();
        translate(width /4, height / 2 - 110 + 75);
        rotate(radians(angleA2));
        fill(r, b, g);
        ellipse(50, y, 30, 30);
        pop();
        angleA2 = angleA2 + velA2;

    //constrain rotating movment of ellipses to the shape of a 
    if (angleA2 < -135 ) {
        velA2 = velA2 * -1;
    }

    //if surpasses "semicircle", stop rotating and move downwards.
    if (angleA2  >= 0 & velA2 === 1) {
        angleA2 = 0;
        y = y + velA2;
    }

    //if hits bottom, come back up
    if (y > 115) {
        y = y - 115;
        velA2 = velA2 * -1;
        angleA2 = angleA2 + velA2;
    }
  }

    //draw circle made up of more circles, quantity/length controled by mouseX
    for (var i = 0; i <= mouseX / 2; i ++) {
        noStroke();
        push();
        translate(width / 4, height / 2 + 30);
        rotate(radians(angleA));
        let xc = constrain(mouseX, 0, 50); //constrain diameter of circle
        fill(r, b, g);
        ellipse(xc, 0, 30, 30);
        pop();
        angleA = angleA - i * 0.8;
    }

    //draw C, made up of circles
    for (var i = 0; i <= 45; i ++) {
        noStroke();
        push();
        translate(width / 4 * 3, height / 2);
        //C is constantly roatating
        rotate(radians(angleC + i * 5));
        //constrain size of C based on mouseX
        let xc = constrain(mouseX / 4, 0 , width / 8);
        fill(bC, rC, gC);
        ellipse(xc, 0, 30, 30);
        angleC = angleC - cVel1;
        pop();
    }

    //constrain rotation of C to go back and forth and not become a circular motion
    if (angleC2 < 90) {
        cVel1 = cVel1 * -1;
    }

    if (angleC2 > 0) {
        cVel1 = cVel1 * -1;
    }

    //create two rings of circles around and inside C
    let numb = constrain(mouseX, 0, 50)
    for (var a = 0; a <= numb / 5; a ++) {
        noStroke();
        push();
        translate(width / 4 * 3, height / 2);
        rotate(radians(a * 25 + angleC2 ));
        fill(rC, bC , gC );
        size1 = size1 + cVel1
        let xc = constrain(size1, 0, width / 8)
        var size = 5;
        //ellipse size varies with sin and cosine to create explosive firework effect when clicked
        ellipse(xc - 30, 0,  size + xc / 3 * cos(xc) / 2,  size + xc / 3 * cos(xc) / 2);
        angleC2 = angleC2 + cVel1;
        pop();
    }

    for (var a = 0; a <= 20; a ++) {
        noStroke();
        push();
        translate(width / 4 * 3, height / 2);
        rotate(radians(a * 20 + angleC2 - 30));
        fill(bC, gC, rC);
        size1 = size1 + cVel2
        let xc = constrain(size1, 0, width / 5)
        var size = 5;
        ellipse(xc, 0,  size + xc / 3 * sin(xc),  size + xc / 3 * sin(xc));
        angleC = angleC - cVel2 ;
        pop();
    }
}

function mousePressed() {
    loop(); //starts loop
    r = random(100, 255); // r is a random number between 100 - 255
    g = random(100, 255); // g is a random number betwen 100-255
    b = random(100, 255); //b is a random number betwen 100 - 255

    //set velocity and size for movement
    size1 = 1
    cVel2 = 1
    cVel1 = 0.5
    rC = random(100, 255);
    gC = random(30, 200);
    bC = random(100, 255);
}

function mouseReleased() {
    noLoop(); //freezes loop
    //set velocity and sizes to 0
    size1 = 0
    cVel2 = 0
    cVel1 = 0
    angleC = 70 //set C angle to standard
}

This is a fun animation of my initials AC; I wanted to get more into creating motion graphics and decided it would be useful to begin brainstorming animations for a logo or graphic for my website. Interact by clicking and releasing, as well as dragging your mouse across the page. Colors change every click. The motif of circles runs throughout the construction of each letter; every line is drawn with ellipses. Thus, at any frame of the animation, the composition is somewhat unified.