Final Project

sketch
/*
 * Michelle Kim
 * michell4
 * Section B
 */

var count = 0;
var clouds = [];
var opacity = 0;

var hearts;
var hornet;
var blm;
var vote;
var covid;
var crowd;

var alarm;
var yawn;
var shower;
var gettingReady;
var ready;
var cameraShutter;
var hornetSound;
var blmSound;

var hornetX = 600;
var blmX = 600;
var voteX = 600;
var covidX = 600;
var crowdX = 600;

function preload() {
    //preloads all images and sounds
    hearts = loadImage("https://i.imgur.com/WArKv90.gif");
    hornet = loadImage("https://i.imgur.com/WSVUTau.png");
    blm = loadImage("https://i.imgur.com/JAVgfbG.png");
    vote = loadImage("https://i.imgur.com/sRU4uIO.png");
    covid = loadImage("https://i.imgur.com/BY6kaKa.jpg");
    crowd = loadImage("https://i.imgur.com/63dcnGS.png");
    tear = loadImage("https://i.imgur.com/ie45BVh.png");

    alarm = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/alarm.wav");
    yawn = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/yawn-1.wav");
    shower = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/shower.wav");
    gettingReady = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/gettingready.wav");
    ready = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/ready.wav");
    huh = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/huh.wav");
    cameraShutter = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/camerashutter.wav");
    ding = loadSound("hhttps://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/ding.wav");
    hornetSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/hornetsound.wav");
    blmSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/blmsound.wav");
    ehSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/eh.wav");
    cough = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/cough.wav");
    awSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/aw.wav");
}

function setup() {
    createCanvas(600, 600);
    useSound();
    background(220);
    for(var i = 0; i < 3; i++){
        var initialX = random(width);
        var initialY = random(0, 200);
        clouds[i] = makeClouds(initialX, initialY);
    }
    frameRate(3);
}

function soundSetup() {
    alarm.setVolume(0.2);
    yawn.setVolume(0.3);
    shower.setVolume(0.2);
    gettingReady.setVolume(0.2);
    ready.setVolume(0.2);
    huh.setVolume(0.3);
    hornetSound.setVolume(0.3);
    blmSound.setVolume(0.2);
    cameraShutter.setVolume(0.2);
    ding.setVolume(0.3);
    ehSound.setVolume(0.8);
    cough.setVolume(0.2);
    awSound.setVolume(0.2);
}

function draw() {
    background(171, 245, 255);
    //opening scene
    if (count < 10) {
        fill(0);
        square(0, 0, width);
        textSize(30);
        textFont("Helvetica");
        fill(255);
        text("One fine morning...", 150, (height / 2));
    }
    //alarm ringing
    if (count >= 10 & count < 20) {
        clock();
        if (count == 10) {
            alarm.play();
        }
        if (count == 17) {
            yawn.play();
        }
    }
    //character getting ready
    if (count >= 20 & count < 30) {
        fill(0);
        square(0, 0, width);
        if (count == 20) {
            shower.play();
        }
        if (count == 25) {
            shower.stop();
            gettingReady.play();
        }
        if (count == 28) {
            gettingReady.stop();
        }
        if (count == 25) {
            ready.play();
        }
    }
    //boy introduction
    if (count >= 30 & count < 40) {
        boy();
        if (count >= 35 & count < 38) {
            image(hearts, 430, 310, width * 0.1, height * 0.1);
        }
    }
    //clouds
    if (count >= 40) {
        updateClouds();
        removeClouds();
        addClouds();
    }
    //boy on phone
    if (count >= 40 & count < 70) {
        boyWalking();
    }
    //hornet
    if (count >= 40 & count < 105) {
        image(hornet, hornetX, 300, width * 0.05, height * 0.05);
        hornetX -= 10;
        if (count == 40) {
            hornetSound.play();
        }
        if (count >= 55 & count < 60) {
            textSize(40);
            textFont("Georgia");
            fill(0);
            text("!", 170, 350);
            if (count == 56) {
                huh.play();
            }
        }
    }
    //snap of hornet
    if (count >= 70 & count < 75) {
        phonePicture();
        image(hornet, 240, 250, width * 0.2, height * 0.2);
        if (count == 73) {
            cameraShutter.play();
        }
    }
    //boy walking after hornet
    if (count >= 75 & count < 165) {
        boyWalking();
        if (count >= 80 & count < 100) {
            image(hearts, random(150, 170), random(400, 420),
                  width * 0.2, height * 0.2);
            bubble();
            textSize(40);
            textFont("Helvetica");
            fill(150);
            text("Woah!", 295, 415);
        }
        if (count == 80) {
            ding.play();
        }
    }
    //blm protest
    if (count >= 110 & count <= 220) {
        image(blm, blmX, 200, width, height);
        if (count == 110) {
            blmSound.play();
        }
        if (count == 220) {
            blmSound.stop();
        }
        if (count >= 140 & count < 145) {
            textSize(40);
            textFont("Georgia");
            fill(0);
            text("!", 170, 350);
            if (count == 141) {
                huh.play();
            }
        }
        blmX -= 10;
        if (count < 165 || count > 170) {
        boyWalking();
        }
    }
    //snap of blm protest
    if (count >= 165 & count < 170) {
        phonePicture();
        image(blm, 175, 250, width * 0.4, height * 0.35);
        if (count == 168) {
            cameraShutter.play();
        }
    }
    //boy walking after blm protest
    if (count >= 220) {
        boyWalking();
    }
    if (count >= 190 & count < 210) {
        image(hearts, random(150, 170), random(400, 420),
              width * 0.2, height * 0.2);
        bubble();
        textSize(30);
        textFont("Helvetica");
        fill(150);
        text("Inspiring!", 290, 410);
        if (count == 190) {
            ding.play();
        }
    }
    //vote sign
    if (count >= 225 & count < 320) {
        noStroke(0);
        fill(0);
        rect(voteX + 140, 400, 20, 400);
        image(vote, voteX, 250, width * 0.5, height * 0.5);
        voteX -= 10;
        if (count < 265 || count > 270) {
        boyWalking();
        }
        if (count >= 250 & count < 255) {
            textSize(40);
            textFont("Georgia");
            fill(0);
            text("!", 170, 350);
            if (count == 251) {
                huh.play();
            }
        }
        if (count >= 280 & count < 300) {
            image(hearts, random(150, 170), random(400, 420),
                  width * 0.2, height * 0.2);
            bubble();
            textSize(25);
            textFont("Helvetica");
            fill(150);
            text("Awesome!", 290, 410);
            if (count == 280) {
                ding.play();
            }
        }
    }
    //snap of vote sign
    if (count >= 265 & count < 270) {
        phonePicture();
        image(vote, 210, 230, width * 0.3, height * 0.3);
        if (count == 268) {
            cameraShutter.play();
        }
    }
    //covid sign
    if (count >= 325 & count < 420) {
        noStroke();
        fill(0);
        rect(covidX + 50, 200, 5, 400);
        rect(covidX + 250, 200, 5, 400);
        image(covid, covidX, 100, width * 0.5, height * 0.4);
        covidX -= 10;
        boyWalking();
        if (count == 360) {
            ehSound.play();
        }
        if (count >= 345 & count < 350) {
            textSize(40);
            textFont("Georgia");
            fill(0);
            text("!", 170, 350);
            if (count == 346) {
                huh.play();
            }
        }
    }
    //crowd
    if (count >= 425 & count < 510) {
        tint(255, 50);
        image(crowd, crowdX, 300, width * 1.1, height * 0.8);
        if (count < 490) {
            crowdX -= 10;
        }
        if (count == 495) {
            cough.play();
        }
        boyWalking();
        if (count >= 505 & count < 510) {
            textSize(40);
            textFont("Georgia");
            fill(0);
            text("!", 170, 350);
            if (count == 506) {
                huh.play();
            }
        }
    }
    //boy sad face
    if (count >= 510 & count < 520) {
        boyFace();
        if (count >= 15 & count < 520) {
            tint(255, 255);
            image(tear, 250, 320, width * 0.03, height * 0.05);
        }
        if (count == 513) {
            awSound.play();
        }
    }
    //end scene
    if (count >= 520) {
        background(0);
        textFont("Helvetica");
        textSize(50);
        fill(255);
        text("Wear a mask.", 150, 300);
        textSize(20);
        text("Spread awareness.", 210, 340);
    }
    count ++;
}

function clock() {
    background(255);
    stroke(0);
    strokeWeight(20);
    line(180, 180, 200, 200);
    line(400, 200, 420, 180);
    line(290, 125, 310, 125);
    line(300, 125, 300, 150);
    strokeWeight(5);
    //black
    fill(255);
    //bells
    arc(190, 190, 155, 155, radians(140), radians(310), CHORD);
    arc(410, 190, 155, 155, radians(230), radians(40), CHORD);
    fill(0);
    //body
    circle((width / 2), (height / 2), 300);
    //bells
    arc(180, 180, 120, 120, radians(130), radians(320), CHORD);
    arc(420, 180, 120, 120, radians(220), radians(50), CHORD);
    //bells
    circle(132, 132, 30);
    circle(468, 132, 30);
    //legs
    circle(210, 430, 50);
    circle(390, 430, 50);
    //white
    noStroke();
    fill(255);
    //body
    circle((width / 2), (height / 2), 250);
    //black
    stroke(0);
    strokeWeight(5);
    fill(0);
    //inside details
    circle((width / 2), (height / 2), 20);
    line((width / 2), 190, (width / 2), (height / 2));
    line((width / 2), (height / 2), 270, 370);
    //highlights
    stroke(255);
    strokeWeight(5);
    fill(255);
    line(292, 122, 308, 122);
    noFill();
    //bells
    arc(132, 132, 20, 20, radians(150), radians(200));
    arc(468, 132, 20, 20, radians(340), radians(30));
    //body
    arc(290, 280, 250, 230, radians(200), radians(250));
    arc(310, 320, 250, 230, radians(20), radians(70));
    //legs
    arc(210, 430, 30, 30, radians(140), radians(210));
    arc(392, 430, 30, 30, radians(330), radians(40));
}

function boy() {
    background(255);
    stroke(0);
    strokeWeight(3);
    //arms
    fill(255, 245, 215);
    line(180, 380, 220, 390);
    circle(170, 375, 20);
    line(380, 390, 420, 380);
    circle(430, 375, 20);
    //shirt
    fill(174, 255, 242);
    rect(220, 370, 50, 40);
    rect(330, 370, 50, 40);
    quad(270, 330, 330, 330, 360, 470, 240, 470);
    fill(126, 225, 208);
    square(310, 390, 20);
    //face
    fill(255, 245, 215);
    circle(230, (height / 2), 20);
    circle(370, (height / 2), 20);
    circle((width / 2), (height / 2), 140);
    line(300, 215, 300, 230);
    line(290, 220, 300, 230);
    line(310, 220, 300, 230);
    fill(0);
    circle(290, 290, 5);
    circle(310, 290, 5);
    noFill();
    arc(300, 310, 70, 60, 0, radians(180));
    //phone
    fill(0);
    rect(430, 330, 20, 40);
    noFill();
    stroke(255);
    strokeWeight(1);
    rect(432, 332, 16, 30);
    circle(440, 367, 5);
}

function updateClouds() {
    //update clouds
    for (var i = 0; i < clouds.length; i++) {
        clouds[i].move();
        clouds[i].display();
    }
}

function removeClouds() {
    //get rid of clouds
    var keepClouds = [];
    for (var i = 0; i < clouds.length; i++) {
        if (clouds[i].x + 50 > 0) {
            keepClouds.push(clouds[i]);
        }
    }
    clouds = keepClouds;
}

function addClouds() {
    //add new clouds
    var newClouds = 0.05;
    if (random(0,1) < newClouds) {
        var y = random(0, 200);
        clouds.push(makeClouds(width, y));
    }
}

function moveClouds() {
    //clouds move to left
    this.x += this.speed;
}

function displayClouds() {
    //cloud drawing
    fill(255);
    noStroke();
    circle(this.x, this.y + 50, 50);
    circle(this.x + 40, this.y + 50, 70);
    circle(this.x + 80, this.y + 70, 40);
    circle(this.x + 90, this.y + 40, 50);
}

function makeClouds(cloudsX, cloudsY) {
    var cloud = {x: cloudsX,
                 y: cloudsY,
                 speed: -4,
                 move: moveClouds,
                 display: displayClouds}
    return cloud;
}

function boyWalking() {
    stroke(0);
    strokeWeight(3);
    //shirt
    fill(174, 255, 242);
    quad(70, 450, 120, 450, 150, height + 2, 60, height + 2);
    quad(90, 520, 110, 520, 115, 550, 85, 550);
    //face
    fill(255, 245, 215);
    circle(100, 420, 140);
    circle(90, 440, 10);
    fill(0);
    circle(150, 430, 5);
    noFill();
    arc(152, 450, 35, 30, radians(90), radians(180));
    line(100, 335, 100, 350);
    line(90, 340, 100, 350);
    line(110, 340, 100, 350);
    //phone
    noStroke();
    fill(209, 250, 255);
    quad(200, 465, 200, 500, 175, 530, 150, 530);
    stroke(0);
    strokeWeight(5);
    line(200, 500, 175, 530);
    //arms
    strokeWeight(3);
    line(100, 550, 100, 570);
    line(100, 570, 170, 540);
    fill(255, 245, 215);
    circle(170, 540, 20);
}

function phonePicture() {
    //phone camera
    stroke(0);
    strokeWeight(20);
    fill(171, 245, 255);
    rect(200, 100, 200, 400);
    strokeWeight(10);
    line(200, 400, 0, height);
    line(400, 400, width, height);
    stroke(255);
    strokeWeight(5);
    line(250, 220, 250, 240);
    line(250, 220, 270, 220);
    line(350, 220, 350, 240);
    line(330, 220, 350, 220);
    line(250, 380, 250, 360);
    line(250, 380, 270, 380);
    line(350, 380, 350, 360);
    line(350, 380, 330, 380);
}

function bubble() {
    //phone comments
    fill(255);
    noStroke();
    ellipse(350, 400, 150, 100);
    triangle(290, 400, 320, 440, 280, 450);
}

function boyFace() {
    //boy sad face
    background(255);
    strokeWeight(3);
    fill(255, 245, 215);
    circle(100, (height / 2), 50);
    circle(500, (height / 2), 50);
    circle((width / 2), (height / 2), 400);
    line(300, 70, 300, 100);
    line(280, 80, 300, 100);
    line(320, 80, 300, 100);
    fill(0);
    circle(270, 290, 10);
    circle(330, 290, 10);
    noFill();
    arc(300, 420, 140, 120, radians(200), radians(340));
}

For this project, I chose to create a short animation that depicted some of the major events that occurred in 2020. The increasing use of technology and social media platforms has definitely raised awareness for important causes and happenings during this year. For example, one of the biggest contributors for raising awareness and protests was social media and the sharing of information through these platforms.

My inspiration for this project was a typical commercial, one that can be watched through advertisements or on TV. I tried to imitate the basic form of story-like commercial with a message at the end. The main message that I am conveying through this short clip is spread more awareness about the importance of masks. With the currently increasing cases of COVID-19, I decided to focus on this specific theme because unfortunately, masks are still being refused by many people around the world.

If I had more time, I would have liked to add an additional scene that depicted the detrimental effects of contracting COVID-19. I believe that this would have added more of an impact to my “commercial”.

To interact with my program, simply click on the canvas to start the clip. Note: Use volume for sound.

FINAL PROJECT

I was inspired by digital interactive infographics and how they are able to relay important information to educate the audience in a very effective and engaging way. I thought it was important to show the visuals in order to help visual learners better understand and connect the information to the real world. I feel that 2020 was a rough year for many things but the current world has always been harsh to the environment. I had my infographic focused on the environment because I didn’t want people to forget about the horrible things happening to the environment because of the pandemic. I had my birds turn to grayscale to show the decrease in biodiversity due to the accelerating extinction of birds. I intended for the hills to turn to a dimmer color in order to fit the final image where the clouds and sky look gloomy with trees on fire and stone like birds flying across the page. However, I originally intended it to show how satellite images showed that the Amazon Forest is slowly becoming less green and less efficient at processing carbon dioxide due to the pollution. I am pretty happy with how the project turned out and I think I learned a lot during the debugging process and problem solving!

sketch
var trees = [];
var bird = [];
var cloud = [];
var hillVar= 0.009
var r = 188
var g = 219
var b = 245
var tr =14
var tg = 99
var tb = 42
var sky = 0
var newTreeLikelihood = 0.03; 
var newBirdLikelihood= 0.2;
var newCloudLikelihood=0.04;
var textShown = 1
var hillCondition = 0
var clickCondition = 0
var fire = 0
var fx = []
var fy = []
var birdcolor = 0
var birdDiv = ["https://i.imgur.com/L7k89AJ.png",
               "https://i.imgur.com/dnY7u7s.png",
               "https://i.imgur.com/a1m3PWp.png"]

function preload() {
  img = loadImage("https://i.imgur.com/W9zRul7.png");
  brd = loadImage(random(birdDiv));
  brdgray = loadImage("https://i.imgur.com/ile7nc8.png")
  //crackling = loadSound('https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/414767__samarobryn__crackling-fire.wav')
}

function soundSetup(){
    crackling.setVolume(7)
}

function setup() {
    createCanvas(480, 480); 
    
    // create an initial collection of buildings


    for (var i = 0; i < 10; i++){
        var rx = random(width);
        var ry = random(10, 50);
        trees[i] = makeTree(rx);
        bird[i] = makeBird(rx);
        for(var f = 0; f< 8; f++){

          fx[f] = trees[i].x-trees[i].breadth*2-350//random(trees[i].x-1,trees[i].x+1);
          fy[f] = -trees[i].nFloors*20//random(trees[i].nFloors*20,-90)
      }
}
frameRate(10);
    }
    

    


function draw() {
    background(r, g, b);
    if (sky == 0) {
    r = 188
    g = 219
    b = 245
  }
  else if (sky==1) {
    r = 177
    g = 194
    b = 199
  } else if (sky == 2) {
    r = 167
    g = 169
    b = 171
  } 



    drawHill() 

    updateAndDisplayCloud();
    removeCloud();
    addNewCloud()


    

    displayHorizon();

    updateAndDisplayTrees();
    removeTreesThatHaveSlippedOutOfView();
    addNewTreesWithSomeRandomProbability(); 

    updateAndDisplayBird();
    removeBird();
    addNewBird()

    instructionbox()

}

function makeclouds(birthLocationX) {
  var k ={x: birthLocationX,
    y:round(random(10,180)),
    sizer:round(random(25,30)),
    speed:-3,
    move:cloudMove,
    display:cloudDisplay,
    click:cloudClick,
    }
    return k 
  //noStroke()
}

function cloudClick(cx,cy) {
  push()

  let dc = dist(cx,cy,this.x+20,this.y);

  if (dc < 30 ) {
      newCloudLikelihood += 0.1
      this.sizer += 3
      textShown = 4
  }
  pop()
}

function cloudMove() {
  this.x += this.speed;
  this.y += random(-3,3);
}

function cloudDisplay() {
  push();
  noStroke();
  fill(r-20,g-20,b-20);
  ellipse(this.x,this.y,this.sizer,this.sizer)
  ellipse(this.x+10,this.y+10,this.sizer,this.sizer)
  ellipse(this.x+30,this.y+10,this.sizer,this.sizer)
  ellipse(this.x+30,this.y-10,this.sizer,this.sizer)
  ellipse(this.x+20,this.y-10,this.sizer,this.sizer)
  ellipse(this.x+40,this.y,this.sizer,this.sizer)

  
  pop()
}

function updateAndDisplayCloud(){
  for (var i = 0; i <cloud.length; i++){
    cloud[i].move();
    cloud[i].display()
  }
}
function removeCloud(){
  var cloudToKeep = [];
  for (var i = 0; i <cloud.length; i++){
    if (cloud[i].x+40>0){
      cloudToKeep.push(cloud[i])
    }
  }
  cloud = cloudToKeep
}

function addNewCloud(){
  
  if(random(0,1)<newCloudLikelihood){
    cloud.push(makeclouds(width));
  }
}



function instructionbox() {
  push()
  rectMode(CENTER)
  fill(255)
  strokeWeight(8)
  rect(240,400,440,100)
  noStroke()
  fill(0)
  textSize(19.7)
  if (textShown==1){
      text("Click on objects to see how WE affected them",40,405)
    } else if (textShown==2) {
      textSize(15)
      text("Scientists have recently found that birds are going extinct",40,395)
      text("much quicker than we thought. Help by donating to RSPB!",40,415)
    } else if ( textShown ==3) {
      textSize(16.5)
      text("Wildfire has burned more than 4% of California in 2020",40,395)
      text("Help by donating to California's wildfire relief fund!",40,415)
    } else if (textShown == 4) {
      textSize(15)
      text("China has surpassed pre-COVID air pollution levels soon",40,395)
      text("after business returned to normal.",40,415)
    } else if (textShown == 5) {
      textSize(15)
      text("Satelite image shows that Amazon forest has became less ",40,395)
      text("green over time due to pollution",40,415)
    }
  
  pop()
}

function birdbox() {
  push()
  rectMode(CENTER)
  fill(255)
  strokeWeight(8)
  rect(240,400,440,100)
  noStroke()
  fill(0)
  textSize(20)
  text("Bird are ded",40,405)

  pop()
}

function mouseClicked(){
  sky += 1
  if (sky>2){
    r -= 10
    g -= 10
    b -= 10
  }

  clickCondition = 1 

  for (var i = 0; i <bird.length; i++){
    bird[i].click(mouseX, mouseY)
  }

  for (var i = 0; i <trees.length; i++){
    trees[i].click(mouseX, mouseY)
  }

  for (var i = 0; i <cloud.length; i++){
    cloud[i].click(mouseX, mouseY)
  }




}

function makeBird(birthLocationX) {
  var k ={x: birthLocationX,
    y:round(random(-60,-280)),
    breadth:round(random(40,70)),
    speed:2,
    birdHeight:round(random(9,15)),
    move:birdMove,
    display:birdDisplay,
    click:birdClick,
    color:color(random(50,240),random(50,240),random(50,240))}
    return k 
}

function birdClick(bx, by) {
  let d = dist(bx, by, this.x, height-190+this.y)
  if (d <= this.breadth){
    this.color = color(40)
    textShown = 2
    birdcolor = 1
  }


}

function birdMove() {
  this.x += this.speed
}

function birdDisplay() {
  push();
  fill(this.color)
  translate(this.x, height-190);
  strokeWeight(1);
  stroke(0);
  push()
  if (birdcolor == 1){
    image(brdgray,-0,this.y,this.breadth,this.breadth)
  } else {
    image(brd,-0,this.y,this.breadth,this.breadth)
  }
  pop()
  pop()
}

function updateAndDisplayBird(){
  for (var i = 0; i <bird.length; i++){
    bird[i].move();
    bird[i].display()
  }
}
function removeBird(){
  var birdToKeep = [];
  for (var i = 0; i <bird.length; i++){
    if (bird[i].x+bird[i].breadth>0){
      birdToKeep.push(bird[i])
    }
  }
  bird = birdToKeep
}

function addNewBird(){
  var newBirdLikelihood=0.1;
  if(random(0,1)<newBirdLikelihood){
    bird.push(makeBird(0));
  }
}



function drawHill() {
  push()
  noStroke()
  fill(tr, tg, tb)
  beginShape()
  for (var h = 0; h<width; h++){
    var a = (h*hillVar)+(millis()*0.0002)
    var y = map(noise(a),0,1,height/8,height/9*5);
    vertex(h,y)
    if (mouseY < h & y-1< mouseX =72 && tg <=87 && tb >=77){
    tr = 72
    tg = 87
    tb = 77
  }  


  pop()

  vertex(480,480);
  vertex(0,480)
  endShape()
  pop()
}

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


function removeTreesThatHaveSlippedOutOfView(){
    var treesToKeep = [];
    for (var i = 0; i < trees.length; i++){
        if (trees[i].x + trees[i].breadth > 0) {
            treesToKeep.push(trees[i]);
        }
    }
    trees = treesToKeep; 
}


function addNewTreesWithSomeRandomProbability() {
    if (random(0,1) < newTreeLikelihood) {
        trees.push(makeTree(width));
    }
}



function treeMove() {
    this.x += this.speed;
}
    


function treeDisplay() {
  push()
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight; 
    fill(74, 21, 22);  
    push();
    translate(this.x, height - 170);
    rect(0, -bHeight, this.breadth, bHeight);
    noStroke()

    for (var i = 0; i < this.nFloors; i++) {
      fill(2, 61, 21)
      noStroke()

      triangle(this.breadth/2,0-(i * floorHeight)-60,-20,20-(i * floorHeight)-40,this.breadth+20,20-(i * floorHeight)-40);
    }

    var fireSize = random(10,80)

    if( fire == 1){
      for(var f = 0; f < 8; f++){
        image(img,fx[f],fy[f],fireSize,fireSize)
      }
    }

    strokeWeight(3)
    pop();
}



function makeTree(birthLocationX) {
    var bldg = {x: birthLocationX,
                breadth: 15,
                speed: -3.0,
                nFloors: round(random(2,8)),
                move: treeMove,
                click: treeClick,
                display: treeDisplay}
    return bldg;
}

function treeClick(tx,ty) {
  var floorHeight = 20;
  var bHeight = this.nFloors * floorHeight;
  let dtx = dist( tx, height-170, this.x+this.breadth/2, height-170)
  let dty = dist( this.x , ty, this.x, -bHeight/2+height-170 )
  if (dtx<20+this.breadth/2 & dty

Final Project

This final project was inspired by what’s currently transpiring to aquariums within the country during this pandemic. I’m a huge fan of aquariums and am constantly nervous about how much these vital institutions are struggling to stay afloat while visitors can’t go walk through their physical buildings and admire all of the different marine life. I wanted this project to bring a little awareness to this extremely niche but nevertheless devastated part of the current fabric of the world being heavily impacted by the pandemic.

For this project, the viewer just needs to click on the canvas to cycle through
different facts about COVID-19’s impact on aquariums and marine life. They can also make the aquarist move across the screen and view the passing marine life with their mouse. The visuals and designs of the animals were based off the Monterey Bay Aquarium‘s illustrated advertisements. Each animal moves across the screen at different speeds as the illustrated background moves with them.

If I had more time on this project, I definitely would have added a level of
interactivity with the marine life, whether through animations triggered by clicks or sounds to accompany the piece. I’m pretty proud of how it turned out though.

sketch
var teal;
var barColor;

var tankbg;
var kelp;
var sunlight;

var sidewayScroll = 0;
var bgLength = 2100;
var bgHeight = 600;

let turtleCycle = [];
let animatedFrame = 0;
let turtleX = 0;
let time = 0;

let rayY = 0;
let rayX = 0;
var ray;

let seahorseY = 0;
let seahorseX = 0;
var seahorse;

var sharkY = 0;
var sharkX = 0;
var shark;

var orangefishX = 0;
var orangefishY = 0;
var orangefish;

var dx = [];
var c = [];
var x = [];
var y = [];

var employeeLeft;
var employeeRight;

var facts = ["Because the pandemic has reduced tourism, there has been a huge baby sea turtle boom in Florida's beaches.", "Stingrays and other fish have been showing signs of loneliness since the pandemic started due to the lack of visitor interactions.", "An endangered species of seahorse has returned to Dorset in the UK due to the coronavirus lockdown.", "Aquariums around the country are struggling to stay afloat due to COVID-19 closures and lack of financial help from the federal government.", "Many aquariums are now showing exhibits virtually to keep visitors engaged at home."];
var index = 0;

function preload() {
    //exhibit images
    tankbg = loadImage("tankbg.png");
    kelp = loadImage("kelp.png");
    sunlight = loadImage("light.png");

    //turtle images
    turtleCycle[0] = loadImage("turtle-02.png");
    turtleCycle[1] = loadImage("turtle-03.png");
    turtleCycle[2] = loadImage("turtle-04.png");
    turtleCycle[3] = loadImage("turtle-05.png");
    turtleCycle[4] = loadImage("turtle-06.png");
    turtleCycle[5] = loadImage("turtle-05.png");
    turtleCycle[6] = loadImage("turtle-04.png");
    turtleCycle[7] = loadImage("turtle-03.png");

    //stingray image
    ray = loadImage("ray.png");

    //seahorse image
    seahorse = loadImage("seahorse.png");

    //shark
    shark = loadImage("shark.png");

    //orange fish
    orangefish = loadImage("orangefish.png");

    //employee
    employeeLeft = loadImage("employee_left.png");
    employeeRight = loadImage("employee_right.png");

}

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

    //tank setup
    teal = color(89, 185, 189);
    barColor = color(20, 48, 67);

    //fish setup
    for (i = 0; i < 100; i++) {
        dx[i] = random(-2, 2);
        c[i] = color(random(100), random(175), random(100), 50);
        x[i] = random(25, width - 25);
        y[i] = random(25, height - 25);
    }

}

function draw() {
    noStroke();
    background(teal);

    //sunlight
    image(sunlight, width/4, 0, 400, bgHeight);

    for (i = 0; i < 100; i++) {
        fish(x[i], y[i], dx[i], c[i]);
        x[i] += dx[i];

        if (x[i] > width - 20){
            dx[i] = -dx[i];
        }
        else if (x[i] < 0){
            dx[i] = -dx[i];
        } 
    }

    //shark
    image(shark, sharkX, sharkY, 189.42, 47.7);

    sharkX = sharkX + 1;
    if (sharkX >= width) {
        sharkX = -300;
        sharkY = random(200, 400);
    }

    //scrolling background
    image(tankbg, sidewayScroll, -150, bgLength, bgHeight);
    image(tankbg, sidewayScroll + bgLength, -150, bgLength, bgHeight);

    //sea turtle
    image(turtleCycle[animatedFrame], turtleX, 100, 200, 97);

    if (time > 13) {
        turtleX += 13;
        animatedFrame += 1;
        if (animatedFrame >= turtleCycle.length) {
            animatedFrame = 0;
        }
        time = 0;
    }
    time++;
    if (turtleX > width) {
        turtleX = -500;
    }

    //orange fish
    image(orangefish, orangefishX, orangefishY, 243, 86.3);

    orangefishX = orangefishX + 2;
    if (orangefishX >= width) {
        orangefishX = -600;
        orangefishY = random(0, 400);
    }

    //seahorse
    image(seahorse, seahorseX, seahorseY, 25, 45);
    image(seahorse, seahorseX + 50, seahorseY + 50, 35, 55);

    seahorseX = seahorseX + 0.5;
    if (seahorseX >= width) {
        seahorseX = -100;
        seahorseY = random(0, 400);
    }

    //scrolling kelp
    image(kelp, sidewayScroll, -150, bgLength, bgHeight);
    image(kelp, sidewayScroll + bgLength, -150, bgLength, bgHeight);

    sidewayScroll -= 1;
    if (sidewayScroll <= -bgLength) {
        sidewayScroll = 0;
    }

    //stingray
    image(ray, rayX, rayY, 150, 192);

    rayY = rayY + 1;
    if (rayY >= height) {
        rayY = -300;
        rayX = random(-400, 100);
    }
    else {
        rayX = rayX + 1;
    }
    
    //glass tank bars
    fill(barColor);
    rect(200, 0, 15, height);
    rect(400, 0, 15, height);

    //aquarium employee
    let canvasEdge = constrain(mouseX, width/4, 400);
    if (mouseX < width/2) {
        image(employeeLeft, canvasEdge, 300, 82, 172.6);
    } else {
        image(employeeRight, canvasEdge, 300, 82, 172.6);
    }
 
    //pandemic facts
    let factsEdge = constrain(mouseX, 50, 400);
    fill(255, 200);
    rect(factsEdge, 200, 175, 85, 10);
    fill(0);
    textSize(10);
    textFont("Volte");
    text(facts[index], factsEdge + 15, 212, 150, 200);

}

//background fish
function fish(x, y, dx, c) {
    fill(c);
    ellipse(x, y, 20, 10);

    if(dx < 0) {
        triangle(x+10, y, x+15, y-5, x+15, y+5);
    }
    else {
        triangle(x-10, y, x-15, y-5, x-15, y+5);
    }
}

//click to cycle through pandemic facts
function mousePressed() {
    index = floor(random(facts.length));
    if (index == facts.length) {
        index = 0;
    }
}
Exhibit background, made in Illustrator
Sea turtle, made in Illustrator
Stingray, made in Illustrator
Spotted Bamboo Shark, made in Illustrator
Seahorse, made in Illustrator
Aquarist, made in Illustrator

Final Project

The project is representing two events we had to deal with in 2020, the so-called Asian murder hornets and the coronavirus.
The project is a game that mimics arcade-style 2D shooter games.
The player is a hornet facing off against cells of the coronavirus and taking them down with glowing green bullets.
Whenever a virus reaches the bottom of the screen, the player loses.

While developing this project, I came across a lot of problems , the most complicated being the interaction between the bullet and virus.
I was not sure how to call a property of an object in an array while comparing it to another property of an object in another array and then making something happen with it.
However, I ended up using a nested for loop to linear search both the virus and bullet and using a conditional to check if the x and y value of those searched are matching.

Creating a project for myself and implementing the coding strategies I’ve learned over this semester definitely cemented what I’ve learned and see the usage of these techniques in my own way.
Overall, I learned about my strength and weaknesses when tackling a coding project through this experience.

sketch

var movement = []
var bullets = [];
var xpos;
var ypos;
var cv;
var score;
var c=0
var virus = [];
var cvimage = [];
var cvlinks = [
"https://i.imgur.com/Nw3KzRI.png", // virus images
"https://i.imgur.com/JlYsbHq.png",
"https://i.imgur.com/rIXhNzt.png",
"https://i.imgur.com/SjJmecC.png"
]
var count = 0;

function preload(){
  for (var i = 0; i<4; i++){ // loading images into array
    cvimage[i] = loadImage(cvlinks[i]);
  }
  hornet = loadImage("https://i.imgur.com/tU0dXCU.png")
  hornetshadow = loadImage("https://i.imgur.com/JErLPWR.png")
}
function setup() {
    createCanvas(500, 500);
    for (var i = 0; i < 100; i++){ // initial background lines
        var rx = random(width);
        var ry = random(height);
        movement[i] = makemovement(rx,ry);
    }
}
function draw() {
    background(255)
    startgame();
    updatemovement();
    removemovement();
    addmovement();
    updatevirus();
    addvirus();
    removevirus();
    drawhornet();
    updateremovebullet();
    bulletvirusinteraction();
    lose();
    count++
}

function startgame(){ // openning of game
  push()
  translate(width/2,height/2)
  fill(0)
  scale(c)
  circle(0,0,5)
  c+=2
  pop()
}
// BACKGROUND MOVEMENT
function updatemovement(){
    for (var i = 0; i < movement.length; i++){ //background lines appearing and moving
        movement[i].move(); //moving
        movement[i].display(); // appearing
    }
}
function removemovement(){
    var movementtokeep = []; // array to keep existing lines
    for (var i = 0; i < movement.length; i++){ //going through lines to see which to keep
        if (movement[i].y + 100 < 500) {
            movementtokeep.push(movement[i]);
        }
    }
    movement = movementtokeep; //return kept lines back inot movement array
}
function addmovement() {
      for (var i = 0; i < 100; i++){ // adding more background lines
          var rx = random(width);
          var ry = random(height);
          movement.push(makemovement(0))
          movement[i] = makemovement(rx,ry);
      }
}
function mvmtMove() {
    this.y += this.speed; // lines movement down canvas
}
function mvmtDisplay() { // white lines
    stroke(255);
    line(this.x,this.y,this.x,this.y+100);
}
function makemovement(startx,starty) { //properties of background object
    var mvmt = {x: startx,
                y: starty,
                speed: 1,
                move: mvmtMove,
                display: mvmtDisplay}
    return mvmt;
}
function drawhornet(){
    xpos=constrain(mouseX,0,width-50); // keep hornet in canvas
    ypos=map(mouseY,0,height,350,450);// keep hornet in bottom portion of the canvas
    image(hornet,xpos,ypos,50,50); // draw hornet
}

// VIRUS

function updatevirus(){
    for (var i = 0; i < virus.length; i++){ // showing and mocing viruses
        virus[i].move();
        virus[i].display();
    }
}
function addvirus() { // creating a new row of virus
    if (count % 100 == 0){
      for (var i = 0; i < 4; i++){
          virus.push(makecv(int(random(10))*50)); // x position of virus is at mulitples of 50
      }
    }
}
function removevirus(){ // if virus is less than height of canvas the virus is kept
    var viruskeep = [];
    for (var i = 0; i < virus.length; i++){
        if (virus[i].y < height) {
            viruskeep.push(virus[i]);
        }
    }
    virus=viruskeep
}
function makecv(startx) { // object propeties of virus with x value being varied from loop from before
    var virus = {x:startx,
                y: -100,
                speed:.5,
                img: random(cvimage),
                move: virusmove,
                display: virusdisplay}
    return virus;
}
function virusmove() { // virus movement
    this.y += this.speed;
}
function virusdisplay() {// show virus
    image(this.img,this.x,this.y,50,50);
}

//BULLET

function mousePressed(){ // when mouse is pressed a new bullet is generated
      var startingbullet = makebullet(xpos, ypos);
      bullets.push(startingbullet);
}
function updateremovebullet(){ //move and show bullet while keeping if under 150 counts to keep array short
  newbullets = [];
  for (var i = 0; i < bullets.length; i++) {
      var b = bullets[i];
      b.stepFunction();
      b.drawFunction();
      if (b.age < 150) {
          newbullets.push(b);
      }
  }
  bullets = newbullets; // kept bullets back into bullets array
}
function bulletmove() { // bullet movement
    this.y -= this.dy;
    this.age ++
  }
function bulletdisplay() { // glowing green bullets
    fill(0,200,0)
    ellipse(this.x,this.y,10)
    fill(0,255,0)
    ellipse(this.x,this.y,5)
}
function makebullet(bulletx, bullety) { // bullet object properties
    b = {x: bulletx,
         y: bullety,
         dy: 4,
         age: 0,
         stepFunction: bulletmove,
         drawFunction: bulletdisplay
        }
    return b;
}
function bulletvirusinteraction (){
  for (var i= virus.length-1;i >0; i--) { // linear search virus backwards so when spliced it doesnt skip one
    for (var j= bullets.length-1;j >0; j--) { // linear search bullets
      if ((bullets[j].x <= virus[i].x+50) // range of bullet and virus x values must match
        & (bullets[j].x >= virus[i].x-50)
        && (bullets[j].y <= virus[i].y+25)){ // range of bullet and virus y values must match
      virus.splice(i,1); //if they match then both bullet and virus disappear from the array
      bullets.splice(j,1);
      }
    }
  }
}
function lose (){
    for (var i= 0 ;i < virus.length; i++) {
      if ( virus[i].y==450){ // if any virus' y value passes 450 then player loses
        gameover(); // trigger gameover screen
      }
    }
}
function gameover (){
  fill(255,0,0);
  rect(0,0,500,500);
  noStroke();
  fill(0);
  textSize(50);
  text('GAME OVER',100, height/2);
  textSize(20);
  frameRate(0); // end frame
}

Final Project

Welcome to Covid Retreat!

For this project I was inspired to create a virtual escape due to the restrictions Covid-19 has created. I experimented with sound, location design, a game-like set up.

The program includes 4 locations and you can select your location of choice. Clicking on the icon allows you to enter that location, while pressing the back arrow on your keyboard returns you to the game page. Each location has a unique sound that is supposed to be ambient and relaxing so you can meditate to it. The city backdrop has stars that spin with the mouse X location and the village backdrop has snow falling. These act as additional visual aids.

The poppy field has sounds of birds and how a relaxing field would sound. The beach has the calming noise of waves and seagulls in the distance. The city has street noise as well as ambient jazz street music. The village has noise of wind chimes fluttering in the wind. The pictures of the locations act as aids to visualize the location you’re in, and then you can close your eyes and listen to the sounds to meditate.

graanak-15
//This is supposed to be a meditation simulation where you can escape to a location because 
// of the restrictions covid has placed on us. Welcome to Covid Retreat!

var homePage = true;
var gamePage = false;
var locationPoppy = false;
var locationBeach = false;
var locationCity = false;
var locationVillage = false;

//image variables
var gpage;
var poppyImg;
var cityImg;
var beachImg;
var villageImg;

//sounds variables
var field;
var beach;
var seagull;
var city;
var jazz;
var chimes;

//snow variables 
var xpos = [];
var ypos = [];
var dir = [];


function preload() {
	gpage = loadImage("https://i.imgur.com/kWIbADG.png");
	poppyImg = loadImage("https://i.imgur.com/gX6nVv0.png");
	villageImg = loadImage("https://i.imgur.com/ncTFXtG.png");
	cityImg = loadImage("https://i.imgur.com/JzdvYPw.png");
	beachImg = loadImage("https://i.imgur.com/l9hqxRW.png");

	field = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/135472__kvgarlic__summeropenfielddusk.wav");
	beach = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/320306__sophronsinesounddesign__beach-9.wav");
	seagull = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/353416__squashy555__seagull-on-beach.mp3");
	city = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/182872__klankbeeld__nightcity-hum-01-130212.mp3");
	jazz = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/54066__reinsamba__jazz-street-musicians.wav");
	chimes = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/324325__opmartin__wind-chimes.mp3");
}

function soundSetup() { 
	field.rate(0.75);
	field.setVolume(0.5);
	beach.rate(0.5);
	beach.setVolume(0.15);
	seagull.setVolume(0.1);
	city.setVolume(0.5);
	jazz.setVolume(1);
	chimes.setVolume(1.5);
}


function setup() {
    createCanvas(600, 500);
    useSound();
    //snow setup
    for(var i = 0; i < 100; i++){
    	xpos[i] = random(0, width);
    	ypos[i] = random(0, height);
    	dir[i] = random(1, 3);
    }
}

function draw() {

	//drawing the homepage using p5js commands

	if(homePage==true){
		background(230);
		noStroke();

		cube();

		fill(255);
		textSize(15);
		text('Welcome to Covid Retreat. Let us begin your relaxation journey.', 100, 350);

		fill(168, 255, 28, 200);
		rect(209, 420, 188, 58);
		fill(255);
		rect(209, 420, 181, 50);

		fill(0);
		text('Click to start.', 250, 450);

		fill(168, 255, 28);
		circle(mouseX, mouseY, 5);
		fill(168, 255, 28, 200);
		circle(mouseX, mouseY, 15);
		fill(168, 255, 28, 100);
		circle(mouseX, mouseY, 20);

//setting the backdrops for each of the locations
//setting the mouse pointer for the cursor the gamepage

	} else if(gamePage==true){
		image(gpage, 0, 0, 600, 500);
		fill(168, 255, 28);
		circle(mouseX, mouseY, 5);
		fill(168, 255, 28, 200);
		circle(mouseX, mouseY, 15);
		fill(168, 255, 28, 100);
		circle(mouseX, mouseY, 20);
		fill(0);
		textSize(10);
		text('If you would like to return to this page, press the back arrow on your keyboard.', 75, 100);

	} else if(locationPoppy==true){
		image(poppyImg, 0, 0, 600, 500);
		
	}else if(locationCity==true){
		//creating the stars that rotate with mouseX position for the city backdrop
		image(cityImg, 0, 0, 600, 500);
		stars(17, 13);
		stars(32, 36);
		stars(214, 10);
		stars(293, 30);
		stars(306, 16);
		stars(364, 59);
		stars(438, 13);
		stars(569, 21);

	}else if(locationBeach==true){
		image(beachImg, 0, 0, 600, 500);

	}else if(locationVillage==true){
		image(villageImg, 0, 0, 600, 500);
		fill(255);
		noStroke();
		//implementing the snow command
		snowing();
	}

}

//creating the logo on the homepage
function cube(){
	fill(255);
	beginShape();
	vertex(300, 70);
	vertex(390, 145);
	vertex(390, 248);
	vertex(300, 320);
	vertex(209, 248);
	vertex(209, 145);
	endShape();

	fill(220);
	beginShape();
	vertex(300, 70);
	vertex(390, 145);
	vertex(300, 210);
	vertex(209, 145);
	endShape();
}

//causing the screen changes and sound changes for each screen
function mousePressed(){
	var my = mouseY;
	var mx = mouseX;

	if(homePage){
		if(mx > 209 & mx < 390 & my > 420 & my < 470){
			gamePage = true;
			homePage = false;
		}
	}else if(gamePage){
		if(mx > 54 & mx < 139 & my > 132 & my < 217){
			locationPoppy = true;
			gamePage = false;
			field.play();
			field.setLoop(true);
		} else if(mx > 54 & mx < 139 & my > 336 & my < 421){
			locationCity = true;
			gamePage = false;
			city.play();
			city.setLoop(true);
			jazz.play();
			jazz.setLoop(true);
		} else if(mx > 338 & mx < 423 & my > 132 & my < 217){
			locationBeach = true;
			gamePage = false;
			beach.play();
			beach.setLoop(true);
			seagull.play();
			seagull.setLoop(true);
		} else if(mx > 338 & mx < 423 & my > 336 & my < 421){
			locationVillage = true;
			gamePage = false;
			chimes.play();
			chimes.setLoop(true);
		}
	}


}	

//function to return to the gamepage 

function keyPressed(){
	if (keyCode === LEFT_ARROW){
		gamePage = true;
		locationPoppy = false;
		locationBeach = false;
		locationCity = false;
		locationVillage = false;
		field.stop();
		beach.stop();
		seagull.stop();
		city.stop();
		jazz.stop();
		chimes.stop();
	}
}

function snowing(){
	for (var i=0; i < xpos.length; i++){
		circle(xpos[i], ypos[i], 2);
		ypos[i] += dir[i];

		if(ypos[i] >= height){
			ypos[i] = 0;
		}
	}
}

function stars(xp, yp){
	stroke(255, 239, 143);
	push();
	translate(xp, yp);
	rotate(radians(mouseX));
	line(-3, 0, 3, 0);
	line(0, -3, 0, 3);
	pop();
}

Final Project

peachsketchfinal
//Sarah Kwok Section B
//sarahkwo


var walkImage = []; //holds sprite walk cycle  
var People = []; //holds randomly sprouting museum-goers
var yloc = 300; //y location of walking figure
var z = 600; //month image x coordinate
var months = []; //holds images for each of the months
var imageWidth = 300; 
var imageHeight = 175;
var r = 0; //x location of rope
var imageLoc = 100; //image y coordinate
var monthfiles = []; //loads month images
var monthindex = 0; // keeps track of which month function is at
var monthnames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]
//emotions matching the events
var emotions = ["R.I.P.", ":(", "!!!", ":0", "bzzz", "BLM", "take off!","prayers","R.I.P.","lol","SAVED", ":)"]
//news headlines matching events 
var commentary = ["Basketball icon Kobe Bryant passes away in tragic accident", 
"Wildfires ravage forests and wildlife around the world",
"Coronavirus is declared a global pandemic", 
"The Pentagon releases never seen before UFO footage",
"Killer Hornets found in Seattle!",
"Black Lives Matter protests sweep the nation",
"SpaceX launches first commercial flight",
"Warehouse explosion devastates Beirut",
"Supreme Court Justice Ruth Bader Ginsburg passes away",
"President Cheeto gets COVID-19",
"Joe Biden wins the 2020 Presidential Election",
"Several promising vaccines emerge. The future seems bright."]

function preload(){

rope = loadImage("https://i.imgur.com/Opiv3O8.png")
frame = loadImage("https://i.imgur.com/ZNqHge9.png")
thoughtbubble = loadImage("https://i.imgur.com/BLov0ZV.png")
	
    //walk cycle sprite images
    var filenames = [];
    filenames[0] = "http://i.imgur.com/svA3cqA.png";
    filenames[1] = "http://i.imgur.com/jV3FsVQ.png";
    filenames[2] = "http://i.imgur.com/IgQDmRK.png";
    filenames[3] = "http://i.imgur.com/kmVGuo9.png";
    filenames[4] = "http://i.imgur.com/jcMNeGq.png";
    filenames[5] = "http://i.imgur.com/ttJGwkt.png";
    filenames[6] = "http://i.imgur.com/9tL5TRr.png";
    filenames[7] = "http://i.imgur.com/IYn7mIB.png";

    for (var i = 0; i < filenames.length; i++) {
        walkImage[i] = loadImage(filenames[i]);
    }

    //images for each month
    monthfiles[0] = "https://i.imgur.com/IzzQZ2Z.jpg"
    monthfiles[1] = "https://i.imgur.com/RY8heXd.jpg"
    monthfiles[2] = "https://i.imgur.com/6HM3WnG.jpg"
    monthfiles[3] = "https://i.imgur.com/oBki9og.png"
    monthfiles[4] = "https://i.imgur.com/asttHaY.jpg"
    monthfiles[5] = "https://i.imgur.com/z1d6yIB.jpg"
    monthfiles[6] = "https://i.imgur.com/Acilo1q.jpg"
    monthfiles[7] = "https://i.imgur.com/E1mWLZS.jpg"
    monthfiles[8] = "https://i.imgur.com/UkKfRWx.jpg"
    monthfiles[9] = "https://i.imgur.com/14WgN8Z.jpg"
    monthfiles[10] = "https://i.imgur.com/EWo1aiy.jpg"
    monthfiles[11] = "https://i.imgur.com/vW73ESI.jpg"

for (var j = 0; j < monthfiles.length; j++){
	months[j] = loadImage(monthfiles[j]);
}

}

//sprite character walks in place w/ scrolling background 
function stepCharacter (){

    if (this.imageNumber < 7){
    	this.imageNumber ++
    }
    else {
    	this.imageNumber = 0
    }
}

function drawCharacter (){
	image(walkImage[this.imageNumber], this.x, this.y);
}

function makeCharacter(px, py, pdx, pdy) {
    p = {x: px, y: py,
         imageNumber: 0,
         stepFunction: stepCharacter,
         drawFunction: drawCharacter
        }
        return p;
}

var characters = [];

function setup() {

    createCanvas(600, 500);
    frameRate(25)
    textAlign(CENTER)
    textSize(18);
    textStyle(BOLDITALIC);
    textFont('Georgia');
       var p = makeCharacter(100, yloc,5,1) 
       characters.push(p);

    for (var i = 0; i < 5; i++){
        var rx = random(width);
        var ry = random(height/5*3, height);
        People[i] = makePeople(rx, ry);
    }
}


function draw() {

background(122, 24, 49)
fill(61, 29, 7)
    rect(0,height/4*3, width, height);
fill(0)
//update and draws sprite character

//when the image disappears off the left side of canvas, the x location is reset for next image
//after December scrolls past, cycle loops, and program never ends
if (z <  -imageWidth) {
	z = width
	if (monthindex == months.length-1){
		monthindex = 0
	}
	else {monthindex ++}
}

z -= 5


//cycles through array of month images 
	image(frame, z-20, imageLoc -20, imageWidth+40, imageHeight+40)
	image(months[monthindex], z, imageLoc, imageWidth, imageHeight) 
    fill(222, 197, 109)
    stroke(222, 197, 109)
    rect(z-125, imageLoc+imageHeight -25, 110, 35)
    fill(0)
	text(monthnames[monthindex],z - 70, imageLoc+imageHeight)
    noStroke()

//rope scrolls, and, when rope image leaves canvas, redraws on other side 
if (r < -600){
    r = -5
    }

r -= 5

image(rope, r,height/4*3-65)

//update sprite walks
push();
    p.stepFunction();
    p.drawFunction();
pop();

//people (other people at the museum) randomly spawn
    updatePeople();
    removePeople();
    addNewPeople(); 

//if mouse is pressed, corresponding headline appears at top of screen and sprite character reacts
    if (mouseIsPressed){

        image(thoughtbubble, 150, yloc - 55, 90,80)
        text(emotions[monthindex], 195, yloc-25)
        fill(255)
        text(commentary[monthindex], width/2,50)
        noFill()
    }

}

//people move at same rate as background scrolls, making it seem as though they are standing
function updatePeople(){
    for (var i = 0; i < People.length; i++){
        People[i].move();
        People[i].display();
    }
}

function removePeople(){
    var PeopleToKeep = [];
    for (var i = 0; i < People.length; i++){
        if (People[i].x + People[i].breadth > -50) {
            PeopleToKeep.push(People[i]);
        }
    }
    People = PeopleToKeep; 
}

function addNewPeople() {
    var newPeopleLikelihood = 0.05; 
    if (random(0,1) < newPeopleLikelihood) {
        People.push(makePeople(width, random(height/5*3, height)));
    }
}

function PeopleMove() {
    this.x += this.speed;
}
  
//randomly translate canvas and call object at these locations to draw people
//the other people are random indexes called from sprite walkimage array   
function PeopleDisplay() { 
    push();
    translate(this.x, this.y);
   image(walkImage[this.randomImage], this.breadth, this.nsize)
    pop();
}


function makePeople(birthLocationX, birthLocationY) {
    var People = {x: birthLocationX,
                breadth: 50,
                y:birthLocationY,
                speed: -5.0,
                nsize: round(random(20,40)),
                randomImage: floor(random(8)),
                move: PeopleMove,
                display: PeopleDisplay}
    return People;
}

My program is an animation with some user interactivity. It depicts a character walking through a museum that is representative of the year 2020. Each month is marked by an image of a major event that took place that month. While the character walks, if the viewer presses the mouse, a text description corresponding to each event appears as well as a thought bubble and reaction from the walking figure. On a coding level, I was inspired by the scrolling landscapes, and thought I could apply it in a more layered and complex way. Going through the indices of the array (to change the months) while also timing the scrolling (and corresponding further with the ropes) was much more difficult than I had expected! On a conceptual level, I was inspired to create the Museum of 2020 after my sister was shocked remembering that the murder hornets emerged this year, rather than a longer time ago. It has been a long year marred by unprecedented events, and I thought it would be interesting to revisit these moments that defined the world. If I had more time, I would have wanted to try introducing a more three dimensional element, such as manipulating camera views in order to show different aspects/perspectives/rooms of the museum. I also think it would be difficult to try to pause the program and have the sprite figure turn to each of the images and consider each one.

Final Project: Santa and Rudolph Take on COVID-19

For my project, I wanted to do a Christmas themed game that still demonstrated the severity of COVID-19. For example, the starting screen gives context to the situation, in which all of Santa’s reindeer, except Rudolph, are sick with COVID-19. Therefore, Rudolph is calling on the user to help guide him and Santa through the sky to collect presents and avoid COVID-19.

How the user plays the game: The user plays by clicking on the “START” button on the start screen. This will then take the user to the game, where they will move their mouse up and down to avoid the floating COVID particles, and come in contact with the floating presents in the sky. The user will die and be sent to the “Game Over” screen if they come into contact with the COVID-19 particles floating in the sky. The user will be sent to the “Winner” screen if they can successfully collect 15 presents without touching COVID-19.

I specifically made my code to respond to clicks on a starting button and collisions with presents and COVID-19 particles. For the mouse interaction, I mapped the Y location of the mouse to a smaller range of Y values because I wanted the mouse to not be able to go off of the bottom edge of the canvas too easily, especially because the mountains conceal some of the view. By mapping it, I found that the mouse interaction would have to be in a very far Y location (past 480, the height of the canvas) in order to go off of the screen, and I thought this was better for user control, as the mouse can be very sensitive.

If I had more time, I would have liked to included some audio that made a subtle ‘clink’ noise when collecting presents, and more Christmas-like audios, because what is December without Christmas songs? I would have also like to have more control of how quickly and how frequently the COVID-19 particles and presents were generated. Sometimes they tend to overlap slightly, or the objects tend to be placed so close together that it is hard to collect a present without touching COVID-19 due to lack of space. Overall, I am pleased with this project. 🙂

sketch
//Annie Kim
//anniekim@andrew.cmu.edu
//Section B
//Final Project

/* 
WHAT FULFILLED EACH REQUIREMENT FROM MY PROJECT:
ARRAYS : arrays used for the snowy mountains, snow, presents, and covid
USER-DEFINED OBJECT : presents, covid, snow, and snowflakes (on end screen)
CONDITIONAL PROGRAMMING : if/else for snowflakes on winner screen, if for start button, etc
LOOPS : used for snow, mountains, presents, covid, etc
USER-DEFINED FUNCTION : the snowflake function called in winner screen
TRANSFORMATIONS : rotating covid particle on start screen
*/


/* ~~GLOBAL VARIABLES~~*/ 
//making the snow landscape:
var hillvalue = []; //array for values
var noiseParam = 0;
var noiseStep = 0.009; //rounding the hill values
//start screen alternating to game:
var mode = 0; 
//images variable stated:
var tree; //holds tree png image
var rudolph; //holds rudolph png image
var santa; //holds santa png image
var covid; //holds covid png image
//snow falling (object):
var snow = []; 
var numSnow = 1000;
//rotation
var angle = 0;
//covid particles
var covidGerm = [];
var newCovidLikelihood = 0.015;
//gift "particles"
var gifts = [];
var newGiftLikelihood = 0.02;
//to slow Santa and sled from going off of the screen
var mouseYmapped;
//present counter
var collected = 0;


function preload() { //preloading images that I drew
	tree = loadImage("https://i.imgur.com/gr2EEki.png");
	rudolph = loadImage("https://i.imgur.com/9zvf4hQ.png");
	santa = loadImage("https://i.imgur.com/1oJP4Sx.png");
	covid = loadImage("https://i.imgur.com/RW2zPYi.png");
	present = loadImage("https://i.imgur.com/dZPuHKd.png");
	snowflake = loadImage("https://i.imgur.com/MJawG90.png");
	ripSanta = loadImage("https://i.imgur.com/0c4yP1h.png");
}

function setup() {
    createCanvas(600, 480);
    background(24, 41, 81);
    //setup for the snowy mountains
    for (var i = 0; i <= width/5; i ++) {
    	var n = noise(noiseParam); //value from 0 to 1
    	var value = map(n, 0, 1, height/2, height); 
    	hillvalue.push(value);
    	noiseParam += noiseStep;
    }
    //setup for the snow falling
    for (var j = 0; j < numSnow; j++) {
    	var s = makeSnow(random(0, 600), random(-100, 480), random(-3, 3), 0);
    	snow.push(p);
    }
    frameRate(10);
} 


function draw() {
	//different screen modes
	if (mode == 0) {
		startScreen();
	}
	if (mode != 0) {
		gameStart();
		hills();
	}
} 


function startScreen() { //start screen of the game
	textAlign(CENTER, CENTER);
	textSize(20);
	textFont("GeorgiaBOLD");
	background(24, 41, 81);
	fill(255);
	//instructions and context
	text("The other reindeer are all sick with COVID-19.", width/2, 40);
	text("Press the START button to help Santa and Rudolph on Christmas night!", width/2, 80);
	fill(255);
	text("Move your mouse up and down to guide Santa, and his sled", width/2, 120);
	text("away from COVID-19, and collect the presents!", width/2, 160);
	text("COLLECT 15 PRESENTS TO WIN!", width/2, 200);
	//start button shape
	fill(157, 214, 232);
	noStroke(); 
	rect(210, 400, 180, 65);
	fill(255);
	rect(220, 410, 160, 45);
	fill(0);
	textSize(35);
	text("START", width/2, 435);
	image(tree, -6, 202, 230, 300);
	image(rudolph, 370, 198, 230, 320);
	//rotating covid particle image
	push();
	translate(300, 310);
	rotate(radians(angle));
	image(covid, -85, -85, 170, 170);
	angle -= 5;
	push();
} 


function gameStart() {
    mouseYmapped = map(mouseY, 0, 480, -100, 200);
	fill(24, 41, 81);
	rect(0, 0, 600, 480);
	hills();
	//BOX THAT IS THE "COLLECTED" AREA BEHIND SANTA AND SLED:
	noStroke();
	fill(24, 41, 81); 
	rect(25, mouseYmapped + 15, 230, 110);
	//cue falling snow
	snowingSnowflakes();
	//counter sign
	fill("white");
	strokeWeight(1);
	textSize(30);
	textFont("Times New Roman");
	text("Collected : " + collected, 300, 25);
	image(santa, 0, mouseYmapped, 270, 150);
	//adding "floating" covid particles and presents
	addNewGiftsWithSomeRandomProbability();
	updateAndDisplayGifts();
	updateAndDisplayCovid();
	addNewCovidWithSomeRandomProbability();
} 


function gameOver() {
	fill(0);
	rect(0, 0, 600, 480);
	fill("red");
	stroke("red");
	textSize(60);
	textFont("Times New Roman");
	//game over sign
	text("GAME OVER!", width/2, height/2);
	textSize(30);
	textAlign(LEFT);
	//reminder to refresh to play again
	text("Refresh to play again!", 5, 30);
	//santa's grave image
	image(ripSanta, 200, 12, 270, 200);
}


function gameWin() {
	fill(24, 41, 81);
	rect(0, 0, 600, 480);
	fill("green");
	stroke("green");
	textSize(60);
	textFont("Times New Roman");
	//game winner sign
	text("WINNER!", width/2, height/2 - 100);
	//reminder to refresh to play again
	text("Refresh to play again!", width/2, height/2 - 30);
	//use of snowflakes for decoration
	snowflakes(100, 90);
	snowflakes(300, 60);
	snowflakes(500, 90);

}


function mousePressed() {
	//helps move user from start to game stage
	if (mouseX > 210 & mouseX < 390) {
		if (mouseY > 395 && mouseY < 470) {
			mode = (mode + 1);
		}
	} 
} 


function hills() {
	if (hillvalue.length > 80) { //making hills moves
		hillvalue.shift();
		frameRate(8);
		for (var i = 0; i < width / 5; i ++) {
			var n = noise(noiseParam);
			var value = map(n, 0, 1, height/2, height);
			hillvalue.push(value);
			noiseParam += noiseStep;
		}
	}
	fill(248);
	noStroke();
	beginShape(); //making the hills randomly
	for (var i = 0; i < width/5; i ++) {
		vertex(i*5, hillvalue[i]);
	}
	vertex(width + 150, height);
	vertex(0, height);
	endShape();
} 


function makeSnow(px, py, pdx, pdy) {//snow object
	p = {x: px, y: py,
		dx: pdx, dy: pdy,
		age: 0,
		size : random(1, 4),
		color: color(255),
		stepFunction: snowStep,
		drawFunction: snowDraw
	}
	return p;
} 

//specifying the object
function snowDraw() {
	stroke(this.color);
	strokeWeight(this.size);
	point(this.x, this.y);
} 

//making the snowflakes "bounce" subtly off of the edges 
//of the canvas so they dont disappear off of the screen
function snowStep() {
	this.age++;
	this.x += this.dx;
	this.y += this.dy;
	if (this.x > width) {
		this.dx = -this.dx;
	} else if (this.x < 0) {
		this.dx = - this.dx;
	}
} 

//snowflakes in the background of game screen
function snowingSnowflakes() {
	for (var i = 0; i < numSnow; i ++) {
		var s = snow[i];
		s.stepFunction();
		s.drawFunction();
	}
}

//adding to covid array 
function updateAndDisplayCovid() {
	for (var i = 0; i < covidGerm.length; i++) {
		covidGerm[i].move();
		covidGerm[i].display();
		//deleting covid from array once touched
		//and triggering game over screen when touched
		if (covidGerm[i].x < 255 & covidGerm[i].x > 25) {
			if (covidGerm[i].y < mouseYmapped + 110 && covidGerm[i].y > mouseYmapped + 15) {
				covidGerm.splice(i, 5);
				gameOver();
				noLoop();
			} 
		}
		//if user wins, delete covid from array to make it not show
		if (collected == 15) {
			covidGerm.splice(i, 10);
			noLoop();
		}
	}
}

//randomly making covid particles with a probability
function addNewCovidWithSomeRandomProbability() {
	if (random(0,1) < newCovidLikelihood) {
		covidGerm.push(makeCovid(random(600, 650), random(0, 270)));
	}
} 


function moveCovid() { //speed of covid movement
	this.x += this.speed;
} 


function drawCovid() { //covid scaled size and x/y location
	image(covid, this.x, this.y, 45, 45);
} 


function makeCovid(locationX, locationY) {//covid object
	var covidGerm = {x: locationX,
	y: locationY,
	speed: random(-5, -8),
	move: moveCovid,
	display: drawCovid
	}
	return covidGerm;
} 

//updating and adding to array of presents
function updateAndDisplayGifts() {
	for (var i = 0; i < gifts.length; i ++) {
		gifts[i].move();
		gifts[i].display();
		//deleting present from array once touched
		if (gifts[i].x < 255 & gifts[i].x > 25) {
			if (gifts[i].y < mouseYmapped + 110 && gifts[i].y > mouseYmapped + 15) {
				gifts.splice(i, 1);
				collected += 1;
				//if user wins, game win screen shows
				if (collected == 15) { 
					gameWin();
					noLoop();
					gifts.splice(i, 10);
				}
			}
		}
	}
}

//adding presents randomly
function addNewGiftsWithSomeRandomProbability() {
	if (random(0,1) < newGiftLikelihood) {
		gifts.push(makeGifts(random(600, 650), random(0, 270)));
	}
}


function moveGifts() { //presents moving speed
	this.x += this.speed;
}


function drawGifts() { //drawing presents at this scale and x/y location
	image(present, this.x, this.y, 55, 55);
}


function makeGifts(locationX, locationY) { //present object
	var gifts = {x: locationX,
		y: locationY,
		speed: random(-10, -7),
		move: moveGifts,
		display: drawGifts
	}
	return gifts;
}


function snowflakes(x, y) { //my user-defined function
	var w;
	var h;
	//if snowflake is on the lefthand third of canvas, make it 
	//size 130
	if (x < 200) {
		w = 130;
		h = 130;
		//if snowflake is in middle of canvas, make it size 100
	} else if (x > 200 & x < 400) {
		w = 100;
		h = 100;
		//if snowflake is on righthand third of canvas, make it
		//size 130
	} else {
		w = 130;
		h = 130;
	}
	imageMode(CENTER);
	image(snowflake, x, y, w, h);
}


















Final Project: Monument to the Lost Year

The program that I created for the final project is the Memorial to the Lost Year, a group of digital monuments about the year 2020. I was inspired to create this memorial because I was reflecting on previous pandemics in world history and how we remember those today, and I was curious as to how future generations would reflect upon the Covid-19 Pandemic and the behavioral and cultural changes that came with it. Aesthetically, the collages I created as for each scene were inspired by the work of Cruz Garcia and Nathalie Frankowski and the collages I made while taking a class taught by them this summer.

A local host is needed to run the program. The program starts at a floor plan of the different areas. If the user clicks on the red marker associated with an area they are transported to that scene. At the Entrance Gallery, the user can flip through a selection of images related to life in the year 2020 by clicking the canvas. In the Zoom Monument Scene the user can place candles by clicking on the pedestal. At the Covid-19 Statue, the user is invited to focus on the spinning rings and to meditate or reflect on the pandemic. At the 2020 Election Memorial, users can click the Vote button to submit a mail-in ballot. To move between scenes, the user can press the left arrow key to return to the floor plan and then click on a different red marker.

If I had more time, I would have liked to add more exhibits to the memorial that covers more aspects of life in the year 2020.

monumentDownload

/*Image Sources:
	Zoom Monument Collage:
		Background: https://1.bp.blogspot.com/-clsypiRLZo4/XOPVE1F8TgI/AAAAAAAGZm4/3NzoNNpDCuo5w66qzYwf75csYIhacaj8QCLcBGAs/s1600/Worthington-Whittredge-Foothills-Colorado.jpg
		Zoom Logo: https://humtech.ucla.edu/wp-content/uploads/2018/08/zoom-560x560.png
		Pedestal: https://kingdomhigh.com/image/cache/data/orlandi/provence-riser-stand-pedestal-statue-base-15in-stone-statue-fs8216-orn-fs8216-200142557-700x700.jpg
	Covid-19 Statue Collage
		Background: https://www.thewadsworth.org/wp-content/gallery/hudson-river-school/copy_0_1868.3.jpg
		Sky: https://www.artfixdaily.com/images/fl/july2_cropsey1500x813.jpg
		virus: https://source.wustl.edu/wp-content/uploads/2018/12/flu.jpg
		column: https://victoriafrederick.files.wordpress.com/2014/09/loadbearing-polystone-columns-architectural-columns-roman-corinthian-fluted-columns.jpg
		marble texture: https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fwww.decomurale.ca%2Fwp-content%2Fuploads%2F2015%2F10%2FS_shutterstock_132172547.jpg&f=1&nofb=1
		Sound: https://freesound.org/people/HerbertBoland/sounds/78448/
	Election Memorial Collage:
		Background: https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fwww.thewadsworth.org%2Fwp-content%2Fgallery%2Fhudson-river-school%2F1948.190.jpg&f=1&nofb=1
		Biden Head: https://www.kindpng.com/picc/m/560-5606161_joe-biden-head-hd-png-download.png
		Trump Head: https://basicgestalt.files.wordpress.com/2017/07/trumphead2.png?w=356&h=509
		Bronze Texture 1: https://media.istockphoto.com/photos/bronze-metal-texture-background-picture-id453084961?k=6&m=453084961&s=612x612&w=0&h=AdlZR8A8q8ZXtdDb7aKmYY7rO0iS5Th3OLFKPLUPGFU=
		Bronze Texture 2: https://cdn.wallpapersafari.com/34/19/qP0HSo.jpg
	Image Gallery:
		Collage:
			Background: https://d2jf00asb0fe6y.cloudfront.net/hudson-river-school_05_0abb3e55e0fc49ea59240af9e6e1b9cd.jpg
			Brick Wall: https://jooinn.com/images/brick-wall-154.jpg
		Gallery Images:
			Pence Fly: https://www.india.com/wp-content/uploads/2020/10/mike-pence-debate-1602128479.jpg
			BLM Protest: https://milwaukeerecord.com/wp-content/uploads/2020/06/BLM_PRIDE_MKE_612020-23.jpg
			Biden-Kamala: https://i.dailymail.co.uk/1s/2020/08/21/05/32204630-8649691-Hand_in_hand_Kamala_Harris_and_Joe_Biden_joined_hands_in_the_air-a-16_1597985527220.jpg
			Masks: https://images.assettype.com/swarajya/2020-03/0d8cd05f-25be-4429-b1af-93495e880fef/EThrpG_UwAEEYuA.jfif?w=1280&q=100&fmt=pjpeg&auto=format
			Joe Exotic: https://www.licc.org.uk/app/uploads/2020/05/Tiger-King-Web-MJ-Edit-700x540.png
			Dr. Fauci: https://cspinet.org/sites/default/files/49809803361_8cb800f519_o.jpg
			White House Picket Signs: https://www.vidaenelvalle.com/news/politics-government/ijdvpj/picture247039187/alternates/LANDSCAPE_1140/319913bf2ae577f9ea2d18b8560f6f8b8b025745
			Trump vs Biden: https://stevechabot.com/blog/admin/wp-content/uploads/2020/05/052720-2033-05-500.jpg
			Zoom Meeting: https://d.newsweek.com/en/full/1580408/zoom-meeting.jpg
			Social Distancing: https://qual360.com/wp-content/uploads/2020/04/social-distancing.jpg
*/

var zoomMon;
var floor;
var covidStatue;
var candleColors = ["blue","white","black","green","red"];
var candles = [];
var sceneNumber = 0;
var wind;
var sceneEnter = false;
var election;
var ballots = [];
var wall;
var galleryLinks = ["https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/bidenkamala.jpg",
					"https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/blmprotest.jpg",
					"https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/fauci.jpg",
					"https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/joeexotic.jpg",
					"https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/masks.jpg",
					"https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/pencefly.jpg",
					"https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/socdist.jpg",
					"https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/trumpbiden.jpg",
					"https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/whitehousepicket.jpg",
					"https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/zoommeeting.jpg"];
var galleryImages = [];
var chooseImg;
var angle = 0;


function preload() {
    // call loadImage() and loadSound() for all media files here
    //Zoom Monument Scene Background
    zoomMon = loadImage("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/zoommonument.jpg");
    //Starting Floor Plan
    floor = loadImage("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/floorplan.jpg");
    //Covid-19 Statue Background
    covidStatue = loadImage("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/covidstatue.jpg");
    //Wind Sound
    wind = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/wind.mp3");
    //Election Memorial Background
    election = loadImage("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/election.jpg");
    //Image Gallery Background
    wall = loadImage("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/imagewall.png");
    //Gallery Images
    for (var i = 0; i < galleryLinks.length; i++){
    	var g = galleryLinks[i];
    	galleryImages.push(loadImage(g));
    }


}



function setup() {
    // you can change the next 2 lines:
    createCanvas(400, 400);
    background(255);
    useSound();
    chooseImg = int(random(0,galleryImages.length));

}

function soundSetup() {
	wind.setVolume(.5);

}


function draw() {
	if (sceneNumber == 0){
		image(floor,0,0,400,400);
		//Zoom Monument Marker
		noStroke();
		fill("red");
		circle(150,170,10);
		//Covid statue marker
		circle(150,290,10);
		//Election Memorial Marker
		circle(250,290,10);
		//Entrance Gallery Marker
		circle(250,170,10);
		fill("black");
		text("Click a Marker to go to that Location",10,20);

	} else if (sceneNumber == 1) {
		zoomMonument();

	} else if (sceneNumber == 2) {
		if (sceneEnter == true){
			wind.loop();
			sceneEnter = false;
		}
		nineteenStatue();
	} else if (sceneNumber == 3){
		electionScene();
		noStroke();
		fill("yellow");
		text("Click 'VOTE!' to Cast Ballot",10,20);
		text("Press the Left Arrow to Return",10,30);
		text("2020 ELECTION MEMORIAL",width/2 + 40,height-20);
	} else if (sceneNumber == 4){
		gallery();
	}

	if (sceneNumber != 2){
		wind.stop();
	}
	if (sceneNumber != 3){
		//empty ballots array when you leave election memorial
		ballots = [];
	}
	if (sceneNumber != 1){
		//empty candles array when you leave zoom monument
		candles = [];
	}

}

function mousePressed(){
	//go to Zoom Monument
	if (mouseX >= 140 & mouseX <= 160 && mouseY >= 160 && mouseY <= 180 && sceneNumber == 0 ){
		sceneNumber = 1;
	}
	//go to Covid Statue
	if (mouseX >= 140 & mouseX <= 160 && mouseY >= 280 && mouseY <= 300 && sceneNumber == 0){
		sceneNumber = 2;
		sceneEnter = true;
	}
	//Candle Object Creation
	if (mouseX >= 132 & mouseX <= 245 && sceneNumber == 1){
		var ca = makeCandles(mouseX,302);
		candles.push(ca);
	}
	//go to Election Memorial
	if (mouseX >= 240 & mouseX <= 260 && mouseY >= 280 && mouseY <= 300 && sceneNumber == 0){
		sceneNumber = 3;
	}
	//Ballot object creation
	if(mouseX >= 5 & mouseX <= 45 && mouseY >= 305 && mouseY <= 345 && sceneNumber == 3){
		var mail = makeMailBallots();
		ballots.push(mail);
	}
	//go to Entrance Gallery
	if (mouseX >= 240 & mouseX <= 260 && mouseY >= 160 && mouseY <= 180 && sceneNumber == 0){
		sceneNumber = 4;
	}
	//Click through Image Gallery
	if (sceneNumber == 4){
		choosingImage();
	}


}

function keyPressed (){
	if (keyCode == LEFT_ARROW){
		sceneNumber = 0;
	}
}

function zoomMonument(){
		image(zoomMon,0,0);
		fill("yellow");
		text("Click Pedestal to Place Candle",10,20);
		text("Press the Left Arrow to Return",10,30);
		text("ZOOM MONUMENT",width/2 + 70,height-20);
		for (var i = 0; i < candles.length; i++){ 
			var c = candles[i];
			c.candleDraw();
		}
}

function nineteenStatue(){
	image(covidStatue,0,0);
	fill("white");
	text("Stare Into the Rings and Reflect",10,20);
	text("Press the Left Arrow to Return",10,30);
	text("COVID-19 STATUE",width/2 + 70,height-20);
	hypnoticRing();
}

function makeCandles(candleX,candleY){
	var candle = {x: candleX, y: candleY,
					candleDraw: drawCandles,
					color: candleColors[int(random(0,candleColors.length))]};
	return candle;
}

function drawCandles(){
	//candle base
	noStroke();
	fill(this.color);
	rect(this.x,this.y,5,-10);
	//flame
	fill("yellow");
	beginShape();
		vertex(this.x + 2.5,this.y - 10);
		curveVertex(this.x,this.y - 15);
		vertex(this.x + 2.5, this.y - 21);
		curveVertex(this.x + 5,this.y - 15);
	endShape();
}

function electionScene() {
	image(election,0,0,);
	voterBox();
	for (i = 0; i < ballots.length; i++){
		var b = ballots[i];
		b.drawMail();
		b.moveMail();
	}
}

function voterBox() {
	noStroke();
	fill(0,255,255);
	rect(0,400,50,-100);
	fill(0,90);
	square(0,300,50);
	fill("red");
	circle(25,325,40);
	fill(0);
	text("VOTE!",9,329);
}

function makeMailBallots() {
	var mail = {x: random(60,width - 20), y: 0,
				dy: random(3,5), color: color(random(0,255),random(0,255),random(0,255)),
				drawMail: mailDraw, moveMail: mailMove,};
	return mail;
}

function mailDraw() {
	strokeWeight(1);
	stroke(0);
	fill(this.color);
	rect(this.x,this.y, 20,10);
	noFill();
	triangle(this.x,this.y,this.x + 20, this.y, this.x + 10, this.y + 5);
}

function mailMove() {
	this.y += this.dy;
}

function gallery() {
	image(wall,0,0);
	fill("white");
	text("Click To Change Image Displayed",10,20);
	text("Press the Left Arrow to Return",10,30);
	text("ENTRANCE GALLERY",width/2 + 70,height-20);
	image(galleryImages[chooseImg],100,height*.5,150,150);
}

function choosingImage() {
	var randImg = 0;
	var newImage = 0;
	//make sure new image that shows isn't the same as the previous
	while(newImage < 1){
		randImg = int(random(0,galleryImages.length));
		if (randImg != chooseImg){
			chooseImg = randImg;
			newImage++;
		}
	}
	return chooseImg;
}

function hypnoticRing() {
	noFill();
	strokeWeight(2);
	var ringColors = [];
	for(var i = 0; i < 4; i++){
		var c = color(random(0,255),random(0,255),random(0,255));
		ringColors.push(c);
	}
	push();
		translate(width/2,height/2);
		stroke(ringColors[0]);
		circle(-20*cos(degrees(angle)),0,100);
		stroke(ringColors[1]);
		circle(20*cos(degrees(angle)),0,100);
		stroke(ringColors[2]);
		circle(-20*cos(degrees(angle)),50*sin(degrees(angle)),100);
		stroke(ringColors[3]);
		circle(20*cos(degrees(angle)),50*sin(degrees(angle)),100);
	pop();

	angle += 10;
}

Final Project: Among Us Social Distancing Game

My final project is an Among Us-themed social distancing game. Among Us is an online multiplayer game that has gained significant popularity over the last several months during the quarantine. In my game, you play as a crewmate moving through the environment (the cafeteria environment from the Among Us game). Other crewmates are running past you and toward you and your goal is to socially distance from them by controlling your character’s movements with the keys. To make it easier to play within the blog the key controls are: W= up, A=left, S= down, and D= right, but in my submission, the character’s movements are controlled by the arrow keys. If one of the other crewmates enters your social distancing bubble (blue transparent circle around your character), you get a strike, and after five strikes you will lose the game. As you advance through the game, there will be more crewmates to avoid, requiring more skill and dexterity with the keys. You will win the game after successfully social distancing for one minute.
You can change your character’s color on the start screen by hitting enter. You can also click to advance to the instructions page and then again into gameplay. When the game is over you can click to play again. Overall, I am really happy with how this game turned out, but given more time I would add a settings page with a difficulty level selector and a sound option you can adjust before you play.

Social Distancing Game
var timer = 60;	//will hold seconds value for countdown (from 60 seconds)
var diams = [];	//holds diamond tiles of cafeteria floor
var lastOdd = false;	//boolean to determine when rows are eliminated
var startx = 270;	//starting x position for your character
var starty = 250	//starting y position for your character
var crewMate = makeCharacter(startx, starty, true);	//your character
var buddies = [];	//array to hold crewmates onscreen
var someoneInside = false	//is someone inside your social distancing bubble?
var counter = 0;	//how many strikes you have
var gameOver = false;	//did you lose?
var win = false;	//did you win?
var setting = 0;	//which screen you are on (0: starting, 1: instruction, 2: gameplay, 3: defeat, 4: victory)
//variables associated with choosing your character's color------------------------------------------------------------
var charcols = ['red', 'orange', 'yellow', 'limegreen', 'green', 'blue', 'cyan', 'hotpink', 'brown', 'gray', 'white']; 
var clr = 0;
var colChoice = 'red';	//this array will hold your character's color
//properties for stars on start screen---------------------------------------------------------------------------------
var starx = []; 
var stary = []; 
var stardx = [];
var starsize = [];
//preload game graphics------------------------------------------------------------------------------------------------
let img;
let winimg;
let startimg;
let instruct;

function preload() {
	img = loadImage('https://i.imgur.com/tMs0pNd.png');
	winimg = loadImage('https://i.imgur.com/ff97vVO.pngs');
	startimg = loadImage('https://i.imgur.com/Yy27NCE.png');
	instruct = loadImage('https://i.imgur.com/lIoslK6.png');
}

function setup() {
    createCanvas(600, 600);
    background(165,167,154);
    //set up the grid for the cafeteria floor tiles
    for (var row=0; row < 7; row++){
    	d_row = []
    	if (row % 2 == 0) {
    		for (var col=0; col < 6; col++){
    			if (col % 2 == 0) {
    				d_row.push(smallDiamond(col*105, row*105+35))
    			}
    			else {
    				d_row.push(bigDiamond(col*105+35, row*105+35)) 
    			}
    		}
    		diams.push(d_row)
    	}
    	else {
    		for (var col=0; col < 7; col++){
    			if (col % 2 == 0){
    				d_row.push(bigDiamond(col*105+35, row*105+35))
    			}
    			else {
    				d_row.push(smallDiamond(col*105, row*105+35))
    			}
    		}
    		diams.push(d_row)
    	}
    }
    //set up the array for the crew members that appear
    for (var i=0; i < 3; i++) {
    	buddies[i] = (makeCrew());
    }
    //set up arrays for stars on start screen
    for (var i=0; i<75; i++)  {
			starx[i]= random(width); 
			stary[i]= random(30, height-30); 
			stardx[i]= random(-5, -1);
			starsize[i] = random(3,8) 	
	}
    frameRate(10);
}

function draw() {
	var frameNum = frameCount
	if (setting == 0) {
		startScreen();
	}
	else if (setting == 1) {
		instructionPage();
	}
	else if (setting == 2) {
		gamePlay();
	}
	else if (setting == 3) {
		GameOver();
	}
	else if (setting == 4) {
		GameWon();
	}
	print('frameNum')
}

function mousePressed() {
	if (setting == 0) {	//proceed through the start screen and instructions to the actual gameplay
		setting = 1
	}
	else if (setting == 1) {	//enter gameplay
		setting = 2;	
	}
	//when the game ends, click to play again
	else if (setting == 3) {	
		gameReset()
		setting = 0
	}
	else if (setting == 4) {
		gameReset()
		setting = 0
	}
}
//display the start screen where you can change your character's color
function startScreen() {
	background(0)
	image(startimg, 0, 0, 600, 600);
	for (i=0; i<75; i++) {
		noStroke();
		fill(255);
		circle(starx[i], stary[i], starsize[i]);
		starx[i] += stardx[i]
	}
	starx.shift()	//shift array, moving first value
	stary.shift()
	starsize.shift()
	stardx.shift()
	var newX = 600; 
	var newY = random(30,height-30); 
	var newDX = random(-10, -5);
	var newSize = random(1,8)
	starx.push(newX);
	stary.push(newY);
	stardx.push(newDX);
	starsize.push(newSize);
	push();
	scale(3.75,3.75);
	translate(50,45)
	AmongUs1(colChoice)
	pop();
}
//pressing ENTER on the start screen will change your character's color
function keyPressed() {
	if (keyCode === ENTER & setting == 0){
	if (clr == 10) {
		clr=0
	}
	else {
		clr++; 
	}
	colChoice = charcols[clr]
	}	
}
//instructions: display the instructions for the game
function instructionPage() {
	background(0);
	image(instruct, 0, 0, 600, 600);
	for (i=0; i<75; i++) {
		noStroke();
		fill(255);
		circle(starx[i], stary[i], starsize[i]);
		starx[i] += stardx[i]
	}
	starx.shift()	//shift array, moving first value
	stary.shift()
	starsize.shift()
	stardx.shift()
	var newX = 600; 
	var newY = random(30,height-30); 
	var newDX = random(-10, -5);
	var newSize = random(1,8)
	starx.push(newX);
	stary.push(newY);
	stardx.push(newDX);
	starsize.push(newSize);
}
//reset the gameplay if you play again
function gameReset() {
	//resetting all sketch variables to original values
	frameNum = frameCount
    timer = 60;
	startx = 270;
	starty = 250
	crewMate = makeCharacter(startx, starty, true);	//starting position for your character
	buddies = [];
	someoneInside = false
	counter = 0;
	gameOver = false;
	win = false;
	charcols = ['red', 'orange', 'yellow', 'limegreen', 'green', 'blue', 'cyan', 'hotpink', 'brown', 'gray', 'white']; 
	clr = 0;
	colChoice = 'red';	//this array will hold your character's color
}
//GAMEPLAY--------------------------------------------------------------------------------------------------------------
function gamePlay() {
	if (timer == 0 & gameOver == false) {
		win = true
		setting = 4
	}
	background(165, 167, 154);
	displayDiamond();
	updateFloor();
	elimRow();
	updateRow();
	crewMate.draw();
	crewMate.update();
	updateRadius();
	drawbuddies();
	removebuddies();
	addMate();
	updatebuddies();
	StrikeCounter();
	Timer();
}
//crewmate constructor
function makeCharacter(x, y, right = true) {
	var c = getColor();
	var guy = {charx: x, chary: y, pos: 1, update: updateCharacter, draw: drawCharacter, col: c, facingRight: right}
	return guy;
}
//ACCESSORIES FOR YOUR CHARACTER---------------------------------------------------------------------------------------
//indicate how far away from others your character needs to be
function socialDistanceBubble(x,y,size) {
	noStroke();
	if (someoneInside == true) {	//if someone is inside your social distance bubble, your bubble turns red
		fill(200,0,0,.1*size)
	}
	else {
		fill(0,0,200,.1*size);
	}
	circle(x, y, size);
}
//function to draw shadow which will appear under your character
function Shadow(x,y) {
	noStroke();
	fill(60,60,60,200);
	ellipse(x, y, 70, 12)
}
//DISPLAY YOUR CHARACTER-----------------------------------------------------------------------------------------------
//display your character with x, y positions and color associated to them
//when you go left, your character will face left
function drawCharacter() {
	socialDistanceBubble(this.charx+30, this.chary+40, 220);
	Shadow(this.charx+30, this.chary+82)
	if (this.facingRight == false){
		push();
		scale(-1,1);
		if (this.pos == 1) {
			push();
			translate(-1*this.charx-60, this.chary);
			AmongUs1(colChoice);
			pop();
		}
		else if (this.pos == 2) {
			push();
			translate(-1*this.charx-60, this.chary);
			AmongUs2(colChoice);
			pop();
		}
		else if (this.pos == 3) {
			push();
			translate(-1*this.charx-60, this.chary);
			AmongUs3(colChoice);
			pop();
		}
		else if (this.pos == 4) {
			push();
			translate(-1*this.charx-60, this.chary);
			AmongUs4(colChoice);
			pop();
		}
		else {
			push();
			translate(-1*this.charx-60, this.chary);
			AmongUs5(colChoice);
			pop();
		}
		pop();
	}
	if (this.facingRight == true) {
		if (this.pos == 1) {
			push();
			translate(this.charx, this.chary);
			AmongUs1(colChoice);
			pop();
		}
		else if (this.pos == 2) {
			push();
			translate(this.charx, this.chary);
			AmongUs2(colChoice);
			pop();
		}
		else if (this.pos == 3) {
			push();
			translate(this.charx, this.chary);
			AmongUs3(colChoice);
			pop();
		}
		else if (this.pos == 4) {
			push();
			translate(this.charx, this.chary);
			AmongUs4(colChoice);
			pop();
		}
		else {
			push();
			translate(this.charx, this.chary);
			AmongUs5(colChoice);
			pop();
		}
	}
}
//UPDATE YOUR CHARACTER'S POSITION-----------------------------------------------------------------------------
//update the among us character function drawn so the guy looks like he is walking
//you can control your character with the arrow keys
//your character cannot travel outside the boundaries of the screen
function updateCharacter(){
	if (keyIsDown(65) & this.charx > 20) {	//"A"
    	this.facingRight = false
    	this.charx -= 10;
  	}
  	if (keyIsDown(68) & this.charx < 540) {	//"D"
    	this.facingRight = true
    	this.charx += 10;
  	}
  	if (keyIsDown(87) & this.chary > 5) {	//"W"
    	this.chary -= 10;
  	}
  	if (keyIsDown(83) & this.chary < 520) {	//"S"
    	this.chary += 10;
  	}
	if (this.pos == 5){
		this.pos = 1;
	}
	else {
		this.pos += 1;
	}
}
//CHECK IF SOMEONE IS INSIDE YOUR SOCIAL DISTANCING BUBBLE------------------------------------------------------------
//update position of crewmate relative to your character
function updateRadius() {
	var inRad = false
	for (var i = 0; i < buddies.length; i++) {
		d = dist(buddies[i].charx, buddies[i].chary, crewMate.charx, crewMate.chary);
		if (d < 110) {
			inRad = true;
		}
	}
	if (inRad == true) {
		if (someoneInside ==  false) {
			counter++;
			if (counter == 5) {
				gameOver = true
				setting = 3
			}
			if (timer == 0 & counter < 5 && gameOver == false) {
				win = true
				setting = 4
			}
		}
		someoneInside = true;
	}
	else {
		someoneInside = false;
	}
}
//GAME FEATURES-------------------------------------------------------------------------------------------------------
//displays the strikes in the bottom left
function StrikeCounter() {	
	stroke(255)
	fill(0)
	strokeWeight(3)
	rect(20,550,160,35);
	noStroke()
	textStyle(BOLD);
	textSize(32);
	fill('#bf0000');	//dark red color for the X's
	if (counter == 1) {
		text('X', 40, 570);
	}
	if (counter == 2) {
		text('X', 40, 570);
		text('X', 70, 570);
	}
	if (counter == 3) {
		text('X', 40, 570);
		text('X', 70, 570);
		text('X', 100, 570);
	}
	if (counter == 4) {
		text('X', 40, 570);
		text('X', 70, 570);
		text('X', 100, 570);
		text('X', 130, 570);
	}
	if (counter == 5) {
		text('X', 40, 570);
		text('X', 70, 570);
		text('X', 100, 570);
		text('X', 130, 570);
		text('X', 160, 570);
	}
}
//display game timer in bottom right corner (countdown from 60 seconds)
function Timer() {
	var frameNum = frameCount
	stroke(255)
	fill(0);
	if (timer <= 10) {
		//noStroke();
		fill('#bf0000')
		textStyle(BOLD)
	}
	textFont('Arial Narrow')
	textAlign(CENTER, CENTER);
  	textSize(32);
  	text(timer, width-25, 570);
  	if (frameNum % 10 == 0) { 
    	timer --;
  	}
}
//displays when game is lost
function GameOver() {
	if (gameOver == true) {
		image(img, 0, 0, 600, 600);
		push();
		scale(5,5);
		translate(25,20)
		Dead1(colChoice)
		pop();
		textFont('Arial Narrow')
		textStyle(NORMAL)
		textAlign(CENTER, CENTER);
	  	textSize(35);
	  	fill(255)
	  	noStroke();
		text('Click to play again', width/2, 550)
		setting = 3
	}
}
//displays when game is won
function GameWon() {
	if (win == true) {
		image(winimg, 0, 0, 600, 600);
		push();
		scale(5,5);
		translate(25,25)
		AmongUs1(colChoice)
		pop();
		textFont('Arial Narrow')
		textStyle(NORMAL)
		textAlign(CENTER, CENTER);
	  	textSize(35);
	  	fill(255)
	  	noStroke();
		text('Click to play again', width/2, 550)	
		setting = 4
	}
}
//CREW (PROPERTIES OF OTHER CREWMATES)-----------------------------------------------------------------------------------
//display crew with x, y positions and color associated to them
function drawCrew() {
	if (this.fig == 0) {
		if (this.pos == 1) {
			push();
			translate(this.charx, this.chary)
			AmongUs1(this.col);
			pop();
		}
		else if (this.pos == 2) {
			push();
			translate(this.charx, this.chary)
			AmongUs2(this.col);
			pop();
		}
		else if (this.pos == 3) {
			push();
			translate(this.charx, this.chary)
			AmongUs3(this.col);
			pop();
		}
		else if (this.pos == 4) {
			push();
			translate(this.charx, this.chary)
			AmongUs4(this.col);
			pop();
		}
		else {
			push();
			translate(this.charx, this.chary)
			AmongUs5(this.col);
			pop();
		}
	}
	else {
		push();
		translate(this.charx, this.chary)
		Dead1(this.col);
		pop();
	}
}
//updates crewmate positions with different speeds (to go down canvas if walking and up if dead)
function updateCrew() {
	if (this.fig == 0) {
		this.chary += this.speed;
		if (this.pos == 5) {
			this.pos = 1;
		}
		else {
			this.pos += 1
		}
	}
	else {
		this.chary -= this.speed;
	}
}
//choose a random x position for newly generated crewmates
function getX() {
	var x = random(20, 530)
	if (x >= 160) {
		x += 70;
	}
	else {
		x -= 20;
	}
	return x;
}
//choose starting position at top of canvas for walking crewmates and bottom for dead crewmates so it looks like they are all moving with the screen
function start(f) {
	if (f == 0) {
		return 0
	}
	else {
		return 600
	}
}
//return a random speed from the array, to be assigned to individual crewmate
function getVelocity(status) {
	if (status == 0){
		return Math.floor(random(1,6));
	}
	else {
		return 5;
	}
}
//return a random color from the array, to be assigned to individual crewmate
//other crewmates will not have the same color as your character
function getColor() {
	var cols = ['red', 'orange', 'yellow', 'limegreen', 'green', 'blue', 'cyan', 'hotpink', 'brown', 'gray', 'white'];
	var index = Math.floor(Math.random() * cols.length); 
	while (colChoice == cols[index]) {
		index = Math.floor(Math.random() * cols.length)
	}
	return cols[index]
}
//assign object properties to the crew (crewmates onscreen)
function makeCrew() {
	var x = getX();
	var f = Math.floor(random(0,2));
	var y = start(f);
	var v = getVelocity(f);
	var c = getColor();
	var crew = {charx: x, chary: y, speed: v, update: updateCrew, pos: 1, fig: f, draw: drawCrew, col: c}
	return crew
}
//draw new crewmates
function drawbuddies() {
	for (var i=0; i < buddies.length; i++){
		buddies[i].draw();
	}
}
//update position of new crewmates
function updatebuddies() {
	for (var i=0; i < buddies.length; i++){
		buddies[i].update();
	}
}
//remove crewmates as they pass offscreen
function removebuddies() {
	keep = []
	for (var i=0; i < buddies.length; i++){
		if (buddies[i].chary +600 > 0) {
			keep.push(buddies[i])
		}
	}
	buddies = keep;
}
//add new crewmates with a probability based on the stage (increasing difficulty every 15 seconds)
function addMate() {
	var threshold;
	if (60>timer & timer>=45) {
		threshold = 0.02
	}
	if (45>timer && timer>=30) {
		threshold = 0.045
	}
	if (30>timer && timer>=15) {
		threshold = 0.055
	}
	if (15>timer && timer>=0) {
		threshold = 0.06
	}
	if (random(0,1) < threshold) {
		buddies.push(makeCrew())
	}
}
//CHARACTER DRAWING-----------------------------------------------------------------------------------------------------
//draw all the stages of walking for one crewmate
function AmongUs1(c) {
	stroke(0);
	strokeWeight(5);
	fill(c)
	//backpack
	beginShape();
	curveVertex(16,23);
	curveVertex(4,28);
	curveVertex(4,57);
	curveVertex(18,62);
	endShape(CLOSE);
	//body
	beginShape();
	curveVertex(20,9);
	curveVertex(15,29);
	curveVertex(15,64);
	curveVertex(21,77);
	curveVertex(32,75);
	curveVertex(33,63);
	curveVertex(39,63);
	curveVertex(42,75);
	curveVertex(52,72);	//front of foot
	curveVertex(57,60);
	curveVertex(56,42);
	curveVertex(59,24);
	curveVertex(50,10);
	curveVertex(35,3);
	endShape(CLOSE);
	//goggles
	fill(204,227,238);
	beginShape();
	curveVertex(31,16);
	curveVertex(56,18);
	curveVertex(59,29);
	curveVertex(55,33);
	curveVertex(32,33);
	curveVertex(24,24);
	endShape(CLOSE);
}

function AmongUs2(c) {
	stroke(0);
	strokeWeight(5);
	fill(c)
	//backpack
	beginShape();
	curveVertex(16,23);
	curveVertex(4,28);
	curveVertex(4,57);
	curveVertex(18,62);
	endShape(CLOSE);
	//back leg
	beginShape();
	curveVertex(15,57);
	curveVertex(5,68);
	curveVertex(19,78);
	curveVertex(34,63);
	endShape(CLOSE);
	//body
	beginShape();
	curveVertex(22,6);
	curveVertex(15,30);
	curveVertex(15,56);
	curveVertex(24,65);
	curveVertex(34,65);
	curveVertex(42,66);
	curveVertex(55,79);
	curveVertex(68,70);
	curveVertex(52,59);	//front of foot
	curveVertex(55,47);
	curveVertex(55,34);
	curveVertex(58,21);
	curveVertex(47,7);
	curveVertex(33,2);
	endShape(CLOSE);
	//goggles
	fill(204,227,238);
	beginShape();
	curveVertex(31,16);
	curveVertex(56,18);
	curveVertex(59,29);
	curveVertex(55,33);
	curveVertex(32,33);
	curveVertex(24,24);
	endShape(CLOSE);
}
function AmongUs3(c) {
	stroke(0);
	strokeWeight(5);
	fill(c)
	//backpack
	beginShape();
	curveVertex(16,23);
	curveVertex(4,28);
	curveVertex(4,57);
	curveVertex(18,62);
	endShape(CLOSE);
	//back leg
	beginShape();
	curveVertex(46,56);
	curveVertex(48,73);
	curveVertex(19,72);
	curveVertex(19,62);
	endShape(CLOSE);
	//body
	beginShape();
	curveVertex(19,10);
	curveVertex(15,35);
	curveVertex(17,61);
	curveVertex(25,68);
	curveVertex(28,75);
	curveVertex(24,83);
	curveVertex(36,82);
	curveVertex(41,71);
	curveVertex(39,60);	//front of foot
	curveVertex(49,58);
	curveVertex(57,50);
	curveVertex(56,35);
	curveVertex(58,25);
	curveVertex(54,14);
	curveVertex(45,8);
	curveVertex(32,4);
	endShape(CLOSE);
	//goggles
	fill(204,227,238);
	beginShape();
	curveVertex(31,16);
	curveVertex(56,18);
	curveVertex(59,29);
	curveVertex(55,33);
	curveVertex(32,33);
	curveVertex(24,24);
	endShape(CLOSE);
}
function AmongUs4(c) {
	stroke(0);
	strokeWeight(5);
	fill(c)
	//backpack
	beginShape();
	curveVertex(16,23);
	curveVertex(4,28);
	curveVertex(4,57);
	curveVertex(18,62);
	endShape(CLOSE);
	//back leg
	beginShape();
	curveVertex(40,60);
	curveVertex(56,79);
	curveVertex(66,65);
	curveVertex(54,52);
	endShape(CLOSE);
	//body
	beginShape();
	curveVertex(25,4);
	curveVertex(16,24);
	curveVertex(15,54);
	curveVertex(19,61);
	curveVertex(8,61);
	curveVertex(5,74);
	curveVertex(19,76);
	curveVertex(28,69);
	curveVertex(32,63);	//front of foot
	curveVertex(45,63);
	curveVertex(56,56);
	curveVertex(58,38);
	curveVertex(58,26);
	curveVertex(54,12);
	curveVertex(43,3);
	endShape(CLOSE);
	//goggles
	fill(204,227,238);
	beginShape();
	curveVertex(31,16);
	curveVertex(56,18);
	curveVertex(59,29);
	curveVertex(55,33);
	curveVertex(32,33);
	curveVertex(24,24);
	endShape(CLOSE);
}
function AmongUs5(c) {
	stroke(0);
	strokeWeight(5);
	fill(c)
	//backpack
	beginShape();
	curveVertex(16,23);
	curveVertex(4,28);
	curveVertex(4,57);
	curveVertex(18,62);
	endShape(CLOSE);
	//back leg
	beginShape();
	curveVertex(32,61);
	curveVertex(34,76);
	curveVertex(49,76);
	curveVertex(50,56);
	endShape(CLOSE);
	//body
	beginShape();
	curveVertex(24,3);
	curveVertex(17,24);
	curveVertex(16,51);
	curveVertex(15,59);
	curveVertex(23,59);
	curveVertex(10,64);
	curveVertex(12,72);
	curveVertex(32,70);
	curveVertex(37,62);	//front of foot
	curveVertex(49,62);
	curveVertex(56,54);
	curveVertex(58,34);
	curveVertex(58,23);
	curveVertex(54,13);
	curveVertex(47,5);
	curveVertex(35,1);
	endShape(CLOSE);
	//goggles
	fill(204,227,238);
	beginShape();
	curveVertex(31,16);
	curveVertex(56,18);
	curveVertex(59,29);
	curveVertex(55,33);
	curveVertex(32,33);
	curveVertex(24,24);
	endShape(CLOSE);
}
//draw a dead crewmate
function Dead1(c) {
	stroke(0);
	strokeWeight(5);
	fill(255);
	//bone sticking out
	beginShape();
	curveVertex(33,39);
	curveVertex(32,29);
	curveVertex(27,22);
	curveVertex(32,18);
	curveVertex(35,23);
	curveVertex(37,17);
	curveVertex(41,21);
	curveVertex(38,32);
	curveVertex(38,42);
	endShape(CLOSE);
	fill(c);
	//arm
	beginShape();
	curveVertex(2,39);
	curveVertex(12,34);
	curveVertex(20,38);
	curveVertex(18,60);
	curveVertex(6,59);
	endShape(CLOSE);
	//half body
	beginShape();
	curveVertex(15,37);
	curveVertex(28,40);
	curveVertex(34,37);
	curveVertex(44,40);
	curveVertex(58,38);
	curveVertex(57,66);
	curveVertex(45,74);
	curveVertex(41,62);
	curveVertex(35,62);
	curveVertex(32,74);
	curveVertex(17,73);
	curveVertex(14,49);
	endShape(CLOSE);
}
//BACKGROUND-------------------------------------------------------------------------------------------------------------
//draw the cafeteria floor
//make small diamond tile object
function smallDiamond(x, y) {
	var diamond = {diamondx: x, diamondy: y, diamondw: 70, diamondh: 35, speed: -5.0, draw: drawDiamond, update: updateDiamond}
	return diamond;
}
//draw small diamond
function drawDiamond() {
	noStroke();
	fill(133,135,124);
	beginShape();
	vertex(this.diamondx,this.diamondy);
	vertex(this.diamondx+this.diamondw/2,this.diamondy-this.diamondh);
	vertex(this.diamondw+this.diamondx, this.diamondy);
	vertex(this.diamondx+this.diamondw/2,this.diamondy+this.diamondh);
	endShape(CLOSE);
}
//update position of the tile with speed
function updateDiamond() {
	this.diamondy += this.speed;
}
//make big diamond tile object
function bigDiamond(cx, cy) {
	var bigdiam = {leftD: smallDiamond(cx-70, cy), topD: smallDiamond(cx-35, cy-35), rightD: smallDiamond(cx, cy), bottomD: smallDiamond(cx-35, cy+35), draw: drawBigDiamond, update: updateBigDiamond}
	return bigdiam;
}
//make big diamond tile from smaller diamond tiles
function drawBigDiamond() {
	this.leftD.draw()
	this.topD.draw()
	this.rightD.draw()
	this.bottomD.draw()
}
//update position of big diamond tiles
function updateBigDiamond() {
	this.leftD.update();
	this.topD.update();
	this.rightD.update();
	this.bottomD.update();
}
//draw the diamonds
function displayDiamond() {
	for (var i=0; i < diams.length; i++){
		for (var j=0; j < diams[i].length; j++){
			diams[i][j].draw();
		}
	}
}
//update the positons of the diamonds as the screen scrolls
function updateFloor() {
	for (var i=0; i < diams.length; i++) {
		for (var j=0; j < diams[i].length; j++) {
			diams[i][j].update();
		}
	}
}
//get rid of rows that have slipped offscreen
function elimRow(){
	keepRow = false;
	for (var i=0; i < diams[0].length; i++) {
		if (lastOdd == false){
			if (i % 2 == 0) {
				if (diams[0][i].diamondy + diams[0][i].diamondh > 0) {
					keepRow = true
				}
			}
			else {
				if (diams[0][i].bottomD.diamondy + diams[0][i].bottomD.diamondh > 0){
					keepRow = true
				}
			}
		}
		else {
			if (i % 2 == 0) {
				if (diams[0][i].bottomD.diamondy + diams[0][i].bottomD.diamondh > 0){
					keepRow = true
				}
			}
			else {
				if (diams[0][i].diamondy + diams[0][i].diamondh > 0){
					keepRow = true
				}
			}
		}
	}
	if (keepRow == false){
		diams.shift();
	}
}
//update the new rows added such that they match the original cafeteria tile pattern
function updateRow() {
	if (diams.length < 7){
		n_row = []
		if (lastOdd == true){
			for (var col=0; col < 7; col++){
				if (col % 2 == 0) {
	    			n_row.push(smallDiamond(col*105, 665))
	    		}
	    		else {
	    			n_row.push(bigDiamond(col*105+35, 665)) 
	    		}
			}
			diams.push(n_row);
			lastOdd = false;
		}
		else {
			for (var col=0; col < 7; col++){
	    		if (col % 2 == 0){
	    			n_row.push(bigDiamond(col*105+35, 665))
	    		}
	    		else {
	    			n_row.push(smallDiamond(col*105, 665))
	    		}
	    	}
	    	diams.push(n_row);
	    	lastOdd = true;
		} 
	}
}

Final Project

For my final project, I created an animation. My animation tells a story about myself and how I personally am affected by the pandemic. I believe my story will resonate with a lot of students. My animation highlights the unseen effects that COVID has had on students and shows the progressive loss of motivation and the effects on mental health.
The animation runs without user interaction; however, if the user clicks the mouse, a text box appears describing the current state of the pandemic in a quick “news flash”

covidanimationDownload
//Flora Xia Section B

var sR = 157; //sky red component
var sG = 196; //sky green component
var sB = 245; //sky blue component
var sRC = .5;
var sGC = .5;
var sBC = .5;
//original positions for mask
var mX = 112;
var mY = 340;
var mW = 300;
var mL = 150;
//change in 
var mdX = 1;
var mdY = 1;
var mdW = 1;
var mdL = 1;
//eyes
var eyeRLinks = [
    "https://i.imgur.com/yT0USca.png",
    "https://i.imgur.com/0LktvFO.png",
    "https://i.imgur.com/Dh0klJU.png",
    "https://i.imgur.com/n7e82Zj.png"]

var eyeLLinks = [
    "https://i.imgur.com/LzeqRqt.png",
    "https://i.imgur.com/dcffyk3.png",
    "https://i.imgur.com/UDx8Xmn.png",
    "https://i.imgur.com/WMngOhd.png"]

var eyeR;
var eyeL;

var eyeRImages = [];
var eyeLImages = [];
//details
var detailLinks = [
    "https://i.imgur.com/611Lsvj.png",
    "https://i.imgur.com/iBUjUeg.png",
    "https://i.imgur.com/1dlHNvm.png"]

var detail;
var detailImages = [];
//clouds
var clouds = []


function preload(){
	//eye images
	for (var i = 0; i < 4; i++){
		eyeRImages[i] = loadImage(eyeRLinks[i]);
		eyeLImages[i] = loadImage(eyeLLinks[i]);
	}
	eyeR = eyeRImages[0];
	eyeL = eyeLImages[0];
	for (var j = 0; j < 3; j++){
		detailImages[j] = loadImage(detailLinks[j]);
	}
	detail = detailImages[0];
}


function setup() {
    createCanvas(510, 600);
    frameRate(5);
    for (var i = 0; i < 2; i++){
    	var rx = random(width);
    	var ry = random(20, 200);
    	clouds[i] = makeCloud(rx, ry);
    }
}

function draw() {
	background(sR, sG, sB);
	skyGrey();
	face();
	eyes();
	maskLaptop();
	details();
	updateCloud();
	removeCloud();
	addCloud();
	if (frameCount > 125){
		appleLogo();
	}
	print(frameCount);
}

function mousePressed(){
	let m1 = 'BREAKING NEWS : COVID-19';
	let m2 = 'NEWS: COVID-19 Gets Worse';
	let m3 = 'NEWS: Cases Rising';
	let m4 = 'NEWS: Second Peak';
	fill(255, 150);
	rect(0, 260, 500, 50);
	fill(255, 0, 0);
	textSize(35);
	if (frameCount <= 50){
		text(m1, 0, 300);
	}else if (frameCount > 50 & frameCount <= 100){
		text(m2, 0, 300);
	}else if (frameCount > 100){
		text(m3, 0, 300);
	}

}

function eyes(){
	if (frameCount <= 50){
		//normal eyes
		eyeR = eyeRImages[0];
		eyeL = eyeLImages[0];
	}else if (frameCount > 50 & frameCount <= 100){
		//eyes w eyebags
		eyeR = eyeRImages[1];
		eyeL = eyeLImages[1];
	}else if (frameCount > 100 & frameCount <= 150){
		//eyes tearing
		eyeR = eyeRImages[2];
		eyeL = eyeLImages[2];
	}else if (frameCount > 150){
		//crying
		eyeR = eyeRImages[3];
		eyeL = eyeLImages[3];
	}
	//position images
	image(eyeR, 285, 225, 130, 130);
	image(eyeL, 102, 225, 130, 130);
}

function details(){
	if (frameCount <= 50){
		//details mask
		detail = detailImages[0];
	}else if (frameCount > 50 & frameCount <= 75){
		//details hair
		detail = detailImages[1];
	}else if (frameCount > 75 & frameCount <= 100){
		//details hair
		detail = detailImages[2];
	}else if (frameCount > 100 & frameCount <= 125){
		detail = detailImages[1];
	}else if (frameCount > 125){
		detail = detailImages[2];
	}
	image(detail, 0, 0);
}

function skyGrey(){
	//color change
	sR -= sRC;
	sG -= sGC;
	sB -= sBC;
	if (sR == 134){
		sRC = 0;
	} 
	if (sG == 145) {
		sGC = 0;
	}
	if (sB == 158) {
		sBC = 0;
	}
	

}

function face(){
	//hair back
	noStroke();
	fill(74, 63, 47);
	rect(37, 220, 430, 400);
	//neck
	fill(190, 150, 110);
	rect(175, 450, 150, 120);
	//shirt
	fill(245, 235, 244);
	ellipse(250, 570, 480, 60);
	rect(10, 570, 480, 60);
	fill(190, 150, 110);
	ellipse(250, 540, 150, 40);
	//face shape
	fill(194, 156, 118);
	ellipse(250, 300, 350, 420);
	eyebrows();
	//hair bangs left
	push();
	rotate(radians(30));
	fill(207, 201, 167);
	ellipse(200, 55, 150, 300);
	ellipse(245, 45, 70, 175)
	fill(74, 63, 47);
	ellipse(190, 55, 150, 300);
	ellipse(235, 45, 70, 175)
	pop();
	//hair bangs right
	push();
	rotate(radians(330));
	fill(207, 201, 167);
	ellipse(245, 315, 150, 300);
	ellipse(185, 250, 70, 175);
	fill(74, 63, 47)
	ellipse(250, 315, 150, 300);
	ellipse(190, 250, 70, 175);
	pop();
	//hair bangs top
	fill(74, 63, 47);
	ellipse(250, 50, 250, 100);
	//ears
	fill(194, 165, 125);
	ellipse(60, 290, 40, 80);
	//earrings
	fill(222, 210, 140);
	circle(60, 320, 10);
	circle(50, 310, 7);
	//nose
	nose();
}

function eyebrows(){
	fill(82, 64, 33, 150);
	rect(300, 225, 50, 15);
	rect(150, 225, 50, 15);
	fill(82, 64, 33, 50);
	rect(295, 225, 50, 15);
	rect(155, 225, 50 ,15);
	rect(290, 225, 50, 15);
	rect(160, 225, 50, 15);
}

function nose(){
	fill(163, 130, 96, 150);
	ellipse(260, 385, 50, 15);
	stroke(163, 130, 96, 150);
	strokeWeight(3);
	arc(275, 340, 10, 50, (PI / 2), (PI / 2) * 3);
}

function maskLaptop(){
	if (frameCount < 50){
		//mask
		fill(140, 196, 212);
	    stroke(255);
	    strokeWeight(3);
	    //masklines
	    //earloops
	}
	if (frameCount >= 50){
		//turning into laptop
	    mX -= mdX;
	    mY += mdY;
	    mW += mdW;
	    mL += mdL;
	    fill(140, 196, 210);
	    if (mX == 60){
		    mdX = 0
		    fill(150, 190, 200);
	    }
	    if (mY == 400){
		    mdY = 0
		    fill(161, 185, 190);
	    }
	    if (mW == 375){
		    mdW = 0
		    fill(172, 185, 189)
	    }
	    if (mL == 210){
		    mdL = 0
		    fill(182, 185, 186);
		    //add mac symbol
	    }
	    strokeWeight(3);
	    stroke(255);
	}
	rect(mX, mY, mW, mL); 
}

function appleLogo(){
	fill(255);
	noStroke();
	circle(255, 530, 50);
	fill(182, 185, 186);
	circle(283, 528, 30);
	push();
	translate(255, 530);
	rotate(radians(30));
	fill(255)
	ellipse(-15, -40, 5, 20);
	pop();
}

//cloud object
function updateCloud(){
    for (var i = 0; i < clouds.length; i ++){
        clouds[i].move();
        clouds[i].display();
    }
}

function removeCloud(){
    var keepClouds=[];
    for (var i = 0; i < clouds.length; i++) {
        if (clouds[i].x < width) {
            keepClouds.push(clouds[i]);
        }
    }
    clouds = keepClouds;
}

function addCloud(){
    //little probability
    var newCloudLikelihood = 0.007; 
    if (random(0,1) < newCloudLikelihood) {
        clouds.push(makeCloud(15, 15));
    }
}

function moveCloud(){
    this.x += this.speed;
}

function displayCloud(){
    fill(255);
    noStroke();
    push();
    translate(this.x, this.y - 20);
    circle(0, 0, 135);
    circle(-60, 10, 90);
    circle(60, 10, 90);
    fill(110);
    textSize(24);
    text('anxiety', -40 ,0);
    pop();
}

function makeCloud(birthLocationX, birthLocationY){
    var cloud = {x: birthLocationX,
                y:birthLocationY,
                speed:random(3, 7),
                move: moveCloud,
                display: displayCloud};
    return cloud;
}