Final Project: Reminders from the Room

finalproject-cb
//Caitlyn Baensch
//cbaensch@andrew.cmu.edu
//Section D

var shelf;
var bedroom;
var wind;
var steam;
var birds = [];
var fish = [];
var enter = false;
var phoneon = false;
var fadeg = 140;
var fadeb = 150;
var steamy = 266;
var steamdy = .5;

//load illustrations
function preload() {
    shelf = loadImage("https://i.imgur.com/FCmktLo.png");
    bedroom = loadImage("https://i.imgur.com/WVYB6XA.png");
    wind = loadImage("https://i.imgur.com/qjTV5Rs.png");
    steam = loadImage("https://i.imgur.com/k561c6E.png");
}

function setup() {
    createCanvas(600, 425);
    
    //setup for birds
    for(var i = 0; i < 6; i++) {
        birdsx = random(width);
        birds[i] = makeBirds(birdsx);
    }

    //setup for fish
    for (var i = 0; i < 12; i++) {
        fishx = random(325, 385);
        fish[i] = makeFish(fishx);
    }

    frameRate(12);
    angleMode(DEGREES);
}

function draw() {
    background(0);

    //show intro screen with instructions
    intro();

    //show the room when enter button is clicked
    if(enter == true) {
        room();
    }
}


//birds helper functions
//update the bird positions and display them
function displayBirds() {
    for (var i = 0; i < birds.length; i++) {
        birds[i].move();
        birds[i].draw();
    }
}

//remove birds that are off the canvas from the array
function removeBirds() {
    var birdsToKeep = [];
    for (var i = 0; i < birds.length; i++) {
        if (birds[i].x + birds[i].w > 0) {
            birdsToKeep.push(birds[i]);
        }
    }
    birds = birdsToKeep;
}

//with a small probability, add a new bird to end of the array
function addNewBirds() {
    var newBirdLikelihood = 0.12;
    if (random(0,1) < newBirdLikelihood) {
        birds.push(makeBirds(width+20));
    }
}

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

function drawBird() {
    push();
    translate(this.x, this.y);
    fill(249, 228, 222);
    noStroke();
    triangle(0, 0, this.w, -this.h, this.w, 0);
    triangle(0, 0, this.w/2, -this.h, this.w/2, 0);
    pop();
}

//bird constructor (random location, size, and speed)
function makeBirds(birdsx) {
    var b = {x: birdsx, y: random(height),
            w: random(8, 16), h: random(4, 8),
            speed: random(-5, -10),
            move: moveBird,
            draw: drawBird
    }
    return b;
}


//fish helper functions
function displayFish() {
    for (var i=0; i<fish.length; i++) {
        fish[i].move();
        fish[i].draw();
    }
}

function moveFish() {
    this.x += this.dx;
    if (this.x > 385 || this.x < 325) {
        this.dx = -this.dx;
    }
}

function drawFish() {
    noStroke();
    fill(this.c);
    ellipse(this.x, this.y, this.w, this.h);
    if (this.dx < 0) {
        triangle(this.x+3, this.y, this.x+6, this.y-3, this.x+6, this.y+3);
    } else {
        triangle(this.x-3, this.y, this.x-6, this.y-3, this.x-6, this.y+3);
    }
}

//fish constructor (random location, size, speed, and color)
function makeFish(fishx) {
    var f = {x: fishx, y: random(195, 240),
        w: random(8, 12), h: random(3, 7),
        dx: random(-3, 3),
        c: color(random(100, 255), random(100, 255), random(100, 255)),
        move: moveFish,
        draw: drawFish
    }
    return f;
}


//wall clock function
function clock() {
    var hr = hour();
    var mn = minute();
    var sc = second();

    //second hand
    strokeWeight(2.15);
    var s = map(sc, 0, 60, 0, 360);
    push();
    rotate(s);
    stroke(255, 176, 148);
    line(0, 0, 16, 0);
    pop();

    //minute hand
    var m = map(mn, 0, 60, 0, 360);
    push();
    rotate(m);
    stroke(110, 160, 133);
    line(0, 0, 14, 0);
    pop();

    //hour hand
    var h = map(hr % 12, 0, 12, 0, 360);
    push();
    rotate(h);
    stroke(110, 160, 133);
    line(0, 0, 10, 0);
    pop();
}


//interactions for tip screens helper functions
//headphones: listen to music
function headphones() {
    if (mouseX > 22 & mouseX < 80 && mouseY > 150 && mouseY < 170) {
        tip('Listen to your favorite music.', 'Listening to music can help you focus, feel better, and relax.');
    }
}

//journals: reflect
function journals() {
    if (mouseX > 73 & mouseX < 102 && mouseY > 110 && mouseY < 122) {
        tip('Reflect on how you are feeling.', 'Try keeping a journal or taking some time each day to check in with yourself.');
    }
}

//tea: stay hydrated
function tea() {
    if (mouseX > 113 & mouseX < 134 && mouseY > 287 && mouseY < 308) {
        tip('Stay hydrated with water or a cup of hot tea.', 'Being well-hydrated improves sleep quality, cognition, and mood.');
    }
}

//phone: check in with friends
function phone() {
    if (mouseX > 137 & mouseX < 171 && mouseY > 303 && mouseY < 312) {
        tip('Check in with friends and family.', 'Catch up over text or phone call and see how everyone is doing.');
    }
}

//window: go for a walk
function win() {
    if (mouseX > 158.5 & mouseX < 268.5 && mouseY > 107 && mouseY < 217) {
        tip('Go outside for a 10-minute walk.', 'A walk can improve your mood and cognitive function as well as reduce stress.');
    }
}

//fish tank and cat: spend time with pets
function pets() {
    if ((mouseX > 313 & mouseX < 401 && mouseY > 187 && mouseY < 251) || (mouseX > 543 && mouseX < 594 && mouseY > 245 && mouseY < 274)) {
        tip('Spend time with pets.', 'Some quality time with your animal friends is sure to make you smile.');
    }
}

//books: read a book
function books() {
    if (mouseX > 325 & mouseX < 367 && mouseY > 278 && mouseY < 308) {
        tip('Get lost in a book.', 'Reading is the perfect way to unwind. Try it before bed instead of using your phone.');
    }
}

//yoga mat: stretch
function yoga() {
    if (mouseX > 318 & mouseX < 600 && mouseY > 378 && mouseY < 425) {
        tip('Take a break and stretch.', 'Doing yoga can help break up long periods of sitting at a desk and clear your mind.');
    }
}

//decorations: surround yourself with things that make you happy
function decoration() {
    if ((mouseX > 314 & mouseX < 378 && mouseY > 122 && mouseY < 174) || (mouseX > 468 && mouseX < 496 && mouseY > 182 && mouseY < 212)) {
        tip('Surround yourself with things you love.', 'Decorate your space with photos, art, and other meaningful items. Avoid clutter!');
    }
}

//clock: keep a daily routine
function time() {
    if (mouseX > 521 & mouseX < 572 && mouseY > 112 && mouseY < 163) {
        tip('Keep a daily routine.', 'Having a daily routine can reduce anxiety and create rhythm in your day.');
    }    
}


//text formatting for headers
function header() {
    textSize(24);
    textStyle(BOLD);
    textFont('Avenir');
}

//text formatting for body
function body() {
    textSize(14);
    textStyle(NORMAL);
    textFont('Avenir');
}


//tip screens formatting
function tip(line1, line2) {
    background(250, 227, 221, 230);
    fill(237, 122, 93);
    header();
    text(line1, 40, 250);
    body();     
    text(line2, 40, 285);
}


//intro opening screen with title and instructions
function intro() {
    background(255, 136, 108);
    fill(250, 227, 221);
    image(shelf, 40, 100, 286, 95);
    textSize(36);
    textStyle(BOLD);
    textFont('Avenir');
    text('Reminders from the Room', 40, 250);
    body();    
    text('Some quick tips for working from home during the pandemic.', 40, 285);
    text('Enter and hover over elements in the illustration to see relevant tips and info.', 40, 302);
    noStroke();
    fill(250, 227, 221);
    rect(456, 335, 100, 38, 38);
    fill(255, 136, 108);
    header();
    text('Enter', 476.5, 362);
    //if enter button is hovered over
    if (mouseX > 456 & mouseX < 555 && mouseY > 335 && mouseY < 373) {
        fill(244, 181, 161);
        rect(456, 335, 100, 38, 38);
        fill(237, 122, 93);
        header();
        text('Enter', 476.5, 362);
    }
}

//if enter button is pressed, enter the room
function mousePressed() {
    if (mouseX > 456 & mouseX < 555 && mouseY > 335 && mouseY < 373) {
        enter = true;
        room();
    }
}


//room environment
function room() {
    //landscape outside window
    image(wind, 146, 100, 125, 116);
    
    //birds flying outside window
    displayBirds();
    removeBirds();
    addNewBirds();

    //bedroom
    image(bedroom, 0, 0, width, height);

    //fish swimming in fish tank
    push();
    displayFish();
    fill(178, 190, 209, 50);
    rect(326, 187, 74, 56);
    pop();

    //wall clock by bed ticking
    push();
    translate(545, 138);
    rotate(-90);
    clock();
    pop();

    //phone screen new notifications
    push();
    noStroke();
    fill(37, 66, 52);
    quad(140, 303.5, 165, 303.5, 167, 308, 139, 308);
    if (frameCount % 90 == 0) {
        phoneon = true;
        if (phoneon == true) {
            fadeg = 240;
            fadeb = 240;
            fill(249, fadeg, fadeb);
            quad(140, 303.5, 165, 303.5, 167, 308, 139, 308);
        }
    } else {
        if (fadeg >= 140 & fadeb >= 150) {
            fadeg = fadeg - 3;
            fadeb = fadeb - 3;
            fill(249, fadeg, fadeb);
            quad(140, 303.5, 165, 303.5, 167, 308, 139, 308);
            phoneon = false;
        }
    }
    pop();

    //steam floats up over cup of tea
    image(steam, 115, steamy, 14, 24);
    steamy -= steamdy;
    if (steamy <= 257 || steamy > 267) {
        steamdy = -steamdy;
    }

    //show tip screens for user interaction
    headphones();
    journals();
    tea();
    phone();
    win();
    pets();
    books();
    yoga();
    decoration();
    time();
}

For my final project, I made an interactive illustration featuring tips for working from home during the pandemic. With hours spent locked up inside in endless Zoom meetings, I think that Zoom fatigue, a warped sense of time, and feelings of stress and anxiety are all common sentiments. I want to bring awareness to these challenges and offer simple strategies to combat fatigue and stress. I wanted my program to have a relaxing and calming feeling to it, so I chose a light, playful color palette for my illustrations as well as used an inviting typeface.

To interact with my program, follow the instructions on the intro screen. Click the “Enter” button to enter the room and explore the environment. Hover over different elements in the animated illustration to view relevant tips and information.

If I had more time, I might consider adding sound to some of the elements in the room. I would also maybe think about adding illustrations/animations to the advice screens and using p5.js to create patterns on objects or wallpaper.

Final Project

sketch
/*
Bon Bhakdibhumi
bbhakdib
Section D
*/

var particles = [];


function setup() {
    createCanvas(400, 400);
    for (var i = 0; i < 50; i ++) {
        particles[i] = new Object();
        particles[i].x = random(width);
        particles[i].y = random(height);
        particles[i].dx = random(-2,5);
        particles[i].dy = random(-2,5);
        particles[i].c = color(86, 137, 179);
        particles[i].covid = false;
    }
    frameRate(25);
}

function draw() {
    background(201, 156, 105);
    for (var j = 0; j < 50; j ++) {
        drawParticles(particles[j]);
        moveParticles(particles[j]);
    }
    if (frameCount == 50 || frameCount % 100 == 0) {
        particles[2].covid = true;
    }
// calculate distance for infection
    for (var i = 0; i < particles.length; i ++) {
        for (var j = 0; j < particles.length; j ++) {
            var d = int(dist(particles[i].x, particles[i].y, particles[j].x, particles[j].y));
            if (d < 20) {
                if (particles[i].covid == true) {
                    particles[j].covid = true;
                }
            }
        }
    }
// display counter
//if all particles have covid, then display the warning text
     var covidCounter = 0;
    for (var i = 0; i < particles.length; i ++) {
        if (particles[i].covid == true) {
            covidCounter ++;
        }
    }
    noStroke();
    fill(255);
    textAlign(LEFT);
    textSize(20);
    text("Infected People:", 10, 25);
    text(covidCounter, 160, 25);
    if (covidCounter == particles.length) {
        fill(255, 253, 131);
        textAlign(CENTER);
        textSize(30);
        text('STOP CORONA!', width/2, height/2.15);
        textSize(35)
        text('KEEP YOUR DISTANCE!', width/2, height/1.75);
    }
}

// reset canvas and cure all particles
function keyPressed() {
        for (var i = 0; i < particles.length; i ++) {
            particles[i].covid = false;
        }
}

// cure covid with mouse
function mousePressed() {
    for (var i = 0; i < particles.length; i ++) {
        var mouseDistance = int(dist(mouseX, mouseY, particles[i].x, particles[i].y));
        if (mouseDistance < 10) {
            particles[i].covid = false;
        }
    }
}

function drawParticles(p) {
    if (p.covid == true) {
        stroke(1);
        fill(204, 61, 61);
    } else {
        stroke(1);
        fill(p.c);
    }
    ellipse(p.x, p.y, 12, 12);
}

function moveParticles(p) {
    p.x += p.dx;
    p.y += p.dy;
    if (p.x > width || p.x < 0) {
        var resetX = random(100);
        if (resetX < 50) {
            p.x = 0;
        } else {
            p.x = width;
        }
    p.dx = random(-2, 5);
    }
    if (p.y > height || p.y < 0) {
        var resetY = random(100);
        if (resetY < 50) {
            p.y = 0;
        } else { 
            p.y = height;
        }
    p.dy = random(-2, 5);
    }
}

The final result of my project is a Covid-19 infection simulator using particles. The canvas represents a public space, and the particles represent people traveling around without social distancing.  Initially, all the particles are not infected. However, as they “travel” around freely–some going off canvas and reentering the canvas from somewhere else–one of the particles would contract “Covid-19, ” turning red. This infected particle will then continue to spread the virus to other particles if other particles are too close–“less than 6 feet”–to it. A counter is displayed at the top left of the canvas, showing how many particles are infected on the screen at the moment. Once every particle is infected, a text is displayed saying “STOP CORONA! KEEP YOUR DISTANCE!”This program is also interactive. Using the mousePressed() function, when the user clicks on an infected particle, he or she can cure it from the virus. However, the particles can become infected again similar to Covid reinfections we have seen on the news. By clicking on any key, the user can also reset the particles to their normal state, restarting the simulation again.

The project is inspired by the frustration I get from watching the news and seeing people not properly social distancing. Hopefully, this project illustrates the importance of social distancing to the viewers while providing them with visual elements that are captivating and interactive. 

If provided more time, I would like to add mutual repulsion to the program, illustrating what effective social distancing looks like, which was one of the main features I planned to implement initially but failed to do so since I didn’t fully understand the physics behind the example code and didn’t want a completely broken program.

Final Project

sketchDownload
 /*
Rachel Kim
Section C
rachelki@andrew.cmu.edu

Nicholas Wong 
Section A 
nwong1@andrew.cmu.edu
*/


//Every function has a comment before it showing who did the majority of the code: Nick, Rachel, or both of us.
//For functions that we did together, specific blocks, statements, and expressions are commented to show who did them.

//Player properties
var gravity = 0.4;
var defaultSpeed = 2;
var jumpForce = 10;
var constantSpeed = 2;
var playerStartPos = 300;
var walkImage = [];

//Stage properties
var stagePos = 0;
var stageSpeed = 2;

//Game state properties
var points = 0;
var gameOver = false;
var startGame = false;

//Game object lists
var platforms = [];
var covids = [];


//Background object lists
var backgroundBuildings = [];
var backgroundObjects = [];
var clouds = [];

//Building images
var housesA;
var housesB;
var supermarket;

//Background images
var cloud;
var sky;
var ground;

//Misc Images
var lampPost;
var streetSign;
var covidImage;


 //Preload images - Rachel Kim
function preload(){
 
    // These URLs are for the individual walk cycle images,
    var filenames = [];
    filenames[0] = "https://i.imgur.com/URNRJvg.png";
    filenames[1] = "https://i.imgur.com/dt8xXHQ.png";
    filenames[2] = "https://i.imgur.com/jmhE5QQ.png";
    filenames[3] = "https://i.imgur.com/twdsSdv.png";
    filenames[4] = "https://i.imgur.com/HWf5XmA.png";
    filenames[5] = "https://i.imgur.com/45onU9z.png";
    filenames[6] = "https://i.imgur.com/ey2SDeI.png";
    filenames[7] = "https://i.imgur.com/cG56PdF.png";
    filenames[8] = "https://i.imgur.com/533xGwE.png";
 
    for (var i = 0; i < filenames.length; i++) 
    {
    	walkImage[i] = loadImage(filenames[i]);
    }

    //loading images for use

    //Background elements
    lampPost = loadImage("https://i.imgur.com/zEDU732.png");
    streetSign = loadImage("https://i.imgur.com/TJ9H37E.png");
    housesA = loadImage("https://i.imgur.com/cwlJyQN.png");
    housesB = loadImage("https://i.imgur.com/lmhZBn8.png");
    supermarket = loadImage("https://i.imgur.com/Q0iAh9M.png");

    //Further background elements
    cloud = loadImage("https://i.imgur.com/4SgU4y8.png");
    sky = loadImage("https://i.imgur.com/34BWtmE.png");
    ground = loadImage("https://i.imgur.com/qLiqpgd.png");


    //Covid obstacles
    covidImage = loadImage("https://i.imgur.com/eJskXy6.png");
}

//Setup Function - Both Rachel and Nick
function setup()
{
	createCanvas(600, 400);
	rectMode(CENTER);
	textAlign(CENTER);
	translate(width/2,height/2)

	pl1 = new createPlayer(50,250,0); //Create a new player at (50,250) - Nick Wong


	//Unless otherwise noted, everything within the dashed lines was done by Rachel Kim:
	//---------------------------------------------------------------------------------------------------------

	//Create buildings
	for (let i = 0; i < 60; i++)
	{
		backgroundBuildings.push(createBuildings(500*i, 120, round(random(0,2))));
	}

	//Create street items
	for (let i = 0; i < 100; i++)
	{
		backgroundObjects.push(createStreetItems(400*i, 335, round(random(0,1))))
	}

	//Create clouds
	for(let i = 0; i < 50; i++)
	{
		clouds.push(createClouds(500*i, random(100,0), random(0,1)));
	}

	//Create platforms
	for (let i = 0; i < 100; i++)
	{
		var colour = color(random(50,150),150,random(50,150));
		platforms.push(createPlatform(100*i + 300, random(100,290), random(50,120), random(20,15), colour));
	}

	//Create covid obstacles
	for (let i = 0; i < 100; i++)
	{
		covids.push(createCovid(random(350,750)*i + 800, random(150,275)));
	}

	//-----------------------------------------------------------------------------------------------------------
	// ***Note***
	// The reason why we are not procedurally generating objects on the fly
	// as the screen scrolls and instead instantiating everything in setup
	// is because it messes with collision detection sometimes.
}

//Main update function - Both Rachel And Nick
function draw()
{
	//Background sky and ground - Rachel Kim
	image(sky, 0, 0, width, height)
	image(ground, 0 , 240, width, height/2);

	//Point calculation and display - Nick Wong
	points = round(-stagePos/10);
	textSize(14);
	text("Points: " + points.toString(), 35,25);

	//Unless otherwise noted, everything within the dashed lines was done by Nick Wong:
	//------------------------------------------------------------------------------------------------------------
	if(!gameOver & startGame)
	{
		push();
		stagePos -= defaultSpeed; //Set scroll speed to default speed
		translate(stagePos + playerStartPos,0); //Translate entire canvas by scroll speed

		drawBackground(); //Draw background - by Rachel Kim


		pl1.update(); //Update player
		pl1.display(); //Update player display

		//Update canvas display
		for(let i = 0; i < platforms.length; i++)
		{
			platforms[i].display();
		}

		//Update covid obstacle display
		for(let i = 0; i < covids.length; i++)
		{
			covids[i].display();
		}
		pop();

		//Increase scroll and movement speed if total points is a multiple of 300
		if(points % 300 == 0 & points > 0)
		{
			defaultSpeed += 0.5;
			constantSpeed += 0.5;
		}
	}
	//---------------------------------------------------------------------------------------------------------------
	//Game over screen - Rachel Kim
	else if(gameOver)
	{
		push();
		translate(width/2, height/2);
		textSize(32);
		fill(0);
		text("Game Over!", 10,0); 
		textSize(18);
		text("You scored " + points.toString() + " points!", 10,30);
		text("Press [Space] to restart");
		pop();
	}
	//Start game screen (only shows up once) - Nick Wong
	else if(!startGame)
	{
		push();
		translate(width/2, height/2);
		textSize(32);
		fill(0);
		text("Press [Space] to Start", 10,0);
		pop();
	}
	
}


//Draw background elements - Rachel Kim
function drawBackground()
{
	//Loop through and draw clouds
	for (let i = 0; i < clouds.length; i++)
	{
		clouds[i].display();
		clouds[i].update();
	}
	//Loop through and draw buildings
	for (let i = 0; i < backgroundBuildings.length; i++)
	{
		backgroundBuildings[i].display();
	}
	//Loop through and draw signs and lamps
	for (let i = 0; i< backgroundObjects.length; i++)
	{
		backgroundObjects[i].display();
	}

	//Draw ground
	push();
	fill(141,156,141);
	noStroke();
	rectMode(CORNERS);
	rect(-width, height - 100, width*100, height);
	pop();
}

//Animate player character - Rachel Kim
function drawPlayer() //Loop through walk images
{
	//Loop through at 1/5 speed
	if (frameCount % 5 == 0)
	{
		this.index++
	}

	//Reset image when it reaches end of list
	if(this.index >= 7)
	{
		this.index = 0;
	}

	image(walkImage[this.index],this.x,this.y - this.height/2,this.width,this.height)
}

//Update player - Both Rachel and Nick
function updatePlayer()
{	
	//Game over if player falls off stage - By Rachel Kim
	if(this.x <= -stagePos - playerStartPos)
	{
		gameOver = true;
	}

	//Game over if player touches a covid particle - By Nick Wong
	for(let i = 0; i < covids.length; i++)
	{
		if(this.x + this.width/2 >= covids[i].x - covids[i].width/2 & this.x - this.width/2 <= covids[i].x + covids[i].width/2 && 
			this.y + this.height/2 >= covids[i].y - covids[i].height/2 && this.y - this.height/2 <= covids[i].y + covids[i].height/2)
		{
			gameOver = true;
		}
	}

	//Unless otherwise noted, everything within the dashed lines was done by Nick Wong:
	//-------------------------------------------------------------------------------------------------------------------------------------------

	this.y += this.dy; // Add y velocity to y position

	//Check if player is on ground (not platforms)
	if(this.y > height - 100 - this.height/2)
	{
		//Set y velocity to 0 and y position to top of ground rect
		this.dy = 0;
		this.y = height - 100 - this.height/2;
		this.grounded = true;
	}
	else
	{
		this.grounded = false;
	}
	

	//Calculate x speed
	let previousLoc = this.x //Store previous x position
	this.x += constantSpeed; //Add speed
	let currentLoc = this.x //Store current x position
	this.dx = currentLoc - previousLoc; //The difference between previous and current is dx

	//Check platform collisions (still a bit buggy)
	for(let i = 0; i < platforms.length; i++)
	{
		//Check boundary of player is colliding with boundary of platform
		if(this.x + this.width/2 >= platforms[i].x - platforms[i].w/2 & this.x - this.width/2 <= platforms[i].x + platforms[i].w/2)
		{

			//Check boundary of player is colliding with boundary of platform
			if(this.y + this.height/2 > platforms[i].y - platforms[i].h/2 && this.y - this.height/2 < platforms[i].y + platforms[i].h/2)
			{
				//Check if colliding with side of platform
				if(this.dx > 0 && this.dy == 0)
				{
					constantSpeed = 0;
				}

				//Check if below platform
				if(this.dy < 0) //If player is traveling up, player touch bottom of platform
				{
					if(this.y - this.height/2 > platforms[i].y)
					{
						this.y = platforms[i].y + platforms[i].h/2 + this.height/2 + 2; //Set position to bottom of platform
						this.dy = 0 //Y speed to 0
					}

				}
				//Check if on top of platform
				if(this.dy > 0) //If player is traveling down, player touch top of platform
				{
					if(this.y + this.height/2 < platforms[i].y)
					{
						this.y = platforms[i].y - platforms[i].h/2 - this.height/2 + 2; //Set position to top of platform
						this.dy = 0; //Set Y speed to 0
						this.onPlatform = true; //On platform is true (can jump)

					}

				}

			}
			else
			{
				this.onPlatform = false //On platform is not true if not colliding
				constantSpeed = defaultSpeed; //Set player speed to default
			}
			
		}
	}
	this.dy += gravity; //Add gravity
	//-------------------------------------------------------------------------------------------------------------------------------------------
}

//Create player - Nick Wong
function createPlayer(px,py,pdy)
{
	var player = {x: px, y: py, dx: 0, dy: pdy, width: 25, height:45, grounded: false, onPlatform: false, index: 0, display: drawPlayer, update: updatePlayer}

	return player;
}


//Create platform - Nick Wong
function createPlatform(px,py,pw,ph,colour)
{
	var platform = {x: px, y: py, w: pw, h: ph, colour: colour, display: drawPlatform}

	return platform;
}

//Draw platform - Nick Wong
function drawPlatform()
{
	push();
	noStroke();
	fill(this.colour);
	rectMode(CENTER);
	rect(this.x, this.y, this.w, this.h);
	pop();
}

//Create Covid obstacle - Nick Wong
function createCovid(cx, cy)
{
	var cvd = {x: cx, y: cy, width: 20, height: 20, display: drawCovid}
	return cvd;
}

//Create Covid obstacle - Nick Wong
function drawCovid(cx, cy)
{
	push();
	image(covidImage, this.x, this.y, this.width, this.height);
	pop();
}

//Create buildings - Rachel Kim
function createBuildings(bx, by, i)
{
	var bdg = {x: bx, y: by, index: i, display: drawBuilding}
	return bdg;
}

//Render buildings - Rachel Kim
function drawBuilding()
{
	var buildings = [housesA, housesB, supermarket]
	image(buildings[this.index], this.x, this.y);
}

//Create lamps and signs - Rachel Kim
function createStreetItems(bx, by, i)
{
	var items = {x: bx, y: by, index: i, display: drawStreetItems}
	return items;
}

//Render lamps and signs - Rachel Kim
function drawStreetItems()
{
	push();
	scale(0.5,0.5); //Scale because too big
	var streetItems = [streetSign,lampPost]
	image(streetItems[this.index], this.x, this.y);
	pop();
}

//Create clouds - Rachel Kim
function createClouds(bx, by, s)
{
	var cld = {x: bx, y: by, speed: s, display: drawCloud, update: updateCloud}
	return cld
}

//Render clouds - Rachel Kim
function drawCloud()
{
	image(cloud, this.x, this.y);
}

//Add speed to clouds - Nick Wong
function updateCloud()
{
	this.x -= this.speed;
}

//Reset game by setting all values and lists to default - Nick Wong
function resetGame()
{
	covids = [];
	platforms = [];
	clouds = [];
	backgroundBuildings = [];
	streetItems = [];
	stagePos = 0;
	defaultSpeed = 2;
	constantSpeed = 2;
	setup();
	startGame = true;
	gameOver = false;
}

//Spacebar input - Both Rachel and Nick
function keyPressed()
{
	//Spacebar is pressed
	if(keyIsDown(32))
	{
		//Check if not in air - Nick Wong
		if(pl1.grounded || pl1.onPlatform)
		{
			pl1.dy -= jumpForce; //Jump if player is not in the air
		}

		//Reset game if game over - Rachel Kim
		if(gameOver)
		{
			resetGame();
		}

		//Start game if first time opening - Rachel Kim
		if(!startGame)
		{
			resetGame();
		}

	}
}




To run this program, simply press space.

This game is a side-scrolling platform game, where the screen constantly scrolls and the player can only jump.
The goal of the game is to not touch any covid particles and to not fall of the edge of the screen. The longer you survive, the faster the screen scrolls.

We created a side-scrolling game because we thought it would be fun. The theme was around Covid to stay relevant. A side-scrolling game proved to be somewhat challenging due to the dynamic collision detection. Checking bounds and making particles bounce off of things were covered in class, however it was a little harder to implement that in a game where we needed to know exactly where the player collided with an object, and how to deal with positioning the player during/after the collision. Due to time constraints, we did not have much time to play-test the game. For example, we realized only after implementing the graphical elements that the game was pretty hard to read; the player and covid obstacles constantly blended in with the background, making it hard to see where everything was.

Overall, if we had more time, we would have refined the collision detection system and added in an actual algorithm for creating obstacles and platforms, as currently they are being randomly generated and do not take into account whether it is possible to ‘beat’ or ‘pass’ any given set of platforms or obstacles. Also, we would implement sound.

Done by Rachel Kim and Nicholas Wong.

Final Project

This game is about “Trowing out flammable objects” like cigarettes, sparklers, fireworks, lanterns, heaters, and etc. With this game, I would be able to inform people to throw away caution objects, instead of leaving them in the forest.

*Systems & Keys

For this game, I have two scoring systems. One system is adding points(+)when the user successfully throws out an item while another system is deducting points(-) when the user throws out an item that is not dangerous.

Right arrow, Left arrow, ENTER (detailed instructions in the program)

*Goal

Score at least 5 points by throwing out flammable objects

*Attention

If you score lower than -5, Fail page will pop up. If you fail, you can’t start again because you CAN NOT undo wildfire 🙁 But you can start again if you success by pressing ENTER key 🙂

sketch copy
//Final Project

var introPage; //Click page
var introScreen; //click screen 
var item_counter = 0;
var item_interval = 13; // items amount decreases as the user earns more point
var item_startPage; // How page
var item_finishPage; // Congrats page
var item_finishFailPage;  //fail page
var item_startScreen; // How page illustration 
var item_finishScreen; //Congrats page illustration
var item_finishFailScreen; //Fail page illustration
var weapons = [];  //dangerous items array
var nonWeaps = []; //non-weapons array
var dropping_weapons = [] 
var dropping_nonWeaps = []
var trashcan; // trash can image
var backg;
var rate = 2; // speed of items falling
var item_score = 0; // score of throwing out items
var x = 0;
var height = 540;
var y = height - 100;

//trash can keys
var moveRight = false;
var moveLeft = false;

function preload() { // preloads images of dangerous weapons
    var Weapons = [
      "https://i.imgur.com/nu43pvX.png", //lantern
      "https://i.imgur.com/iftAnZO.png", //cigarette
      "https://i.imgur.com/JWyEvWW.png", //firework
      "https://i.imgur.com/RDVdcYb.png"]; //sparklers
    for (var i = 0; i < Weapons.length; i++){
      weapons.push(loadImage(Weapons[i]));
    }
    var NonWeaps = [
      "https://i.imgur.com/y3uSh1k.png", //leaf
      "https://i.imgur.com/RVbYaC6.png", //branch
      "https://i.imgur.com/2UQizyS.png"]; //acorn
    for (var i = 0; i < NonWeaps.length; i++){
      nonWeaps.push(loadImage(NonWeaps[i]));
    }
}

function item_setup () {
  createCanvas(450, 440);
  item_score = 0;
  item_startPage = false; 
  item_finishPage = false;
  trashcan = loadImage("https://i.imgur.com/JpPvsJn.png"); //trash can image
  item_startScreen = loadImage("https://i.imgur.com/in44Atu.png"); // How page of the game
  backg = loadImage("https://i.imgur.com/m6iJCVQ.png"); // forest background
  item_finishScreen = loadImage("https://i.imgur.com/UJUGvtS.png"); // congrats page of the game
  item_finishFailScreen = loadImage("https://i.imgur.com/JZkuboH.png");  //Fail page of the game
  item_counter = 0; // counts the number of trash caught in the trash can
  item_interval = 50;
}

function item_keyPressed() { 
  item_startPage =false;
  if (key === RIGHT){
    moveRight = true;
  } else if(key === LEFT){
    moveLeft = true;
  }
  if (item_startPage) {  // starts the game after pressing any key
      item_startPage = false;
  } else if (keyCode == ENTER) { // returns back to home screen 
      setup();
  }
}

function item_draw() { // draws other functions that is needed for game page
    if (item_startPage == true) {
      push();
      scale(1/4);
      image(item_startScreen, 0, 0);
      pop();
    } else {
      scale(0.35);
      image(backg, 0, 0);
      scale(1/0.4);
      drawTrashCan(); // draw trash can
      drawItems(); // draw dangerous items
      drawNonWeaps();    
      item_drawScore(); // number of items thrown out
      item_update(); // drops items continuously
    }
    if (item_finishPage == true) { // appears the finish page as the game ends
      push();
      scale(0.28);
      image(item_finishScreen,0,0);
      pop();
    }
    if (item_finishFailPage == true){
      push();
      scale(0.28);
      image(item_finishFailScreen,0,0);
      pop();
    }
}

function ScoreMax() { // if score of 5(maximum) is reached, shows congratulation page
    max = 5;          
    if(item_score >= max){
      item_finishPage = true;
    }
}

function ScoreMin(){  // if score of -5(minimum) is reached, shows Fail page
    min = -5;
    if(item_score <= min){
      item_finishFailPage = true;
    }
}

function item_drawScore() { // score on top left of the screen
  textSize(15);
  fill(25,30,37);
  text(("Your score: " + this.item_score), 10, 30);
}

function makeNonWeap(xposs, yposs, imagee) {
  var non = {
    "x": xposs,
    "y": yposs,
    "img": imagee,
    }
  return non;
}

function makeItem(xx, yy, image) {
  var item = {
    "x": xx,
    "y": yy,
    "img": image,
    }
  return item;
}

function drawNonWeaps() { 
    for (var i = 0; i < dropping_nonWeaps.length; i++){
      var non = dropping_nonWeaps[i];
      image(non.img, non.x, non.y,50,50);
    }
}

function drawItems() { 
    for (var i = 0; i < dropping_weapons.length; i++){
      var item = dropping_weapons[i];
      image(item.img, item.x, item.y,50,50);
    }
}

function drawTrashCan() { // renders the trash can
  image(trashcan, this.x, this.y-90,120,180);
}

function updateNonWeapY() { // updates the varying dropping of the non weapons
  for (var i = 0; i < dropping_nonWeaps.length; i++){
    var non = dropping_nonWeaps[i];
    non.y += rate;
    if (non.y > height) { 
      dropping_nonWeaps.splice(i, 1);
    }
  }
}

function updateItemY() { 
  for (var i = 0; i < dropping_weapons.length; i++){
    var item = dropping_weapons[i];
    item.y += rate;
    if (item.y > height) { 
      dropping_weapons.splice(i, 1);
    }
  }
}

function itemHitsTrashCan(item) { // moment when dangerous items hit the trash can
  var hit = this.x < item.x + 10 & item.x < this.x + 80 - 20 & item.y > this.y - 110; 
  return hit;
}

function nonWeapHitsTrashCan(non) { // moment when non-weapon items hit the trash can
  var hitt = this.x < non.x + 10 & non.x < this.x + 80 - 20 & non.y > this.y - 110;
  return hitt;
}

function updateNonWeapHit() { // the non-weapons disappear when it hits the trash can
  for (var i = 0; i < dropping_nonWeaps.length; i++){
    var non = dropping_nonWeaps[i];
    if(nonWeapHitsTrashCan(non)) {
      dropping_nonWeaps.splice(i, 1);
      item_score -= 1; //score decreases 
    }
  }
}

function updateItemHit() { // dangerous items disappear when it hits the trash can
  for (var i = 0; i < dropping_weapons.length; i++){
    var item = dropping_weapons[i];
    if(itemHitsTrashCan(item)) {
      dropping_weapons.splice(i, 1);
      item_score++; //score increases
      item_interval += 1; 
    }
  }  
}

function item_update() { // update random items from the top
  if(item_counter % item_interval == 0){
    var new_item = makeItem(random(10, 440), -80, random(weapons)); 
    dropping_weapons.push(new_item);
    var new_non = makeNonWeap(random(9,430),-80, random(nonWeaps));
    dropping_nonWeaps.push(new_non);
    item_counter = item_counter % item_interval; 
  }
  if(keyIsDown(RIGHT_ARROW) & this.x < width - 10){  // right arrow moving the trash can
     this.x += rate;
   }
  if (keyIsDown(LEFT_ARROW) & this.x > -10){ // left arrow moving the trash can
     this.x -= rate;
  }
  item_counter++;
  updateItemY();
  updateNonWeapY();
  updateItemHit();
  updateNonWeapHit();
  ScoreMax();
  ScoreMin();
}

function setup() {
  createCanvas(450, 450);
  introPage = true; // intro page is "true" here because it should start with this
  score = 0; //initial score
  introScreen = loadImage("https://i.imgur.com/EWQ38kD.png"); // home screen
  item_setup(); // calls the item setup function to combine
}

function keyPressed(){
  if (item_startPage | item_finishPage){
    item_keyPressed();
  } else if(item_finishPage & key == ENTER){  //going back to start page
    setup();
  }
}

function draw() {
  if (introPage == true) { // draws the intro page
    push();
    scale(1/4);
    image(introScreen, 0, 0);
    pop();
  } else {
    item_draw(); // game page
  }
}

function mouseClicked() {
  var xx = mouseX;
  var yy = mouseY;
  if (introPage) {
    if (0 < xx & xx < width & 0 < yy & yy < height) { //click any part of the screen
      item_startPage = true; // start page shows up
      introPage = false; 
    }
  }
}

Final Project

Virus Run

For my final project, I have created a side-scrolling game in which the player takes on the role of a coronavirus particle. As obstacles such as masks and hand sanitizer fly from right to left, the player must use the space bar to make the virus “jump” and avoid these obstacles. The longer the user holds down the key, the higher the virus floats, until it reaches the max height. If any of the obstacles are touched, the game stops. The score is then calculated based on the frame count. I was inspired by the dinosaur game which people can play when trying to use google with no internet connection, and if I had more time, I would have liked to make it so that the longer the game goes on, the more obstacles there are and the faster they move.

Some Screenshots of what the full canvas looks like:


sketch
var imgV; // image of virus
var imgM; // image of mask obstacle
var imgHS; // image of hand sanitizer

var imgStart; // image for starting screen
var imgGO; // image for game over


var mask = []; // array for masks on ground level
var mx = 800 // x coord of mask

var handSan = []; // array for hand sanitizer flying overhead
var hsx = 800 // x coord of hand sanitizer

var virusX = 100; // permanent x position of virus
var virusY = 270; // starting y position of virus
var virusR = 70; // radius of virus
var virusDy = 0; // change in height of virus when jumping

var score = 0; //counts score based on frames

var start = true; // checks to see if starting page is showing

var hills = []; // making moving hills as a background element
var noiseParam = 0;
var noiseStep = 0.02;

function preload(){
    imgV = loadImage("https://i.imgur.com/k04oKtW.png");
    imgM = loadImage("https://i.imgur.com/v2CRQLt.png");
    imgHS = loadImage("https://i.imgur.com/iFAELeQ.png");
    imgGO = loadImage("https://i.imgur.com/ORHbmPV.png");
    imgStart = loadImage("https://i.imgur.com/OUL56Za.png");

}



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

    //making hills
    for(var i = 0; i <= width/5; i++){
        var n = noise(noiseParam);
        hills[i];
        var value = map(n, 0, 1, 0, height/2);
        hills.push(value);
        noiseParam += 0.5*noiseStep;
    }
}

function draw(){
    
    if (start == true){
    	startingPage();

    } else { 

        background(8, 6, 51); // dark blue background
        drawHills();
        fill(55, 0, 104); // purple floor
        rect(0, 370, 800, 30);
        image(imgV, virusX, virusY, 107, 100); // image of virus
    
        if(keyIsDown(32)){ 
            virusY -= 10;
            // while the space bar is down, the virus moves upward
        } else if (virusY < 270){ 
            virusY +=10;
            // when the space bar is let go while the virus is in the air, 
            //the virus moves down
        } else { virusY = 270; } 
            // otherwise, the virus stays on the ground
        if (virusY < 40)
        { virusY += 10}

        createNewMask();
        displayMask();

        createNewHandSan();
        displayHandSan();

        checkIfGameOver();
    
        score += 1; 

        //display score count in the top right corner during the game
        textSize(15);
        fill(190, 215, 62);
        text(score, 745, 40);
        
    }
    
}

function startingPage(){ // starting page with instructions
	push();
	fill(8, 6, 51);
	rect(-1, -1, 801, 801);
	fill(190, 215, 62);
	textSize(25);
	text('Press any key to begin >', 487, 365);
	textSize(15);
	text('Use the space bar to avoid obstacles!', 490, 230);
	pop();

	image(imgStart, 40, 80, 700, 100);
	image(imgM, 540, 250, 60, 58);
	image(imgHS, 620, 247, 62, 70);
	image(imgV, virusX, virusY, 107, 100);
	

}

function keyPressed(){ 
	if(start == true){ start = false; } // game begins
	
}

//drawing hills (background element)
function drawHills(){
	push();
    translate(0, 130)
    hills.shift();
    var n = noise(noiseParam);
    var value = map(n, 0, 1, 0, height/2);
    hills.push(value);
    // draws shape for sand
    beginShape();
    vertex(0, height);
    for(var i = 0; i <= width/5; i++){
        //filling the hill color
        fill(255, 255, 255, 10);
        noStroke();
        //vertex function to fill the hills
        vertex((i * 5), hills[i]); 
        vertex((i + 1) * 5, hills[i + 1]);   
    }
    vertex(width, height);
    endShape(CLOSE);
    pop();
}


function checkIfGameOver (){

	for (i = 0;i < mask.length;i++)
    {
        if ((dist(mask[i].x, 400,  virusX, 400) <= virusR) 
            // tests if the mask comes within a certain distance of the virus
             & virusY == 270){

            gameOver(); // the screen goes darker
            noLoop(); // the game stops
        }
    }

	for (i = 0;i < handSan.length;i++){
        if ((dist(handSan[i].x, handSan[i].y,  virusX, virusY) <= virusR)){ 
            //tests if the hand sanitizer comes within a certain distance of the virus


            gameOver(); // the screen goes darker
            noLoop(); // the game stops
        }
    }
}


// BEGIN CODE FOR MASK OBSTACLES



function displayMask(){ // update mask positions and display them
    for(var i = 0; i < mask.length; i++){
        mask[i].move();
        mask[i].draw();
    }
}

function createNewMask(){ 
// makes new masks with some random probability
    if(random(0, 1) < 0.008){
        mask.push(makeMask(800));
    }
}

function moveMask(){
    this.x -= 10;
}

function drawMask(){
    mask.push();
    image(imgM, this.x, this.y, 60, 60); 
}

// function to make mask obstacle object
function makeMask(){
    var m = {x: mx, 
             y: 310,
             move: moveMask,
             draw: drawMask
        }
    return m;
}

// BEGIN CODE FOR HAND SANITIZER OBSTACLES

function displayHandSan(){ // update hand sanitizer positions and display them
    for(var i = 0; i < handSan.length; i++){
        handSan[i].move();
        handSan[i].draw();
    }
}

function createNewHandSan(){ 
// makes new masks with some random probability
    if(random(0, 1) < 0.005){
        handSan.push(makeHandSan(800));
    }
}

function moveHandSan(){
    this.x -= 10;
}

function drawHandSan(){
    handSan.push();
    image(imgHS, this.x, this.y, 80, 90); 
}

// function to make mask obstacle object
function makeHandSan(){
    var h = {x: hsx, 
             y: random(30, 100),
             move: moveHandSan,
             draw: drawHandSan
        }
    return h;
}


function gameOver(){
// screen displayed when the virus hits an obstacle
    push();
    fill(0, 0, 0, 80);
    rect(0, 0, 800, 400);
    pop();

    image(imgGO, 50, 100, 700, 100);    
   
    push();
    fill(190, 215, 62);
    noStroke();
    textSize(20);
    text('SCORE:' + ' ' + score, 340, 250);
    textSize(15);
    text('Refresh to play again!', 340, 280)
    pop();
}


Final Project- COVID-19 cases in America

My final project is an infographic of America with the number of COVID-19 cases in each state. Based on the number of cases in America, and how high the number is, the color of each state varies from a medium pink to a very dark red.

My process and code is very long because I planned out my steps wrong and had the wrong approach. I thought if I separated each state, I would be able to let mouseX and mouseY detect each state. However, because the pngs are the same size, my approach did not work out.

sketch
//Chris Han
//Final Project
//15-104 Section C

var California;
var Alabama;
var Arizona;
var Arkansas;
var Colorado;
var Connecticut;
var Delaware;
var Florida;
var Georgia;
var Idaho;
var Illinois;
var Indiana;
var Iowa;
var Kansas;
var Kentucky;
var Louisiana;
var Maine;
var Maryland;
var Massachussets;
var Michigan;
var Mississippi;
var Minnesota;
var Montana;
var Nebraska;
var Nevada;
var NewJersey;
var NewMexico;
var NewYork;
var NorthCarolina;
var Ohio;
var NorthDakota;
var Oklahoma;
var Oregon;
var Pennsylvania;
var Virginia;
var Washington;
var WestVirginia;
var RhodeIsland;
var SouthCarolina;
var SouthDakota; 
var Tennessee;
var Texas;
var Vermont;
var Utah;
var Wisconsin;
var Wyoming;
var Missouri;
var NewHampshire;

function preload(){
	California = loadImage("https://i.imgur.com/M90B6i6.png");
	Alabama = loadImage("https://i.imgur.com/A0rMfn9.png");
	Arizona = loadImage("https://i.imgur.com/FZgFQXG.png");
	Arkansas = loadImage("https://i.imgur.com/mady7aS.png");
	Colorado = loadImage("https://i.imgur.com/Cm0XtJk.png");
	Connecticut = loadImage("https://i.imgur.com/Kgbe7x6.png");
	Delaware = loadImage("https://i.imgur.com/gPJn6me.png");
	Florida = loadImage("https://i.imgur.com/hH4ByDe.png");
	Georgia = loadImage("https://i.imgur.com/QqS08V1.png");
	Idaho = loadImage("https://i.imgur.com/IAWMdLX.png");
	Illinois = loadImage("https://i.imgur.com/dFEAfM3.png");
	Indiana = loadImage("https://i.imgur.com/yINwRlF.png");
	Iowa = loadImage("https://i.imgur.com/bDpW2F1.png");
	Kansas = loadImage("https://i.imgur.com/viHxihJ.png");
	Kentucky = loadImage("https://i.imgur.com/dYri9KS.png");
	Louisiana = loadImage("https://i.imgur.com/fmCBz3P.png");
	Maine = loadImage("https://i.imgur.com/MLwg0xh.png");
	Maryland = loadImage("https://i.imgur.com/GR8e2uJ.png");
	Massachussets = loadImage("https://i.imgur.com/llu4pfW.png");
	Michigan = loadImage("https://i.imgur.com/Dzu9Anc.png");
	Mississippi = loadImage("https://i.imgur.com/HRFksTw.png");
	Minnesota = loadImage("https://i.imgur.com/PQ2rbnn.png");
	Montana = loadImage("https://i.imgur.com/FFZVEDr.png");
	Nebraska = loadImage("https://i.imgur.com/pjSdpc4.png");
	Nevada = loadImage("https://i.imgur.com/gKE4OD7.png");
	NewJersey = loadImage("https://i.imgur.com/pLxSZQ6.png");
	NewMexico = loadImage("https://i.imgur.com/ZxZ5TGy.png");
	NewYork = loadImage("https://i.imgur.com/fOMfdss.png");
	NorthCarolina = loadImage("https://i.imgur.com/ml7w2CO.png");
	Ohio = loadImage("https://i.imgur.com/P6npxwO.png");
	NorthDakota = loadImage("https://i.imgur.com/IHceHrO.png");
	Oklahoma = loadImage("https://i.imgur.com/YUe8N4U.png");
	Oregon = loadImage("https://i.imgur.com/lKD2lzT.png");
	Pennsylvania = loadImage("https://i.imgur.com/q8BZJJY.png");
	Virginia = loadImage("https://i.imgur.com/xXbl27h.png");
	Washington = loadImage("https://i.imgur.com/iYUxkXx.png");
	WestVirginia = loadImage("https://i.imgur.com/opvQBQx.png");
	RhodeIsland = loadImage("https://i.imgur.com/Eqyjeyw.png");
	SouthCarolina = loadImage("https://i.imgur.com/n7mnprl.png");
	SouthDakota = loadImage("https://i.imgur.com/0dnuWnc.png");
	Tennessee = loadImage("https://i.imgur.com/fA9Ey2X.png");
	Texas = loadImage("https://i.imgur.com/N3H2oM5.png");
	Vermont = loadImage("https://i.imgur.com/VKAgM5K.png");
	Utah = loadImage("https://i.imgur.com/HsGInYv.png");
	Wisconsin = loadImage("https://i.imgur.com/1706iC4.png");
	Wyoming = loadImage("https://i.imgur.com/P2FMqfi.png");
	NewHampshire = loadImage("https://i.imgur.com/JUHRFya.png");
	Missouri = loadImage("https://i.imgur.com/KtNPgmC.png");


}

function setup() {
    createCanvas(600,400);
    //background('white');
    background('white');
}


function draw() {
	textSize(10);
    fill('black');
    text('COVID-19 cases in America', 250, 70);
    textSize(7);
    text('click on any state to start',270, 85);

	California.resize( 400,400);
	image(California, 0,0);

	Alabama.resize( 400,400);
	image(Alabama, 0, 0);

	Arizona.resize( 400,400);
	image(Arizona, 0, 0);

	Arkansas.resize( 400, 400);
	image(Arkansas, 0 , 0);

	Colorado.resize( 400, 400);
	image(Colorado, 0, 0);

	Connecticut.resize( 400, 400);
	image(Connecticut, 0, 0);

	Delaware.resize(400, 400);
	image(Delaware, 0,0);

	Florida.resize(400, 400);
	image(Florida, 0, 0);

	Georgia.resize(400, 400);
	image(Georgia, 0, 0);

	Idaho.resize(400, 400);
	image(Idaho, 0, 0);

	Illinois.resize(400, 400);
	image(Illinois, 0, 0);

	Indiana.resize(400, 400);
	image(Indiana, 0, 0);

	Iowa.resize(400, 400);
	image(Iowa, 0, 0);

	Kansas.resize(400,400);
	image(Kansas, 0, 0);

	Kentucky.resize(400,400);
	image(Kentucky, 0, 0);

	Louisiana.resize(400,400);
	image(Louisiana, 0, 0);

	Maine.resize(400,400);
	image(Maine, 0, 0);

	Maryland.resize(400,400);
	image(Maryland, 0, 0);

	Massachussets.resize(400,400);
	image(Massachussets, 0, 0);

	Michigan.resize(400,400);
	image(Michigan, 0, 0);

	Mississippi.resize(400,400);
	image(Mississippi, 0, 0);

	Minnesota.resize(400,400);
	image(Minnesota, 0, 0);

	Montana.resize(400,400);
	image(Montana, 0, 0);

	Nebraska.resize(400,400);
	image(Nebraska, 0, 0);

	Nevada.resize(400,400);
	image(Nevada, 0, 0);

	NewJersey.resize(400,400);
	image(NewJersey, 0, 0);

	NewMexico.resize(400,400);
	image(NewMexico, 0, 0);

	NewYork.resize(400,400);
	image(NewYork, 0, 0);

	NorthCarolina.resize(400,400);
	image(NorthCarolina, 0, 0);

	Ohio.resize(400,400);
	image(Ohio, 0, 0);

	NorthDakota.resize(400,400);
	image(NorthDakota, 0, 0);

	Oklahoma.resize(400,400);
	image(Oklahoma, 0, 0);

	Oregon.resize(400,400);
	image(Oregon, 0, 0);

	Pennsylvania.resize(400,400);
	image(Pennsylvania, 0, 0);

	Virginia.resize(400,400);
	image(Virginia, 0, 0);

	Washington.resize(400,400);
	image(Washington, 0, 0);

	WestVirginia.resize(400,400);
	image(WestVirginia, 0, 0);

	RhodeIsland.resize(400,400);
	image(RhodeIsland, 0, 0);

	SouthCarolina.resize(400,400);
	image(SouthCarolina, 0, 0);

	Tennessee.resize(400,400);
	image(Tennessee, 0, 0);

	Texas.resize(400,400);
	image(Texas, 0, 0);

	Vermont.resize(400,400);
	image(Vermont, 0, 0);

	Utah.resize(400,400);
	image(Utah, 0, 0);

	Wisconsin.resize(400,400);
	image(Wisconsin, 0, 0);

	Wyoming.resize(400,400);
	image(Wyoming, 0, 0);

	SouthDakota.resize(400,400);
	image(SouthDakota, 0, 0);

	NewHampshire.resize(400,400);
	image(NewHampshire, 0, 0);

	Missouri.resize(400,400);
	image(Missouri, 0, 0);

	mouseClicked();

}


function mouseClicked(){

	//CALIFORNIA

		if (mouseX > 40 & mouseX < 65 && mouseY > 115 && mouseY < 235) {
		textSize(5);
		fill('white');
		text('CA, 1.49M', 45, 170);
	}

	//nevada
	if(mouseX > 59 & mouseX < 102 && mouseY > 126 && mouseY < 211){
		textSize(5);
		fill('white');
		text('NV, 179K', 70, 160);
	}

	//oregon
	if(mouseX > 41 & mouseX < 84 && mouseY < 126 && mouseY > 86){
        textSize(5);
		fill('white');
		text('OR, 89K', 70, 104);
	}
	//washington
	if( mouseY > 49 & mouseY < 94 && mouseX < 95 && mouseX > 62 ){
		textSize(5);
		fill('white');
		text('WA, 201K', 70, 75);
	}

	//idaho
	if (mouseX > 92 & mouseX < 111 && mouseY > 64 && mouseY < 140){
		textSize(5);
		fill('white');
		text('ID, 118K', 95, 123);
	}
	//utah
	if( mouseX > 93 & mouseX < 126 && mouseY > 143 && mouseY < 199){
		textSize(5);
		fill('white');
		text('utah lol', 102, 176);
	}
	//arizona
	if( mouseX > 81 & mouseX < 119 && mouseY > 198 && mouseY < 262){
		textSize(5);
		fill('white');
		text('AZ, 390K', 90, 221);
	}

	//montana
	if ( mouseX > 110 & mouseX < 170 && mouseY > 72 && mouseY < 120){
		textSize(5);
		fill('white');
		text('MT, 71K', 127, 92);

	}

	//wyoming
	if ( mouseX > 121 & mouseX < 165 && mouseY > 119 && mouseY < 164){
		textSize(5);
		fill('white');
		text('WY, 38K', 133, 142);

	}

	//colorado

	if ( mouseX > 129 & mouseX < 173 && mouseY > 166 && mouseY < 209){
		textSize(5);
		fill('white');
		text('CO, 283K ', 136, 187);
	}

	//new mexico
	if (mouseX > 118 & mouseX < 160 && mouseY > 209 && mouseY < 262){
		textSize(5);
		fill('white');
		text('NM, 117K', 127, 235);
	}

	//north dakota
	if (mouseX > 174 & mouseX < 212 && mouseY > 87 && mouseY < 119){
	    textSize(5);
		fill('white');
		text('ND, 87K ', 179, 101);

	}

	//south dakota
	if ( mouseX > 168 & mouseX < 212 && mouseY > 120 && mouseY < 152){
		textSize(5);
		fill('white');
		text('SD, 89K', 176, 134);

	}

	//nebraska
	if ( mouseX > 165 & mouseX < 211 && mouseY > 153 && mouseY < 185){
		textSize(5);
		fill('white');
		text('NE, 147K', 173, 159);
	}

	//kansas
	if ( mouseX > 173 & mouseX < 219 && mouseY > 186 && mouseY < 218){
		textSize(5);
		fill('white');
		text('KS, 188K', 179, 198);
	}

	//oklahoma
	if ( mouseX > 182 & mouseX < 220 && mouseY > 217 && mouseY < 254 ){
		textSize(5);
		fill('white');
		text('OK, 229K', 187, 231);
	}
	//texas
	if ( mouseX > 160 & mouseX < 220 && mouseY > 250 && mouseY < 338){
		textSize(5);
		fill('white');
		text('TX, 1.42M', 174, 274);
	}

	//minnesota
	if (mouseX > 212 & mouseX < 237 && mouseY > 92 && mouseY < 150){
		textSize(5);
		fill('white');
		text('MN, 371K', 220, 112);
	}

	//iowa
	if (mouseX > 213 & mouseX < 243 && mouseY > 150 && mouseY < 181){
		textSize(5);
		fill('white');
		text('IA, 254K ', 220, 164);
	}

	//missouri
	if (mouseX > 220 & mouseX < 246 && mouseY > 183 && mouseY < 226){
		textSize(5);
		fill('white');
		text('MO, 355K ', 226, 207);
	}

	//arkansas
	if (mouseX > 219 & mouseX < 246 && mouseY > 227 && mouseY < 264){
		textSize(5);
		fill('white');
		text('AR, 182K', 226, 244);
	}

	//louisiana
	if( mouseX > 226 & mouseX < 240 && mouseY > 265 && mouseY < 302){
		textSize(5);
		fill('white');
		text('LA, 264K ', 229, 277);
	}

	//wisconin
	if(mouseX > 236 & mouseX < 265 && mouseY > 118 && mouseY < 161){
		textSize(5);
		fill('white');
		text('WI, 461K', 243, 133);
	}
	//illinois
	if(mouseX > 242 & mouseX < 266 && mouseY > 162 && mouseY < 218){
		textSize(5);
		fill('white');
		text('IL, 835K', 249, 188);
	}

	//kentucky
	if( mouseX > 256 & mouseX < 302 && mouseY > 207 && mouseY < 222){
		textSize(5);
		fill('white');
		text('KY, 221K', 272, 215);
	}

	//tennessee
	if(mouseX > 254 & mouseX < 296 && mouseY > 222 && mouseY < 241){
		textSize(5);
		fill('white');
		text('TN, 426K', 261, 233);
	}

	//Mississippi
	if(mouseX > 244 & mouseX < 263 && mouseY > 243 && mouseY < 287){
		textSize(5);
		fill('white');
		text('MS, 175K', 244, 263);
	}

	//michigan
	if(mouseX > 274 & mouseX < 296 && mouseY > 127 && mouseY < 166){
		textSize(5);
		fill('white');
		text('MI, 460K ', 276, 145);
	}

	//indiana
	if( mouseX > 267 & mouseX < 285 && mouseY > 168 && mouseY < 203){
		textSize(5);
		fill('white');
		text('IN, 415K', 270, 185);
	}
	//alabama
	if( mouseX > 263 & mouseX < 286 && mouseY > 243 && mouseY < 285){
		textSize(5);
		fill('white');
		text('AL, 289K', 270, 264);
	}
	//ohio
	if( mouseX > 285 & mouseX < 311 && mouseY > 169 && mouseY < 198){
		textSize(5);
		fill('white');
		text('OH, 542K', 289, 184);
	}

	//georgia
	if( mouseX > 286 & mouseX < 313 && mouseY > 242 && mouseY < 288){
		textSize(5);
		fill('white');
		text('GA, 513K', 293, 266);
	}
	//florida
	if( mouseX > 307 & mouseX < 327 && mouseY > 289 && mouseY < 346){
		textSize(5);
		fill('white');
		text('FL, 1.11M', 309, 311);
	}
	//west virginia
	if (mouseX > 299 & mouseX < 322 && mouseY > 186 && mouseY < 216){
		textSize(5);
		fill('white');
		text('WV, 60K', 303, 200);
	}

	//virginia
	if (mouseX > 299 & mouseX < 343 && mouseY > 196 && mouseY < 219){
		textSize(5);
		fill('white');
		text('VA, 274K', 318, 209);
	}

	//north carolina
	if (mouseX > 299 & mouseX < 347 && mouseY > 220 && mouseY < 241){
		textSize(5);
		fill('white');
		text('NC, 425K', 312, 230);
	}

	//south carolina
	if (mouseX > 303 & mouseX < 334 && mouseY > 239 && mouseY < 265){
		textSize(5);
		fill('white');
		text('SC, 245K', 306, 245);
	}

	//pennylvania
	if (mouseX > 311 & mouseX < 345 && mouseY > 158 && mouseY < 182){
		textSize(5);
		fill('white');
		text('PA, 276K', 319, 169);
	}

	//new jersey
	if (mouseX > 347 & mouseX < 356 && mouseY > 164 && mouseY < 190){
		textSize(5);
		fill('white');
		text('NJ, 392K', 350, 173);
	}
	//maryland
	if (mouseX > 329 & mouseX < 342 && mouseY > 184 && mouseY <200){
		textSize(5);
		fill('white');
		text('MA, 280K', 356, 147);
	}

	//delaware
	if( mouseX > 345 & mouseX < 353 && mouseY > 186 && mouseY < 195){
		textSize(5);
		fill('white');
		text('DE, 476K', 347, 189);
	}

	//newyork
	if( mouseX > 317 & mouseX < 355 && mouseY >123 && mouseY < 156){
		textSize(5);
		fill('white');
		text('NY, 760K', 325, 149);
	}
	//conneticut
	if( mouseX > 356 & mouseX < 365 && mouseY > 152 && mouseY < 163){
		textSize(5);
		fill('white');
		text('CT, 147K', 359, 162);
	}

	//rhode island
	if( mouseX > 365 & mouseX < 370 && mouseY > 150 && mouseY < 158){
		textSize(5);
		fill('white');
		text('RI, 70K ', 371, 158);
	}
	//massachusetts
	if(mouseX > 355 & mouseY < 372 && mouseY > 144 && mouseY < 150){
		textSize(5);
		fill('white');
		text('MA, 280K', 368, 142);
	}

	//vermont
	if( mouseX > 351 & mouseX < 360 && mouseY > 121 && mouseY < 145){
		textSize(5);
		fill('white');
		text('VT, 5K', 351, 125);
	}

	//new hampshire
	if(mouseX > 359 & mouseX < 368 && mouseY > 117 && mouseY < 143){
		textSize(5);
		fill('white');
		text('NH, 29K', 362, 136);
	}
	//maine
	if(mouseX > 364 & mouseX < 388 && mouseY > 91 && mouseY < 128){
		textSize(5);
		fill('white');
		text('ME, 15K', 365, 106);
	}




}




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

Final Project – Polarization & Authoritarianism

I interpreted the 2020 theme as part of our ongoing political crisis. The Republican party has begun to show their true colors as authoritarians, so I tried to explain what that process means in this project using simple particle visualizations.

Users can learn some basic political science, and have fun screwing over democracy in the process.

For the most part, the project acts as a sort of slideshow, moving between animations. The last slide, however, allows users to manipulate the system directly for themselves. The particle simulation code we used extensively in class was used & heavily modified for this simulation. The program also relies heavily on for-loops, objects, and if-statements.

-Robert

sketch
var slide = 0;  //variable that keeps track of which slide is being displayed. 0 corresponds to the title screen.

var democrat    //these four are color variables, used to keep track of each type of voter
var rep
var auth    //authoritarians
var orange  //orange represents 'the strongman leader'.
var voters  //'neutral', or persuadable voters

var vPart = []; //particle array representing "generic" voters
var dPart = []; //particle array representing democrat voters
var rPart = []; //particle array representing republican voters
var aPart = []; //particle array representing authoritarian voters
var dict = [];

//hard boundaries are on by default for all particles so that they can be put in boxes.

function createVParticles(n, x, y, w, h, v) {   //creates voters given a quantity n, position range defined by x, y, w, & h, and a velocity range -v to v
    for(i=0; i<n; i++) {
        newP = makeParticle(random(x, x+w), random(y, y+h), random(-v, v), random(-v, v));
        newP.bHardBoundaries = true;
        append(vPart, newP);
    }
}

function createDParticles(n, x, y, w, h, v) {   //creates democrat particles within a given rectangle & velocity range
    for(i=0; i<n; i++) {
        newP = makeParticle(random(x, x+w), random(y, y+h), random(-v, v), random(-v, v));
        newP.bHardBoundaries = true;
        append(dPart, newP);
    }
}

function createRParticles(n, x, y, w, h, v) {   //creates republican particles within a given rectangle & velocity range
    for(i=0; i<n; i++) {
        newP = makeParticle(random(x, x+w), random(y, y+h), random(-v, v), random(-v, v));
        newP.bHardBoundaries = true;
        append(rPart, newP);
    }
}

function createAParticles(n, x, y, w, h, v) {   //creates authoritarian particles within a given rectangle & velocity range
    for(i=0; i<n; i++) {
        newP = makeParticle(random(x, x+w), random(y, y+h), random(-v, v), random(-v, v));
        newP.bHardBoundaries = true;
        append(aPart, newP);
    }
}

function makeDictator(x, y, d) {    //makes a dynamic orange circle
    var d = {tx: x, ty: y, diameter: d, force: 1, drawFunction: drawDictator};

    dict[0] = d;
}

function drawDictator() {   //draws the circle, maps it to the mouse
    var left = this.tx - this.diameter/2;
    var right = this.tx + this.diameter/2;
    var top = this.ty - this.diameter/2;
    var bottom = this.ty + this.diameter/2;

        this.tx = mouseX;
        this.ty = mouseY;

    push();
    noStroke();
    fill(orange);
    circle(this.tx, this.ty, this.diameter);
    pop();
}

function setup() {
    createCanvas(950, 500);   //multiplication is used to keep the canvas the same w/h ratio as the american flag. This setup is 950 x 500
    background(255);+
    text("p5.js vers 0.9.0 test.", 10, 15);
    frameRate(60);

    dem = color(70, 70, 240);
    rep = color(240, 70, 70);
    auth = color(25);   
    voter = color(200);
    orange = color(255, 140, 25);

    noStroke();
}

var count = 0;  //used to make stuff move

function draw() {
    if (slide == 0) {   //title screen. Each slide is coded separately here, and simply clicking will advance the slide.
        push();
            background(255);
            if (count < width/64) { //displays the moving title screen intro, then the interactive title screen
                titleIntro();
            } else {
                titleScreen();
            }
        pop();
    }

    if (slide == 1) {   //Explainer screen, explains the diagrams, what the particles mean, and gives context
        push();
            background(65);

            push();
            rectMode(CENTER);
            textAlign(CENTER, CENTER);
            textSize(30);
            fill(255);
            text('These particles represent voters. Each color represents a political leaning, and each box represents a grouping.',width/2, 100, width/2, 300);
            
            textStyle(BOLD);    //labels for each voter box
            textSize(25);
            fill(dem);
            text('Liberal', 157.5, 400);

            fill(rep)
            text('Conservative', 367.5, 400);

            fill(voter);
            text('Moderate', 577.5, 400);

            fill(auth);
            text('Authoritarian', 787.5, 400);
            pop();            

            for(i=0; i < dPart.length; i++) {   //these for loops update the position of each particle & draws them
                dPart[i].draw(dem, 15);         //dems
                dPart[i].update(105*1, 250, 105, 105);
            }  
            for(i=0; i < rPart.length; i++) {   //reps
                rPart[i].draw(rep, 15);
                rPart[i].update(105*3, 250, 105, 105);
            }
            for(i=0; i < vPart.length; i++) {   //swing voters
                vPart[i].draw(voter, 15);
                vPart[i].update(105*5, 250, 105, 105);
            }
            for(i=0; i < aPart.length; i++) {   //authoritarians
                aPart[i].draw(auth, 15);
                aPart[i].update(105*7, 250, 105, 105);
            }

            noStroke();
            stroke(255);
            strokeWeight(10);
            noFill();
            for(i=1; i<=7; i+=2) {
                rect(105*i-10, 250-10, 105+20, 105+20);
            }
        pop();
        slideOut(); //slideOut creates a fade-in transition for the slide. It needs to be put last so that it can fade in ON TOP of everything else.
    }

    if (slide == 2) {   //Geographic polarization, civil war thru WWII
        push();
            background(65);
            push();
                fill(255);
                textAlign(CENTER, CENTER);
                textSize(30);
                text('Since before the civil war through the 60s, Americans are divided sharply by geography & slavery. Regional loyalties are strong, and the glacial pace of information keeps regions separate.', 50, 50, 850, 150);
            pop();

            push();
                textStyle(BOLD);

                fill(255);
                textAlign(RIGHT, TOP);
                textSize(25);
                text('Republican (North)', 50, 235, 150, 200);

                textAlign(LEFT, TOP);
                textSize(25);
                text('Democrat (South)', 750, 235, 150, 200);
            pop();

            for(i=0; i < dPart.length; i++) {   //these for loops update the position of each particle & draws them
                dPart[i].draw(dem, 15);         //dems
                if(i < dPart.length/2) {
                    dPart[i].update(225, 250, 200, 200);    //because there are two boxes with the same kind of voter
                } else {                                    //doing updates has to be divided in half
                    dPart[i].update(525, 250, 200, 200);
                }
            }  
            for(i=0; i < rPart.length; i++) {   //reps
                rPart[i].draw(rep, 15);
                if(i < rPart.length/2) {
                    rPart[i].update(225, 250, 200, 200);
                } else {
                    rPart[i].update(525, 250, 200, 200);
                }
            }
            for(i=0; i < vPart.length; i++) {   //swing voters
                vPart[i].draw(voter, 15);
                if(i < vPart.length/2) {
                    vPart[i].update(225, 250, 200, 200);
                } else {
                    vPart[i].update(525, 250, 200, 200);
                }
            }

            push();
                noFill();
                stroke(255);
                strokeWeight(10);
                rect(525-10, 250-10, 200+20, 200+20);   //right rect
                rect(225-10, 250-10, 200+20, 200+20);   //left rect
            pop();
        pop();
        slideOut();
    }

    if (slide == 3) {   //ideological consolidation, WWII thru 1990s.
        push();
            background(65);

            push();
                fill(255);
                textAlign(CENTER, CENTER);
                textSize(30);
                text('Later, mass media allowed disparate people to connect. Conservative Republicans & liberal Democrats consolidated, creating idealogically distinct parties - with fewer swing voters.', 50, 50, 850, 150);
            pop();

            push();
                textStyle(BOLD);

                fill(255);
                textAlign(RIGHT, TOP);
                textSize(25);
                text('Democrat', 50, 235, 150, 200);

                textAlign(LEFT, TOP);
                textSize(25);
                text('Republican', 750, 235, 150, 200);
            pop();

            for(i=0; i < rPart.length; i++) {   //these for loops update the position of each particle & draws them
                rPart[i].draw(rep, 15);         //reps (now on the right)
                rPart[i].update(225, 250, 500, 200);
                rPart[i].vx += .015                              //slowly alters particle velocties so they fall to the right
                rPart[i].vx = constrain(rPart[i].vx, -2, 5)     //constrains their velocities so they stay generally on the right
            }  
            for(i=0; i < dPart.length; i++) {   //dems (now on the left)
                dPart[i].draw(dem, 15);
                dPart[i].update(225, 250, 500, 200);
                dPart[i].vx -= .015                              //slowly fall to the left
                dPart[i].vx = constrain(dPart[i].vx, -5, 2)     //constrains to the left
            }
            for(i=0; i < vPart.length; i++) {   //swing voters
                vPart[i].draw(voter, 15);       //swing voters float free
                vPart[i].update(225, 250, 500, 200);
            }
            push();
                noFill();
                stroke(255);
                strokeWeight(10);
                
                beginShape();   //left box
                    vertex(435, 240);
                    vertex(215, 240);
                    vertex(215, 460);
                    vertex(435, 460);
                endShape();

                beginShape();   //left box
                    vertex(515, 240);
                    vertex(735, 240);
                    vertex(735, 460);
                    vertex(515, 460);
                endShape();
            pop();
        pop();
        
        slideOut();
    }

    if (slide == 4) {   //Something strange has happened recently
        background(65);
        push();
            for (i=0; i<9; i++) {
                for (j=0; j<9; j++) {
                    fill(auth);
                    circle(375+20*(j+1) + random(-2, 2), 250+20*(i+1) + random(-2, 2), 15); //Because these 'voters' are supposed to be in lockstep, I presented them here as circles instead of particles
                }   //it makes the code simpler
            }

            push();
                fill(255);
                textAlign(CENTER, TOP);
                textSize(30);
                text('Recently, something strange has happened: the emergence of a new kind of voter. A minority of voters, mostly conservative, became afraid of losing power - and looked to strongman leaders.', 50, 50, 850, 150);
            pop();

            noFill();   //the authoritarian box (appropriately orange)
            stroke(255);
            strokeWeight(10);
            rect(375-10, 250-10, 200+20, 200+20);

            push();
                fill(orange);   //the 'leader' circle, whose location will act as an attractor point
                noStroke();
                ellipse(width/2, 350, 40, 40);

                fill(255);
                textAlign(LEFT, TOP);
                textSize(22);
                text('Authoritarians dont act like normal voters. What is most important to them is group loyalty. They value safety & order, and look for leaders that make them feel strong.', 650, 235, 250, 220);
            pop();
        pop();

        slideOut();
    }

    if (slide == 5) { //the authoritarian consolidation
        background(65);
        push();
            push();
                fill(255);
                textAlign(CENTER, TOP);
                textSize(30);
                text('In 2016, authoritarian voters became activated in response to demographic change. They consolidated around a leader in the republican party, pushing out or converting other conservatives.', 50, 50, 850, 150);
            pop();

            push();
                textStyle(BOLD);

                fill(255);
                textAlign(RIGHT, TOP);
                textSize(25);
                text('Democrat', 50, 235, 150, 200);

                textAlign(LEFT, TOP);
                textSize(25);
                text('Republican', 750, 235, 150, 200);
            pop();

            for(i=0; i < rPart.length; i++) {   //these for loops update the position of each particle & draws them
                rPart[i].draw(rep, 15);         //reps (now on the right)
                rPart[i].update(225, 250, 500, 200);
                rPart[i].vx += .01              //slowly alters particle velocties so they fall to the right
                if (rPart[i].px > 585) {        //if they go TOO FAR to the right, then they get pushed back
                    rPart[i].vx -= .5
                }                                               
                rPart[i].vx = constrain(rPart[i].vx, -2, 5)     //constrains their velocities so they stay generally on the right
            }  
            for(i=0; i < dPart.length; i++) {   //dems (now on the left)
                dPart[i].draw(dem, 15);
                dPart[i].update(225, 250, 500, 200);
                dPart[i].vx -= .02                              //slowly fall to the left
                dPart[i].vx = constrain(dPart[i].vx, -5, 2)     //constrains to the left
            }
            for(i=0; i < vPart.length; i++) {   //swing voters
                vPart[i].draw(voter, 15);       //swing voters float free
                vPart[i].update(225, 250, 300, 200);

                if (vPart[i].px >= 585) {        //if they go TOO FAR to the right, then they get pushed back
                    vPart[i].vx -= .5
                }
                vPart[i].vx = constrain(rPart[i].vx, -2, 2)     //constrains their velocities so they don't go too fast
            }
            for(i=0; i < aPart.length; i++) {   //dems (now on the left)
                aPart[i].draw(auth, 15);
                aPart[i].update(600, 250, 125, 200);
            }

            push();
                noFill();
                stroke(255);
                strokeWeight(10);
                
                beginShape();   //left box
                    vertex(435, 240);
                    vertex(215, 240);
                    vertex(215, 460);
                    vertex(435, 460);
                endShape();

                beginShape();   //left box
                    vertex(515, 240);
                    vertex(735, 240);
                    vertex(735, 460);
                    vertex(515, 460);
                endShape();
            pop();
        pop();
        slideOut();
    }

    if (slide == 6) { //authoritarian simulation
        background(65);
        push();
            push();
                fill(255);
                textAlign(CENTER, TOP);
                textSize(30);
                text('Even an otherwise stable political system can be disrupted by strongman demagogues.', 50, 50, 850, 150);

                //textStyle(BOLD);
                textSize(20);
                text('Move the mouse to disrupt democracy.', 50, 175, 850, 150);
            pop();

            for(i=0; i < rPart.length; i++) {   //these for loops update the position of each particle & draws them
                rPart[i].draw(rep, 15);         //reps are attracted to the dictator weakly
                rPart[i].update(225, 250, 500, 200);

                if (rPart[i].px > dict[0].tx) {rPart[i].vx -= .05}
                if (rPart[i].px < dict[0].tx) {rPart[i].vx += .05}
                if (rPart[i].py > dict[0].ty) {rPart[i].vy -= .05}
                if (rPart[i].py < dict[0].ty) {rPart[i].vy += .05}

                rPart[i].vx = constrain(rPart[i].vx, -5, 5);
                rPart[i].vy = constrain(rPart[i].vy, -5, 5);
            }  
            for(i=0; i < dPart.length; i++) {   //dems get pushed away by the circle strongly
                dPart[i].draw(dem, 15);
                dPart[i].update(225, 250, 500, 200);

                if (dPart[i].px > dict[0].tx) {dPart[i].vx += .2}
                if (dPart[i].px < dict[0].tx) {dPart[i].vx -= .2}
                if (dPart[i].py > dict[0].ty) {dPart[i].vy += .2}
                if (dPart[i].py < dict[0].ty) {dPart[i].vy -= .2}

                dPart[i].vx = constrain(dPart[i].vx, -5, 5);
                dPart[i].vy = constrain(dPart[i].vy, -5, 5);
            }
            for(i=0; i < vPart.length; i++) {   //swing voters get pushed away by the circle weakly
                vPart[i].draw(voter, 15);
                vPart[i].update(225, 250, 500, 200);

                if (vPart[i].px > dict[0].tx) {vPart[i].vx += .1}
                if (vPart[i].px < dict[0].tx) {vPart[i].vx -= .1}
                if (vPart[i].py > dict[0].ty) {vPart[i].vy += .1}
                if (vPart[i].py < dict[0].ty) {vPart[i].vy -= .1}

                vPart[i].vx = constrain(vPart[i].vx, -5, 5);
                vPart[i].vy = constrain(vPart[i].vy, -5, 5);
            }
            for(i=0; i < aPart.length; i++) {   //authoritarians move towards the circle strongly
                aPart[i].draw(auth, 15);
                aPart[i].update(225, 250, 500, 200);

                if (aPart[i].px > dict[0].tx) {aPart[i].vx -= .2}
                if (aPart[i].px < dict[0].tx) {aPart[i].vx += .2}
                if (aPart[i].py > dict[0].ty) {aPart[i].vy -= .2}
                if (aPart[i].py < dict[0].ty) {aPart[i].vy += .2}

                aPart[i].vx = constrain(aPart[i].vx, -5, 5);
                aPart[i].vy = constrain(aPart[i].vy, -5, 5);
            }

            push();
                noFill();
                stroke(255);
                strokeWeight(10);
                
                beginShape();   //left box
                    vertex(435, 240);
                    vertex(215, 240);
                    vertex(215, 460);
                    vertex(435, 460);
                endShape();

                beginShape();   //left box
                    vertex(515, 240);
                    vertex(735, 240);
                    vertex(735, 460);
                    vertex(515, 460);
                endShape();
            pop();
            dict[0].drawFunction();
        pop();
        slideOut();
    }

    if (slide == 7) {
        background(65);
        push();
                fill(255);
                textAlign(CENTER, TOP);
                textSize(20);
                text('- Benjamin Franklin', 50, 175, 850, 150);

                textSize(30);
                text('Thank You for Playing', 50, 350, 850, 150);


                textStyle(BOLD);
                textSize(30);
                text('“Those who would give up essential liberty to purchase a little temporary safety, deserve neither liberty nor safety.”', 50, 50, 850, 150);

        pop();
        slideOut();
    }

}

function titleIntro() { //Provides the introduction to the title screen, where the rectangles fly in
        push();
            fill(dem);
            rect(0, 0, count*32, height);
        pop();

        push();
            fill(rep);
            rect(width, 0, -count*32, height);
        pop();

        if(count < width/64) {
                count++
        }
}

function titleScreen() {    //Displays the title screen
    push();
        noStroke();
        fill(dem);
        rect(0, 0, width/2, height);
    pop();

    push();
        noStroke();
        fill(rep);
        rect(width/2, 0, width, height);
    pop();

    if (mouseX > width/2 & mouseY > 0 && mouseY < height) {
        push();
            fill(auth);
            rect(width/2, 0, constrain(mouseX-width/2-25, 0, width/2-25), height);
        pop();
        

        push();
            noStroke();
            fill(rep);
            textAlign(RIGHT, CENTER);
            textSize(40);
            text('POLARIZATION & AUTHORITARIANISM', (width/2 + constrain(mouseX-width/2-50, 0, width/2-25))/2, 0, constrain(mouseX, 0, width/2-25), height);
            textSize(10);
            text('CLICK TO PROCEED', (width/2 + constrain(mouseX-width/2-50, 0, width/2-45))/2, 60, constrain(mouseX, 0, width/2-25), height);
        pop();

        push();
            noStroke();
            fill(dem);
            rect(0, 0, width/2, height);
        pop();
    }   
}

function slideOut() {   //Runs on top of each slide, creating the illusion of a smooth fade-in
    push();
        fill(65, 255-count);
        rect(0, 0, width, height);
    pop();
    if (count <= 255) {
        count+=3
    }
}

function mousePressed() {   //advances which simulation is shown. Also used to instance functions which need to run exactly once for a slide.
    slide++


    vPart = []; //empties all the arrays whenever the slide changes, giving a fresh slate.
    dPart = [];
    rPart = [];
    aPart = [];
    dictator = [];
    count = 0;

    if (slide == 1) {
        createDParticles(1, 105*1, 250, 105, 105, 2);
        createRParticles(1, 105*3, 250, 105, 105, 2);
        createVParticles(1, 105*5, 250, 105, 105, 2);
        createAParticles(1, 105*7, 250, 105, 105, 2);
    }

    if (slide == 2) {
        createDParticles(5, 225, 250, 200, 200, 2);
        createRParticles(5, 225, 250, 200, 200, 2);
        createVParticles(5, 225, 250, 200, 200, 2);

        createDParticles(5, 525, 250, 200, 200, 2);
        createRParticles(5, 525, 250, 200, 200, 2);
        createVParticles(5, 525, 250, 200, 200, 2);
    }

    if (slide == 3) {
        createDParticles(6, 225, 250, 200, 200, 2);
        createRParticles(6, 225, 250, 200, 200, 2);
        createVParticles(3, 225, 250, 200, 200, 2);

        createDParticles(6, 525, 250, 200, 200, 2);
        createRParticles(6, 525, 250, 200, 200, 2);
        createVParticles(3, 525, 250, 200, 200, 2);
    }

    if (slide == 4) {
        //just a placeholder in case I wanted to put stuff here later
    }

    if (slide == 5) {
        createDParticles(10, 225, 250, 200, 200, 2);
        createRParticles(6, 585, 250, 140, 200, 2);

        createVParticles(4, 365, 250, 200, 200, 2);

        createAParticles(14, 585, 250, 140, 200, 5);
    }

    if (slide == 6) {
        createDParticles(10, 225, 250, 200, 200, 0);
        createRParticles(10, 525, 250, 200, 200, 0);

        createVParticles(10, 225, 250, 200, 200, 0);
        createAParticles(10, 525, 250, 200, 200, 0);

        makeDictator(width/2, height/2, 40);
    }


    if (slide > 7) {    //wraps the whole program around if the last slide is reached
        slide = 0;
    }
}

//start particle code [CODE BELOW IS MODIFIED FROM EARLIER EXAMPLES TO MAKE IT MORE GENERAL & FLEXIBLE]
function makeParticle(x, y, dx, dy) {
    var p = {px: x, py: y, vx: dx, vy: dy,
             bFixed: false,
             bLimitVelocities: false,
             bPeriodicBoundaries: false,
             bHardBoundaries: false,
             update: particleUpdate,
             handleBoundaries: particleHandleBoundaries,
             draw: particleDraw
            }
    return p;
}

// Update the position based on force and velocity. x, y, w, h define a rectangle within which the particle bounces around.
function particleUpdate(x, y, w, h) {
        this.handleBoundaries(x, y, w, h);
        this.px += this.vx;
        this.py += this.vy;
}

// do boundary processing if enabled. Modified to process bounds within a given rectangle instead of the canvas. x, y, w, h are passed off from te particleUpdate function
function particleHandleBoundaries(x, y, w, h) {
    if (this.bPeriodicBoundaries) {
        if (this.px > x + w) this.px -= width;
        if (this.px < x) this.px += width;
        if (this.py > y + h) this.py -= height;
        if (this.py < y) this.py += height;
    } else if (this.bHardBoundaries) {
        if (this.px >= x + w) {
            this.vx = -abs(this.vx);
        }
        if (this.px <= x) {
            this.vx = abs(this.vx);
        }
        if (this.py >= y + h) {
            this.vy = -abs(this.vy);
        }
        if (this.py <= y) {
            this.vy = abs(this.vy);
        }
    }
}

//Draws the particle, given a color & size
function particleDraw(c, s) {
    fill(c);
    ellipse(this.px, this.py, s, s);
}

Project – 2020 Calendar

2020 Calendar shaunmurDownload
//Diana McLaughlin and Shaun Murray
//dmclaugh@andrew.cmu.edu and shaunmur@andrew.cmu.edu
//Section A and Section B
//A calendar commemorating a major event from each month in 2020
//All global variables except image variables are with the start of the respective month's program. Some of these variables are called in set up, but you'll find them before their clickMonthX() function
//Shaun's code starts at clickMonthJan(). He also wrote the makeCalendar(), clearBkgd(), and backButton() functions
//Diana's code starts at clickMonthJul(). She also wrote the writeMonths() function
//Aside from the makeCalendar and writeMonths functions, Shaun did everything related to January - June and Diana did everything related to July - December
//"The biggest waste of computer processing power in 15-104" -Shaun

//Image Variables
//for the main calendar
var imgJanCal, imgFebCal, imgMarCal, imgAprCal, 
	imgMayCal, imgJunCal, imgJulCal, imgAugCal, 
	imgSepCal, imgOctCal, imgNovCal, imgDecCal;

//for the month functions
var imgJan2, imgMar, aprImg, aprImg2, 
    aprImg3, imgJun1, imgJun2, imgJun3, 
    imgJul, imgOct, imgNov;


function preload() {
	imgJanCal = loadImage("https://i.imgur.com/mGCWr67.jpg?2"); //January main calendar
	imgFebCal = loadImage("https://i.imgur.com/8hI9x3x.jpg"); //February main calendar
	imgMarCal = loadImage("https://i.imgur.com/hozlVRU.jpg"); //March main calendar
	imgAprCal = loadImage("https://i.imgur.com/PUDQpPe.jpg"); //April main calendar
	imgMayCal = loadImage("https://i.imgur.com/FyUdmy7.png"); //May main calendar
	imgJunCal = loadImage("https://i.imgur.com/1V9Akde.jpg"); //June main calendar
	imgJulCal = loadImage("https://i.imgur.com/Tvukiin.jpg"); //July main calendar
	imgAugCal = loadImage("https://i.imgur.com/kECFW1b.jpg"); //August main calendar
	imgSepCal = loadImage("https://i.imgur.com/O6e3LcQ.jpg"); //September main calendar
	imgOctCal = loadImage("https://i.imgur.com/CcQpShS.jpg"); //October main calendar
	imgNovCal = loadImage("https://i.imgur.com/8Sqt5Um.jpg"); //November main calendar
	imgDecCal = loadImage("https://i.imgur.com/DrModlG.jpg"); //December main calendar

    imgJan = loadImage("https://i.imgur.com/UO8RoiW.png"); //santa hat for JAN
    imgJan2 = loadImage("https://i.imgur.com/lM5i1Gp.jpeg") //A-Bomb Jan
    imgFeb = loadImage("https://i.imgur.com/AIq3z8n.jpeg"); //House Chamber background
    imgMar = loadImage("https://i.imgur.com/VFoP91O.png"); //background image for March
    mayImg1 = loadImage("https://i.imgur.com/RhNvf13.jpeg"); //Kim Jong Un
	mayImg2 = loadImage("https://i.imgur.com/huOal0b.png"); //podium
	mayImg3 = loadImage("https://i.imgur.com/20G2Bj4.jpg"); //NK flag
    aprImg = loadImage("https://i.imgur.com/G0SnXSB.jpg"); //Tiger
	aprImg2 = loadImage("https://i.imgur.com/VVfSCll.jpeg"); //Oklahoma
	aprImg3 = loadImage("https://i.imgur.com/IgLfZQb.png"); //Joe Exotic
	imgJun1 = loadImage("https://i.imgur.com/V8MHehF.jpg"); //St John's Church
	imgJun2 = loadImage("https://i.imgur.com/on3fzqb.jpg"); //President
	imgJun3 = loadImage("https://i.imgur.com/SAUkUd3.jpg"); //Protesters
	imgJul = loadImage("https://i.imgur.com/FXdV1Bk.jpg"); //John Lewis photograph for July
    imgOct = loadImage("https://i.imgur.com/a7W8anl.png"); //map for Oct
    imgNov = loadImage("https://i.imgur.com/OCT1IpR.jpg"); //auditorium for November
}

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

    //set up March
    for (var i = 0; i < 1; i++) {
    // make virus cell
    	var v = makeVirus(200, 200,
                             random(-50, 50), random(10, 50));
        viruses.push(v);
    }

    //set up for April
    for (var i = 0; i < 12; i++){ // create an initial collection of cats
        var rx = random(width);
        tigers[i] = makeTigers(rx);
    }

    //set up August
    for (var i = 0; i < 1; i++){
        var hy = random(height/3, height);
        hurricane[i] = makeHurricane(hy);
    } 
    
    //set up September
    //set up mountains
    for (var i = 0; i <= 100; i++) {
        var n = noise(noiseParam);
        var value = map(n, 0, 1, 0, height/2);
        mountain.push(value);
        noiseParam += noiseStep;
    }  

    //set up fire
    for (var i = 0; i <= 100; i++) {
        var n = noise(fNoiseParam);
        var value = map(n, 0, 1, 0, height);
        fire.push(value);
        fNoiseParam += fNoiseStep;
    }  
    
    //draw initial trees
    for (var i = 0; i < 10; i++){
        var rx = random(width);
        trees[i] = makeTree(rx);
    }
    
    //draw initial smoke clouds
    for (var i = 0; i < 10; i++){
        var cx = random(width);
        smoke[i] = makeSmoke(cx);
    }
    
}

function draw() {
	clickMonthJan();
	clickMonthFeb();
	clickMonthMar();
	clickMonthApr();
	clickMonthMay();
	clickMonthJun();
	clickMonthJul();
	clickMonthAug();
	clickMonthSep();
	clickMonthOct();
	clickMonthNov();
	clickMonthDec();
	backButton();
}

function makeCalendar() {
	fill(0);
    strokeWeight(1);
    //draw lines between the months on the calendar
    for (let i = 0; i < 3; i++) {
        line(0, i*133.33 + 133, width, i*133.33 + 133);
        line(i*125 + 125, 0, i*125 + 125, height);
    }

    //background pictures
    var calPics = [imgJanCal, imgFebCal, imgMarCal, imgAprCal, imgMayCal, imgJunCal, imgJulCal, imgAugCal, imgSepCal, imgOctCal, imgNovCal, imgDecCal];
    var xCo = [0.5, 125.5, 250.5, 375.5, 0, 125.5, 250.5, 375.5, 0.5, 125.5, 250.5, 375.5];
    var yCo = [0, 0, 0, 0, 132.83, 132.83, 132.83, 132.83, 267.16, 267.16, 267.16, 267.16];
    for (var i = 0; i < calPics.length; i++) {
    	image(calPics[i], xCo[i], yCo[i], 124.5, 132.83);
    }

    writeMonths();

}

function writeMonths() {
	//display text on calendar
	var monthText = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
	var monthCode = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", " ", "="];
	var monthX = [55, 180, 305, 430, 55, 180, 305, 430, 55, 180, 305, 430];
	var monthY = [65, 65, 65, 65, 200, 200, 200, 200, 335, 335, 335, 335];
	strokeWeight(1);
	textFont('Times');
    textSize(24);
    textAlign(CENTER);
    stroke(0);
    fill(255);
    for (var i = 0; i < monthText.length; i++) {
    	text(monthText[i], monthX[i], monthY[i]);
    	text(monthCode[i], monthX[i], monthY[i] + 30);
    }
    textSize(40);
    text("-", 300, 363);
    textSize(15);
    textAlign(LEFT);
    text("Press a key to begin", 3, 25); //written instruction
    text("Press ESC to return", 380, 25);
}

function backButton() { //click to return to calendar
    if (keyCode === 27) {
        clearBkrd();
        makeCalendar();

        //reset March
        v.diam = 25;

        //reset November
        pCount = 0;
        vpCount = 0;
    }
}

function clearBkrd() { //clear background
    background(255);
}

//Shaun's Code

function clickMonthJan() {
	//Referencing the anticipation of North Korea's overdue X-mas gift
    if (keyCode === 49) {
        clearBkrd();
        frameRate(30);
        JanBackground();
        USflag();
        NKflag();
        nuclear(width/2, height/2);
        JanText(45, height-85);
        backButton(); 
    }
         
}

	function JanBackground() {
		image(imgJan2, 0, 0, width, height);
	}

    function starJan() {
        var x1 = [340, 348, 364, 354, 356, 340, 324, 326, 315, 332]; //star points
        var y1 = [44, 58, 62, 75, 92, 85, 92, 75, 62, 58];
        var nPoints= x1.length;
        beginShape();
        fill('Red');
        for (var i= 0; i< nPoints; i++) {
            vertex(x1[i] + 35, y1[i] + 5);
        }
        endShape(CLOSE);
    }

    function USflag() {// United States Flag minus stars
        fill('Red');
        rect(25, 25, width/3, height/4);
        for(let i = 0; i < 7; i++) { //white rects on flag
            fill('white');
            rect(25, 30 + (i * 13.5), width/3, 7);
        }
        fill(0, 0, 155);
        rect(25, 25, 50, 50);
    }

    function NKflag() { //North Korean Flag
        fill('Blue');
        rect(width-164, 25, width/3, height/4);
        push();
        fill('Red');
        strokeWeight(5);
        noStroke();
        rect(width-163, 40, width/3 + 6, 70); //white border in flag
        stroke('White');
        line(width, 40, width-161, 40);
        line(width, 110, width-161, 110);
        pop();
        noStroke();
        fill('White');
        circle(width-125, 75, 53);
        stroke(0);
        push();
        starJan();
        pop();
    }

    function nuclear(x, y) { //nuclear symbol
        push();
        translate(x, y);
        let d = 80
        let d1 = 10
        stroke(0);
        strokeWeight(3);
        fill('yellow'); //draw circles
        circle(0, 0, d);
        fill('black');
        circle(0, 0, d1);

        let deg = 120;
        let dx = 5;
        let angle = 45;

        rotate(radians(angle));
        for (let i = 0; i < 3; i++) { //draw triangles 
            rotate(radians(deg));
            beginShape();
            fill('black');
            vertex(-7, -7);
            vertex(-30, -10);
            vertex(-10, -30);
            endShape(CLOSE);
        }

        angle = angle + dx;
        pop();

        push();
        rotate(radians(-20));
        image(imgJan, 135, 185, 100, 100); //santa hat
        pop();

    }

    function JanText(x, y) { //display text for Jan
        push();
        translate(x, y);
        textSize(23);
        fill(255);
        text("United Shaysh of America VS. North Korea", 0, 0);
        pop();
    }

//Global variables for Feb
var rip = 0//checks to see if SotU is ripped

function clickMonthFeb() {
	//Referencing the ripped speech at the State of the Union address
    if (keyCode === 50) {
        clearBkrd();
        frameRate(30);
        drawPaper();
		drawRip();
		mendPaper();
        backButton();
    }   
    
}

	//February helper functions
	function drawPaper() { //draw initial SotU
		push();
		background('grey');
		image(imgFeb, 0, 0);
		fill('white');
		rectMode(CENTER);
		rect(width/2+30, height/2, 200, 300);
		rect(width/2+15, height/2, 200, 300);
		rect(width/2, height/2, 200, 300);
		textStyle(ITALIC);
		textSize(22);
		fill('black');
		text("State of the Union", 160, 80);
		fill('white');
		text("Click and hold to rip!", width-205, 25);
		text("Nancy Pelosi Simulator", 10, 25);
		line(180, 110, 320, 110);
		for (let i = 0; i < 20; i++) {
			line(165, 120 + i*11, 335, 120 + i*11);
		}
		pop();
	}

	function drawRip() { //Rip SotU
		push();
		if (mouseIsPressed) {
			background('grey');
			image(imgFeb, 0, 0);
			textStyle(ITALIC);
		    textSize(22);
			fill('white');
			text("Release mouse to mend...", 10, 25);
			push();
			rotate(radians(-30));
			fill('white');
			rectMode(CORNER);
			rect(width/2-300, height/2-80, 100, 300);
			for (let i = 0; i < 20; i++) {
				line(-40, 190 + i*11, 40, 190 + i*11);
			}
			fill('black');
			text("State of t", -50, 160);
			rotate(radians(60));
			fill('white');
			rect(width/2+160, height/2-345, 100, 300);
			for (let j = 0; j < 20; j++) {
				line(width/2+175, height/2-280 + j*11, width/2+250, height/2-280 + j*11);
			}
			fill('black');
			text("he Union", width/2+162, height/2-300);
			pop();
			pop();
			rip = 1;
		}
	}

	function mendPaper() { //Tape SotU back together like a good American
		push();
		if (rip == 1 & !mouseIsPressed) {
			background('grey');
			image(imgFeb, 0, 0);
			fill('white');
			rectMode(CENTER);
			rect(width/2+30, height/2, 200, 300);
			rect(width/2+15, height/2, 200, 300);
			rect(width/2, height/2, 200, 300);
			textStyle(ITALIC);
			textSize(22);
			fill('black');
			text("State of the Union", 160, 80);
			fill('white');
			text("Click and hold to rip!", width-205, 25);
		    text("Nancy Pelosi Simulator", 10, 25);
			fill('black');
			line(180, 110, 320, 110);
			for (let i = 0; i < 20; i++) {
				line(165, 120 + i*11, 335, 120 + i*11);
			}
	        fill(255, 248, 220);
			rect(width/2-15, height/2, 30, 300);
			pop();
		}
	}
//Global variable for March
var viruses = [];

function clickMonthMar() {
	//Referencing the spread of COVID-19 in the U.S.
    if (keyCode === 51) {
        clearBkrd();
        backButton();
        frameRate(15);
        image(imgMar, 0, 0, 500, 400);

	    for (var i = 0; i < viruses.length; i++) {
	        var v = viruses[i];
	        v.stepFunction();
	        v.drawFunction();
	        if (v.diam > 450) {
	        	background(0);
	        	stroke(255, 0, 0);
	        	strokeWeight(4);
	        	push();
	        	textSize(48);
	        	translate(width/2, height/2)
	        	rotate(radians(90));
	        	text(":(", 0, 0);
	        	pop();
	        	stroke(0);
	        	strokeWeight(2);
	        	fill('white');
	        	text("Sad", width/2, height/2 + 100);
	        }
	    }
    }   
    
}

	//March Helper Functions
	function virusStep() {
    this.age++;
    this.x += this.dx;
    this.y += this.dy;
    if (this.x > width) { // bounce off right wall
        this.x = width - (this.x - width);
        this.dx = -this.dx;
        this.diam *= 1.25;
    } else if (this.x < 0) { // bounce off left wall
        this.x = -this.x;
        this.dx = -this.dx;
        this.diam *= 1.25;
    }
    if (this.y > height) { // bounce off bottom
        this.y = height - (this.y - height);
        this.dy = -this.dy;
        this.diam *= 1.25;
    } else if (this.y < 0) { // bounce off top
        this.y = -this.y;
        this.dy = -this.dy;
        this.diam *= 1.5;
    }
	}


	function virusDraw() {
		stroke('black');//body of virus
		strokeWeight(2);
		fill('red');
		push();
	    translate(this.x, this.y);
		circle(0, 0, this.diam);
		strokeWeight(3);//stems of virus
		var angle = 45;
		for (let i = 0; i < 8; i++) {
			rotate(radians(angle));
			beginShape();
	        vertex(this.diam/2 - 10, 0)
	        vertex(random(this.diam/2 + 4, this.diam/2 + 8), random(-2, 2));
	        endShape(CLOSE);
	        ellipse(random(this.diam/2 + 8, this.diam/2 + 6), random(1, 3), 11, 9);
	    }
	    pop();
	}


	// create a "Particle" object with position and velocity
	function makeVirus(vx, vy, vdx, vdy) {
	    v = {x: vx, y: vy,
	         dx: vdx, dy: vdy,
	         age: 0,
	         diam: 25,
	         stepFunction: virusStep,
	         drawFunction: virusDraw
	        }
	    return v;
	}	

// Global variables for April
var tigers = [];
var deg = 10
var joe = 1;

function clickMonthApr() {
	//Referencing the popularity of the Tiger King documentary on NETFLIX in March/April
    if (keyCode === 52) {
        clearBkrd();
        frameRate(12);
        displayHorizon();
   		updateAndDisplayTigers();
    	removeTigersThatHaveSlippedOutOfView();
    	addNewTigersWithSomeRandomProbability();
        backButton();
    }
       
}

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


	function removeTigersThatHaveSlippedOutOfView(){
	    var tigersToKeep = [];
	    for (var i = 0; i < tigers.length; i++){
	        if (tigers[i].x + tigers[i].breadth > 0) {
	            tigersToKeep.push(tigers[i]);
	        }
	    }
	    tigers = tigersToKeep; // remember the surviving tigers
	}


	function addNewTigersWithSomeRandomProbability() {
	    // With a very tiny probability, add a new cat to the end.
	    var newTigersLikelihood = 0.03; 
	    if (random(0,1) < newTigersLikelihood) {
	        tigers.push(makeTigers(width));
	    }
	}


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

	// draw the cat and more cats
	function tigersDisplay() {
	    push();
	    translate(this.x, height - floor(random(30, 40))); 
	    image(aprImg, 0, -15, 80, 35);
	    pop();
	}


	function makeTigers(birthLocationX) {
	    var tgs = {x: birthLocationX,
	                breadth: 50,
	                speed: -1.0,
	                move: tigersMove,
	                display: tigersDisplay}
	    return tgs;
	}

	function displayHorizon(){
		image(aprImg2, 0, 0, width, height);
		push();
		translate(60, 80);
		imageMode(CENTER);
		rotate(radians(deg));
		for (let i = 0; i < joe; i++) {
			image(aprImg3, 0, 0, 80, 80);
		}
		pop();
		deg = deg + 10;
	}

function clickMonthMay() {
	//Referencing Kim Jong Un's questionable health and reappearance
    if (keyCode === 53) {
        clearBkrd();
        frameRate(60);
        drawBackdrop();
		leader();
		drawPodium();
        backButton(); 
    }  
    
}

	//May helper functions
	function leader() {//place Kim on canvas
		push();
		var top = height/2;
	    var bottom = height;
	    var conY = constrain(mouseY, top, bottom);
		imageMode(CENTER);
		image(mayImg1, width/2, conY, 120, 180);
		pop();
	}

	function drawPodium() {//place podium
		push();
		imageMode(CENTER);
		image(mayImg2, 250, 400, 300, 250);
		pop();
	}

	function drawBackdrop() {//draw flag background
		push();
		imageMode(CENTER);
		image(mayImg3, width/2, height/2, 500, 400);
		textSize(20);
		fill('black');
		text("N.K. Leader Simulator", 10, 30);
		text("Moves with your mouse!", width-210, 30);
		pop();
	}

//Global variable June
var moveJun = 1;

function clickMonthJun() {
	//Referencing President Trump's removal of protesters from St. John's church in D.C.
    if (keyCode === 54) {
        clearBkrd();
        frameRate(30);
        drawChurch();
	    drawPres();
	    drawProtest();
	    fightBack();
        backButton();  
    } 
}

	function drawChurch() {//draw church background
		push();
		imageMode(CENTER);
		image(imgJun1, width/2, height/2, 500, 400);
		textSize(20);
		fill('black');
		text("Click and hold mouse to fight back!", 10, 25);
		pop();
	}

	function drawPres() {//place President on canvas
		push();
		var junX1 = width - 50;
		var conX1 = constrain(junX1 - moveJun, 230, width + 60);
		imageMode(CENTER);
		image(imgJun2, conX1 , height-50, 120, 130);
		pop();
	}

	function drawProtest() {//place protesters on canvas
		push();
		var junX2 = 80;
		var conX2 = constrain(junX2 - moveJun, -100, 230);
		imageMode(CENTER);
		image(imgJun3, conX2, height-50, 200, 150);
		pop();
	}

	function fightBack() {//adjusts Xpos of pres and protest on canvas, default move left
		push();
		moveJun ++;
		print(moveJun);

		if (mouseIsPressed) {
			moveJun -= 2;
		}

		moveJun = constrain(moveJun, -150, 230);
		pop();
	}

//Diana's Code

var julXPoints = [];
var julYPoints = [];
var julClr = [];

function clickMonthJul() {
//Remembering John Lewis
    if (keyCode === 55) {
    	clearBkrd();
    	frameRate(60);
        imgJul.resize(width, height);
        imgJul.loadPixels();
        var x = random(width); //randomly draw pixels for a portrait of John Lewis
	    var y = random(height);
	    var clr = imgJul.get(x, y);
    	stroke(clr);
		strokeWeight(5);
	   	noFill();
	   	point(x, y); 
	   	julXPoints.push(x); //push the coordinates into arrays so it doesn't look like the background keeps drawing over it
	   	julYPoints.push(y);
	   	julClr.push(clr);
	   	for (var i = 0; i < julXPoints.length; i++) {
	   		stroke(julClr[i]);
	   		point(julXPoints[i], julYPoints[i]);
	   	}
        backButton(); 
    }
      
}

function clickMonthAug() {
//SpaceX Launch
	strokeWeight(1);
	stroke(0);
    if (keyCode === 56) {
        clearBkrd();
        background(0);
        frameRate(30);
		for (var i = 0; i < 3; i++) {
			for(var j = 0; j < 4; j++){
				star(i*200 + 25, j*100);
			}	
		}

		for (var a = 0; a < 2; a++) {
			for (var b = 0; b < 4; b++) {
				star(a*200 + 125, b*100 + 50);
			}
		}
		spaceship(200, 150);
		backButton(); 
	    }
}
    //August Helper Functions
	function spaceship(x, y) {
		push();
		translate(x, y);
		rotate(radians(30));
		fill(255);
		ellipse(25, 0, 50, 100); //spaceship body
		rect(0, 0, 50, 150);
		stroke(255, 0, 0);
		strokeWeight(3);
		push();
		rotate(radians(-90));
		text("SpaceX", -120, 25);
		pop();
		stroke(0);
		strokeWeight(1);
		triangle(0, 75, 0, 150, -35, 150); //wings
		triangle(50, 75, 50, 150, 85, 150);
		push();
		translate(-35, 150);
		for (var i = 0; i < 3; i++) { //draw flames
			fill(255, 175, 0);
			triangle(i*40, 0, (i+1)*40, 0, (i*40 + random(15, 25)), random(95, 105));
		}
		pop();
		pop();
	}

	function star(x, y) {
		var sx = [0, 5.5, 16.5, 9.5, 10.5, 0, -10.5, -9.5, -16.5, -5.5];
		var sy = [0, 9.5, 12.5, 21, 32, 27.5, 32, 21, 12.5, 10.5];
		push();
		translate(x, y);
		fill(255, 255, 0);
	    var nPoints = sx.length;
	    beginShape();
	    for (var i = 0; i < nPoints; i++) {
	    	vertex(sx[i] + random(-1, 1), sy[i] + random(-1, 1));
	    }
	    endShape(CLOSE);
	    pop();
	}

//Global Variables for September
var trees = [];
var smoke = [];
var mountain = [];
var fire = [];
var noiseParam = 0; //controls mountain landscape
var noiseStep = 0.01;
var fNoiseParam = 0; //controls fire
var fNoiseStep = 0.05;

function clickMonthSep() {
//West Coast Wildfires
    if (keyCode === 57) {
        clearBkrd();
        text("Sep TEST", width/2, height/2);
        backButton();
        frameRate(10);
        background(100); //dark grey

	    updateAndDisplaySmoke();
	    removeSmokeThatHasSlippedOutOfView();
	    addNewSmokeWithSomeRandomProbability();

	    mountains();
	    makeFire();
	    fill(75);
	    rect(0, 335, width, 65); //ground

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

//September Helper Functions
	function updateAndDisplayTrees(){
	    // Update the trees' positions
	    for (var i = 0; i < trees.length; i++){
	        trees[i].move();
	        trees[i].display();
	    }
	}


	function removeTreesThatHaveSlippedOutOfView(){
	    //remove these trees from the array
	    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() {
	    // Add a new tree to the end of the array
	    var newTreeLikelihood = 0.05; 
	    if (random(0,1) < newTreeLikelihood) {
	        trees.push(makeTree(width));
	    }
	}

	function treeMove() {
	    this.x += this.speed;
	}
	    
	function treeDisplay() {
	    //draw the tree
	    var tHeight = 90; 
	    strokeWeight(5);
	    stroke(0); 
	    push();
	    translate(this.x, height - 40);
	    line(0, -tHeight, 0, 0);
	    line(0, -40, -22, -75);
	    line(0, -40, 22, -75);
	    line(0, -50, -15, -85);
	    line(0, -50, 15, -85);
	    line(0, -30, -30, -65);
	    line(0, -30, 30, -65);
	    stroke(200); 
	    pop();
	}


	function makeTree(birthLocationX) {
	    var tr = {x: birthLocationX,
	                breadth: 50,
	                speed: -3.5,
	                move: treeMove,
	                display: treeDisplay}
	    return tr;
	}

	//Smoke Clouds

	function updateAndDisplaySmoke(){
	    // Update the smoke positions
	    for (var i = 0; i < smoke.length; i++){
	        smoke[i].move();
	        smoke[i].display();
	    }
	}


	function removeSmokeThatHasSlippedOutOfView(){
	    // remove clouds that are no longer visible
	    var smokeToKeep = [];
	    for (var i = 0; i < smoke.length; i++){
	        if (smoke[i].x + smoke[i].breadth > 0) {
	            smokeToKeep.push(smoke[i]);
	        }
	    }
	    smoke = smokeToKeep;
	}


	function addNewSmokeWithSomeRandomProbability() {
	    // Add smoke clouds to the end of the arrayS
	    var newSmokeLikelihood = 0.02; 
	    if (random(0,1) < newSmokeLikelihood) {
	        smoke.push(makeSmoke(width));
	    }
	}

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

	// draw smoke
	function smokeDisplay() { 
	    fill(50); 
	    noStroke(); 
	    push();
	    translate(this.x, this.y);
	    ellipse(0, this.y, 90, 15);
	    ellipse(0, this.y+10, 100, 15);
	    ellipse(0, this.y-10, 80, 15);
	    pop();
	}


	function makeSmoke(birthLocationX) {
	    var smk = {x: birthLocationX,
	    	        y: random(0, height/2),
	                breadth: 50,
	                speed: -3.,
	                move: smokeMove,
	                display: smokeDisplay}
	    return smk;
	}


	function mountains() {
	    //use random noise to draw mountains
	    mountain.shift();
	    var n = noise(noiseParam);
	    var value = map(n, 0, 1, 0, height);
	    mountain.push(value);
	    noiseParam += noiseStep;
	    
	    
	    fill(0); //black - mountain shadows
	    beginShape();
	    vertex(0, height);
	    for (var i = 0; i <= 100; i++) {
	        vertex(i*5, mountain[i]);
	    }
	    vertex(width, height);
	    endShape(); 
	}

	function makeFire() {
	    //use random noise to draw mountains
	    fire.shift();
	    var n = noise(fNoiseParam);
	    var value = map(n, 0, 1, 0, height);
	    fire.push(value);
	    fNoiseParam += fNoiseStep;
	    
	    
	    fill(255, 0, 0); //red layer
	    beginShape();
	    vertex(0, height);
	    for (var i = 0; i <= 100; i++) {
	        vertex(i*5, fire[i]);
	    }
	    vertex(width, height);
	    endShape(); 

	    fill(255, 175, 0); //orange layer
	    beginShape();
	    vertex(0, height);
	    for (var j = 0; j <= 100; j++) {
	    	vertex(j*5, fire[j] + 50);
	    }
	    vertex(width, height);
	    endShape();

	    fill(255, 255, 0); //yellow layer
	    beginShape();
	    vertex(0, height);
	    for (var p = 0; p <= 100; p++) {
	    	vertex(p*5, fire[p] + 100);
	    }
	    vertex(width, height);
	    endShape();
     
}

//October Global Variables
var hurricane = [];
var xMove = [];
var imgOct;

function clickMonthOct() {
	//Busiest hurricane season on record
    if (keyCode === 48) {
        clearBkrd();
        frameRate(15);
        translate(width, 0);
	    image(imgOct, -width-50, -107, 650, 560);
		updateAndDisplayHurricane(); 
		removeHurricanesThatHaveSlippedOutOfView();
		addNewHurricanesWithSomeRandomProbability();
        backButton();
    }
}

	//October Helper Functions
		function updateAndDisplayHurricane(){
	    // Update the hurricanes' positions
	    for (var i = 0; i < hurricane.length; i++){
	        hurricane[i].move();
	        hurricane[i].display();
	    }
	}

	function removeHurricanesThatHaveSlippedOutOfView(){
	    //remove these hurricanes from the array
	    var hurricanesToKeep = [];
	    for (var i = 0; i < hurricane.length; i++){
	        if (hurricane[i].x > -550 || hurricane[i].y > -50) {
	            hurricanesToKeep.push(hurricane[i]);
	        }
	    }
	    hurricane = hurricanesToKeep;
	}

	function addNewHurricanesWithSomeRandomProbability() {
	    // Add a new hurricane to the end of the array
	    var newHurricaneLikelihood = 0.025;
	    var newHY = random(height/3, height);
	    this.xMove = random(10);
	    this.yMove = random(10);
	    if (random(0,1) < newHurricaneLikelihood) {
	        hurricane.push(makeHurricane(newHY));
	    }
	}

	function hurricaneMove() {
		this.x -= this.hxMove;
		this.y -= this.hyMove;
		this.spin += 10;
	}

	function hurricaneDisplay() {
		push();
		translate(this.x, this.y);
		rotate(radians(this.spin));
	    noStroke();
	    fill(255, 0, 0);
	    ellipse(0, 0, 30, 30);
	    fill(230);
	    ellipse(0, 0, 10, 10);
		push();
		scale(0.7);
		translate(-40, 5);
		stroke(255, 0, 0);
		strokeWeight(5);
		noFill();
		beginShape();
		for (var i = 2; i <= 4; i += 0.1) {
			var y1 = Math.pow(2.6, i);
	    	vertex(i*25, -y1);
		}
		endShape();
		pop();
	    
	    push();
	    scale(0.7);
	    stroke(255, 0, 0);
		strokeWeight(5);
		noFill();
	    translate(40, -5);
	    rotate(radians(180));
		beginShape();
		for (var i = 2; i <= 4; i += 0.1) {
			var y1 = Math.pow(2.6, i);
	    	vertex(i*25, -y1);
		}
		endShape();
		pop();
		pop();
	}

	function makeHurricane(birthLocationY) {
		var h = {x: 0, y: birthLocationY, hxMove: xMove, hyMove: 5, move: hurricaneMove, spin: 0, display: hurricaneDisplay}
	    return h;
	}

//November Global Variables
var theta = 0;
var txp = 0;
var typ = 0;
var thetavp = 0;
var txvp = 0;
var tyvp = 0;
//counters
var pCount = 0;
var vpCount = 0;

function clickMonthNov() {
//2020 US Presidential Election
    strokeWeight(1);
	stroke(0);
	textSize(14);

    if (keyCode === 189) {
        clearBkrd();
        frameRate(15);
        backButton();
        image(imgNov, -150, -60, 800, 650);
        stroke(255);
		president(150, 200);
		vicePresident(350, 200);
		fill(255);
		text("Who will be the first to 270?", 150, 20);
		text("Click the mouse on the left to give Alec Baldwin electoral votes", 75, 45)
		text("Click the mouse on the right to give Jim Carrey electoral votes", 75, 70);
		text(pCount, 150, 120);
		text(vpCount, 350, 120);
		debate();
	}

    	if (pCount >= 270) {
			background(255, 0,0);
			textSize(30);
			stroke(0);
			fill(0);
			text("I did it! It was RIGGED but I won!", 20, height/2 - 15);
			text("Very good for our Great Country", 25, height/2 + 15);
		}

		if (vpCount >= 270) {
			background(0, 0, 255);
			textSize(50);
			stroke(255);
			fill(255);
			text("Will you shut up man!", 5, height/2);
		}
	
}
    //November Helper Functions    
	function debate(){
		if (mouseIsPressed) {
			if (mouseX < width/2) { //move president
				theta = 15;
				txp = 150;
				typ = -100
				pCount = pCount + 5;				
			}

			if (mouseX >= width/2) { //move vice president
				thetavp = -15;
				txvp = -150;
				tyvp = 0;
				vpCount = vpCount + 5;
			}
		}
	} 

	function mouseReleased() {
		if (theta === 15) { //reset president
			theta = 0;
			txp = 0;
			typ = 0;					
		}

		if (thetavp === -15) { //reset vice president
			thetavp = 0;
			txvp = 0;
			tyvp = 0;				
		}
	}

	function president(x, y) {
		push();
		rotate(radians(theta));
		translate(x + txp, y + typ);
		noStroke();
		fill(255, 175, 0);
		push();
		rotate(radians(75)); //mouth
		ellipse(17, -12, 4, 15);
		rotate(radians(30));
		ellipse(15, -17, 4, 15);
		pop();
		fill(255, 175, 0); //head
		ellipse(0, 0, 40, 50);
		fill(255, 255, 0); //hair
		ellipse(3.5, -20, 45, 15);
		fill(255); //eyes
		ellipse(10, -2, 8, 8);
		fill(0);
		ellipse(10, -2, 4, 4);
		stroke(0);
		line(25, 17, 40, 17);
		line(25, 9, 40, 1);
		line(25, 25, 40, 33);
		noStroke();

		//suit
		fill(255); //shirt
		rect(-15, 23, 32, 50);
		fill(0, 0, 255); //suit jacket
		rect(-15, 23, 25, 50);
		fill(255, 0, 0); //tie
		rect(14, 23, 3, 30);
		fill(0); //shoes
		ellipse(3, 133, 35, 15);
		fill(0, 0, 255); //pants
		rect(-15, 73, 27, 60);
		push(); //arm
		rotate(radians(-40));
		fill(255, 175, 0);
		ellipse(15, 40, 15, 10);
		fill(0, 0, 255);
		rect(-35, 35, 50, 10);
		pop();
		pop();
	}

	function vicePresident(x, y) {
		push();
		rotate(radians(thetavp));
		translate(x + txvp, y + tyvp);
		noStroke();
		fill(250, 237, 203); //head
		ellipse(-2, 0, 40, 50);
		fill(255); //hair
		ellipse(0, -22, 35, 8);
		fill(255); //eyes
		ellipse(-10, -4, 8, 8);
		fill(0);
		ellipse(-10, -4, 4, 4);
		fill(255, 0, 0); //mouth
		ellipse(-12, 13, 8, 8);
		stroke(0);
		line(-25, 13, -40, 13);
		line(-25, 8, -40, 0);
		line(-25, 18, -40, 26);
		noStroke();

		//suit
		fill(255); //shirt
		rect(-15, 23, 25, 50);
		fill(0, 0, 255); //suit jacket
		rect(-8, 23, 18, 50);
		fill(255, 0, 0); //tie
		rect(-15, 23, 3, 30);
		fill(0); //shoes
		ellipse(-7, 133, 35, 15);
		fill(0, 0, 255); //pants
		rect(-15, 73, 25, 60);
		push(); //arm
		rotate(radians(40));
		fill(250, 237, 203);
		ellipse(-18, 45, 10, 10);
		fill(0, 0, 255);
		rect(-18, 40, 50, 10);
		pop();
		pop()
		}

//December global variables - firework coordinate arrays     
var xpos = 0;
var xcoord = [35, 25, 55, 200, 240, 400, 470, 440, 455, 230, 280, 415, 100, 280];
var ycoord = [25, 100, 350, 120, 150, 75, 45, 175, 300, 320, 365, 340, 215, 50];

function clickMonthDec() {
	//abstract clock to wait for the end of 2020
    if (keyCode === 187) {
        clearBkrd();
        backButton();
        frameRate(5);
    	background(0);
	    var sec = second();
	    var min = minute();
	    var hr = hour();
	    var d = day();
	    background(0);

	    //draw fireworks in the background
	    for (var i = 0; i < 14; i++) {
	        firework(xcoord[i], ycoord[i]);
	    }

	    push();
	    scale(0.5);
	    president(16*d, 40); //moves with day
	    pop();
	    decVirus(20*hr, 150); //hour
	    image(aprImg3, 8*min, 200, 80, 80); //minute
	    decHurricane(8*sec, 350); //second

	}
}

	//December helper functions
	function firework(x, y) { 
	    var r = random(255);
	    var g = random(255);
	    var b = random(255);
	    push();
	    translate(x, y);
	    stroke(r, g, b);
	    for (var i = 0; i < 12; i++) { //draw lines
	        push();
	        rotate(radians(i*30));
	        line(xpos, 0, xpos + 15, 0);
	        pop();
	    }

	    if (xpos <= 25) { //grow
	    xpos += 1;
	    }

	    else if (xpos > 25) { //reset
	        xpos = 0;
	    }
	    pop();
	}

	function decVirus(x, y) { //design taken from Shaun's virus object - I did not code
	        stroke('black');//body of virus
	        strokeWeight(2);
	        fill('red');
	        push();
	        translate(x, y);
	        circle(0, 0, 35);
	        strokeWeight(3);//stems of virus
	        var angle = 45;
	        for (let i = 0; i < 8; i++) {
	            rotate(radians(angle));
	            beginShape();
	            vertex(35/2 - 10, 0)
	            vertex(random(35/2 + 4, 35/2 + 8), random(-2, 2));
	            endShape(CLOSE);
	            ellipse(random(35/2 + 8, 35/2 + 6), random(1, 3), 11, 9);
	        }
	        pop();
	}

    function decHurricane(x, y) { //from October 
        push();
        translate(x, y);
        noStroke();
        fill(255, 0, 0);
        ellipse(0, 0, 30, 30);
        fill(230);
        ellipse(0, 0, 10, 10);

        //hurricane lines
        push(); 
        scale(0.7);
        translate(-40, 5);
        stroke(255, 0, 0);
        strokeWeight(5);
        noFill();
        beginShape();
        for (var i = 2; i <= 4; i += 0.1) {
            var y1 = Math.pow(2.6, i);
            vertex(i*25, -y1);
        }
        endShape();
        pop();
        push();
        scale(0.7);
        stroke(255, 0, 0);
        strokeWeight(5);
        noFill();
        translate(40, -5);
        rotate(radians(180));
        beginShape();
        for (var i = 2; i <= 4; i += 0.1) {
            var y1 = Math.pow(2.6, i);
            vertex(i*25, -y1);
        }
        endShape();
        pop();
        pop();
    }
      

The purpose of our project is to create an interactive calendar that displays important events, memes/jokes,
and or popular culture references to every month in 2020. Each program on its own is not very substantial,
but we aimed to incorporate as many programing elements from the semester as possible. It is a 2020 themed variety show!
The user-interface is a grid displaying the months of the year with instructions on how to access each month.
We have each month bound to a key, “1” through “=,” representing all 12 months.
When a particular key is pressed, the set of functions for the month run until the user presses the “esc” key to return to the main calendar.
The plans for my months are as follows:
Jan – Reference to the tension between the U.S. and North Korea at the tail end of 2019.
Feb – Pelosi Simulator: ripping President Trump’s speech at the State of the Union.
Mar – Object-oriented corona virus representation bouncing around a world map until it covers the U.S.
Apr – Something about Tiger King indeed.
May – Kim Jong Un hiding behind a podium after his health speculations .
Jun – President Trump removing protesters from St. John’s Church in Washington D.C.
We sincerely hope that 2021 is a much better year. Enjoy!

FinalProject-wildFire

sketch-koalaDownload
//Huijun Shen
//huijuns@andrew.cmu.edu 
//section D


//fire
var fireAnim = [];
var fireArr = [];

//particles
var drag = 0.0002;    
var gravity = 0.3;
var particles = [];

//koala
var koalaImg;
var koala;

//var counter
var counter = 5;


function preload(){
 
    //fire animation image
    var filenames = [];
    filenames[0] = "https://i.imgur.com/31vYPuX.png";
    filenames[1] = "https://i.imgur.com/ZhfTftF.png";
    filenames[2] = "https://i.imgur.com/iGSBFBe.png";
    filenames[3] = "https://i.imgur.com/GCq7AjU.png";
    filenames[4] = "https://i.imgur.com/zZGdjbN.png";
    
 
    for (var i = 0; i < filenames.length; i++) {
        fireAnim[i] = loadImage(filenames[i]);
    }

    koalaImg = loadImage("https://i.imgur.com/Xm5QW4o.png");

}

function setup(){
    createCanvas(480,480);
    frameRate(24);
    imageMode(CENTER);

    koala = koalaMake(45,420);
       
}   


function draw(){
    background(144,232,232);  

    //background trees
    var  col = 0; 
    var  row= 0;
    
    var  r = 0;
    for( col = 0; col < 18; col++){ //tree coloe gradation
        var  g = 200;
        var  b = 50;
        for( row = 3; row < 12; row++ ){
           fill(r,g,b);
           b +=5;
           treeDraw(col*28+12,row*38); 
        }
    r +=10;
    }    

    //counter

    textSize(15);
    fill(200,50,0);
    text("fire count ",15,25);
    text(counter.toString(),80,25);

    //intro text
    if(frameCount>0 & frameCount < 24){
        textSize(50);
        fill(255);
        text("Click Mouse",150,200);
    }

    if(frameCount>=24 & frameCount < 48){
        textSize(50);
        fill(255);
        text("Hit Key w",150,200);
    }

    //fire

    if(frameCount % 72 == 0){
        //print(startCount);
        var fire = makeFire(480,410);
        fireArr.push(fire);
    }

    for(var i = 0; i < fireArr.length; i++){
        var f = fireArr[i]
        f.drawFunction();
        f.stepFunction();

        print(f.size);
        //print(counter);

        if (f.size <= 0.2 || f.x <= 0.2){
            print(f.x);
            counter = counter - 1;

        }

        if (f.size<=0.2|| f.x <= 0.2 ){ //Here I choose 0.2 is because 0 is not working, the condition can not run
            fireArr.splice(i,1);
            print("test splice");
        }


 
    }   

     //sun
    fill(223,242,136);
    circle(400,50,50);

    // add new particle to the object
    newParticles = [];
    for (var i = 0; i < particles.length; i++) { // for each particle
        var p = particles[i];
        p.stepFunction();
        p.drawFunction();

    //particle vanishes
        if (p.age < 200) {
            newParticles.push(p);
        }
    }

    particles = newParticles;

   //trunck
    noStroke()
    fill(82,62,41);
    rect(30,280,12,200);

    //koala
    koala.drawFunction();
    koala.stepFunction();

    //ground
    fill(181,170,156);
    rect(0,450,480,30);

    //game ending, win or loose

    if(counter == 0){
        //background (255);
        textSize(40);
        fill(0,100,200,150);
        rect(0,0,width,height);
        fill(255);  
        image(koalaImg,width/2,height/2-100,150,150);           
        text("KOALA SAVED ! ",width/2-130,height/2);
        
        noLoop();
        
    } 

    for(var i = 0; i < fireArr.length; i++){
        var f = fireArr[i]

        if (dist(f.x,f.y,koala.x,koala.y) <= 50){
        background (255,50,0,150);
        textSize(40);
        fill(255);
        text("MISSION FAILED ! ",width/2-150,height/2);

        noLoop();
        }
    }



}


//make new particles by pressing mouse
function mousePressed() {
    var newp = makeParticle(mouseX, mouseY,
        random(-10, 10), random(-10, 0),color(random(1,255),random(1,255),random(1,255),random(5,15)));
    particles.push(newp);


    for(var j = 0; j < fireArr.length; j ++){
        var fire = fireArr[j];
        if(dist(mouseX,mouseY,fire.x,fire.y)<=  400*0.2*fire.size ){
            fire.size -= 0.2;
        }
        if(abs(fire.size -0.1) <=0.0001  || abs(fire.x-0)<0.0001 ){
            //print(fire.size)
            fireArr.splice(j,1);
        }

    }

}

function keyPressed(){
    if (key === "w"){
        koala.y += koala.dy;
    }
}

function counterUpdate(){
    for(var j = 0; j < fireArr.length; j ++){
        var fire = fireArr[j];
    }

    if (fireArr.length > 0  & fire.size <= 0){
        counter = counter - 1;
    }
    
}


function makeFire(fx,fy){
    var p = {x:fx,
         y:fy,
         dx:-8,
         imageNumber:0,
         size:1.0,
         stepFunction:stepFire,
         drawFunction:drawFire,
         }
    return p;

}

function stepFire(){
    this.imageNumber++;
    //print(this.imageNumber);
    if (this.imageNumber > 4){
        this.imageNumber = 0;
    }   
    this.x+=this.dx;
}

function drawFire(){

    push();
    translate(this.x,this.y);
    scale(0.3*this.size);   
    image(fireAnim[this.imageNumber],0,0);
    pop();

    //print("test", this.x,this.y);
}



function treeMake(tx,ty){
    var t = {x:tx,
         y:ty,
         color:c,     
         //stepFunction:stepFire,
         drawFunction:treeDraw,
         }
    return t;

}


function treeDraw(x,y){
    push();
    translate(x, y);
    triangle(-5,0,5,0,0,-15);
    
    beginShape();
    vertex(0,-35);
    vertex(-8,-20);
    vertex(0,-25);
    vertex(8,-20);
    endShape(CLOSE);

    beginShape();
    vertex(0,-25);
    vertex(-12,-12);
    vertex(0,-15);
    vertex(12,-12);
    endShape(CLOSE);

    pop();
}


//particles

function particleStep() {
    this.age++;
    this.x += this.dx;
    this.y += this.dy;
    this.dy = this.dy + gravity; // force of gravity
    // drag is proportional to velocity squared
    // which is the sum of the squares of dx and dy
    var vs = Math.pow(this.dx, 2) + Math.pow(this.dy, 2);
    // d is the ratio of old velocty to new velocity
    var d = vs * drag;
    //limit the speed
    d = min(d, 0.9);
    // scale dx and dy to include drag effect
    this.dx *= (0.8 - d);
    this.dy *= (0.9 - d);
    if(this.age % 40 == 0){
    this.size*= (1-0.2);
    } 

}

 
function particleDraw() {
   
    fill(this.pc);
    circle(this.x, this.y,this.psize);
}


// create a "Particle" object with position and velocity
function makeParticle(px, py, pdx, pdy,pc,psize) {

    p = {x: px, y: py,
         dx: pdx, dy: pdy,
         age: 0,
         pc:color(0,random(100,150),random(150,250)),
         psize:random(5,15),
         stepFunction: particleStep,
         drawFunction: particleDraw
        }
    return p;
}

//koala

function koalaMake(kx,ky){
    var k = {
        x:kx,
        y:ky,
        dy:-40, 
        gravityK:3,
        drawFunction:koalaDraw,
        stepFunction:koalaStep,
    }
    return k;
}

function koalaDraw(){

    image(koalaImg,this.x,this.y,70,70);

}

function koalaStep(){
    this.y += this.gravityK;
    this.y = constrain(this.y,280,423);

}

I am inspired by the wildfire this year which both happened in Australia and California. Till now I still can remember the pictures I saw about wildlives. Those pictures made me sad.
Also I would like to write one project a bit gamy which can bring some of the interesting points of 15104 together.

How to Play:
1 Hit right button on the fire to extinguish them
2 Or hit W key to move the koala when you failed in 1#
3 When you save your koala for 5 fireballs, you win.
4 If the fireball hit the koala, you lose.

Improvement:
1 If I have more time, I would add a start button. Now the program runs automatically. With the start button, the player will feel better.
2 Also, maybe I would add a tutorial before the game begins. Like, first one fireball is burning in the middle of the canvas, and the player needs to extinguish it first to start the game. Then, a fireball is coming toward the koala, the player needs to hit W to help the koala escape from the fire then start the game.