Final Project

For this final project, I wanted to create a drawing program for users. I wanted to create a platform that inspired users to be creative for themselves. In 2020, practicing my creative interest was a great way for me to keep my mind off of the current social climate, and focus on something that I enjoyed doing – I wanted others to experience that. It is a simple program, but it works, and it is enjoyable. Just run the program, and start drawing!

If I had more time, I would have added stroke features and visuals that effectively guide the user through choosing color and stroke. And perhaps a randomly generating image relating to 2020 asking users to copy the image. 

sketch

var strokeColor;
var hover;
 
function setup() {
    createCanvas(600, 600);
    strokeColor = color(0);
}
 
function draw() {
    
    noStroke();
    fill(0);
    //borders
    rect(0, 0, width, 80);
    rect(0, height - 20, width, 50);
    rect(0, 0, 20, height);
    rect(width - 20, 0, 20, height);
    //text color
    fill(255);
    textSize(10);
    text("Press the circle button to change the color", 20, 55);
    text("Press Q to clear canvas", 20, 70);
    //title
    strokeWeight(5);
    textSize(15);
    text("Draw your favorite moment from 2020!", 20, 30);


    stroke(strokeColor);
    //calculating distance between mouse and circle
    var distance = dist(mouseX, mouseY, 540, 120); 
    //making sure disatnce is less than circle's radius
    if(distance < 15) {
        hover = true;
    } else {
        hover = false;
    }

    push();
    //draw a circle
    ellipseMode(CENTER);
    ellipse(540, 120, 30, 30);
    pop();

    //testing is mouse is over the circle
    if(hover == true) {
        fill(200);
        cursor(HAND);
    } else {
        fill(255); 
        cursor(ARROW); 
    }
    
}
 
function mousePressed() {
    //changing color when button is pressed
    if(hover == true) {
    strokeColor = color(random(255), random(255), random(255));
    }
}

function mouseDragged() { 
    //creating the brush tool
    strokeWeight(8);
    stroke(strokeColor);
    line(mouseX, mouseY, pmouseX, pmouseY);
}
 
function keyPressed() {
    //clearing canvas
    if(key == 'q' || key == 'Q') {
        clear();
    }
}

Final Project – Survive 2020 Game

Our project is inspired by the game Flappy Bird. In our rendition, 2020 events are the obstacles on the pipes and the goal is to “survive” 2020. The character moves up when you hit the letter ‘m’, the game ends if you hit one of the pipes, hit the ground or if you win by passing 12 pairs of pipes. If you lose by hitting a pipe or win you can play the game again, but if you hit the ground you lose and cannot restart the game. The two sounds you hear are the bounce when you move the character and the clash when the character hits one of the pipes. Based on which pipe you hit, you see a different “game over” message. We chose a darker color scheme and used a fire in the background to match the mood of 2020. If we had more time with this project, we would add a webcam function so that the character would be the user’s face instead of just a smiley face. Overall, this project was definitely challenging but also really fun to create.

final project
/* 
 * Final Project 
 * Rishi Karthikeyan and Amy Lee 
 * rkarthik and amyl2
 * Section B 
 */ 

// Run a local server to hear sounds used 
// Press the letter m to control character
// The game ends if the character hits the ground or the pipes 
// If you lose by hitting a pipe or win you can play the game again 
// but if you hit the ground you lose and cannot restart the game

var score = 0;
var count = 0;
var faceX = 50; 
var faceY = 200; 
var hitPipe = false; 
var endGame = false; 
var gameOn = true;
var gameStart = true;
var characterOn = true;
var pipes = []; 
var fire = [];
var pipeImages = []; // an array to store the images 
var factImages = []; // an array to store the dates between the pipes 
var gameOverImages = []; // an array to store the customized game over images 

var timeline1 = ["1/1/20", "1/16/20", "1/19/20", "2/2/20", "3/11/20", 
    "3/19/20", "3/20/20", "4/1/20", "5/1/20", "5/26/20", "11/6/20", "11/7/20"]

var timeline2=["Australian Bush Fire","Trump Impeached","COVID-19","Superbowl",
    "Parasite Wins Oscars","Zoom University","Tiger King","Royal Family Split",
    "Murder Hornets", "BLM Movement", "Election", "First Female VP Elect"]

function preload() {
    // Circular images that go in the pipes 
    var filenames = []; 
    filenames[0] = "https://i.imgur.com/tP1n00I.png"; // Fire 
    filenames[1] = "https://i.imgur.com/sY9uWvm.png"; // Trump 
    filenames[2] = "https://i.imgur.com/lCBeEEt.png"; // Covid 
    filenames[3] = "https://i.imgur.com/3Rckn2m.png"; // Superbowl 
    filenames[4] = "https://i.imgur.com/ul9jOdN.png"; // Oscar 
    filenames[5] = "https://i.imgur.com/iWRAmux.png"; // Zoom 
    filenames[6] = "https://i.imgur.com/dbYhauj.png"; // Tiger King
    filenames[7] = "https://i.imgur.com/lVbGhGa.png"; // Meg and Harry 
    filenames[8] = "https://i.imgur.com/U1PoDE5.png"; // Hornets 
    filenames[9] = "https://i.imgur.com/nqwizdc.png"; // BLM
    filenames[10] = "https://i.imgur.com/xtEZvMR.png"; // Election 
    filenames[11] = "https://i.imgur.com/1lZjhEQ.png"; // Kamala

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

    // Displays game over message based on which pipe the character dies on
    var filenames2 = []; 
    filenames2[0] = "https://i.imgur.com/ibfDcOO.png"; // Fire  
    filenames2[1] = "https://i.imgur.com/vFpcofS.png"; // Trump 
    filenames2[2] = "https://i.imgur.com/NMyD9W2.png"; // Covid 
    filenames2[3] = "https://i.imgur.com/aU3iUST.png"; // Superbowl 
    filenames2[4] = "https://i.imgur.com/hqLtxr4.png"; // Oscar 
    filenames2[5] = "https://i.imgur.com/59MSAMG.png"; // Zoom 
    filenames2[6] = "https://i.imgur.com/ArzVHYU.png"; // Tiger King
    filenames2[7] = "https://i.imgur.com/up0miQL.png"; // Meg and Harry 
    filenames2[8] = "https://i.imgur.com/pSRx5bC.png"; // Hornets 
    filenames2[9] = "https://i.imgur.com/EzfHYCr.png"; // BLM
    filenames2[10] = "https://i.imgur.com/wJvHY17.png"; // Election 
    filenames2[11] = "https://i.imgur.com/929AM73.png"; // Kamala

    for (var i = 0; i < filenames2.length; i ++) {
        gameOverImages.push(loadImage(filenames2[i])); 
    }

    // Load sounds for when the character moves or hits the pipes 
    characterSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/bounce.wav");
    clashSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/clash.wav"); 
}

function setup() {
    createCanvas(450, 400);
    background(12, 22, 24);
    imageMode(CENTER); 
    useSound();

    if (gameOn == true) {
        fire.push(makeFire());
        pipes.push(makePipes());
    } 
}

function soundSetup() { 
    // Set the volume for the sound effects 
    characterSound.setVolume(0.01);
    clashSound.setVolume(0.05); 
}

function draw() {
    background(12, 22, 24);
    gradientSky();

    if (gameOn == true) {
        // Start the count once the game is on 
        count++
        // Display & add fire
        updateAndDisplayFire(); 
        if (count % 50 == 10){
            fire.push(makeFire()); 
        }
        updateAndDisplayPipes();
        // Add new pipes 
        if (count % 120 == 0){
            if (gameOn == true) {
            }

            if (pipes.length < 12) {
                pipes.push(makePipes()); 
            }

            if (count > 300) {
                score += 150;
            }
        }
    }

    // Score tracker  
    textSize(15);
    fill(72,160,141);
    noStroke();
    text('SCORE ' + score, 50, 23);

    drawFace(); 

    if (count >= 1690){ 
        gameOn = false; 
    } 

    if (gameOn == false) {
        gameWon();
    }

    if (hitPipe == true){
        gameOver(round((count/120) - ((120*3)/120))); 
    }
    
}

function gradientSky() {
    // Background color gradient 
    var darkCol = color(0,12,15); 
    var lightCol = color(14,38,39); 
    for (var y = 0; y < height; y ++){
        var backG = map(y, 0, height, 0, 1); 
        var backGColor = lerpColor(darkCol, lightCol, backG); 
        stroke(backGColor); 
        line(0, y, width, y); 
    }

    // Fire Embers 
    for (var i = 0; i < 35; i++) {
        strokeWeight(4);
        if (round(random(1)) == 0 ) {
            stroke(148, 67, 43);
        } else {
            stroke(81, 33, 22);
        }
        point(random(0,width), random(-0, height));
    }
}

// *************** FIRES *************** //
function updateAndDisplayFire(){
    // Update the fire's positions, and display them.
    for (var i = 0; i < fire.length; i++){
        fire[i].move();
        fire[i].draw();
    }
}

// Method to update position of fire every frame
function fireMove() {
    this.x += this.speed;
}

// Draw the fire 
function fireDraw() {
    push();
    translate(0, height - 220);
    scale(1.2, 1.75);
    noStroke();
    fill(81, 33, 22);   //red fire
        beginShape();
        vertex(this.x, this.y + 125);
        vertex(this.x, this.y  + 115);
        vertex(this.x + 5, this.y  + 115);
        curveVertex(this.x + 4, this.y  + 113);
        curveVertex(this.x + 3, this.y  + 112);
        curveVertex(this.x + 3, this.y  + 108);
        curveVertex(this.x + 5, this.y  + 102);
        curveVertex(this.x + 9, this.y  + 98);
        vertex(this.x + 18 + random(-1, 1), this.y + 93+ random(-1, 1));

        curveVertex(this.x + 17, this.y  + 110);
        curveVertex(this.x + 21, this.y  + 112);
        curveVertex(this.x + 31, this.y  + 109);
        curveVertex(this.x + 31, this.y  + 102);
        curveVertex(this.x + 25, this.y  + 95);
        curveVertex(this.x + 24, this.y  + 89);
        curveVertex(this.x + 27, this.y  + 83);
        curveVertex(this.x + 34, this.y  + 77);
        curveVertex(this.x + 40, this.y  + 70);
        curveVertex(this.x + 34, this.y  + 56);
        vertex(this.x + 30 + random(-1, 1), this.y  + 53 + random(-1, 1));

        curveVertex(this.x + 40, this.y  + 56);
        curveVertex(this.x + 50, this.y  + 64);
        curveVertex(this.x + 48, this.y  + 75);
        curveVertex(this.x + 41, this.y  + 83);
        curveVertex(this.x + 38, this.y  + 90);
        curveVertex(this.x + 40, this.y  + 98);
        curveVertex(this.x + 49, this.y  + 99);
        curveVertex(this.x + 52, this.y  + 95);
        curveVertex(this.x + 48, this.y  + 90);
        curveVertex(this.x + 48, this.y  + 84);
        vertex(this.x + 55 + random(-1, 1), this.y  + 75 + random(-1, 1));

        curveVertex(this.x + 54, this.y  + 81);
        curveVertex(this.x + 56, this.y  + 89);
        curveVertex(this.x + 60, this.y  + 97);
        curveVertex(this.x + 56, this.y  + 104);
        curveVertex(this.x + 62, this.y  + 117);
        curveVertex(this.x + 72, this.y  + 118);
        curveVertex(this.x + 80, this.y  + 112);
        curveVertex(this.x + 75, this.y  + 99);
        curveVertex(this.x + 68, this.y  + 92);
        curveVertex(this.x + 63, this.y  + 83);
        curveVertex(this.x + 70, this.y  + 63);
        curveVertex(this.x + 84, this.y  + 54);
        vertex(this.x + 94 + random(-1, 1), this.y  + 50 + random(-1, 1));

        curveVertex(this.x + 85, this.y  + 56);
        curveVertex(this.x + 77, this.y  + 65);
        curveVertex(this.x + 73, this.y  + 73);
        curveVertex(this.x + 77, this.y  + 77);
        curveVertex(this.x + 87, this.y  + 75);
        vertex(this.x + 89 + random(-1, 1), this.y  + 63 + random(-1, 1));

        curveVertex(this.x + 93, this.y  + 68);
        curveVertex(this.x + 93, this.y  + 78);
        curveVertex(this.x + 87, this.y  + 86);
        curveVertex(this.x + 81, this.y  + 93);
        curveVertex(this.x + 87, this.y  + 99);
        curveVertex(this.x + 92, this.y  + 99);
        curveVertex(this.x + 97, this.y  + 92);
        curveVertex(this.x + 94, this.y  + 87);
        curveVertex(this.x + 94, this.y  + 84);
        vertex(this.x + 98 + random(-1, 1), this.y  + 77 + random(-1, 1));

        curveVertex(this.x + 101, this.y  + 85);
        curveVertex(this.x + 104, this.y  + 89);
        curveVertex(this.x + 107, this.y  + 97);
        curveVertex(this.x + 104, this.y  + 104);
        curveVertex(this.x + 101, this.y  + 110);
        curveVertex(this.x + 109, this.y  + 115);

        vertex(this.x + 113, this.y  + 115);
        vertex(this.x + 113, this.y  + 128);
        endShape(CLOSE);
    pop();

    push();
    translate(0, height - 125);
    scale(1, 1);
    noStroke();
    fill(148, 67, 43);  //orange fire   
        beginShape();
        vertex(this.x, this.y + 125);
        vertex(this.x, this.y  + 115);
        vertex(this.x + 5, this.y  + 115);
        curveVertex(this.x + 4, this.y  + 113);
        curveVertex(this.x + 3, this.y  + 112);
        curveVertex(this.x + 3, this.y  + 108);
        curveVertex(this.x + 5, this.y  + 102);
        curveVertex(this.x + 9, this.y  + 98);
        vertex(this.x + 18 + random(-1, 1), this.y + 93+ random(-1, 1));

        curveVertex(this.x + 17, this.y  + 110);
        curveVertex(this.x + 21, this.y  + 112);
        curveVertex(this.x + 31, this.y  + 109);
        curveVertex(this.x + 31, this.y  + 102);
        curveVertex(this.x + 25, this.y  + 95);
        curveVertex(this.x + 24, this.y  + 89);
        curveVertex(this.x + 27, this.y  + 83);
        curveVertex(this.x + 34, this.y  + 77);
        curveVertex(this.x + 40, this.y  + 70);
        curveVertex(this.x + 34, this.y  + 56);
        vertex(this.x + 30 + random(-1, 1), this.y  + 53 + random(-1, 1));

        curveVertex(this.x + 40, this.y  + 56);
        curveVertex(this.x + 50, this.y  + 64);
        curveVertex(this.x + 48, this.y  + 75);
        curveVertex(this.x + 41, this.y  + 83);
        curveVertex(this.x + 38, this.y  + 90);
        curveVertex(this.x + 40, this.y  + 98);
        curveVertex(this.x + 49, this.y  + 99);
        curveVertex(this.x + 52, this.y  + 95);
        curveVertex(this.x + 48, this.y  + 90);
        curveVertex(this.x + 48, this.y  + 84);
        vertex(this.x + 55 + random(-1, 1), this.y  + 75 + random(-1, 1));

        curveVertex(this.x + 54, this.y  + 81);
        curveVertex(this.x + 56, this.y  + 89);
        curveVertex(this.x + 60, this.y  + 97);
        curveVertex(this.x + 56, this.y  + 104);
        curveVertex(this.x + 62, this.y  + 117);
        curveVertex(this.x + 72, this.y  + 118);
        curveVertex(this.x + 80, this.y  + 112);
        curveVertex(this.x + 75, this.y  + 99);
        curveVertex(this.x + 68, this.y  + 92);
        curveVertex(this.x + 63, this.y  + 83);
        curveVertex(this.x + 70, this.y  + 63);
        curveVertex(this.x + 84, this.y  + 54);
        vertex(this.x + 94 + random(-1, 1), this.y  + 50 + random(-1, 1));

        curveVertex(this.x + 85, this.y  + 56);
        curveVertex(this.x + 77, this.y  + 65);
        curveVertex(this.x + 73, this.y  + 73);
        curveVertex(this.x + 77, this.y  + 77);
        curveVertex(this.x + 87, this.y  + 75);
        vertex(this.x + 89 + random(-1, 1), this.y  + 63 + random(-1, 1));

        curveVertex(this.x + 93, this.y  + 68);
        curveVertex(this.x + 93, this.y  + 78);
        curveVertex(this.x + 87, this.y  + 86);
        curveVertex(this.x + 81, this.y  + 93);
        curveVertex(this.x + 87, this.y  + 99);
        curveVertex(this.x + 92, this.y  + 99);
        curveVertex(this.x + 97, this.y  + 92);
        curveVertex(this.x + 94, this.y  + 87);
        curveVertex(this.x + 94, this.y  + 84);
        vertex(this.x + 98 + random(-1, 1), this.y  + 77 + random(-1, 1));

        curveVertex(this.x + 101, this.y  + 85);
        curveVertex(this.x + 104, this.y  + 89);
        curveVertex(this.x + 107, this.y  + 97);
        curveVertex(this.x + 104, this.y  + 104);
        curveVertex(this.x + 101, this.y  + 110);
        curveVertex(this.x + 109, this.y  + 115);

        vertex(this.x + 113, this.y  + 115);
        vertex(this.x + 113, this.y  + 128);
        endShape(CLOSE);
    pop();
}

function makeFire() {
    var fire = {x: width,
                y: 0,
                speed: -2,
                move: fireMove,
                draw: fireDraw}
    return fire;
}

// *************** CHARACTER *************** //
function drawFace() {
    if (characterOn == true) { 
        push(); 
        // Head 
        noStroke();
        fill(72,160,141); 
        ellipse(faceX, faceY, 30, 30); 
        // Eyes 
        fill(12, 22, 24); 
        ellipse(faceX - 9, faceY - 1, 3.5, 3.5); 
        ellipse(faceX + 9, faceY - 1, 3.5, 3.5); 
        // Mouth 
        noFill(); 
        stroke(12, 22, 24); 
        strokeWeight(1); 
        arc(faceX, faceY, 5, 5, 0, PI, OPEN);
        pop(); 
        faceY += 1; 

        // Keep face from going off of the canvas
        if (faceY < 15){
            faceY += 5;
        }
        // Game over if you hit the bottom of the canvas
        if (faceY > height - 15){
           hitBottomGameOver();
        }
    }
}

// *************** PIPES *************** //
function updateAndDisplayPipes(){

    // Update the pipe's positions, and display them
    for (var i = 0; i < pipes.length; i++) {
        pipes[i].move();

        // Game over if face hits the pipes 
        if (((faceY < pipes[i].pipeHeight + 30) & (faceX > pipes[i].x && 
            faceX < pipes[i].x + pipes[i].pipeWidth)) || ((faceY > 400 - 
            ((400 - (pipes[i].pipeHeight + (200 - pipes[i].pipeHeight) + 
            (122 - (200 - pipes[i].pipeHeight)))) + 55)) && 
            (faceX > pipes[i].x && faceX < pipes[i].x + pipes[i].pipeWidth))){

            hitPipe = true; 
            clashSound.play();
        }

        if (gameStart == true) {
            pipes[i].draw();
        }

        // Display image on pipe 
        pipes[i].imageNumber = i;
        if ( pipes[i].imageNumber > 11) {
            pipes[i].imageNumber = 0;
        }

        // Display timeline date in between pipes 
        pipes[i].timelineNumber = i; 
        if ( pipes[i].timelineNumber > 11) {
            pipes[i].timelineNumber = 0;
        }
    } 
}

// Method to update position of pipe every frame
function pipesMove() {
    this.x += this.speed;
}
    
// Draw the pipe 
function pipesDraw() {
    var pipe1Height = this.pipeHeight - 30; 
    var pipe2Height = 400 - (this.pipeHeight + (200 - this.pipeHeight) + 
                    (126 - (200 - this.pipeHeight)) ); 

    fill(34,79,82); 
    noStroke(); 

    // Top Pipe 
    rect(this.x, -30, this.pipeWidth, this.pipeHeight); 
    ellipse(this.x + 40, pipe1Height, this.pipeWidth, this.pipeWidth); 
    image(pipeImages[this.imageNumber], this.x + 40, pipe1Height, 60, 60); 

    // Fact in middle of pipe 
    textSize(15);
    textAlign(CENTER); 
    fill(148, 67, 43);
    text(timeline1[this.timelineNumber], this.x + 40, (pipe1Height + 
        ((400 - ((pipe1Height) + (pipe2Height)))/2)) - 2);
    text(timeline2[this.timelineNumber], this.x + 40, (pipe1Height + 
        ((400 - ((pipe1Height) + (pipe2Height)))/2)) + 15);

    // Bottom Pipe 
    push(); 
    fill(34,79,82); 
    translate(0,400); 
    rect(this.x, -pipe2Height, this.pipeWidth, pipe2Height); 
    ellipse(this.x + 40, -pipe2Height, this.pipeWidth, this.pipeWidth);
    image(pipeImages[this.imageNumber], this.x + 40, -pipe2Height, 60, 60);     
    pop(); 
}

function makePipes() {
    var pipe = {x: 650,
                pipeWidth: 80, 
                pipeHeight: random(130, 200),
                speed: -2, 
                move: pipesMove,
                draw: pipesDraw,
                imageNumber: 0,
                timelineNumber: 0
                }
    return pipe;
}

function keyPressed() {
    if (key == 'm'){ 
        faceY -= 20; 

        if (characterOn == true) {
            characterSound.play();
        }
    }
}

// Function that is run when character hits the bottom of the canvas 
function hitBottomGameOver() {
    push();
    gradientSky();

    noStroke();
    fill(72,160,141);
    rectMode(CENTER);
    rect(width/2, height/2, 227, 55);
    textAlign(CENTER);
    textSize(20);
    fill(148, 67, 43);
    text(' Y O U  L O S T  2 0 2 0 ! ', width/2, height/2);

    characterOn = false;
    noLoop();
    pop();
}

// Function that is run when the character hits the pipe 
function gameOver(pipeNumber){
            // Display the gradient sky
            gradientSky();

            // Display game over image depending on which pipe was hit 
            image(gameOverImages[pipeNumber], width/2, height/2, 250, 250); 

            // Display play again button 
            fill(148, 67, 43);
            stroke(180, 67, 43);
            strokeWeight(2);
            push();
            rectMode(CENTER);
            rect(width/2, height/2 + 160, 110, 35);
            pop();
            textSize(15);
            noStroke();
            fill(255);
            text('PLAY AGAIN', width/2, height/2 + 165);

            gameStart = false;
            characterOn = false;
            hitPipe = true; 
            gameOn = false;
}

// Function that is run when the character wins the entire game 
function gameWon() {
    push();

    // "YOU WON 2020" sign in center of screen 
    noStroke();
    fill(72,160,141);
    rectMode(CENTER);
    rect(width/2, height/2, 225, 55);
    textAlign(CENTER);
    textSize(20);
    fill(148, 67, 43);
    text(' Y O U  W O N  2 0 2 0 ! ', width/2, height/2);

    // Play again button
    fill(148, 67, 43);
    stroke(180, 67, 43);
    strokeWeight(2);
    rect(width/2, height/2 + 55, 110, 35);
    textSize(15);
    noStroke();
    fill(255);
    text('PLAY AGAIN', width/2, height/2 + 55);

    characterOn = false;
    pop();
}

function mousePressed() {
    // Press to play again after a user wins the game 
    if (count >= 1689 & gameOn == false) {
        if (mouseX > width/2 - 55 && mouseX < width/2 + 55 && 
            mouseY < height/2 + 72.5 && mouseY > height/2 + 37.5) {
                gameOn = true;
                gameStart = true;
                characterOn = true;
                endGame = false; 
                count = -50;
                score = 0; 
                pipes = []; 
                fire = [];
        }
    }

    // Press to play again when user lost the game by hitting a pipe 
    if (hitPipe == true) {
        if (mouseX > width/2 - 55 & mouseX < width/2 + 55 && 
            mouseY < height/2 + 177.5 && mouseY > height/2 + 142.5) {
                hitPipe = false; 
                endGame = false; 
                gameStart = true;
                gameOn = true; 
                characterOn = true;
                count = -50;
                score = 0; 
                pipes = []; 
                fire = [];
        }
    }
}





original proposal mockup

***on our Autolab submission we use the up arrow to control the character but here we used the letter m because with the up arrow it would move the whole page up and not just the canvas***

Final Project: survive Covid

sketch

Introduction:
This is a survive Covid game. The goal is to help a ninja who’s trapped in a covid world avoid viruses, obtain masks, and eat sushi! I want to make this educational game to show that to fight covid one needs to wear a mask, stay safe, and eat well. The game is easy to play and has a lighthearted atmosphere. People can play this browser game to kill time and have fun.

Guidelines:
There will be viruses coming from the right of the screen and the player needs to press the space to make the ninja jump over the virus barricades. The player loses if the ninja hits the viruses for more than three times. The player gets an extra life when the ninja gets a mask. The player gets 20 extra points when the ninja eats a sushi. The game gets harder as the player gets higher scores.

Applications:
If I have more time, I wish to implement a shop feature which allows the player to buy new characters and items such as sanitizers and napkins, making the game more interesting.

//Name: Heying Wang  Andrew id: heyingw
//Section B
var ninja;
var ninjaSize=50;
var sushiSize=50;
var virus;
var virusSize=40;
var viruses=[];
var virusImages=[];
var clouds=[];
var sushiArray=[];
//The player has an initial score of 0 and life of 3
var score=0;
var life=3;
var timer=0;

var circleColor = [];
var r=50; //radius
var theta=0; 
var startAngles=[];
var xvalues=[];
var yvalues=[];


function preload() {
    //ninja image
    ninjaImage=loadImage('https://i.imgur.com/kpI63Vj.png')
    //background image
    bgImage=loadImage("https://i.imgur.com/S5mfVFp.jpg");
    //three kinds of covid virus
    virusImage1=loadImage("https://i.imgur.com/SjGhpnK.png")
    virusImage2=loadImage("https://i.imgur.com/AKjfL9n.png")
    virusImage3=loadImage("https://i.imgur.com/nYvztEk.png")
    virusImages.push(virusImage1);
    virusImages.push(virusImage2);
    virusImages.push(virusImage3);

    cloudImg=loadImage("https://i.imgur.com/fLez1dg.png");
    sushiImg=loadImage("https://i.imgur.com/oz3ud5W.png");

    //load the sounds
    game=loadSound('https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/game.wav');
    sushiSound=loadSound('https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/sushi.wav');
    jump=loadSound('https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/jump.wav');
    mask=loadSound('https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/mask.wav');
}


function setup() {
    createCanvas(600, 250);
    useSound();
    //set up with constructors
    ninja=makeNinja(20,height-100,ninjaImage,ninjaSize);
    virus=makeVirus(width-100,height-50,virusSize,random(virusImages));
    viruses.push(virus);
    sushi=makeSushi(width*3,100,sushiImg,sushiSize);
    sushiArray.push(sushi); 

    for (var i = 0; i < 2; i++){
        var rx = random(width,width*2);
        clouds[i] = makeCloud(rx);
    }

    for (var i = 0; i < 12; i++) {
        circleColor[i] = color(random(0,256), random(0, 256), random(0, 256),120);
        startAngles[i] = i*30;
    }
    
}

//set up the sounds
function soundSetup() { 
    game.loop();
    game.setVolume(0.5);
    jump.setVolume(0.1);

    
 
}



function draw() {
    //set a timeCounter
    timer+=1;
    console.log(timer);
    image(bgImage,0,0,600,250);
    fill(255);
    textSize(20);
    text("score: "+score,470,30);
    text("life: "+life,30,30);
    push();
    drawCircles();
    pop();
    //draw ninja. Move ninja
    ninja.show();
    ninja.move();
    for(var i=0;i<sushiArray.length;i++){
        sushiArray[i].show();
        sushiArray[i].move();
    }

    //draw and move every virus in the viruses array
    if(timer>150){
        for(var i=0;i<viruses.length;i++){
            viruses[i].show();
            viruses[i].move();
        }
    }
    console.log(timer);

    //level up as the player gets higher scores
    if(score>50){
        virusSize=50;
    }
    else if(score>120){
        ninjaSize=60;
    }
    else if(score>200){
        virusSize=60;
    }

    /*append new viruses to the list if the virus array is about to 
    running out of virus*/
    if(viruses.length<10){
        makeFiveNewViruses()};
    if(sushiArray.length<2){
        makeNewSushi()};
    //console.log(viruses.length)

    //check collision for every virus in the array
    //check collision only when the timeCounter%10==0
    //we can't check collision at every frame otherwise life will be reducted mulpital times for one collision
    for(var i=0;i<viruses.length;i++){
        if(timer%10==0){
            checkCollision(ninja,viruses[i]);
        }

        //remove the virus that goes off the screen 
        if(viruses[i].x<=-20){
            viruses.splice(viruses[i],1);
            score+=1;
            
        } 



    }

    for(var i=0;i<clouds.length;i++){
        checkCloudCollision(ninja,clouds[i]);
    
    }
    for(var i=0;i<sushiArray.length;i++){
        checkSushiCollision(ninja,sushiArray[i]);
    
    }
    updateAndDisplayClouds();
    removeCloudsThatHaveSlippedOutOfView();
    addNewCloudsWithSomeRandomProbability();
    //constantly check if the game is over
    //gameover condition: life is used up

    checkGameOver(); 

    
  
    
}

//if gameover, clear the canvas, stop the loop
function checkGameOver(){
    if(life==0){
        background(220);
        fill('red');
        text("Game Over!",250,100);
        noLoop();
        game.stop();
    }
}

function drawCircles(){
    noStroke();
    translate(307,85);
    for(var i = 0; i < 12; i++){
        xvalues[i]=r*cos(radians(startAngles[i]+theta));
        yvalues[i]=r*sin(radians(startAngles[i]+theta));
        fill(circleColor[i]);
        circle(xvalues[i],yvalues[i],10);
        theta-=0.05;
    }
}

//ninja consructor
function makeNinja(sx,sy,ninjaImage,ninjaSize){
    var ninja={x: sx, y: sy, sz:ninjaSize,vy: 0, gravity: 1.9, img:ninjaImage, show: ninjaDraw, jump:ninjaJump,
        move:ninjaMove

    }
    return ninja
}


//virus constructor
function makeVirus(sx,sy,virusSize,virusImage){
    var virus={x: sx, y: sy, sz:virusSize, vx:-7, img:virusImage, show: virusDraw, 
        move:virusMove

    }
    return virus
}

//sushi constructor
function makeSushi(sx,sy,sushiImg,sushiSize){
    var ss={x: sx, y: sy, sz:sushiSize, vx:-1, img:sushiImg, show: sushiDraw, 
        move:sushiMove

    }
    return ss
}

//make new viruses when needed
function makeFiveNewViruses(){
    for(var i=0;i<5;i++){
        viruses.push(makeVirus(viruses[viruses.length-1].x+random(120,800),height-50,virusSize,random(virusImages)));
    }
}

function makeNewSushi(){
        sushiArray.push(makeSushi(sushiArray[sushiArray.length-1].x+random(width*2,width*4),random(20,190),sushiImg, sushiSize));
    
}

function ninjaDraw(){
    image(this.img,this.x,this.y,this.sz,this.sz);
}

function virusDraw(){
    image(this.img,this.x,this.y,this.sz,this.sz);
}

function sushiDraw(){
    image(this.img,this.x,this.y,this.sz,this.sz);
}

function ninjaJump(){
    //prevents the ninja from sticking at the top (if player keeps pressing space)
    if(this.y>=height-100){
        this.vy=-25;
    }

    

}


//implement gravity
//use constrain to prevent the ninja from going offscreen
function ninjaMove(){
    this.y+=this.vy;
    this.vy+=this.gravity;
    this.y=constrain(this.y,0,height-this.sz);
 
  

  
    
}


//collision detection
function checkCollisionAandB(A,B){
    if(A.x < B.x + B.sz &
        A.x + A.sz > B.x &&
        A.y < B.y + B.sz &&
        A.y + A.sz > B.y){
            return true
    }
    

}
function checkCollision(ninja,virus){
    if(checkCollisionAandB(ninja,virus)){
            life-=1
    }
    

}

//masks give players life
function checkCloudCollision(ninja,cloud){
    if(checkCollisionAandB(ninja,cloud)){
            mask.play();
            clouds.splice(cloud,1);
            life+=1
    }
    

}

//sushi give players scores
function checkSushiCollision(ninja,sushi){
    if(checkCollisionAandB(ninja,sushi)){
        sushiSound.play();
        sushiArray.splice(sushi,1);
        score+=20; 
    }
    

}




function virusMove(){
    this.x+=this.vx;
  

    
}

function sushiMove(){
    this.x+=this.vx;
  

    
}

//ninja jumps when player presses the space
function keyPressed(){
    if(key==' '){
        ninja.jump();
        jump.play();
    }
}

function updateAndDisplayClouds(){
    // Update the clouds(masks)' positions, and display them.
    for (var i = 0; i < clouds.length; i++){
        clouds[i].move();
        clouds[i].display();
    }
}    

function removeCloudsThatHaveSlippedOutOfView(){
    var cloudsToKeep = [];
    for (var i = 0; i < clouds.length; i++){
        if (clouds[i].x + clouds[i].sz > 0) {
            cloudsToKeep.push(clouds[i]);
        }
    }
    clouds = cloudsToKeep; 
}

function addNewCloudsWithSomeRandomProbability() {
    var newCloudLikelihood = 0.01; 
    if (random(0,5) < newCloudLikelihood) {
        clouds.push(makeCloud(width));
    }
}

function makeCloud(birthLocationX) {
    var cld = {x: birthLocationX,
                cloudImage:cloudImg,
                y:random(10,100),
                speed: -0.5,
                sz:random(25,60),
                move: cloudMove,
                display: cloudDisplay}
    return cld;
};

function cloudMove() {
    this.x += this.speed;
}
function cloudDisplay() {
    image(this.cloudImage,this.x,this.y,this.sz,this.sz*0.5);

}





PROJECT-15 (covid-simulator)

For this project, I decided to go in a direction of analyzing covid spread through showing how if you infect one person, how the others will get infected through probability and chance. I will use an array of people and if one or more is clicked, a droplet of covid is “given” to the person to “infect” them. Over time, the nearby people will heal and recover or pass away. If all people are infected, the population will never recover.

sketch
// 15-104
// SEAN CHEN
// FINAL PROJECT


var people = [];
var wNum = 14;
var hNum = 12;
var chance = .1; // chance of transmission
var speed = 20; // speed of transmission
var deathRate = 0.02; // death rate
var body;

// image for the body
function preload() {
    body = loadImage('https://i.imgur.com/BBvwTQi.png');
}

// creating the heads array
function setup() {
    createCanvas(600, 400);
    for (var i = 0; i < wNum; i++) {
        var temp = []
        for (var j = 0; j < hNum; j++) {
            temp.push(createPerson(i, j));
        }
        people.push(temp);
    }
    frameRate(speed);
}

// drawing people + infection spreading
function draw() {
    background(235);
    updatePerson();
    infectPerson();
}

// step and drawing of people
function updatePerson() {
    for (var i = 0; i < wNum; i++) {
        for (var j = 0; j < hNum; j++) {
            people[i][j].draw();
            people[i][j].step();
        }
    }
}

// creating person object
function createPerson(x, y) {
    var p = {
        px: x*(width/(wNum-1)),
        py: y*(height/(hNum-1)),
        infected: 0,
        age: 0,
        col: 0,
        draw: thePerson,
        step: stepPerson,
    }
    return p;
}

// individual people
function thePerson() {
    stroke(0);
    push();
    translate(-20, 5);
    image(body, this.px, this.py, 40, 80);
    pop();

    push();
    fill(colPerson(this.col));
    circle(this.px, this.py, 30);
    fill(255);
    ellipse(this.px-8, this.py-2, 7, 10);
    ellipse(this.px+8, this.py-2, 7, 10);
    pop();

    push();
    noStroke();
    fill(0);
    circle(this.px-8, this.py-2, 4, 4);
    circle(this.px+8, this.py-2, 4, 4);
    pop();
}

// red for most infected
// green for temp immunity
// black for death
function colPerson(colNum) {
    if (colNum == 0) {
        return color(255);
    } else if (colNum == 1) {
        return color(255, 0, 0);
    } else if (colNum == 2) {
        return color(255, 65, 65);
    } else if (colNum == 3) {
        return color(255, 130, 130);
    } else if (colNum == 4) {
        return color(255, 195, 195);
    } else if (colNum == 5) {
        return color(0, 255, 0);
    } else if (colNum == 6) {
        return color(0);
    }
}

// if infected, what stage infection
function stepPerson() {
    if (this.infected == 2) {
        this.col = 6;
        this.age = 0;
    }
    if (this.infected == 1) {
        this.age++;
        if (this.age <= 10) {
            this.col = 1;
        } else if (this.age > 10 & this.age <= 20) {
            this.col = 2;
        } else if (this.age > 20 & this.age <= 30) {
            this.col = 3;
        } else if (this.age > 30 & this.age < 40) {
            this.col = 4;
        } else if (this.age < 60) {
            if (random(0, 10) < deathRate) {
                this.infected = 2;
            } else {
                this.col = 5;
            }
        } else if (this.age == 60) {
            this.col = 0;
            this.age = 0;
            this.infected = 0;
        }
    }
}

function mouseClicked() {
    clickPerson();
}

// clicking persons to give covid
function clickPerson() {
    for (var i = 0; i < wNum; i++) {
        for (var j = 0; j < hNum; j++) {
            if (dist(mouseX, mouseY, people[i][j].px, people[i][j].py) < 20)  {
                people[i][j].infected = 1;
                people[i][j].col = 1;
                people[i][j].age = 0;
            }
        }
    }
}

// infecting right
function r(i, j) {
    if (random(0, 10) < chance & people[i+1][j].infected != 2) {
        people[i+1][j].infected = 1;
    }
}
// infecting left
function l(i, j) {
    if (random(0, 10) < chance & people[i-1][j].infected != 2) {
        people[i-1][j].infected = 1;
    }
}
// infecting up
function u(i, j) {
    if (random(0, 10) < chance & people[i][j-1].infected != 2) {
        people[i][j-1].infected = 1;
    }
}
// infecting down
function d(i, j) {
    if (random(0, 10) < chance & people[i][j+1].infected != 2) {
        people[i][j+1].infected = 1;
    }
}

// probability and chance of spread
function infectPerson() {
    for (var i = 0; i < wNum; i++) {
        for (var j = 0; j < hNum; j++) {
            if (people[i][j].age >= 20) {
                if (i > 0 & j > 0 && i < wNum-1 && j < hNum-1) {
                    r(i, j);
                    l(i, j);
                    u(i, j);
                    d(i, j);
                } else if (i == 0 & j == hNum-1) {
                    r(i, j);
                    u(i, j);
                } else if (i == wNum-1 & j == 0) {
                    l(i, j);
                    d(i, j);
                } else if (i == 0 & j == 0) {
                    r(i, j);
                    d(i, j);
                } else if (i == 0) {
                    r(i, j);
                    u(i, j);
                    d(i, j);
                } else if (j == 0) {
                    r(i, j);
                    l(i, j);
                    d(i, j);
                } else if (i == wNum-1 & j == hNum-1) {
                    l(i, j);
                    u(i, j);
                } else if (i == wNum-1) {
                    l(i, j);
                    u(i, j);
                    d(i, j);
                } else if (j == hNum-1) {
                    r(i, j);
                    l(i, j);
                    u(i, j);
                }
            }
        }
    }
}