Sihand – Final Project – Snapchat Dog Filter

Dog Filter

filter demonstration

My initial proposal was to create a piece of shadow art. However as I proceeded with the project, I realized that it wasn’t feasible because of two reasons. First is that based on what I am capable of, creating a sufficiently detailed silhouette will cause the image to load very slowly, but in order to make it load at an acceptable speed, the compromise in quality is too big. Second is that the implementing different “monsters” further bogged down the program and was not able to achieve what I pictured.

However, during the course of exploration, I figured out that the falling effect resembles that of a snapchat filter to some extent. So I decided to recreate a primitive version of Snapchat’s signature filter – The Snapchat Dog Filter – and add in some falling snow, since it’s almost Christmas.

To play around with it, carefully place one eye at its corresponding crosshair point, and the filter will come into effect! Have fun!

sihan 23:09

//Sihan Dong
//sihand@andrew.cmu.edu
//Section B
//FINAL PROJECT: snapchat filter

var px;
var py;
var darknessThreshold = 10;
var outlines = [];

//update the falling stuff
function outlineUpdate() {
    var theColorAtPxPy = myCaptureDevice.get(this.px, this.py);

    if(isColor(theColorAtPxPy)){
        var theBrightnessOfPxPy = brightness(theColorAtPxPy);
        if (theBrightnessOfPxPy > darknessThreshold) {
            this.py = this.py + 3;
    } 
 
    while (this.py > 0 & theBrightnessOfPxPy < darknessThreshold) {
            this.py = this.py - 3;
            col = myCaptureDevice.get(this.px, this.py);
            if (isColor(col)) {
                theBrightnessOfPxPy = brightness(col);
            } 
        }     
    }
    
}


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

//draw the falling snow
function outlineRender() {

    var theColorAtPxPy = myCaptureDevice.get(this.px, this.py);
    if(isColor(theColorAtPxPy)){
        var theBrightnessOfPxPy = brightness(theColorAtPxPy);
    
            stroke(255);
            strokeWeight(theBrightnessOfPxPy/20);
            
            //render the flake
            line(this.px - theBrightnessOfPxPy, this.py, this.px+theBrightnessOfPxPy, this.py);
            line(this.px, this.py + theBrightnessOfPxPy, this.px, this.py - theBrightnessOfPxPy);
            line(this.px - theBrightnessOfPxPy/2, this.py - theBrightnessOfPxPy/2,
                        this.px + theBrightnessOfPxPy/2, this.py + theBrightnessOfPxPy/2);
            line(this.px + theBrightnessOfPxPy/2, this.py - theBrightnessOfPxPy/2,
                        this.px - theBrightnessOfPxPy/2, this.py + theBrightnessOfPxPy/2);
        
        
        fill(255, 255, 255, 100 - theBrightnessOfPxPy);


    }
}

//start from the top once the falling snow reach the bottom
function outlineReset() {
    if (this.py > height-3) {
        this.py = 0;


    }
}


//the object function that make the falling snow
function makeOutline(inputX, inputY){
    outline = {px: inputX, py: inputY, 
            update: outlineUpdate,
            reset: outlineReset,
            render: outlineRender  
           };
    return outline;
}


//draw the eye detector
function drawGrid(){
    stroke(246, 192, 94);
    strokeWeight(1);
    line(300, 0, 300, height);
    line(400, 0, 400, height);
    line(0, 2*height/7, width, 2*height/7);
   
}

//draw the left ear of the filter
function drawLeft(lx, ly){
    fill(149, 108, 67);
    noStroke();
    triangle(lx, ly + noise(60), lx - 20, ly - 30+ noise(60), 
        lx + 30, ly - 50+ noise(60));

}

//draw the right ear of the filter
function drawRight(rx, ry){
    fill(149, 108, 67);
    noStroke();
    triangle(rx, ry + noise(60), rx + 20, ry - 30, 
        rx - 30, ry - 50);

}

//draw the nose of the filter
function drawMiddle(mx, my){
    fill(117, 76, 43);
    ellipseMode(CENTER);
    ellipse(mx, my + 10, 90, 60);

    fill(152, 111, 77);
    ellipse(mx - 20, my + 10, 30, 20);
    ellipse(mx + 20, my + 10, 30, 20);
    
    fill(86, 58, 43);
    ellipse(mx, my, 30, 30);

    fill(39, 19, 12);
    ellipse(mx - 8, my + 3, 10, 10);
    ellipse(mx + 8, my + 3, 10, 10);

    fill(255);
    ellipse(mx + 8, my - 8, 10, 5);

}

function setup() {
    createCanvas(640, 480);
    myCaptureDevice = createCapture(VIDEO);
    myCaptureDevice.size(640, 480); // attempt to size the camera. 
    myCaptureDevice.hide(); 
    
    var nb = 20;
    var pointPosition = 0;
     for (var i = 0; i < nb; i++) {

        pointPosition++;
        var outlineFormation = makeOutline(pointPosition*width/nb, 0);//, height - 20);
        outlines.push(outlineFormation);

    }
}

function draw(){
    background(220);
    myCaptureDevice.loadPixels(); //camera setup
    image(myCaptureDevice, 0, 0);
    noStroke();
    
    drawGrid();
    var colorOfEye1 = myCaptureDevice.get(width*4/9, 2*height/7);
    var colorOfEye2 = myCaptureDevice.get(2*width/3, 2*height/7);
    var bOfEye1 = brightness(colorOfEye1);
    var bOfEye2 = brightness(colorOfEye2);
    
 //if either eye is detected at the crosshair, start the filter
    if (bOfEye1 < 20 || bOfEye2 < 20){
        push();
        translate(30, 50);
        drawLeft(width/3, height/10);
        drawRight(2*width/3, height/10);
        drawMiddle(width/2, height/5 + 30);
        pop();


        for (var i = 0; i < outlines.length; i++) {
            var silhouette = outlines[i];
            silhouette.update();
            silhouette.reset();
            silhouette.render();
        }
    }
    
    print(bOfEye1);
}


Denise Jiang – Final Project

For my final project I continued developed the random landscape project, adding a collision with one of the planets. I loaded more images to get the effect and modified the direction of background stars so they look more real when the spaceship is traveling ahead. The collision and explosion would bring the animation to an end.

sketch

//create objects
var planets = [];
var starsLeft = [];
var redStar = [];
var starsRight = [];
var starsBR = [];
var starsBL = [];
var size2 = 20;
var size3 = 350;
var light;
var light2;
var smoke;
var boom;

function preload(){
	light = loadImage("http://i.imgur.com/rU3fzb5.png");
	light2 = loadImage("http://i.imgur.com/UsbCAS5.png");
	smoke = loadImage("http://i.imgur.com/3Uer6bI.png");
	boom = loadImage("http://i.imgur.com/9V62Xu1.png");
}

function setup() {
    createCanvas(600,400);
      frameRate(8);
	// initial planet and stars
		var initialX = random(width/2);
		planets[0] = makePlanets(initialX);
		redStar[0] = makeRedPlanets(initialX);
		redStar[1] = makeRedPlanets(initialX);
		

}

function draw() {
	background(0);
	PlanetsinMotion();
	addPlanets();
	StarsLinMotion();
	addStarsL();
	redStarinMotion();
	addRed();
	StarsRinMotion();
	addStarsR();
	StarsBRinMotion();
	addStarsBR();
	StarsBLinMotion();
	addStarsBL();

	fill("blue");
	noStroke();
	strokeWeight(2);
	ellipse(width/2, height/2, size2, size2);
	size2 +=1;
	if (size2 > 200){
		if (frameCount%2 > 0) {
			image(light, 0,0, 500 ,500);
		}
		
	}
	if (size2 > 300) {
			image(light2, 100, 0, 500, 500);
	}


	spaceship();

	if (size2 > 400) {
		fill("black");
		rect(0, 0, 600, 400);
		fill(255, 108, 17);
		ellipse(width/2, height/2, size3, size3);
		size3 -= 20;
		image(boom, 0, -100, 600, 600);
	}

}


// all about the planets
function PlanetsinMotion() {
	for (var i = 0; i < planets.length; i++) {
		planets[i].move();
		planets[i].display();
	}
}
function addPlanets() {
	var maybeAdd = 0.004;
	if (random(0,1) < maybeAdd) {
		planets.push(makePlanets(width));
	}
}
function moveplanets() {
	this.x += this.speedX;
	this.y += this.speedY;
}
function displayplanets() {
    fill(187, 210, 247);
	noStroke();
	ellipse(this.x, this.y, this.randomsize, this.randomsize);//blue planets
	this.randomsize += -0.01;
}
function makePlanets(planetX) {
	var plt = { x: planetX,
		        y: height/2,
		        speedX: -1.0,
		        speedY: -0.5,
		        randomsize: random (10, 50),
		        move: moveplanets,
		        display: displayplanets,
		        }
    return plt;
}

//all about the red stars
function redStarinMotion() {
	for (var i = 0; i < redStar.length; i++) {
		redStar[i].move();
		redStar[i].display();
	}
}
function moveRed() {
	this.x += this.speedX;
	this.y += this.speedY;
}
function displayRed() {
	fill(122, 43, 19);
	noStroke();
	ellipse(this.x, this.y, this.randomsize, this.randomsize);
	this.randomsize += 0.1;
}
function addRed() {
	var maybeAdd = 0.003;
	if (random(0,1) < maybeAdd) {
		redStar.push(makeRedPlanets(width));
	}
}
function makeRedPlanets(redX) {
	var red = {x: random(100,200),
		       y: random(height-50, height-100),
		       speedX: -0.5,
		       speedY: -0.7,
		       randomsize: random(5, 8),
		       move: moveRed,
		       display: displayRed
	           }
	return red;

}

//all about the starsL
function StarsLinMotion() {
	for (var i = 0; i < starsLeft.length; i++){
		starsLeft[i].move();
		starsLeft[i].display();
	}
}
function displayStarsL() {
	stroke("white");
	point(this.x, this.y);
}
function addStarsL() {
    var maybeAdd = 0.6;
	if (random(0,1) < maybeAdd) {
		starsLeft.push(makeStarsL());
	}
}
function moveStarsL() {
	this.x += this.speedX;
	this.y += this.speedY;
}
function makeStarsL() {
	var str = {x: random(0, width/2-50),
	           y: random(0, height/2+50),
	           speedX: -1.0,
	           speedY: -0.7,
	           move: moveStarsL,
	           display: displayStarsL
	       	   }
	return str;
}



//all about the starsRight
function StarsRinMotion() {
	for (var i = 0; i < starsRight.length; i++){
		starsRight[i].move();
		starsRight[i].display();
	}
}
function displayStarsR() {
	stroke("white");
	point(this.x, this.y);
}
function addStarsR() {
    var maybeAdd = 0.3;
	if (random(0,1) < maybeAdd) {
		starsRight.push(makeStarsR());
	}
}
function moveStarsR() {
	this.x += this.speedX;
	this.y += this.speedY;
}
function makeStarsR(StarX) {
	var strR = {x: random(width/2-2, width-50),
	           y: random(0, height/2+10),
	           speedX: 1.0,
	           speedY: -0.7,
	           move: moveStarsR,
	           display: displayStarsR
	       	   }
	return strR;
}


//all about the starsBR
function StarsBRinMotion() {
	for (var i = 0; i < starsBR.length; i++){
		starsBR[i].move();
		starsBR[i].display();
	}
}
function displayStarsBR() {
	stroke("white");
	point(this.x, this.y);
}
function addStarsBR() {
    var maybeAdd = 0.3;
	if (random(0,1) < maybeAdd) {
		starsBR.push(makeStarsBR());
	}
}
function moveStarsBR() {
	this.x += this.speedX;
	this.y += this.speedY;
}
function makeStarsBR(StarX) {
	var strBR = {x: random(width/2-2, width-50),
	           y: random(height/2-10, height),
	           speedX: 1.0,
	           speedY: 0.7,
	           move: moveStarsBR,
	           display: displayStarsBR
	       	   }
	return strBR;
}


//all about the starsBL
function StarsBLinMotion() {
	for (var i = 0; i < starsBL.length; i++){
		starsBL[i].move();
		starsBL[i].display();
	}
}
function displayStarsBL() {
	stroke("white");
	point(this.x, this.y);
}
function addStarsBL() {
    var maybeAdd = 0.3;
	if (random(0,1) < maybeAdd) {
		starsBL.push(makeStarsBL());
	}
}
function moveStarsBL() {
	this.x += this.speedX;
	this.y += this.speedY;
}
function makeStarsBL(StarX) {
	var strBL = {x: random(0, width/2+50),
	           y: random(height/2-10, height),
	           speedX: -1.0,
	           speedY: 0.7,
	           move: moveStarsBL,
	           display: displayStarsBL
	       	   }
	return strBL;
}


//creating the interior of spaceship
function spaceship() {
	noStroke();
	fill(53, 58, 66);
	rect(0, 315, width, height-315);//floor
	fill(95, 105, 122);//light color
	quad(287, 0, 357, 0, 419, 26, 397, 53);//3rd wall 1
	quad(311, 255, 173, 249, 184, 269, 311, 271);//2nd wall 1
	quad(27, 213, 0, 223, 0, 269, 30, 269);//1st wall 3
	quad(30, 269, 25, 381, 0, 361, 0, 269);//1st wall 4
	fill(81, 90, 104);// medium light
	quad(419, 26, 397, 53, 409, 126, 497, 110);//3rd wall 2
	quad(311, 255, 311, 271, 476, 276, 497, 250);//3rd wall 4
	quad(311, 330, 311, 271, 184, 269, 186, 339);//2nd wall 2
	triangle(495, 0, 357, 0, 419, 26);//1st wall 1-3
	fill(73, 81, 94);//slightly dark
	quad(409, 126, 497, 110, 497, 250, 311, 255);//3rd wall 3
	quad(476, 351, 476, 276, 311, 271, 311, 330);//3rd wall 6
	quad(600, 87, 497, 110, 419, 26, 495, 0);//4th wall 1
	triangle(495, 0, 600, 87, 600, 0);//4th wall 1-2
	fill(62, 68, 78);//dark
	quad(476, 276, 497, 250, 497, 334, 476, 349);//3rd wall 5
	fill(144, 156, 175);//lightest
	quad(187, 271, 162, 229, 27, 213, 30, 269);//1st wall 1
	fill(122, 133, 153);//still very light
	quad(30, 269, 187, 271, 186, 357, 25, 381);//1st wall 2
	fill(65, 73, 86);//darkest
	quad(497, 110, 600, 87, 600, 130, 497, 150);//4th wall 2-1
	quad(497, 150, 536, 142, 536, 345, 497, 334);//4th wall 2-2
	quad(536, 345, 536, 262, 600, 268, 600, 360); //4th wall 2-3


	if (size2 > 350) {
		image(smoke, 0, 0, 500, 300);
	}


}

Shannon Case – Final Project

sketch

//Shannon Case
//Section D
//scase@andrew.cmu.edu
//final project

var eye = [];
var eyeframes = [];

var jar = [];
var jarframes = [];

var fish = [];
var fishframes = [];

var fl = [];
var flframes = [];

var tummy = [];
var tummyframes = [];

var bubbles = [];
var bubblesframes = [];

var pows = [];
var powsframes = [];

var cigs = [];
var cigsframes = [];

var lips = [];
var lipsframes = [];

var swirl = [];
var swirlframes = [];

var word = [];
var wordframes = [];

//global variables for the arrays to store all of my images 

var index;
var index2;
var index3;
var index4;
var index5;
var index6;
var index7;
var index8;
var index9;
var index10;
var index11;

//create index to display images

var s1;
var s2;
var s3;
var s4;
var s5;
var s6;
var s7;
var s8;
var s9;
var s10;
var s11;

//variables for each sound

function preload(){
   s1 = loadSound("audio/sound1.ogg");
   s2 = loadSound("audio/sound2.ogg");
   s3 = loadSound("audio/sound3.ogg");
   s4 = loadSound("audio/poppopPOP.ogg");
   s5 = loadSound("audio/sound4.wav");
   s6 = loadSound("audio/sound6.wav");
   s7 = loadSound("audio/sound7.wav");
   s8 = loadSound("audio/sound8.wav");
   s9 = loadSound("audio/sound9.wav");
   s10 = loadSound("audio/sound10.wav");
   s11 = loadSound("audio/sound11.wav");

  myLoop = loadSound("audio/bgsound.ogg");

//load sounds
  
  eye[0]="images/eye1.png";
  eye[1]="images/eye2.png";
  eye[2]="images/eye3.png";
  eye[3]="images/eye4.png";
  eye[4]="images/eye5.png";
  eye[5]="images/eye6.png";
  eye[6]="images/eye7.png";
  eye[7]="images/eye8.png";
  
  jar[0]="images/jar1.png";
  jar[1]="images/jar2.png";
  jar[2]="images/jar1 2.png";
  jar[3]="images/jar2 2.png";
  jar[4]="images/jar1 3.png";
  jar[5]="images/jar2 3.png";
  jar[6]="images/jar1 4.png";
  jar[7]="images/jar1 4.png";
  
  fish[0]="images/fish1.png";
  fish[1]="images/fish2.png";
  fish[2]="images/fish3.png";
  fish[3]="images/fish4.png";
  fish[4]="images/fish5.png";
  fish[5]="images/fish3.png";
  fish[6]="images/fish7.png";
  fish[7]="images/fish8.png";
  
  fl[0]="images/f1.png";
  fl[1]="images/f2.png";
  fl[2]="images/f3.png";
  fl[3]="images/f4.png";
  fl[4]="images/f5.png";
  fl[5]="images/f6.png";
  fl[6]="images/f7.png";
  fl[7]="images/f8.png";
  
  tummy[0]="images/tummy1.png";
  tummy[1]="images/tummy2.png";
  tummy[2]="images/tummy3.png";
  tummy[3]="images/tummy4.png";
  tummy[4]="images/tummy5.png";
  tummy[5]="images/tummy6.png";
  tummy[6]="images/tummy7.png";
  tummy[7]="images/tummy8.png";
  
  bubbles[0]="images/bubbles1.png";
  bubbles[1]="images/bubbles2.png";
  bubbles[2]="images/bubbles3.png";
  bubbles[3]="images/bubbles4.png";
  bubbles[4]="images/bubbles5.png";
  bubbles[5]="images/bubbles6.png";
  bubbles[6]="images/bubbles7.png";
  bubbles[7]="images/bubbles8.png";
  
  pows[0]="images/pow1.png";
  pows[1]="images/pow2.png";
  pows[2]="images/pow3.png";
  pows[3]="images/pow4.png";
  pows[4]="images/pow5.png";
  pows[5]="images/pow6.png";
  pows[6]="images/pow7.png";
  pows[7]="images/pow8.png";
  
  cigs[0]="images/cig1.png";
  cigs[1]="images/cig2.png";
  cigs[2]="images/cig3.png";
  cigs[3]="images/cig4.png";
  cigs[4]="images/cig5.png";
  cigs[5]="images/cig6.png";
  cigs[6]="images/cig7.png";
  cigs[7]="images/cig8.png";
  
  lips[0]="images/lips1.png";
  lips[1]="images/lips2.png";
  lips[2]="images/lips3.png";
  lips[3]="images/lips4.png";
  lips[4]="images/lips5.png";
  lips[5]="images/lips6.png";
  lips[6]="images/lips7.png";
  lips[7]="images/lips8.png";
  
  swirl[0]="images/swirl1.png";
  swirl[1]="images/swirl2.png";
  swirl[2]="images/swirl3.png";
  swirl[3]="images/swirl4.png";
  swirl[4]="images/swirl5.png";
  swirl[5]="images/swirl6.png";
  swirl[6]="images/swirl7.png";
  swirl[7]="images/swirl8.png";
  
  word[0]="images/word1.png";
  word[1]="images/word2.png";
  word[2]="images/word3.png";
  word[3]="images/word4.png";
  word[4]="images/word5.png";
  word[5]="images/word6.png";
  word[6]="images/word7.png";
  word[7]="images/word8.png";
  
//load all the images
  
  for(var a = 0; a<8; a++){
    eyeframes[a] = loadImage(eye[a]);
    }
    
  for(var b = 0; b<8; b++){
    jarframes[b] = loadImage(jar[b]);
    }
    
  for(var c = 0; c<8; c++){
    fishframes[c] = loadImage(fish[c]);
    }
    
  for(var d = 0; d<8; d++){
    flframes[d] = loadImage(fl[d]);
    }
  
  for(var e = 0; e<8; e++){
    tummyframes[e] = loadImage(tummy[e]);
    }
    
  for(var f = 0; f<8; f++){
    bubblesframes[f] = loadImage(bubbles[f]);
    }
    
  for(var g = 0; g<8; g++){
    powsframes[g] = loadImage(pows[g]);
    }
    
  for(var h = 0; h<8; h++){
    cigsframes[h] = loadImage(cigs[h]);
    }
    
  for(var i = 0; i<8; i++){
    lipsframes[i] = loadImage(lips[i]);
    }
    
  for(var j = 0; j<8; j++){
    swirlframes[j] = loadImage(swirl[j]);
    }
    
  for(var k = 0; k<8; k++){
    wordframes[k] = loadImage(word[k]);
    }
    
  //put all the images into arrays
}

function setup() {
  createCanvas(windowWidth,windowHeight);
  myLoop.loop(); //play background sound
   background(0,0,80);
   imageMode(CENTER); 
   frameRate(10); //set frame rate for the animations
}

function draw() {
  background(0,0,80); //refresh background to play through animations
  

index++;

    if(index < eyeframes.length)
      image(eyeframes[index], width/2, height/2, eyeframes[index].width/2, eyeframes[index].height/2);
      
index2++;

    if(index2 < jarframes.length)
      image(jarframes[index2], width/2, height/2, jarframes[index2].width/2, jarframes[index2].height/2);
      
index3++;

    if(index3 < fishframes.length)
      image(fishframes[index3], width/2, height/2, fishframes[index3].width/5, fishframes[index3].height/5);
      
index4++;

    if(index4 < flframes.length)
      image(flframes[index4], width/2, height/2, flframes[index4].width/3, flframes[index4].height/3);
      
index5++;

    if(index5 < tummyframes.length)
      image(tummyframes[index5], width/2, height/2, tummyframes[index5].width/3, tummyframes[index5].height/3);
      
index6++;

    if(index6 < bubblesframes.length)
      image(bubblesframes[index6], width/2, height/2, bubblesframes[index6].width/3, bubblesframes[index6].height/3);
      
index7++;

    if(index7 < powsframes.length)
      image(powsframes[index7], width/2, height/2, powsframes[index7].width/3, powsframes[index7].height/3);
      
index8++;

    if(index8 < cigsframes.length)
      image(cigsframes[index8], width/2, height/2, cigsframes[index8].width/3, cigsframes[index8].height/3);
     
index9++;

    if(index9 < lipsframes.length)
      image(lipsframes[index9], width/2, height/2, lipsframes[index9].width/2, lipsframes[index9].height/2);
      
index10++;

    if(index10 < swirlframes.length)
      image(swirlframes[index10], width/2, height/2, swirlframes[index10].width/2, swirlframes[index10].height/2);
      
index11++;

    if(index11 < swirlframes.length)
      image(wordframes[index11], width/2, height/2, wordframes[index11].width/2, wordframes[index11].height/2);
 
 //plays each image if its index is set to 0     
} 


function keyPressed(){
  if(key==="A"){
    s2.pause();
    s3.pause();
    s4.pause();
    s1.play();
    index=0;
  }
  if(key==="B"){
    s1.pause();
    s3.pause();
    s4.pause();
    s2.play();
    index2 = 0;
  }

  if(key==="C"){
    s1.pause();
    s2.pause();
    s4.pause();
    s3.play();
    index3 = 0;
  }
  
  if(key==="D"){
    s1.pause();
    s2.pause();
    s3.pause();
    s4.play();
    index4 = 0;
  }
  
  if(key==="E"){
    s1.pause();
    s2.pause();
    s3.pause();
    s5.play();
    index5 = 0;
  }
  
  if(key==="F"){
    s1.pause();
    s2.pause();
    s3.pause();
    s6.play();
    index6 = 0;
  }
  
  if(key==="G"){
    s1.pause();
    s2.pause();
    s3.pause();
    s7.play();
    index7 = 0;
  }
  
if(key==="H"){
    s1.pause();
    s2.pause();
    s3.pause();
    s8.play();
    index8 = 0;
  }
  
if(key==="I"){
    s1.pause();
    s2.pause();
    s3.pause();
    s10.play();
    index9 = 0;
  }
  
if(key==="J"){
    s1.pause();
    s2.pause();
    s3.pause();
    s9.play();
    index10 = 0;
  }
  
if(key==="K"){
    s1.pause();
    s2.pause();
    s3.pause();
    s11.play();
    index11 = 0;
  }
  // if the key is pressed for a certain image, this sets the image index to 0, and plays the animation
 }

For my final project I chose to do a series of short animations and sounds. I wanted to hand draw each of these animations to contrast with the digital way that they are presented. I spend a lot of time drawing each frame for these animations, and then I edited the frames in photoshop so that they would fit into my code. If you press on any keyboard letter A-K, an animation and sound will play. I really struggled to get the animations to play at first, but once I figured out how to play each one separately as related to a key I spent the most amount of time drawing each animation and editing them in photoshop, and recording/editing sounds .

All of the images in my project were created by me. Most of the sounds were things that I recorded using my iPhone, and a few were dowloaded from Freesound.org. I used Audacity to edit all the sounds so that they matched with my animations.

I have to include a link to download my file, as I have over 100 files in my assets folders and they exceed the maximum file size for a wordpress post. It takes a few seconds for all these assets to load. Also my project needs a local server to run.

screen-shot-2016-12-09-at-9-57-53-pm

Here is an example of one of the animations, but it’s really hard to screenshot these short animations so I would definitely recommend downloading it and trying it yourself 🙂

P5 Sequencer- final project

finalproject

//Owen Fox
//Final project
//olf@andrew.cmu.edu
//Section C

var squares = [];
var moveSquares = [];
var sounds = [];
var noteC;
var noteD;
var noteE;
var noteF;
var noteG;
var noteA;
var noteB;
var noteHC;
var forward = 0;

function preload() {
    //C5 scale
    noteC = loadSound("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/C.wav");
    noteD = loadSound("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/D.wav");
    noteE = loadSound("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/E.wav");
    noteF = loadSound("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/F.wav");
    noteG = loadSound("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/G.wav");
    noteA = loadSound("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/A.wav");
    noteB = loadSound("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/B.wav");
    noteHC = loadSound("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/highc.wav");
}

function setup() {
    createCanvas(480, 480);
    background("red");
    frameRate(4);
    sounds = [noteC,noteD,noteE,noteF,noteG,noteA,noteB,noteHC];
    //fills an array of each individual square and gives each a sound from C to high c
    for (var x = 0; x < 8; x ++) {
        for (var y = 0; y < 8; y ++) {
            squares.push(Square(width/10 * x + width/10, height/10 * y + height/10, width/10, height/10,sounds[y]));
        }
    }

    //fills an array of each moving square
    for (var i = 0; i < 8; i ++) {
        moveSquares.push(MoveSquare(width/10,height/10 * i + height/10, width/10, height/10));

    }
}



function draw() {

    //draws each individual square
    for (var i = 0; i < squares.length; i ++) {
        squares[i].drawS();
    }

    //draws each moving square, and pushes them forward every frame
    for (var i = 0; i < moveSquares.length; i ++) {
         moveSquares[i].x = forward + (width/10);
         if((moveSquares[i].x)/(width/10) >= 9) {
            moveSquares[i].x = width/10;
         }
         moveSquares[i].drawMS();
         }

    //draws containing grid
    for(var i = 0; i < 9; i ++) {
      strokeWeight(8);
      stroke("white");
      line(width/10 * i + width/10,height/10,width/10 * i + width/10,height- height/10);
      line(width/10,height/10 * i + height/10,width - width/10,height/10 * i + height/10);
    }

    //if the x position of the moving squares is the same as a pink square that has been clicked on, a sound plays
    for(var w = 0; w < squares.length; w ++) {
        if((squares[w].x == forward) & (squares[w].on == true)) {
            squares[w].play();
        }
    }
    //increases forward variable, which controls moving square postion
    forward += width/10;
    if ((forward/(width/10)) >= 8) {
        forward = 0;
    }
}

function mousePressed() {
    for(var i = 0; i < squares.length; i ++) {
        squares[i].squareS();
    }
}

function Square(squareX,squareY,squareW,squareH,sound) {
    var square = {
    x: squareX,
    y: squareY,
    w: squareW,
    h: squareH,
    color: "lightPink",
    drawS: drawSquare,
    squareS: squareState,
    on: false,
    s: sound,
    play: soundPlay
    };
    return square
}

function drawSquare() {
    fill(this.color);
    rect(this.x,this.y,this.w,this.h);
}

//when the user clicks on a square, that square is set to "on"
function squareState() {
    println("mouse pressed");
        if((mouseX > this.x) & (mouseX < (this.x + this.w)) && (mouseY > this.y) && (mouseY < (this.y + this.h))) {
            this.color = "red";
            this.on = true;
        }
}

function MoveSquare(soundX,soundY,soundW,soundH) {
    var moveSquare = {
    x: soundX,
    y: soundY,
    w: soundW,
    h: soundH,
    drawMS: drawmoveSquare,
    };
    return moveSquare
}

function soundPlay() {
    this.s.play();
}

function drawmoveSquare() {
    fill("lightBlue");
    rect(this.x,this.y,this.w,this.h);
}

For my final project, I made a sequencer. To use: click on a pink square, and as the blue bar passes over it, it will play a note. From top to bottom, each row of the sequencer plays one note of a C5 scale.

rgriswol_FinalProject

My project changed a lot from what I originally intended. At first I wanted a more traditional, Mario-like 8 bit game. However, while I was working on my project I started watching the show Supergirl and fell in love with it, so I wanted to make a game based off of her. Instead of running around and jumping, the player character (Supergirl) flies through the air to save Lois Lane, all while trying to avoid obstacles in her way.
This was a lot of fun to make, and hopefully in the future I can make something more complex!

sketch

/*
* Rachel Griswold
* rgriswol@andrew.cmu.edu
* Section B
* Final Project
*
*/

var started = false;
var gameOver = false;
var terrainSpeed = 0.0003; //speed of hills
var terrainDetail = 0.005;
var terrain = [];
var cloudX = [];
var cloudY = [];
var birdX = [];
var birdY = [];
var treeX = []; // the trees are actually buildings, for reference - changed my mind last minute
var treeH = [];
var speedMod = 0;
var img1; // supergirl
var img2; // airplanes
var img3; // buildings
var img4; // clouds

function preload() {
  img1 = loadImage("http://i.imgur.com/5AvuM6o.png"); // loads supergirl image
  img2 = loadImage("http://i.imgur.com/fYFcwdh.png") // loads airplane image
  img3 = loadImage("http://i.imgur.com/FJQoEeU.png") // loads building image
  img4 = loadImage("http://i.imgur.com/8ULSzx0.png") // loads cloud image
}


function updateLocation(){ //moves the objects
	for(i = 0; i < cloudX.length; i++){
		cloudX[i] = cloudX[i] - 1 - speedMod/200;
			if(cloudX[i] < -150){ //makes the clouds go away
				cloudX.splice(i,1);
				cloudY.splice(i,1);
			}
	}
	for(i = 0; i < birdX.length; i++){
		birdX[i] = birdX[i] - 1 - speedMod/200;
			if(birdX[i] < -100){ //makes the birds go away
				birdX.splice(i,1);
				birdY.splice(i,1);
			}
	}
	for(i = 0; i < treeX.length; i++){
		treeX[i] = treeX[i] - 1 - speedMod/200;
			if(treeX[i] < -150){ //makes the buildings go away
				treeX.splice(i,1);
				treeH.splice(i,1);
			}
	}
}

function drawCloud(x, y){ //creates cloud
	image(img4, x, y);
}

function drawClouds(){ //places clouds
	for(i = 0; i < cloudX.length; i++){
		drawCloud(cloudX[i], cloudY[i]);
	}
}

function drawBird(x, y){ //creates airplane
	image(img2, x, y);
}

function drawBirds(){ //places airplanes
	for(i = 0; i < birdX.length; i++){
		drawBird(birdX[i], birdY[i]);
	}
}

function drawTree(x, h){ //creates building
	image(img3, x, height-h-20);
}

function drawTrees(){ //places buildings
	for(i = 0; i < treeX.length; i++){
		drawTree(treeX[i], treeH[i]);
	}
}

function checkGameOver(){
	for(i = 0; i < treeX.length; i++){
		x = treeX[i];
		h = treeH[i];
		if(!(mouseX < x - 20 || mouseX > x + 142 + 20 || mouseY < height - h - 20 || mouseY > height)){
			gameOver = true;
			break;
		}
	}
	for(i = 0; i < birdX.length; i++){
		x = birdX[i];
		y = birdY[i];
		if(!(mouseX < x - 20 || mouseX > x + 102 + 20 || mouseY < y - 10 || mouseY > y + 83)){
			gameOver = true;
			break;
		}
	}
}

function setup(){
	createCanvas(600, 400);
	noCursor();
}

function draw() {

	if(gameOver == true){
		background(0);
		fill(255, 0, 0);
		textSize(60);
		textAlign(CENTER);
		text("GAME OVER", width/2, height/2);
		textSize(30);
		textAlign(CENTER);
		text("Oh no! Now who will save Lois?", width/2, 280);
		fill(255);
		textSize(20);
		textAlign(CENTER);
		text("click to try again", width/2, 350);


		if(mouseIsPressed){
			gameOver = false;
			started = false;
			treeX = [];
			treeH = [];
			cloudX = [];
			cloudY = [];
			birdX = [];
			birdY = [];

			speedMod = 0;
		}
	}

	else{

	if(started == true){ // loads game
		speedMod++;
    	background(190, 240, 255);

    	fill(255, 0, 0);
    	textSize(16);
    	textAlign(CENTER);
    	text("Score = " + speedMod, 50, 20);

    	checkGameOver();

    	drawClouds(); // draws clouds
    		if(random(0, 100) < 1 + speedMod/2000){
    			cloudX.push(700);
    			cloudY.push(random(20, 200));
    		}
    

    	drawBirds(); // draws airplanes
   			if(random(0, 100) < 0.5 + speedMod/2000){
    			birdX.push(700);
    			birdY.push(random(20, 200));
    		}

    	drawTrees(); // draws buildings 
    		if(random(0, 100) < 0.5 + speedMod/2000){
    			treeX.push(700);
    			treeH.push(random(20, 200));
    		}

    	updateLocation();

    	image(img1, mouseX - 30, mouseY - 30); // supergirl

	}

	else{ // starting screen
		background(140, 220, 235);

		fill(255, 0, 0);
  		textSize(60);
  		textAlign(CENTER);
  		text("SUPERGIRL", width/2, 150);

  		fill(0, 0, 255);
  		textSize(20);
  		textAlign(CENTER);
  		text("Lois Lane is in trouble! Can Supergirl get there in time?", width/2, height/2);
  		text("Don't hit the buildings or the airplanes!", width/2, 240);

  		fill(255);
  		textSize(30);
  		textAlign(CENTER);
  		text("Press any key to play!", width/2, 300);
 		
 		if(keyIsPressed === true){
 			started = true;
 		}

	}
}

}

Final Project- Sofia Syjuco – Don’t Touch The Lava!

lavascreenshot

For my final project, I created a small game. I was inspired by the game many of us played as kids, with only one rule: don’t touch the lava! It’s a fun and simple game that I wanted to recreate in a digital format, to reflect on what we’ve learned this semester, and make something nostalgic and cheerful to combat the stress of year’s end.

To play the game, press any key to jump.
Your goal is to land atop each piece of furniture, and survive as long as you can. There’s some wiggle room (to make up for how kids will climb and latch onto furniture) but if you miss too many pieces of furniture, you’ll fall into the lava!
Stay alive as long as you can to rack up points. Boosters will give you 10 points each. Survive until 100 points to win!

*Don’t worry, it’s not meant to be a difficult game! As long as you pay attention, it should be a light-hearted, nostalgic experience.


Options to Play:
(I’ve posted these options, instead of embedding it, because this project requires the p5.play library from Molleindustria to work. p5.play is included in the downloads below.)
1. link to compressed zip file:finalproject_sofiasyjuco
2. link to download: https://www.dropbox.com/sh/emyra5s8hvgg71k/AADEDrgWffYkxI3NPN7VeSkHa?dl=0

Final Project-jihoonp

My final project is a simple game called, “Cloudy with a chance of dropping.”
it is basically a game in which you have to press one key, “g” to change direction of your character, in order to avoid the droppings from the sky. The game gets more and more difficult as you go

sketch

/*
Jihoon Park
Section A
jihoonp@andrew.cmu.edu
final project : cloudy with a chance of dropping
*/

var xPos = 300;			//x position of person
var yPos =450;			//y position of person
var dir = true;			//direction factor for movement of person
var timer = 0;			//reaction time for entering direction change
var interval = 10;		

var gameDifficulty = 0.008;		//game difficulty 
var minimumDistance;					//distance between person and dropping\
var playGame = true;


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

	for (var i=0; i<5; i++) {
		var droppingX = random(width);
		var droppingY = random(height);
		dropping[i] = makeDropping(droppingX, droppingY);
	}
}

function draw() {

	//game boundary
	background(255);
	rect(1,1, width-2, height-2);
	
	//groundline
	strokeWeight(4);
	stroke(100);
	line(1,height-13, width-1, height-13); 

	//rendering droppings from the sky
	showDropping();
	deleteDropping();
	makeNewDropping();

	//person movement on ground
	if (dir == true){			//makes person move in positive x direction
		xPos = xPos +3;			//makes person reapper from left side
		if (xPos > width){
			xPos = 1;
		}
	} else{						//makes person move negative x direction
		xPos = xPos - 3;		//makes person reappear from right side
		if (xPos < 0){
			xPos = width;
		}
	}
	personDisplay(xPos,yPos);   
	if (timer < interval){
		timer = timer + 1;
	}	

	//making "keypressed" only recognized once in an interval
	if(keyIsPressed & timer == interval){		
		if(key =='g'){
			if (dir == true){
				dir = false;
			} else {
				dir = true;
			}
			timer = 0;
		}
	}

	for(var i=0; i<dropping.length; i++){
		if(yPos+35 >dropping[i].y+19 >yPos) {
			if(xPos > dropping[i].x-14 > xPos+10 || xPos+10<dropping[i].x+14 < xPos) {
				playGame=false;
			}		
		}
	}

}





//rendering player's character
function personDisplay(x, y) {
	push();
	translate(x, y);
	strokeWeight(1);
	stroke(50);
	ellipseMode(CORNER);
	ellipse(0,0, 10,10);
	line(0,10, -5,15);
	line(10,10, 15,15);

	strokeWeight(2);
	fill("red");
	rect(0,10, 10,13);
	fill("yellow");
	rect(0,23, 10,7);
	line(0,30, 0,35);
	line(10,30, 10,35);
	pop();
}
//-------------------------------------------------------------------gg
var dropping = [];

function droppingDisplay() {
	push();
	translate(this.x, this.y);
	fill(208,168,92);
	strokeWeight(2);
	stroke(100);
	ellipse(0,14,28,10);
	ellipse(0,7,18,10);
	ellipse(0,0,10,10);	
	pop();
}

function makeDropping(birthlocationX, birthlocationY) {
	var dropping = {x: birthlocationX, 
					y: birthlocationY,
					 speed: random(2,5),
					 move: droppingMove,
					 display: droppingDisplay}
	return dropping;
}

function droppingMove() {
	if(playGame==true) {
		this.y += this.speed;
	}else{
		this.y = this.y;
	}
	
}

function makeNewDropping() {
	var newDroppingLiklihood = 0.03;
	newDroppingLiklihood += gameDifficulty;
	if(random(0,1) < newDroppingLiklihood) {
		dropping.push(makeDropping(random(width), 0));
	}
}

function deleteDropping() {
	var droppingToKeep = [];
	for (var i=0; i<dropping.length; i++) {
		if(dropping[i].y >500) {
			droppingToKeep.push(dropping[i]);
		}
	}
}

function showDropping() {
	for(var i=0; i<dropping.length; i++) {
		dropping[i].move();
		dropping[i].display();
	}
}
//--------------------------------------------------------------
/*
function checkTouch() {
	for(var i=0; i<dropping.length; i++){
		if(dropping[i].y+19 > yPos & dropping[i].y-5  xPos+10 && dropping[i].x+14 < xPos) {
			playGame = false;
			}
		}
	}
}*/

Final Project – James Katungyi

james-finalproject

//James Katungyi
//Section A 0900
//jkatungy@andrew.cmu.edu
//Project

/* Title: Annual average temperature of a location = Title text showing 
 - location
 - climate  type
 - hour - interactive; to be changed by user. Make a function that returns value for the hour. Hour value changes with slider (make a simple slider)
 ========
 Background: gradient color for canvas pixels from red to blue
 Comfortable band: import data points from excel file;
 connect the data points with red/blue line for upper/lower limit.
 for each month.
 ========
 Temperature bars: low alpha value to show background color
 Height of bars linked to excel data points imported into an array. Height changes with hour value
 Make each bar an object with function to change height 
 ========
 Locate labels outside the colored part of the canvas; left of canvas, above canvas and below canvas???
*/

//var allMonths = [JanTemp, FebTemp, MarTemp, AprTemp, MayTemp, JunTemp, JulTemp, AugTemp, SepTemp, OctTemp, NovTemp, DecTemp];
var Khartoum;
var KhartoumComfortAverages;
var Miami;
var MiamiComfortAverages;
var Pittsburgh;
var PittsburghComfortAverages;
var annualTempAverages = [];//has 12 strings of 24 hourly temperatures each
var comfortTempLimits = [];//has 2 strings of 12 temperatures each
var comfortLimitColors = [];//has two colors - red for upper and blue for lower limit
var counter = 0;//initialize counter at 0;
var myTime = 0;
var myTemp;
var cities = [];
var csvAvTempData = [];
var csvComfLimitData = [];
var cityIndex = 0;

function preload(){
    //load csv file
    Pittsburgh = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/PittsburghAverageTemperatures.csv");
    PittsburghComfortAverages = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/PittsburghComfortLimits.csv");
    Miami = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/MiamiAverageTemperatures.csv");
    MiamiComfortAverages = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/MiamiComfortLimits.csv");
    Khartoum = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/KhartoumAverageTemperatures.csv");
    KhartoumComfortAverages = loadStrings("https://courses.ideate.cmu.edu/15-104/f2016/wp-content/uploads/2016/12/KhartoumComfortLimits.csv");
}

//+++++ canvas & background color ++++++
function setup(){
    createCanvas(700 * 0.8, 400);//scale canvas to fit wordpress
    pixelDensity(1);//regular density
    loadPixels();
    var lowerLimitColor = color(0, 0, 255);
    var upperLimitColor = color(255, 0, 0);
    comfortLimitColors.push(lowerLimitColor);
    comfortLimitColors.push(upperLimitColor);
    //csvAvTempData is an array with average temperatures for 3 cities
    csvAvTempData.push(Khartoum);
    csvAvTempData.push(Miami);
    csvAvTempData.push(Pittsburgh);
    //println(csvAvTempData);
    csvComfLimitData.push(KhartoumComfortAverages);
    csvComfLimitData.push(MiamiComfortAverages);
    csvComfLimitData.push(PittsburghComfortAverages);
    
    //titles array
    cities.push("KHARTOUM");
    cities.push("MIAMI");
    cities.push("PITTSBURGH");
}
function draw(){
    scale(0.8, 1);//scale canvas to fit wordpress
    //change canvas color from pixel array
    for (var y = 50; y < height - 50; y++){//exclude 100 pixels above and below canvas for labels
        for (var x = 80; x <  width; x++){//exclude 100 pixels to left of canvas for labels
            var index = (x + y * width) * 4;//locate each pixel
            pixels[index + 0] = map(y, 0, height, 255, 0);//decrease red down the canvas
            pixels[index + 1] = 0;
            pixels[index + 2] = map(y, 0, height, 0, 255);//increase blue down the canvas
            pixels[index + 3] = 255;
        }
    }
    updatePixels();
    //+++++graph labels++++++
    //graph title
    stroke(0);
    fill(0);
    strokeWeight(1);
    textSize(18);
    textAlign(RIGHT);
    text(("AVERAGE HOURLY TEMPERATURES IN " + cities[cityIndex]), 400, 0, 300, 50);
    textSize(10);
    strokeWeight(0.5);
    textAlign(LEFT, TOP);
    text("click to change time", 100, 0);
    //legend comfort temperature limit
    for (var i = 0; i < comfortLimitColors.length; i++) {
        noFill();
        stroke(comfortLimitColors[i]);
        line(100 + (i * 200), 390, 150 + (i * 200), 390);
        ellipse(100 + (i * 200), 390, 8, 8);
        ellipse(150 + (i * 200), 390, 8, 8);
    }
    stroke(0);
    strokeWeight(1);
    textAlign(LEFT, CENTER);
    text(("Lower Comfort Limit"), 160, 390);
    text(("Upper Comfort Limit"), 360, 390);
    //time check at top of the graph
    
    fill(0);
    textAlign(LEFT);
    textSize(14);
    var timeCheck = ("TIME: " + nf(myTime, 2, 0) + ":" + "00");
    text(timeCheck, 100, 30);
    //y scale from 0 to 120 degrees fahrenheight
    for (var t = 0; t < 121; t+=20){
        var tempScale = map(t, 0, 120, 350, 50);
        textAlign(RIGHT);
        stroke(0);
        text(t, 80, tempScale);
        //y scale grid lines
        stroke(255, 100);//lower alpha value for the grid lines
        //strokeWeight(0.5);
        line(100, tempScale, 700, tempScale);
    }
    //x scale Jan to Dec at bottom of graph
    var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    for (var i = 0; i < monthNames.length; i++){
        var xPosText = 125 + i * 50;
        stroke(0);
        textAlign(CENTER, BOTTOM);
        text(monthNames[i], xPosText, 375);
    }
    //call function to parse csv data into monthly arrays
    csvDataToArray(csvAvTempData[cityIndex], annualTempAverages);
    csvDataToArray(csvComfLimitData[cityIndex], comfortTempLimits);

    //bar graphs: loop through the 12 months and plot the temperature of each month
    //depending on the hour.
    var LimitsForEachCity = comfortTempLimits;
    // var TempAveragesForEachCity = cityAverageTemp[cityIndex];

    var lowerLimitValues = LimitsForEachCity[0];
    var upperLimitValues = LimitsForEachCity[1];
    for (var i = 0; i < annualTempAverages.length; i++){
        var monthlyMin = lowerLimitValues[i];
        var monthlyMax = upperLimitValues[i];
        drawTemperatureBar(annualTempAverages[i], i, monthlyMin, monthlyMax);
    }

    //loop through the 2 sets of limits and plot the max and minimum comfort temperature
    //for each month
    
    for (var i = 0; i < LimitsForEachCity.length; i++){
        stroke(comfortLimitColors[i]);
        TemperatureBoundary(LimitsForEachCity[i]);
    }
}

/*increase the time whenever mouse clicks; increase upto 23;
may integrate a sliding scale to determine the time*/
function mousePressed(){
    counter++;
    myTime = counter%24;//myTime is an integer between 0 and 23
}

//parse csv data into strings and create 12 arrays with 24 data points each
function csvDataToArray(csvFile, myArray){
    for (var i = 0; i < csvFile.length; i++){
        myArray[i] = csvFile[i].split(",");
    }
}
/*drawTemperatureBar is a function that draws one bar for all temperatures of a given month. 
The height of the monthly bar depends on the time of day*/
function drawTemperatureBar(monthlyvalues, monthIndex, MinTemp, MaxTemp){
    stroke(255);
    strokeWeight(2);
    var BarWidth = 50;//bar width distributed evenly across width
    var xPos = 100 + (monthIndex * 50);//x position of bar is determined by month number
    myTemp = monthlyvalues[myTime];//use myTime value as index for Temperature values array
    var barHeight = map(myTemp, 0, 120, 0, 300);//scale temperature value to screen size
    var yPos = height - 50 - barHeight;

    
    //if monthly temperature exceeds comfort temperature limits, highlight the bar with red tint
    //if monthly temperature falls below comfort temperature limit, highlight the bar with blue tint
    if (float(myTemp) > float(MaxTemp)){
        fill(255, 0, 0, 100);
    } else
    if (float(myTemp) < float(MinTemp)){
        fill(0, 0, 255, 100);
    } else {
        fill(255, 50);
    }
    rect(xPos, yPos, BarWidth, barHeight);
    //println("monthIndex" monthIndex myTemp 100 MaxTemp 84 MinTemp 74);
}

/*Comfortable temperature limits differ from one month to the other;
draw upper boundary and lower boundary */
function TemperatureBoundary(LimitValues){
    for (var i = 0; i < LimitValues.length; i++){
        strokeWeight(2);
        noFill();
        var xPos = 125 + (i * 50);//scale x values to fit screen
        var xPos1 = 125 + ((i + 1) * 50);
        var yPos = map(LimitValues[i], 0, 120, 350, 50);//scale temperature value to screen size
        var yPos1 = map(LimitValues[i + 1], 0, 120, 350, 50);
        ellipse(xPos, yPos, 10, 10);
        line(xPos, yPos, xPos1, yPos1);
    }
}
//press keys to change from one city to another
function keyTyped(){
    // if (key == k){
    //     cityIndex = 0;
    //} else 
    if (key === 'm'){
        cityIndex = 1;
    } else if (key === 'p'){
        cityIndex = 2;
    } else if (key === 'k'){
        cityIndex = 0;
    }
}

Introduction

For the final project, I explored weather data visualization for three cities in different climates (Pittsburgh, Miami and Khartoum). Data visualization can make technical information intelligible to the non-technical. This can be useful for convincing building occupants to use less energy. If building occupants can be shown how to use less energy without compromising comfort, they can be instrumental in reducing energy consumption.

khartoum0600hrsmiami1500hrspittsburgh1100hrs

Description

The project consists of an interactive platform that graphs the average hourly temperatures for each month against a blue to red scaled background – blue for cold and red for hot. A comfort band in the middle of the graph represents the narrow range of comfortable temperatures based on the adaptive comfort model (de Dear and Brager, 1998). The upper limit of the comfort band is marked in red while the lower limit is marked in blue. The bars show the outdoor temperature at any given hour for each of the 12 months. When the temperature is below the lower limit, the bar is blue. When it is above the limit, the bar is red. When it is within the limit, the bar is a translucent white. Temperature values were obtained from weather files that are freely available online at https://energyplus.net/weather. The files in epw format were processed in Microsoft Excel to obtain average hourly data which was then saved as csv files. The csv files were then loaded into p5.js. The program runs smoothly in firefox but not in chrome because of the link to the csv files.

Interactivity/Operation

There are two levels of interactivity:

  1. The user, by clicking the mouse, can incrementally advance the hour by 1 from midnight (00:00 hrs) to 23:00 hrs. At each hour, the average temperature is displayed for each month.
  2. The user can also choose one of three cities by pressing the key corresponding to the first letter of the city – ‘m’, ‘p’ or ‘k’.

I hope to enrich it by incorporating humidity and wind speed in the input data. This would better portray human indoor comfort against outdoor weather conditions.

de Dear, R.J., and G.S. Brager, 1998. Towards an adaptive model of thermal comfort and preference. ASHRAE Transactions, Vol 104 (1), pp. 145-167

Final Project-Alison Hoffman

sketch

//Alison Hoffman
//Section D
//achoffma@andrew.cmu.edu
//Final Project 

//This project is an interactive exploration of the psychological phenomenon 
//of random association. Basically it is a random word generator that provides 
//a response to user input

//I used Donald Trump Tweets as the source text
var trumpTweets = ["beautiful","important","evening","man",
"woman","never","forgotten","again","together","never","happy","birthday",
"service","fantastic","first","time","really","good","meeting","great",
"chemistry","very","open","successful","professional",
"protesters","incited","media","very","unfair","love","fact","small",
"groups","protesters","last","night","passion","great","country","together","proud", 
"busy","planned","soon","making","important","decisions","people",
"running","government","express","deepest","gratitude","served","armed","force",
"prove","great","time","unite","losing","subscribers","poor",
"inaccurate","coverage","letter","subscribers","apologizing","coverage","wonder",
"change","doubt","congratulate","very","nice","express","best","wishes","very",
"nice","great","great","great","people","incredible","states","believe",
"countries","acquire","nuclear","weapons","dishonest","never","interview","tonight", 
"game","enjoy","especially","second","third","speeches","intensity",
"large","rallies","great","supporters","election","total","popular",
"campaign","bigger","easily","actually","genius","including","smaller","play",
"different","very","organized","process","decide","positions","finalist","trying",
"children","typically","news","story","failing","totally","wrong","transition",
"foreign","leaders","always","available","upset","fools","coverage","transition", 
"team","hours","fantastic","call","advised","plant","great","confidence",
"working","weekend","great","women","helping","make","America","great","again",
"settled","lawsuit","small","fraction","potential","award","focus","country",
"winning","trial","wonderful","future","harassed","night","theater","cast","cameras",
"blazing","safe","special","place","very","rude","very","good","apologize",
"producers","overrated","immediately","apologize","terrible","behavior","numerous",
"patriots","various","positions","necessary","make","America","great","again",
"totally","one-sided","biased","show","nothing","funny","equal","time","considered",
"impressive","yesterday","good","relationship","smarter","ability","news","update",
"policy","prior","interests","properties","world","crooked","media",
"deal","people","represent","nasty","meantime","complaints","formation","talented",
"terrible","beautiful","exciting","working","scam","defeated","demoralized",
"tabulation","victory","people","illegally","convincingly","serious","fraud","media",
"terminate","embarrassed","burn","consequences","wildfires","terrible","business",
"tragic","wonderful","history","interesting","billions","unwatchable","funny",
"impersonation","worse","regulations","employees","retribution","expensive",
"mistake","losing","scam","massive","complex","thrilled","press","cancel","invest"];

var instrtText0 = "You are here to find the meaning.";
var instrtText1 = "I am here to help you find the meaning";
var instrtText2 = "So this is how this is going to work:";
var instrtText3 = "You give me a word, then I give you a word.";
var instrtText4 = "This will happen six times, after which you must tell me what it all means.";
var instrtText5 = "Got it? Good.";

var sourceWords1 = []; var sourceWords2 = []; var sourceWords3 = [];
var inputWords; var ar = [];
var inputCt = 0; var currentWord; //variables for keeping up with current input words
var jBiebs; //holds song
var myWord; var myGenWords = []; //variables for generator words
var landImgs = []; 
var usedImgs = [];
var randNum;
var wordX; var wordY; //controls word position
var font;
var scaler8; // controls rate of scaling 
var instruction = [instrtText0,instrtText1,instrtText2,instrtText3,
                   instrtText4,instrtText5];

var explaination = ["This program was testing the psychological phenomenon of random association.",
                    "Random association is the propensity for humans to try to find",
                    "meaning or connection among random events. All of the words displayed",
                    "were generated randomly, so any connection you found was coincedental."]

var realExplain = ["So, if you guessed Donald Trump you're not entirely wrong.",
                    "All words were sourced from Trump's tweets since the election.",
                    "However, words were still generated randomly, but the majority of",
                    "what he says is random and has no meaning, so it's still fitting."]
function preload(){
    var landURLs = [];
    landURLs[0] = "http://i.imgur.com/yfhTfHG.jpg";
    landURLs[1] = "http://i.imgur.com/VvhFDxD.jpg";
    landURLs[2] = "http://i.imgur.com/AuLBi3f.jpg";
    landURLs[3] = "http://i.imgur.com/rcqJJjl.jpg";
    landURLs[4] = "http://i.imgur.com/nDdVmCQ.jpg";
    landURLs[5] = "http://i.imgur.com/JrSGcKa.jpg";
    landURLs[6] = "http://i.imgur.com/k2eT8Em.jpg";
    landURLs[7] = "http://i.imgur.com/VzoUiOv.jpg";
    landURLs[8] = "http://i.imgur.com/ck0OEfD.jpg";

    jBiebs = loadSound("WDYM.wav");

    for(var i = 0; i < landURLs.length; i++){ //loads images into array
        landImgs[i] = loadImage(landURLs[i]);
    }
}

function setup() {
    createCanvas(640, 480);
    textAlign(CENTER);
    for(var i = 0; i < trumpTweets.length; i++){ 
        if(trumpTweets[i].length % 2 === 0){ //breaks up source words based on wordlength
            sourceWords2.push(trumpTweets[i]);//even length words
        } else if(trumpTweets[i].length % 2 === 1){ //breaks up source words based on wordlength
            sourceWords3.push(trumpTweets[i]);// odd length words
        }
    }
    for(var i = 0; i < landImgs.length; i++){ 
        landImgs[i].filter("gray"); //puts all images in grayscale
        landImgs[i].loadPixels();
    }
    jBiebs.play(); //play justin bieber song
}

function draw() {
    background(0);
    scaler8 = frameCount;
    //--------------------page reloads based on the number of times input entered
    if(inputCt == 0){ 
        start();
    }
    if(inputCt == 1){
        background(0);
        instructions();
    }

    if(inputCt >= 2){   
        for (var i = 0; i < ar.length; i++){ //displays generated words
            background(220);
            image(landImgs[randNum],0,0);
            fill(255);
            textSize(12);
            textFont("Helvetica");
            textStyle(ITALIC);
            text("Your word: " + currentWord, width/2, 20);
            textSize(72);
            textStyle(NORMAL);
            textFont(str(font));
            push();
            fill(0);
            translate(wordX,wordY)
            scale(scaler8/2000);
            text(myGenWords[i],0,0);
            fill(255);
            text(myGenWords[i],4,0); 
            pop();
            textSize(18);
            textStyle(ITALIC);
            textFont("Helvetica")
            text("Press ENTER to continue", width/2, height-40);
        }
    }
    if(inputCt == 8){ //page for getting last user input
        background(0);
        finale();
    }

    if(inputCt > 8){ //final pages
        background(0);
        explain();
    }
    if(inputCt == 10){
        background(255);
        fill(0);
        textSize(64);
        text("*",100,100);
        textSize(16);
        for(var i = 0; i < realExplain.length; i++){ //displays text line by line
            text(realExplain[i],width/2,height/2+(30*i));
        }
    }
}
//---------does a lot based on user hitting enter
function keyPressed(){
    if (keyCode === ENTER){
        inputCt = inputCt + 1; //incraments input count by one 
        if((inputCt >= 2) & (inputCt < 8)){
            inputWord = prompt("Please type a word"); //asks for user input
                while(inputWord.length < 2){
                    inputWord = prompt("You must type a word");
                }
            currentWord = inputWord; 
            currentWordL = inputWord.length;//used in other functions to compare
            ar.push(inputWord);
            backgroundChooser();//changes background every time enter is pressed
            wordCheck();
            wordPosition();
            fontSelect();
        }
        if(inputCt == 9){
            inputWord = prompt("Tell me what it means");
            while(inputWord.length < 2){
                    inputWord = prompt("You must type a word");
                }
        }
    }
}

//------------chooses background image randomly
function backgroundChooser(){
    randNum = int(random(0,landImgs.length-1));
    var radIndex = usedImgs.indexOf(randNum); //searches used imgaes to see if new random number has been used
    if(radIndex == -1){
        usedImgs.push(randNum); //if not add it to the array and use it
    } else{
        backgroundChooser(); //if it is repeated num, recursively call 
        //function to generate another word
    } 
    println(usedImgs);

}
//-------------checks to make sure the generated word has not been used already
function wordCheck(){
    if(currentWordL % 2 === 0){
        myWord = sourceWords2[int(random(0,sourceWords2.length))];
            for(var i = 0; i < myGenWords.length; i++){
                if(myWord === myGenWords[i]){
                   myWord = sourceWords2[int(random(0,sourceWords2.length))];
                }
            }
    }else {
        myWord = sourceWords3[int(random(0,sourceWords3.length))];
            for(var i = 0; i < myGenWords.length; i++){
                if(myWord === myGenWords[i]){
                    myWord = sourceWords3[int(random(0,sourceWords3.length))];
                }                   
            }
    }
    myGenWords.push(myWord); //adds word to array if it hasnt been used yet
}
//--------------selects font based on whether position in array is even or odd
function fontSelect(){
    var idx = trumpTweets.indexOf(myWord);
    if((idx < 100) & (idx % 2 == 0)){ //if in first half and even position
        font = "Copperplate";
    }else if((idx < 100 ) & (idx % 2 == 1)){ //in first half and odd position
        font = "Impact";
    }else if ((idx >=100) & (idx % 2 == 0)){// in second and even position 
        font = "Arial";
    }else if ((idx >=100) & (idx % 2 == 1)){ //in second and odd position
        font = "Georgia";
    }

}
//----------choose random position of generated word 
function wordPosition(){
    wordX = int(random(200,width-200));
    wordY = int(random(100,height-175));
}
//----start page-------------------
function start(){
    background(landImgs[8]);
    textFont("Palatino");
    textStyle(NORMAL);
    textSize(80);
    fill(0);
    text("What does it",width/2-4, 120); 
    fill(255);
    text("What does it",width/2, 120); 
    textSize(145);
    push();
    fill(0);
    textFont("Helvetica")
    translate(width/2,240);
    text("mean",0, 0);
    fill(255); 
    text("mean",4, 0);
    pop();
    textFont("Palatino");
    for(var i = 0; i < width - 180; i = i + 50){
        textSize(96);
        fill(0);
        text("?", 95 + i, 360);
        fill(255);
        text("?", 99 + i, 360);
    }
    textSize(28);
    textStyle(ITALIC);
    textFont("Helvetica");
    text("Press ENTER to find meaning",width/2, 420);
}
// ----- displays instructions ---------------------
function instructions(){
    fill(255);
    textSize(18);
    textStyle(NORMAL);
    for(var i = 0; i < instruction.length; i++){
        text(instruction[i],width/2,(25*i)+(height/2-80));
    }
    textSize(28);
    textStyle(ITALIC);
    text("Press ENTER to begin",width/2,height-80);
}
//-----displays all generated words and asks for final input
function finale(){
    fill(255);
    textStyle(NORMAL)
    textSize(44);
    textFont("Helvetica");
    textStyle(BOLD);
    text("So, what does it all mean?",width/2, 120);
    textStyle(NORMAL);
    textSize(32);
    for(var i = 0; i < 6; i++){
        text(myGenWords[i],width/2,190+(40*i));
    }
    textStyle(ITALIC);
    textSize(18); 
    text("(Press ENTER)",width/2,height-40); 
}
//---------displays final explaination of project
function explain(){
    textStyle(BOLD);
    textSize(44);
    text("Nothing. It means nothing.",width/2, 100);
    textSize(16);
    for(var i = 0; i < explaination.length; i++){ //loads sentences by line
        text(explaination[i],width/2,height/2+(30*i));
    }
    textFont("TimesNewRoman");
    text("*Press ENTER for more information",width/2,height-20);

}

For this final project I wanted to bring in some sort of perspective with my  primary major. After meeting with Roger I decided to work with the concept of random association — a phenomenon which illustrates our propensity for finding meaning or connection even when events are entirely random. So in its simplest form this is project a random word generator based on user input. For every word a user inputs, the program generates one in response. At the end the user is asked say what is the meaning behind all of the words. The words are displayed to look like the those motivation landscape photos you see on Facebook all of the time. This program is unable to be displayed because it requires running a local server for playing a song file.

The photos I used are not my. They were all sourced from the internet. You can find the photos 1, 2, 3, 4, 5, 6, 7, 8, 9, at the corresponding links.

The song is also not mine. The song I used belongs the new and improved Justin Bieber. No copyright infringement intended.

Lastly, all of the words I used in my source text belong to the president-elect Donald Trump.

Isabella Hong – Final Project

Play this link in a separate tab before starting!
Press keys a, p, m, or y for different displays.

ijhong-final

// Isabella Hong
// Section A
// ijhong@andrew.cmu.edu
// Final Project - AudioVisualMixer

//variables for color in RGB mode 
var colorR = 255; 
var colorG = 255; 
var colorB = 255; 
//variable used in function Beat 
var s = 0; 
//variable used for noise effect
var xoff = 0; 

function setup() { 
	createCanvas(500, 500); //canvas size 
}

function draw() {
	background(0); //background color black

	//create values for the rotation, offset, and diameter of "Ring"
	var rotation = 45; 
	var offset = [50, 100, 150, 200, 250, 300]; 
	var d = [40, 25, 10, 5, 3, 2]; 

	//create continuous ring of ellipses 
	push();
	translate(width / 2, height / 2); 
	for (var i = 0; i < 25; i ++) {
		Ring(offset[0], 0, d[0]); 
		Ring(offset[1], 0, d[1]); 
		Ring(offset[2], 0, d[2]); 
		Ring(offset[3], 0, d[3]); 
		Ring(offset[4], 0, d[4]); 
		Ring(offset[5], 0, d[5]);
		rotate(radians(rotation)); 
		rotate(millis()/9500);  	
	} 
	pop(); 
	//various displays 
	Beat(100, 100);  
	Beat(400, 400); 
	Interject1();
	Interject2();   
	Interject3();  
}

//rotating ring (default display)
function Ring(x, y, d) {
	//randomize colors of ellipses 
	colorR = random(200, 255); 
	colorG = random(100, 255); 
	colorB = random(100, 200); 
	noStroke(); 
	colorMode(RGB); 
	fill(colorR, colorG, colorB); 
	ellipse(x, y, d, d); 
}

//pulsing
function Beat(x, y, s) { 
	s = random(100, 200); 
		if (keyIsPressed) {
			//press key p to display 
			if ((key == 'p')) {
				noStroke();
				//randomize size of ellipses in this range to create pusling effect
				s = random(10, 110);  
				fill(206, 255, 255); 
				ellipse(x, y, s, s);
			
				s = random(100, 200);
				strokeWeight(5); 
				stroke(205, 0, 205);
				noFill();   
				ellipse(x, y, s, s); 
			}
		}	
}

//oscillation
function Interject1() {
	//noise 
	xoff += 0.015; 
	var n = noise(xoff) * width; 
	if (keyIsPressed) {
		//press key m to display 
		if ((key == 'm')) {
			noStroke();
			//randomize color 
			colorR = random(155, 255); 
			colorG = random(155, 255); 
			colorB = random(155, 255);  
			//background
 			fill(colorR, colorG, colorB); 
 			rect(0, 0, 1000, 1000);
 			//objects affected by noise 
			strokeWeight(10); 
			stroke(255); 
			noFill();
			line(0, n, 100, n); 
			line(500, n, 400, n); 
			ellipse(250, 250, n, n); 
 		}
 		
	}
	
}

//rotating bar 
function Interject2() {
	//press key y to display 
	if ((key == 'y')) { 
 		noStroke(); 
 		fill(0); 
		rect(0, 0, 10000, 10000);
		rotate(millis()/275); 
		//create the rectangles to rotate 
		for (var i = 0; i < 1000; i += 50) {
		 	rectMode(CENTER);
		 	noFill(); 
		 	strokeWeight(10); 
			stroke(255, 255, 0);
			rect(i, i, 100, 100)
		 	stroke(255, 0, 255); 
		 	rect(i, i, 200, 200); 
		 	stroke(0, 255, 255); 
		 	rect(i, i, 300, 300); 
		 	strokeWeight(10); 
			stroke(255, 255, 0);
			rect(i, i, 100, 100)
		 	stroke(255, 0, 255); 
		 	rect(i, i, 200, 200); 
		 	stroke(0, 255, 255); 
		 	rect(i, i, 300, 300);
	 	}
 		
 	}
 		
}

//shaky strings 
function Interject3() {
	//press key a to display 
	if ((key == 'a')) {
		//randomize colors
		colorR = random(100, 200); 
		colorG = random(200, 255); 
		colorB = random(200, 150); 
		//background
		fill(colorR, colorG, colorB); 
		rect(0, 0, 1000, 1000); 
		//drawing strings 
		for (var a = 0; a < width; a += 10) {
			stroke(255);
			strokeWeight(1);
			line(a, 400, width, a); 
		}
		for (var b = 0; b < height; b += 10) {
			stroke(255, 0, 255); 
			strokeWeight(1);
			line(b, 400, height - 100, b); 
		}
		for (var c = 0; c < width; c += 10) {
			stroke(255);
			strokeWeight(2);
			line(c, 300, width - 640, c);
		}
		for (var d = 0; d < height; d += 5) {
			stroke(0, 255, 255);
			strokeWeight(1); 
			line(d, 100, height - 640, d); 
		}
	}
}




	
	


	

For my final project, I created an interactive audio visual mixer using the song Shelter by Porter Robinson and Madeon. There are four different display settings that the user can choose from. Pressing the corresponding keys will load animations that correspond to parts of the song. There are three functions called “Interject” that display image oriented animations while the function “Beat” displays pulsing ellipses that coincide with the beats of the song.

The main issue I had was embedding the audio file and having it load properly so I opted to link the file instead of it having it play automatically.

Enjoy!