Final Project-Protect Sam from Coronavirus!

This project was inspired by the biggest theme of the year 2020—COVID-19. It is an invisible enemy that humanities struggled to fight against. The U.S. is surely losing the war on COVID-19, but it did not have to be this way. If people are more aware of how they could be infected by the virus, and understand how to protect themselves, then the pandemic would be more under control. I wanted this program to be educational and relatable to the player.

In my program, the players need to actively engage in using three different tools to protect the character from the coronavirus for 80 seconds. By applying the mask to Sam’s face, you could protect him from viruses that are spreading through the air. By sanitizing the table with disinfectant spray, you could prevent viruses from getting attached to Sam’s hand. However, there might be a few viruses that survived or escaped from the spray, so you need to apply hand sanitizer constantly just in case Sam starts rubbing his eyes.

If I had more time, I probably will explore how to parent the virus to the hand once it is attached. I would also like to make the background and surrounding more like a public space where other characters are also involved in this interaction.

sketch
//jiaqiwa2; Jiaqi Wang; Section C
//final project fall 2020 15-104
var num=0;
var VirusA;
var VirusS;
//the mask variables
var MaskPic;
var mx=445;
var my=60;
var mdragging=false;
var offsetMX;
var offsetMY;
var fhighlight=false;
var maskON=false;

//variables for virus
var airVirus=[];
var surfVirus=[];


//the spray variable
var Spray;
var sx=460;
var sy=125;
var sdragging=false;
var offsetSX;
var offsetSY;
var shighlight=false;
var SprayON=false;
var Sapplied=false;

//variables for animation
var Writing=[];
var Drinking=[];
var Rubbing=[];
var rubbing=false;
var count=0;
var stopwatch=0;
var EndGame=false;
var z;
var win=false;

var mug;
//the hand sanitizer variables
var handSanitizer;
var hx=480;
var hy=230;
var hdragging=false;
var offsetHX;
var offsetHY;
var Hhighlight=false;
var HON=false;
var Happlied=false;


function preload(){
 VirusA=loadImage("https://i.imgur.com/teJshOW.png");
 VirusS=loadImage("https://i.imgur.com/Vs0Z6HV.png");
 Mask=loadImage("https://i.imgur.com/3KxEFPC.png");
 Spray=loadImage("https://i.imgur.com/u0X1SgO.png");


 //writing
 var filenames = [];
    filenames[0] = "https://i.imgur.com/YJbLiPT.png";
    filenames[1] = "https://i.imgur.com/HCMWQFZ.png";
    filenames[2] = "https://i.imgur.com/rx4PTch.png";
    filenames[3] = "https://i.imgur.com/lI2EDs4.png";
    filenames[4] = "https://i.imgur.com/K4I9fup.png";
    filenames[5] = "https://i.imgur.com/EUNV9c7.png";
    filenames[6] = "https://i.imgur.com/HCMWQFZ.png";
    filenames[7] = "https://i.imgur.com/YJbLiPT.png";
    filenames[8] = "https://i.imgur.com/HCMWQFZ.png";
	filenames[9] = "https://i.imgur.com/YJbLiPT.png";
	filenames[10] = "https://i.imgur.com/HCMWQFZ.png";
    filenames[11] = "https://i.imgur.com/YJbLiPT.png";
    filenames[12] = "https://i.imgur.com/HCMWQFZ.png";
	filenames[13] = "https://i.imgur.com/YJbLiPT.png";

	for (var i = 0; i<filenames.length; i++) {
        Writing[i] = loadImage(filenames[i]);
    }
//drinking
var filenames2 = [];
    filenames2[0] = "https://i.imgur.com/YI78DMb.png";
    filenames2[1] = "https://i.imgur.com/pFFMlNc.png";
    filenames2[2] = "https://i.imgur.com/M6VWA4T.png";
    filenames2[3] = "https://i.imgur.com/YIN1o3J.png";
    filenames2[4] = "https://i.imgur.com/Eu7gh1b.png";
    filenames2[5] = "https://i.imgur.com/UlWmeif.png";
    filenames2[6] = "https://i.imgur.com/WFkzYAg.png";
    filenames2[7] = "https://i.imgur.com/xjnNAFU.png";
    filenames2[8] = "https://i.imgur.com/ISv7MwT.png";
	filenames2[9] = "https://i.imgur.com/X6FYgwF.png";
	filenames2[10] = "https://i.imgur.com/ISv7MwT.png";
	filenames2[11] = "https://i.imgur.com/xjnNAFU.png";
	filenames2[12] = "https://i.imgur.com/WFkzYAg.png";
	filenames2[13] = "https://i.imgur.com/UlWmeif.png";
	filenames2[14] = "https://i.imgur.com/Eu7gh1b.png";
	filenames2[15] = "https://i.imgur.com/YIN1o3J.png";
	filenames2[16] = "https://i.imgur.com/M6VWA4T.png";
	filenames2[17] = "https://i.imgur.com/pFFMlNc.png";
	 
    for (var i = 0; i<filenames2.length; i++) {
        Drinking[i] = loadImage(filenames2[i]);
    }
    // mug
    mug=loadImage("https://i.imgur.com/rlJA4yY.png");
    //hand sanitizer
    handSanitizer=loadImage("https://i.imgur.com/d5h6GeR.png");
//rubbing
var filenames3 = [];
    filenames3[0] = "https://i.imgur.com/B1Kr1t2.png";
    filenames3[1] = "https://i.imgur.com/8T6UUR4.png";
    filenames3[2] = "https://i.imgur.com/untVivz.png";
    filenames3[3] = "https://i.imgur.com/DaIu3C6.png";
    filenames3[4] = "https://i.imgur.com/Wvif1mI.png";
    filenames3[5] = "https://i.imgur.com/66gOJPD.png";
    filenames3[6] = "https://i.imgur.com/XhPbm01.png";
    filenames3[7] = "https://i.imgur.com/bDfotS2.png";
    filenames3[8] = "https://i.imgur.com/dzKQ4d7.png";
	filenames3[9] = "https://i.imgur.com/N3plYyV.png";
	filenames3[10] = "https://i.imgur.com/dzKQ4d7.png";
	filenames3[11] = "https://i.imgur.com/N3plYyV.png";
	filenames3[12] = "https://i.imgur.com/dzKQ4d7.png";
	filenames3[13] = "https://i.imgur.com/N3plYyV.png";
	filenames3[14] = "https://i.imgur.com/dzKQ4d7.png";
	filenames3[15] = "https://i.imgur.com/bDfotS2.png";
	filenames3[16] = "https://i.imgur.com/XhPbm01.png";
	filenames3[17] = "https://i.imgur.com/66gOJPD.png";
	filenames3[18] = "https://i.imgur.com/Wvif1mI.png";
	filenames3[19] = "https://i.imgur.com/DaIu3C6.png";
	filenames3[20] = "https://i.imgur.com/untVivz.png";
	filenames3[21] = "https://i.imgur.com/8T6UUR4.png";
 
    for (var i = 0; i<filenames3.length; i++) {
        Rubbing[i] = loadImage(filenames3[i]);
    }
}
function setup() {
    createCanvas(560,400);
    for(var i=0;i<3;i++){
    	var brith=random(1,3);
    	airVirus[i]=makeAirVirus(-20*brith,-20*brith,(360+20*brith)/(150*random(2,4)),(120+20*brith)/(150*random(2,4)));
        surfVirus[i]=makeSurfVirus(-20,random(270,380),random(1,3),0);

    }  
    frameRate(10);   
}
function draw() {
	background(220);
	noStroke();
	if(!EndGame){
	    //drinking
	    //drinking will cause mask removal	    
        if((count>=102&count<=119)||(count>=510&&count<=527)||(count>=918&&count<=935)){
        	print("drink");
        	var j=count%17;
        	image(Drinking[j],0,0,560,400);
        	mx=445;
        	my=60;
        	maskON=false;  
        }
        //rubbing
		else if((count>=189&count<=201)||(count>=567&&count<=588)||(count>=987&&count<=1008)){
			 z=count%21;
			 if(z<10) rubbing=true;
			//print("rub",z);
			image(Rubbing[z],0,0,560,400);
			image(mug,88,263,70,65);

		}
		//writing
        else{
        	rubbing=false;
        	var i=count%13;
        	image(Writing[i],0,0,560,400);
        	image(mug,88,263,70,65);

        }
    }

    // the user interface & text
    fill(235,100);
	rect(440,40,100,300);
	strokeWeight(2);
	fill(255,190);
	textSize(12);
	text("PROTECT SAM FROM CORONAVIRUS WITH TOOLS", 10,20);
	push();
	textSize(30);
	var time=floor(80-(map(count,0,1200,0,80,true)));
	text(time,80,50);
	pop();
	text("FOR", 50,40);
	text("SECONDS",120,40);
	text("TOOLS",470,30);
	text("MASK",470,110);
	text("DISINFECTANT",445,200);
	text("SPRAY",470, 215);
	text("HAND",470, 295);
	text("SANITIZER",460, 310);
	
	//display the mask
	image(Mask,mx,my,80,40);
    //display the spray
	image(Spray,sx,sy,50,60);
	//display the hand sanitizer
	image(handSanitizer, hx,hy,17,50);

	//update and show the virus   	
	removeVirusThatHaveSlippedOutOfView();
	addNewVirusWithSomeRandomProbability();

	for(var i=0;i<airVirus.length;i++){
		airVirus[i].range();
	    airVirus[i].move();
	    airVirus[i].show();
	}

	for(var j=0; j<surfVirus.length;j++){
		if(count>=102){
			//print(j);
			surfVirus[j].range();
			surfVirus[j].range2();
			surfVirus[j].move();
			surfVirus[j].show();
			

		}
	}
//show the tools behaviors
	mask();
	spray();
	HSanitizer();


	count++;
	endGame();
	
}

function removeVirusThatHaveSlippedOutOfView(){
    var AVirusToKeep = [];
    var SVirusToKeep = [];
    for (var i = 0; i < airVirus.length; i++){
        if (airVirus[i].x>-60 & airVirus[i].x-60 && airVirus[i].y0 && surfVirus[i].y=250)&&(my<=400)){
			Project_highlight();

		}
		
	}

}

function HSanitizer(){
	//move the hand sanitizer if it is selected
	if(hdragging){
		hx=mouseX+offsetHX;
		hy=mouseY+offsetHY;
	}
	if(Happlied){
		hx=480;
		hy=230;
		protection();
		stopwatch+=1;
		if(stopwatch==10){
			Happlied=false;
			stopwatch=0;
		}
		

	}
    // highlight the effective area of hand sanitizer
    if(Hhighlight){
		highlight(250,260,80,50);
    }

}

function protection(){
	//visual effect for protection
	for(var i=0;i<5; i++){
	push();
	translate(250+random(i*20),280+random(i*20));
	rectMode(CENTER);
	fill(114,204,82,100);
	rect(0,0,20,9);
	rect(0,0,9,20);
	pop();

	}
	
}

//Virus that moves on the surface
function makeSurfVirus(sx,sy,sdx,sdy){
	var sv={x: sx, y: sy, dx: sdx, dy:sdy, attach:false, VirusTransp: false,
			show: SVirusDraw, move:SVirusMove, range: CheckInProjection, range2:SCheckInBound};
		return sv;
}

function SVirusDraw(){
	image(VirusS,this.x,this.y,30,30);
	if(this.attach &!Sapplied){
		textSize(20);
		fill(255,10,10);
		text("!",this.x,this.y);
		
	}
}
function SVirusMove(){
	this.y+=this.dy;
	this.x+=this.dx;
	if(win){
		this.dy=30;
		this.dx=-30;
	}
}

function CheckInProjection(){
	//check if surface Virus get to the spray area
	if(InATriangle(this.x,this.y)){
		//check if spray is applied
		if(Sapplied){
			//reject virus if spray is applied
			print("reject Surface Virus");
			this.dy=5;
		}
		
	}

}
function SCheckInBound(){
	//check if surface virus is being transported
	if(this.VirusTransp){
		this.dx=0;
		this.dy=-20;
		//check if hand reaches the face
		if(z==9){
			EndGame=true;
		}
	}
	//check if surface Virus get to the hand area
	if((this.x>=250)&(this.x<=250+90)&&(this.y>=270)&&(this.y<=270+30)){
		//check if Hand sanitizer is applied
		if(Happlied){
			//reject virus if hand sanitizer is applied
			print("reject Surface Virus");
			this.dx=0;
			this.dy=5;
		}
		else if(! rubbing){
			//if not applied, attach virus to hand, virus stops moving if not rubbing
			print("Attached");
			this.dx=0;
			this.attach=true;
		}
		else if(rubbing& Happlied==false){
			this.VirusTransp=true;
			
		}
	}
}


//Virus that spreads through air
function makeAirVirus(ax,ay,adx,ady){
	var av={x: ax, y: ay, dx: adx, dy: ady, reject: false, 
		range: CheckInBound, show: AVirusDraw, move:AVirusMove};
	return av;
}

function AVirusDraw(){
	image(VirusA,this.x,this.y,30,30);
}

function AVirusMove(){
	if(this.reject){
		//virus go off canvas if you win
		if(win){
			this.dy=50;
			this.dx=50;
		}		
		this.x-=this.dx;
		this.y-=this.dy;		
	}
	else{
		//virus go off canvas if you win
        if(win){
			this.dy=-50;
			this.dx=-50;
		}
		this.x+=this.dx;
		this.y+=this.dy;	
	}
	    
}

function CheckInBound(){
	//check if air Virus get to the face area
	if((this.x>=240)&(this.x<=320)&&(this.y>=70)&&(this.y<=160)){
		//check if mask is on
		if(maskON){
			//reject virus if mask is on
			this.reject=true;
			print("reject Air Virus");
		}
		else{
			//end game if failed to protect face with mask
			EndGame=true;
			

		}
	}
}

function mousePressed(){
	//select mask
	if((mouseX>=445)&(mouseX<=445+80)&&(mouseY>=60)&&(mouseY<=60+40)){
		mdragging=true;
		fhighlight=true;
		offsetMX=mx-mouseX;
		offsetMY=my-mouseY;
	}
	//select spray
	else if((mouseX>=sx)&(mouseX<=sx+50)&&(mouseY>=sy)&&(mouseY<=sy+60)){
		sdragging=true;
		shighlight=true;
		offsetSX=sx-mouseX;
		offsetSY=sy-mouseY;
		
	}
	//select hand sanitizer
	else if((mouseX>=hx)&(mouseX<=hx+17)&&(mouseY>=hy)&&(mouseY<=hy+50)){
		hdragging=true;
		Hhighlight=true;
		offsetHX=hx-mouseX;
		offsetHY=hy-mouseY;
	}


}

function mouseReleased(){
    //when the mouse is released, mask dragging stops
    if((mx>=250)&(mx<=370)&&(my>=90)&&(my<=145)){
    	mdragging = false;
    	mx=260;
    	my=125;
    	maskON=true;
    	fhighlight=false;
    }
    //when the mouse is released, spray dragging stops
    if((sx>=10)&(sx<=320)&&(sy>=250)&&(my<=400)){
    	sdragging = false;
		Sapplied=true;
		sdragging = false;
    	SprayON=true;
    	shighlight=false;

    }
       //when the mouse is released, hand sanitizer dragging stops
    if((hx>=250)&(hx<=250+90)&&(hy>=270)&&(hy<=270+80)){
    	hdragging = false;
		Happlied=true;
		hdragging = false;
    	HON=true;
    	Hhighlight=false;

    }


    
}

function endGame(){
	//lose game
	if(EndGame){
		fill(120,54,55,100);
		rect(0,0,width,height);
		fill(0);
		textSize(20);
		noStroke();
		text("YOU FAILED TO PROTECT SAM:(", width/4,height/2);	
		airVirus.dx=0;
		airVirus.dy=0;
		surfVirus.dx=0;
		
		noLoop();
	}
	//win game
	if(!EndGame& count>=1200){
		win=true;
		fill(120,191,58,100);
		noStroke();
		rect(0,0,width,height);
		push();
		fill(255);
		textSize(20);
		text("YOU PROTECTED SAM :)", width/3,height/2);
		pop();
		airVirus.dx=-100;
		airVirus.dy=-100;
		surfVirus.dx=-100;
		stopwatch+=1;
		if(stopwatch==10){
			fhightlight=false;
			Hhighlight=false;
			shighlight=false;
			noLoop();
			stopwatch=0;
		}
		
	}
	
}
//highlight area for application
function highlight(x,y,w,h){
	noFill();
	stroke(98,232,228,150);
	strokeWeight(3);
	rect(x,y,w,h);

}

function Project_highlight(){
	noFill();
	stroke(98,232,228,150);
	strokeWeight(5);
	triangle(sx,sy+5,sx-90,sy-50, sx-90, sy+60);

}



function InATriangle(px,py){
var x1 = sx;      // three points of the triangle
var y1 = sy+5;
var x2 = sx-90;
var y2 = sy-50;
var x3 = sx-90;
var y3 = sy+60;

  // get the area of the triangle
  var areaOrig = abs( (x2-x1)*(y3-y1) - (x3-x1)*(y2-y1) );

  // get the area of 3 triangles made between the point
  // and the corners of the triangle
  var area1 =    abs( (x1-px)*(y2-py) - (x2-px)*(y1-py) );
  var area2 =    abs( (x2-px)*(y3-py) - (x3-px)*(y2-py) );
  var area3 =    abs( (x3-px)*(y1-py) - (x1-px)*(y3-py) );

  // if the sum of the three areas equals the original,
  // we're inside the triangle!
  if (area1 + area2 + area3 == areaOrig) {
    return true;
  }
  else{
  	return false;
  }

}

Project-11-Landscape

For this project, I wanted to create a desert landscape with some cactus here and there.

sketch
//jiaqiwa2; Jiaqi Wang; Section C
var marketValue=[];
var noiseParam=0;

var noiseStep=0.03;
var cactus = [];

function setup() {
    frameRate(30);
    createCanvas(600, 240);
    stroke(89,158,90);
    noStroke();
    fill(89,158,90);
    //strokeWeight(5);
    //set up the y value for every 5 pixels across the canvas horizontally
    for(var i=0;i<=120;i++){
        var n=noise(noiseParam);
        var value=map(n,0,1,height/3,height);
    	marketValue.push(value);
    	noiseParam+=noiseStep;
    }
    frameRate(20);

    for (var i = 0; i < 10; i++){
        var rx = random(width);
        cactus[i] = makeCactus(rx);
    }

}

function draw() {
	background(234,197,119);
  fill(249,242,215);
  noStroke();
  ellipse(width/2,height/2,100,100);
  //remove the first point
    marketValue.shift();
    var n=noise(noiseParam);
    var value=map(n,0,1,height/3,height);
    //and add it to the last point
    marketValue.push(value);
    noiseParam+=noiseStep;
    //start shape from (0,height)
    noStroke();
    fill(186,109,78);

  beginShape();
  curveVertex(0,height);
  curveVertex(0,height);
	for(var i=0;i<width/10;i++){
       
       vertex(i*10, marketValue[i]);
       //check if the hill is close to the right end
        if(i==59){
         i+=1;
         vertex(i*10, marketValue[i]);
         vertex(width, height);
         vertex(0,height);
         vertex(0,height);
         endShape();
       }
  }

  beginShape();
  curveVertex(0,height);
  curveVertex(0,height);



  

 

  updateAndDisplayCactus();
  removeCactusThatHaveSlippedOutOfView();
  addNewCactusWithSomeRandomProbability(); 
     
	   
	//noLoop();
}



function updateAndDisplayCactus(){
    // Update the building's positions, and display them.
    for (var i = 0; i < cactus.length; i++){
        cactus[i].move();
       cactus[i].display();
    }
}


function removeCactusThatHaveSlippedOutOfView(){
    // If a building has dropped off the left edge,
    // remove it from the array.  This is quite tricky, but
    // we've seen something like this before with particles.
    // The easy part is scanning the array to find buildings
    // to remove. The tricky part is if we remove them
    // immediately, we'll alter the array, and our plan to
    // step through each item in the array might not work.
    //     Our solution is to just copy all the buildings
    // we want to keep into a new array.
    var cactusToKeep = [];
    for (var i = 0; i < cactus.length; i++){
        if (cactus[i].x + cactus[i].breadth > 0) {
            cactusToKeep.push(cactus[i]);
        }
    }
    cactus = cactusToKeep; // remember the surviving buildings
}


function addNewCactusWithSomeRandomProbability() {
    // With a very tiny probability, add a new building to the end.
    var newCactusLikelihood = 0.007; 
    if (random(0,1) < newCactusLikelihood) {
         cactus.push(makeCactus(width));
    }
}


// method to update position of building every frame
function  cactusMove() {
    this.x += this.speed;
}
    

// draw the building and some windows
function  cactusDisplay() {
  
    push();
    fill(55,104,50);
    stroke(16,66,7);
    strokeWeight(5);
    translate(this.x, height+90);
    ellipse(0,-100,this.breadth,this.Tall);
    
    push();
    
    translate(this.breadth/2,-this.Tall/2);
    rotate(radians(-20));
    ellipse(0,-100,this.breadth/3*2,this.Tall/3*2);
    pop();

    translate(this.breadth/2,-this.Tall/2);

    push();
    rotate(radians(20));
    translate(-this.branch,0);
    ellipse(0,-100,this.breadth/3*2,this.Tall/3*2);
    pop();


   
    translate(-this.branch/5,-this.Tall/3);
    ellipse(0,-100,this.breadth/6*2,this.Tall/6*2);
    pop();

}


function makeCactus(birthLocationX) {
    var bldg = {x: birthLocationX,
                breadth: round(random(20,40)),
                speed: -2,
                Tall:random(40,120),
                branch:random(30,40),
                theta: round(random(10,40)),
                move:  cactusMove,
                display:  cactusDisplay}
    return bldg;
}


function displayHorizon(){
    stroke(0);
    line (0,height-50, width, height-50); 
}





LookingOutwards-11


The artist I want to talk about is Milica Zec. She is a New York City-based film and virtual reality director, editor, and screenwriter. One of her projects in the virtual reality medium was a short narrative piece called, “Giant,” which is a VR immersive experience based on true events during a war. “Giant” transports the viewer into a bomb shelter in an active war zone, where two parents are trying to distract their children from the war by telling a story. I admire how powerful and influential her work is in creating empathy. Many viewers indicated that they felt strongly connected to the refugees. I like how she used VR as a tool of storytelling, and the story she told is very meaningful.

Giant

Before entering the field of virtual reality, Milica has been collaborating for 9-years with the performance artist Marina Abramovic. Specifically, Milica has been Marina’s filmmaker, editor, and video-installation designer. As for her educational background, Milica is a graduate of The University of Dramatic Arts in Belgrade, Serbia, and SCPS NYU.

Project-10-Sonic-Story

For this project, I wanted to create a weird but delightful story with many fun little elements. I spent a lot of time thinking about how to make the transition between each scene smooth and fun. One of the solutions I came up with was creating an unexpected interaction between the background and the water in the fish tank.

Basically, my story goes like this:

Cat girl walked into the frame (walking sound). She blowed up her chewing gum (blowing balloon sound) and gradually shrined(venting balloon sound) it down to a size of a fish tank. As the water in the background flowed into the fish tank hat (filling water sound), a goldfish appeared, bubbling(bubble sound).

sketch new
//jiaqiwa2; Jiaqi Wang; Section C
//Story: a cat girl walked into the frame while chewing a gum. 
//She blowed up the gum and shrinked it down to the size of a fish tank.
//water started filling up the tank and a goldfish appeared.
//She enjoyed the goldfish bubbling infront of her eyes.
var CatGirlImage = [];   // an array to store the images
var fish;
var count=0;
var xC=700;
var yoff=0.0;
var yC=5;
var stepC=40;
var fC=0;


var blowing=false;
var diam=5;
var shrink=0;

var arcS=90;
var arcE=90;

var rise=0;
var filling=false;

var fishSX=175;
var fishSY=455;
var fishXoff=0.0;

var secondHalf=false;

//sound file variable
var walkingSound;
var GrowingSound;
var shrinkingSound;
var fillingSound;
var bubbleSound;

 
function preload(){

    var filenames = [];
    filenames[0] = "https://i.imgur.com/Em6d4RR.png";
    filenames[1] = "https://i.imgur.com/lWdTJLj.png";
    filenames[2] = "https://i.imgur.com/sdhFyfz.png";
    filenames[3] = "https://i.imgur.com/HEiFHNA.png";
    filenames[4] = "https://i.imgur.com/bJF8rmQ.png";
    filenames[5] = "https://i.imgur.com/D8MFSK6.png";
 
    for (var i = 0; i<filenames.length; i++) {
        CatGirlImage[i] = loadImage(filenames[i]);
    }
    fish=loadImage("https://i.imgur.com/UzyMgov.png");

   walkingSound=loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/11/bubbleSound.wav");
   GrowingSound=loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/11/bubbleSound.wav");
   shrinkingSound=loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/11/bubbleSound.wav");
   fillingSound=loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/11/bubbleSound.wav");
   bubbleSound=loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/11/bubbleSound.wav");
}

function setup() {
    createCanvas(400,600);
    frameRate(10);
    background(144,181,232);
    useSound();

}

function draw() {
	//scale up to the top left area for the second half of the story
	if(secondHalf){
    	scale(1.75,1.75);
	    translate(-20,-40);
	}
    //start dropping water in the background
	if(filling){
		fill(229,147,147);
		rect(0,0,400,min(115,rise*2));
	}
	else{
        fill(144,181,232);
        rect(0,0,400,600);
    }
	
//---------------------------------catGirl walking into the frame and stopped---------------------

	if(count<20){
		catGirlWalking();
	}
    else if(count<303){
    	 catGirlStopped();
    }
   
	
//---------------------------------the gum grows and shrinks to a fish tank----------------------
	gumGrowing(count);
//---------------------------------water filling+ goldfish appears-------------------------------
	waterFilling(count);      
	        
//-----------------------------------bubble popping----------------------------------------------
	bubble(count);

	if(count>=250){
	   noLoop();
	}



   count++;
   print(count);


}  



function mousePressed(){
	print(count);
	
	noLoop();
}

//update the x&y position of the catGirl walking into the frame
function catGirlWalking(){
		//sound
		if(fC==0||fC%3==0){
			walkingSound.play();
		}
		
		//keep the frame of catGirl animation looping
		if(fC%5==0&fC!=0){
		   fC=0;
	    }
	    //keep moving to the left if catGirl does not reach the stopping point
	    if(xC>=50){
		   xC-=stepC;
	    }

	//keep moving up and down to feel more lively
		yoff=yoff+0.01;
		if(fC%3==0){
        	yC+= noise(yoff);
		}
		else if(yC>0){
			yC-= noise(yoff);
		}
		//draw the catGirl
   		image(CatGirlImage[fC],xC,yC,400,600);
   		fC++;
}
function catGirlStopped(){
	//keep the frame of catGirl animation looping
		if(fC%5==0&fC!=0){
		   fC=0;
	    }
	    //keep moving up and down to feel more lively
		yoff=yoff+0.01;
		if(fC%3==0){
        	yC+= noise(yoff);
		}
		else if(yC>0){
			yC-= noise(yoff);
		}
		image(CatGirlImage[fC],0,yC,400,600);
   		fC++;

}

function gumGrowing(count){
	//gum growing bigger
	if(count>=20&count<45){
	   	fill(229,147,147,170);
	   	noStroke();
	   	diam+=count;
	    ellipse(200,380,diam,diam);
	    if(count%3==0){
	    	GrowingSound.play();
	    }


	}
	
	if(count>=45){
		shrink++;
	    fill(229,147,147,170);
	    if(count==49){
			
			shrinkingSound.play();
		}
		 //if size of gum gets down to 500, stop changing
	    if(diam-shrink*15<510&shrink>10){
	        ellipse(250,240,460,460);
				
	    }
	    else{
	        ellipse(250,240,diam-shrink*15);
	    }
	}

}

function waterFilling(count){
	if(count>=75){
		if(count==75){
	    	fillingSound.play();
	    }

		filling=true;
		rise+=1.08;
		fill(144,181,232,130);
	    arcS-=rise*0.1;
	    arcE+=rise*0.1;
	    
	    //fish appears
	    if(count>100){

	        	image(fish,fishSX-100*(noise(fishXoff)),max(110,fishSY-rise*3),min(100,40+(rise*0.8)),min(150, 60+(rise*1.2)));
	    }
	    if(count<130){
	        	arc(250,240,460,460,radians(arcS),radians(arcE), OPEN);
	    }
	    else{
	        	arc(250,240,460,460,-1.0471975511965976 +random(-0.003,0.0003),4.1887902047863905+random(-0.003,0.0003), OPEN);
	    }
	    fishXoff+=0.04;
	}

}

function bubble(count){
	   if(count>=160){
	   	    secondHalf=true;
	   		
	   	if(count%24==0){
	   		bubbleSound.play();
	   	}
	   	fill(144,219,232,220);
	   	//generating bubbles
	   	for(var i=0;i<5;i++){
	   		ellipse(fishSX-100*(noise(fishXoff))+random(30+i),max(110,fishSY-rise*3)-random(40+i),random(10-i));
	   		ellipse(fishSX-100*(noise(fishXoff))+random(5+i),max(110,fishSY-rise*3)+random(40+i),random(20-i));
	   	}


	   }
}
Sketching characters
Storyboard sketch

LookingOutwards-10

The Stanford Mobile Phone Orchestra (MoPhO) is an innovative ensemble that explores social music-making using mobile devices, instantiated in 2007, directed by Ge Wang.

images of MoPho

This project takes advantage of existing technologies and turns them into personal musical instruments. People on the internet could also add sound to existing music.

I admire how this project affords new possibilities for us to be expressive in the field of music creation. In the past, only those who received special training could play certain instruments, but with MoPhO, anyone interested in music could easily express themselves musically with available devices. For example, one of the instrument it could mimic is the ancient flute. By simply blowing into the microphone, the sensor embedded in the phone could detect the strength of your sound and synthesizing the sound according to where the fingers are pressing on the screen interface. This changes the way humans think about making music and the approach they use.

Project-09-Portrait

For this project, I want to convey the feeling of the breeze with the moving waves made of pixels.

sketch
//jiaqiwa2; Jiaqi Wang; Section C
var portrait;
//I learned & referenced how to make a moving sin wave from this example:
//https://p5js.org/examples/math-sine-wave.html
let xspacing = 5; // Distance between each horizontal location
let w; // Width of entire wave
let theta = 0.0; // Start angle at 0
let amplitude = 20.0; // Height of wave
let period = 700.0; // How many pixels before the wave repeats
let dx; // Value for incrementing x
let yvalues; // Using an array to store height values for the wave
var num=8;

function preload(){

	portrait=loadImage("https://i.imgur.com/J6Im42B.jpg");
}


function setup() {
  createCanvas(460,400);   
  w = width + 16;
  dx = (TWO_PI / period) * xspacing;
  yvalues = new Array(floor(w / xspacing));
  frameRate(10);
    
}



function draw() {
  //image(portrait,0,0,460,400);
  background(250);
 //gradually "open" the portrait
 if(num<40){
   num+=0.5;
  }

 for(var i=0;i<num;i++){
 	var yUpper;
  var yLower;
  
  yUpper=height/2-i*5;
  yLower=height/2+i*5;
  amplitude+=1;
  if(amplitude>40){
    amplitude-=1;
  }  

  calcWave();
  renderWave(yUpper);
  renderWave(yLower);


  
  
    }
  
}

function calcWave() {
  // Increment theta (try different values for
  // 'angular velocity' here)
  theta += 0.02;

  // For every x value, calculate a y value with sine function
  let x = theta;
  for (let i = 0; i < yvalues.length; i++) {
    yvalues[i] = sin(x) * amplitude;
    x += dx;
  }
  
}


function renderWave(Start) {
  noStroke();
  
  // draw the wave with an ellipse at each location
  for (let x = 0; x < yvalues.length; x++) {
  	//y postition of the ellipse
  	var y=Start + yvalues[x];
  	//x position of the ellipse
  	var X=x * xspacing;
  	//find the corresponding pixel's location on my portriat
  	var Px=map(X,0,460,0,portrait.width);
    var Py=map(y,0,400,0,portrait.height);
    //check if this pixel is within the canvas.
    if(y>0 & y<400){
    	let pix = portrait.get(Px, Py);
        fill(pix);
        ellipse(X, y, 7, 7);

    }
    
  }
}
my original portrait
screenshot
screenshot 2

LookingOutwards-09

I think this project is very performance-oriented in the way it captures the nuance of the changing surroundings from a more philosophical aspect. In creating the garments, the designer was inspired by a patient whose self-identity changes depends on the surroundings. I do agree with Isabel on how this project embodies the complexity and rhythm of the changing environment. To a certain extend, I also agree with her notion on how this project questions the traditional assumptions about clothing with the use of technologies and computation, but I believe the innovative part is not all about combining robotics with fabrication. On a deeper level, it challenges us to reflect on the role of the clothes and the wearer. In the past, human chose what to wear base on their needs, which is constantly changing as the weather, social occasion, and many other variables would be taken into considerations, but this new garment has its judgment, whether rational or not, on how to react to the immediate present.

I would say that the message that the creator wanted to deliver is more about the philosophical relationship between individuals and the changing surrounding, and less on the algorithm and the tools she used.

Ying Gao, 2019, “flowing water, standing time”.

@Isable Xu LookingOutwards-03: https://courses.ideate.cmu.edu/15-104/f2020/2020/09/19/lookingoutwards-03-4/

LookingOutwards-08

Mike Tucker is an Interactive Director at Magic Leap, a company focused on creating the future of Spatial Computing. Before he dived into the field of augmented reality, his focus of work moved from graphic design, website, mobile apps, media installation, and so on. He said in the speech that he always aspires to break the expectation of how medium should be experienced in general. In his day-to-day work, he mainly works on prototyping, designing, and shipping Spatial Computing projects alongside the new platform.

One of the Spatial Computing projects-“Tónandi”

Mike Tucker worked with different teams like the hand-tracking team, graphic team, and so on. I admire how they would prototype a lot before finally reaching a final result and they are willing to give up a concept that has been put a lot of work into if there is potentially a better one. I want to talk about the project “Tónandi” that he worked on together with Sigur Rós. This project explores the future of music through this interactive audio-visual experience in mixed reality. I admire how the team he directed experimented with a variety of ways to interact with virtual content and ways that music could be delivered. I especially admire how they make this design helpful to blind people. Users with visual disabilities could mark a specific spot in the space with a music note, which helps them to find the spot later on. 

Eyes for the Blind

They started off presenting a video of the final work. It is not the most impressive version, but good enough to keep the audience engaged. Then, they went through a different phase of prototyping and what small elements they achieve at each stage. Finally, they present the most impressive version of the final work and left the audience admire how worthwhile those efforts put into this project are.

Link to the speech: https://vimeo.com/channels/eyeo2019/page:4

Project-07-Curves

Please move your cursor around and feel the heartbeats.

heart
//jiaqiwa2; Jiaqi Wang; Section C
function setup() {
    createCanvas(480, 480);
    background(220);
    
}

function draw() {
	// Create a blended background
	fill(0, 10);
    rect(0, 0, width, height);
    //Keep track of how far mouse is away from the center
	var dX=Math.abs(mouseX-width/2);
	var dY=Math.abs(mouseY-height/2);
	//xoff and yoff are used to continuously govern 
	//two parameters of the curve respectively
	var xoff=map(dX,0,240,1,17);
	var yoff=map(dY,0,240,1,17);
	fill(220,49,63,60);
    heart(width/2,height/2,xoff,yoff);

}

function heart(Px,Py, xoff,yoff){
	push();
	//move the heart to the center of the canvas
	translate(Px,Py);
	noStroke();
	//start drawing heart curve 
	//with respect to mouse's distance from the center
	beginShape();
	for(var i=0;i<TWO_PI; i+=0.01){
		 var x=xoff*16*pow(sin(i),3);
		 var y=-yoff*(13*cos(i)-5*cos(2*i)-2*cos(3*i)-cos(4*i));
		 vertex(x,y);
	}
	endShape();
	pop();
}


For this project, I wanted to create a dynamic feeling of heartbeat using the Heart Curve.

LookingOutwards-07

The project that inspired me is Kepler, developed by Roberto Fazio. Kepler is an interactive immersive experience based on NASA open data describing in real-time the properties and features of most exoplanets discovered up to the present time. I think the concept of having real-time updates instead of using the algorithm to summarize the data collected over years is very intriguing. Also, the way they visualize data in virtual reality creates a fresh sensation and curious experience, which is suitable media for the content Kepler displays-always going beyond the limits of the knowledge, proceeding into the unknown world.

video of “Kepler”

As for the algorithm, I know that Kepler is recorded in real-time from the Unity 3D application. I happened to know a little bit of unity. It is a very powerful software that combines coding, visualization, and even more functions, which allows artists, designers, and developers to create a real-time 3D immersive experience together.

Kepler’s representation of exoplanet

In the past, perhaps most people learn about exoplanet through documentary film or vague images captured by spacecraft, which do not necessarily convey the thrillingness of the discovery. I would say the creator’s sensibility is manifest through finding the most suitable media that perfectly embody the content, which, according to the creator, “ shapes the relationship between creative technologies and anthropic observation, placing humankind as witness of the multisensory artistic experiment.”

Links:
https://frm.fm/a/roberto_fazio/kepler
http://studiorf.io/