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.
//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;
}
}