Final Project

2020 was full of surprises that shook our world and changed the lives of many. My final project comments on the concept of misfortune and plays with the sense of control that many felt like they didn’t have in the face of a global pandemic, monumental election, civil rights movements, wildfires, and more. The 2020 slot machine presents the user with an attractive and exciting prospect of winning, but ultimately delivers the raw reality of this year.

To play, click and drag down on the lever, then release. The reels will spin and generate your 2020. Observe the effects of a jackpot!

I was inspired to create a slot machine for my final project because when presented with the project theme “2020,” I couldn’t narrow down to one single event that I wanted to focus on. I instead wanted to take a more macro approach and reflect on the year as a whole and satirize it with a classic casino game. With more time, I would add a greater jackpot effect, more buttons, and user interaction opportunities to the slot machine.

Icon Key
sketchDownload
//2020 SLOT MACHINE
//Elysha Tsai

//All illustrated assets made by me
var bg;
var symbolLinks = [
    "https://i.imgur.com/gj4Ztah.png", //COVID
    "https://i.imgur.com/a8qsuTb.png", //AUSTRALIAN BUSHFIRES
    "https://i.imgur.com/TLZnWQ9.png", //BLM
    "https://i.imgur.com/1tdvXwb.png", //ELECTION
    "https://i.imgur.com/SsV7YIF.png", //2020
    "https://i.imgur.com/EHQEMEP.png", //MURDER HORNETS
]
var textLinks = [
    "https://i.imgur.com/qBgKflt.png", //COVID
    "https://i.imgur.com/jTMJxU5.png", //AUSTRALIAN BUSHFIRES
    "https://i.imgur.com/L47KJMN.png", //BLM
    "https://i.imgur.com/IAmvG2D.png", //ELECTION
    "https://i.imgur.com/051k4xi.png", //2020
    "https://i.imgur.com/sRj9Ipi.png", //MURDER HORNETS
]

var maxlinks = 6;

//assign links to 3 separate reels
var reelA;
var reelB;
var reelC;

var reelimages=[];
var reeltext=[];
var reelAindex=0
var defaultText;
var textimage;
var jackpotWin;

var count =0;
var doneReel=0;
var jackpotindex=0;

//light object variables
var light =[];
var x; //position of light
var speed;

var leverpull;
//var jackpotwin;
var ball;
var slotmachine;
var chair;

function preload() {

  //IMAGES
  bg= loadImage("https://i.imgur.com/Mt81CeD.jpg"); //green gradient background
  ball= loadImage("https://i.imgur.com/5UZk7nN.png"); //lever ball
  slotmachine= loadImage("https://i.imgur.com/3OioKHj.png");
  chair= loadImage("https://i.imgur.com/KXMlSo1.png");

  defaultText= loadImage("https://i.imgur.com/dcfoYh5.png");
  jackpotWin= loadImage("https://i.imgur.com/ih2wbgn.png");

  for (var i=0; i<maxlinks; i++) { 
    reelimages[i] = loadImage(symbolLinks[i]);
  } 
  for (var i=0; i<maxlinks; i++) { 
    reeltext[i] = loadImage(textLinks[i]);
  }

//initial array assignment
  reelA=reelimages[2];
  reelB=reelimages[0];
  reelC=reelimages[4];


}

function setup() {
    createCanvas(600, 450);
    frameRate(10); //mechanical feeling of lever

    //textimage = defaultText;


    //setup light object
    var dist =0;
    for (var i =0; i<1000; i++){
      light[i]= varLight(dist);
      dist +=12; //distance b/w lights
    }
}
/*
function soundSetup() { 
    leverpull.setVolume(1);
    jackpotwin.setVolume(1.2);
    */

function draw() {
  image(bg, -50, -50, 700, 550);

  //draw lightstrip
  push();
  noStroke();
  fill(110, 186, 173); //green
  rect(0, 14, width, 12);
  pop();

  //draw lights
  for(var i = 0; i < light.length; i++){
        light[i].display();
        light[i].move();
  }

  image(slotmachine, 0, 0, 600, 450);
  image(chair, 0, 0, 600, 450);

  //draw text
  push();
  //imageMode(CENTER)
  //image(jackpotWin, 0, 0);
  pop();

  
//JACKPOT
//background flashes when hit jackpot after reels stop changing
  if ((reelA == reelB) & (reelB == reelC) && doneReel){

    //background flashes when hit jackpot after reels stop changing
    rect(0, 0, 600, 450);
    image(slotmachine, 0, 0, 600, 450);
    image(chair, 0, 0, 600, 450);
    image(chair, 0, 0, 600, 450);
     
    count ++;

    if(count==1){
      fill(255, 0, 0);
      }else if(count==2){
        fill(0, 255, 0);
      }else if(count==3){
        fill(0, 0, 255);
        count = 0; 
      }
      
      image(jackpotWin, 0, 0);
      //textimage= reeltext[jackpotindex];
      //assign jackpot symbol to text

      //displayText();
  }

    
  

  //draw images in a row
  image(reelA, 119.5, 181.5, 53, 138);
  image(reelB, 178.5, 181.5, 53, 138);
  image(reelC, 237.5, 181.5, 53, 138);

  lever(); 
}

function lever(){

//hold down mouse to pull down lever
    if (mouseIsPressed  
       & mouseX> 330 && mouseX < 370){

    var x1 = 350; //base x
    var y1 = 293; //base y
    var x2 = constrain(mouseX, 350, 350);//lever only moves vertically
    var y2 = constrain(mouseY, 191, 333);

    
  //stick
    strokeWeight(8);
    stroke(248, 230, 194); //cream
    strokeCap(ROUND);
    line(x1, y1 + (y2/40), x2, y2);
  //ball handle
    push();
    imageMode(CENTER)
    image(ball, x2, y2, 25, 25);
    pop();

    var d = dist(x1, y1, x2, y2); //line length determined by distance from base and handle
    
    }else{ //default lever state
  
  //stick
    strokeWeight(8);
    stroke(248, 230, 194);
    strokeCap(ROUND);
    line(350, 293, 350, 191);
  
  //ball handle
    push();
    imageMode(CENTER)
    image(ball, 350, 191, 25, 25); 
    pop();
      

    }
  }
  
// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}
// based on https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep

// actual wait time based on clock
function waittime(milliseconds) {
  
  const date = Date.now();

  let currentDate = null;

  do {
    
    currentDate = Date.now();

  } while (currentDate - date < milliseconds);

}


function mouseReleased(){

  if (mouseX> 330 & mouseX < 370){   //end position of lever

    reelA=reelimages[int(random(0,maxlinks))];
    reelB=reelimages[int(random(0,maxlinks))];
    reelC=reelimages[int(random(0,maxlinks))]; 
    
    doneReel=0 // start reel turning, not done yet

    //randomize symbol display with lever push
    // for each reel sleep for a random time between 0 and 200ms then show image
    // left to right
    for (var i =0; i<20; i++){
      
      sleep(50).then (()=> {
        reelAindex=int(random(0,maxlinks));
        reelA=reelimages[reelAindex];
          sleep(50).then(()=> {
          reelB=reelimages[int(random(0,maxlinks))];
            sleep(50).then(()=> {
            reelC=reelimages[int(random(0,maxlinks))]; 
          });
        });
      })
      
      waittime(int(random(0,50))) // wait random time up to 100ms before changing 
    }  
    // wait some time for all reels to settle before calling it done
    sleep(500).then(()=> {
      doneReel=1
    })
  }
}

//lightstrip functions

  function varLight(basex){
    var light ={lighty:20,
                x: basex,
                lightw:4,
                display: createLight,
                move: movestrip,
                speed: 4.0,
                }
    return light;
  }

  function createLight(){
    strokeWeight(1.5);
    stroke(227, 88, 158);//pink outline
    fill(248, 230, 194); //cream
    ellipse(this.x, this.lighty, this.lightw, this.lightw);
  }

  function movestrip(){
    this.x -= this.speed
  }
/*
function displayText(){
  push();
  imageMode(CENTER);
  image(reeltext[jackpotindex], 200, 148);
  pop();

}
/*
/*
function mousePressed(){
  if (mouseX>330 & mouseX<370 &&){
    jackpotwin.stop();
    leverpull.play();
  }
}
*/

Final Project

hcFinal
var picfiles = ["S0UUF6k.png", "QRebAPt.png", "kPzEtew.png", "GDfUrs9.png", 
"RdaK8Db.png", "rJua0RK.png", "OFcSHV3.png", "MOsS3A0.png", "gqBXY2d.png",
"O6M0opw.png", "dMPlHtH.png", "KQPXYro.png", "0k3Synd.png", "lXtNJ7L.png",
"046RWzZ.png", "gybarRF.png"];
var soundfiles = ["a.mp3", "b.mp3", "c.mp3", "d.mp3", "e.mp3", "f.mp3","g.mp3",
"h.mp3", "i.mp3", "j.mp3", "k.mp3", "l.mp3", "m.mp3", "n.mp3", "o.mp3", "p.mp3"]; //Will add more sound files later
var pics = [];
var sounds = [];
var channelobj = [];
var oldindex = -1;
var letters = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"];
var colors = [];
var titles = ["Australia fire", "BLM protest", "Chadwick Bosewman death", "Death of Chadwick Boseman", "Explosion in Beirut",
"Florida man saves his dog from an alligator", "Gas explosion in Nigeria", "Harvey Weinstein convicted",
"Impeachment trial of Trump", "Joe Biden wins", "Kobe Bryant death", "Locust swarm", "Murder hornets in US",
"NASA's Mars 2020", "Olympics postponed", "Presidential election"]
var relkey=-1;

function preload(){
    //sound files
    for (var i = 0; i < soundfiles.length; i++){
       sounds[i] = createAudio(concat ("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/12/", soundfiles[i])); //stop() doesn't work with loadSound
        //image files
       pics[i] = loadImage(concat ("https://i.imgur.com/", picfiles[i]));
    }
}

function makeChannel(letter, letterColor){ //Using object to combine letters and their color
    ch = {l: letter, lc: letterColor
         }
    return ch;
}

function setup(){
    createCanvas(500, 500);
    rectMode(CENTER);
    imageMode(CENTER);
    //Giving all letters the same gray color in the beginning
    for (var i = 0; i < letters.length; i++){
        channelobj[i] = makeChannel(letters[i], color(222, 217, 209));
    }
}

function draw(){
    background(240, 255, 254);
    TV();
    drawTitle(relkey);
    drawText(relkey);
}

function drawText(nSelect){
    if (nSelect > -1 & nSelect < letters.length){ //Making selected letter to turn black
        channelobj[nSelect].lc = color(0);
    }
    for (var i = 0; i < channelobj.length; i++){ //Giving characteristics and placement to the letters
        textFont('Baskerville')
        textAlign(CENTER);
        fill(channelobj[i].lc);
        textSize(25);
        text(channelobj[i].l, 20 * i + 100, 450);
    }
    if (nSelect > -1 & nSelect < letters.length){ //Making the letters to turn back to gray
        channelobj[nSelect].lc = color(222, 217, 209);
    }
}

function drawTitle(nSelect){
    noStroke();
    fill(240, 255, 254);
    rect(250, 60, 500, 120); //drawing rect to cover previous titles
    if (nSelect > -1 & nSelect < titles.length){
        textFont('Baskerville')
        textAlign(CENTER);
        fill(0);
        textSize(25);
        text(titles[nSelect], 250, 90);
    }
}

function keyPressed(){
    loop();
    relkey = keyCode - 65; //65 = 'a' keycode, found on p5js.org
    if (relkey > channelobj.length - 1 || relkey < 0){ //Checking the pressed key is in between a~p
        return; //returning any key that is not a~p
    }

    for(var i = 0; i < sounds.length; i++){ //Stopping the audio from previous channel (isPlaying found on p5js.org)
          sounds[i].stop(0);
    }
    sounds[relkey].play(); //Calling the correct audio
    started = true;
}

function TV(){
    //Drawing TV
    stroke(200);
    fill(168, 237, 170);
    rect(250, 270, 370, 270, 35);
    fill(209, 196, 186);
    circle(390, 200, 30);
    circle(390, 250, 30);
    for (var i = 300; i < 360; i += 10){
        rect(390, i, 20, 5);
    }
    fill(100);
       if (relkey > - 1 & relkey < channelobj.length ) {
     image(pics[relkey], 220, 270); //Calling the correct image
    } else {
    rect(220, 270, 260, 220);
    loading();
    for(var i = 0; i < sounds.length; i++){ //Stopping the audio from previous channel
          sounds[i].stop(0);
        }
    }
}

function loading(){ //drawing loading screen
    fill(255);
    push();
    translate(220, 270);
    for (var i = 0; i < 6; i++){
        push();
        rotate(radians(frameCount + 60 * i));
        ellipse(30, 0, 20, 10);
        pop();
    }
    pop();
}

For this project, I wanted to create a television that shows the events that happened in 2020. I was inspired to work on this project since so many people talked about how they will never speak of 2020 in the future. I thought it would be fun to create a program that sums up this year and show it to people in the future to bring their memories back. 

I tried to find a somewhat cute way to show the events since a lot of them are disturbing news. It felt like 2020 was a disastrous year and it was hard to pin down just one main event to show. So I decided to find a way to show all the “key” events of 2020. 

You can watch the channels by pressing the keyboard from “a” to “p.” If you press any keyboard that is not one of those alphabets, the television will stop playing.

Final Project – social distance

sketch

I created a interactive game about Covid-19. When the program runs, it first gives the instruction of the game for the first few seconds, You have to click on the heads of the humans to remove them, so that they keep social distance. If you successfully keep the number of the people under 4, you succeed. If you fail to do so and there are more than 12 people, game over. I was inspired by how the social distance is crucial to keep us safe during this time of pandemic. We just have to keep ourselves not too crammed in one place! I wish I could add more interactive/intuitive features including click to start or click to restart the game.

//Jae Son , Section C

var humans = []; 

function setup() {
    createCanvas(500, 400);
    rectMode(CENTER);
    frameRate(20);
}

function draw() {
    background(210,237,178);
    
    for (var i = 0; i < humans.length; i++){
      var human = humans[i];
      humans[i].display();
    }
    //game instruction in the beginning
    if (frameCount <80) {
      noStroke();
      fill(152,183,108);
      rect(250,200,300,200);
      fill(255);
      textSize(20);
      textStyle(BOLD);
      text('click the head and',140,180);
      text('remove the humans to',140,200);
      text('keep the social distance',140,220);
    }
    //game starts after the instruction
    if (frameCount > 80 & frameCount % 10 == 0){
      var newHuman = createHuman(random(25,476),random(10,278),0,0);
      humans.push(newHuman);
    } 
    //if there is more than 12 people, game over
    if (humans.length > 12) {
      fill(242,158,158);
      rect(250,200,350,250);
      fill(255);
      textSize(20);
      textStyle(BOLD);
      text('No one bothered to keep',130,140);
      text('the social distance',130,160);
      text('and Now we are at the',130,180);
      text('highest risk of COVID 19.',130,200);
      text('Try better!',130,240);
      frameRate(0);
    } 
    //if there is less than 4 people, game clear
    if (humans.length < 4 & frameCount > 200){
      fill(157,209,244);
      rect(250,200,300,250);
      fill(255);
      textSize(20);
      textStyle(BOLD);
      text('Everyone kept the',140,140);
      text('social distance and',140,160);
      text('and we are at',140,180);
      text('lower risk of COVID 19.',140,200);
      text('Good job!',140,240);
      frameRate(0);
    }
}


//humans

//creating Human objects and drawing them
function createHuman(humanx,humany,humandx,humandy){
  var human = {x: humanx, y: humany,
               dx: humandx, dy: humandy,
               display: drawHuman,
               humancolor: color(random(220,255),random(80,100),random(100,200))
              }
  return human;
}

function drawHuman(){
    noStroke();
    fill(this.humancolor);
    push();
    ellipse(this.x,this.y,15,15);
    rect(this.x,this.y+22,16,27);
    rect(this.x-12,this.y+22,4,22);
    rect(this.x+12,this.y+22,4,22);
    rect(this.x-3,this.y+52,5,33);
    rect(this.x+3,this.y+52,5,33);
    pop();
}

//remove humans when their head is clicked
function mousePressed() {
  for (var i = humans.length - 1; i >= 0; i--) {
    if (dist(humans[i].x, humans[i].y, mouseX, mouseY) < 20) {
      humans.splice(i, 1);
    }
  }
}


Final Project: Electoral Map Swing States

sketchDownload="">
//Alyssa Song
//Section C

var trump; //trump and trump 2 are the animations of trump talking
var trump2;
var biden; //biden and biden 2 are the animations of biden talking
var biden2;
var repLead; //decorative marks when trump wins a state
var demLead; //decorative marks when biden wins a state
var trumpWin; //trump illustration when he gets more than 270 votes
var bidenWin; //biden illustration when he gets more tahn 270 votes
var mapUs; //US map of states
var counter = 0; 
var mouseCount = 0;

var demVote = 264; //controls democratic electoral votes
var repVote = 232; //controls republican electoral votes

var mouseCountNV = 0; //mousepress count for nevada
var mouseCountPA = 0; //mousepress count for pennsylvania
var mouseCountGA = 0; //mousepress count for georgia

var rx = []; //controls x, y, speed, and color of red confetti
var ry = [];
var rdx = [];
var rc = [];

var dx = []; //controls x, y, speed, and color of blue confetti
var dy = [];
var ddx = [];
var dc = [];

var vNV, vPA, vGA; 

function preload() {
  trump = loadImage('https://i.imgur.com/vs8qJCA.png');
  trump2 = loadImage('https://i.imgur.com/vSXFveX.png');
  biden = loadImage('https://i.imgur.com/KyIf8lC.png');
  biden2 = loadImage('https://i.imgur.com/s50pOcq.png');
  mapUs = loadImage('https://i.imgur.com/JZU3xQQ.png');
  repLead = loadImage('https://i.imgur.com/aTzVMNw.png');
  demLead = loadImage('https://i.imgur.com/XqAbIHD.png');
  trumpWin = loadImage('https://i.imgur.com/XY9IJ0M.png');
  bidenWin = loadImage('https://i.imgur.com/4NKsHuM.png');

}

function setup() {
  createCanvas(600, 400);
  background(220);
  frameRate(10);
  textSize(32);

  //sets up different speeds, x, y, and color for confetti
  for (var i = 0; i < 120; i++) {
    rx[i] = random(width);
    ry[i] = random(height);
    rdx[i] = random(-10, 10);
    rc[i] = color(random(150, 255),
    random(0, 100), random(0, 50));
    dx[i] = random(width);
    dy[i] = random(height);
    ddx[i] = random(-10, 10);
    dc[i] = color(random(0, 100),
    random(0, 100), random(150, 255));
  }

  //create object of states
  vNV = vState(0);
  vPA = vState(1);
  vGA = vState(2);

}

function draw() {
  imageMode(CENTER);
  strokeWeight(0);

  //writes the swing states and number of electoral votes
  push();
  fill(50);
  textSize(12);
  text("Nevada: 6 electoral votes", 200, 280);
  text("Pennsylvania: 20 electoral votes", 200, 300);
  text("Georgia: 16 electoral votes", 200, 320);
  pop();

  image(mapUs, 275, 150, 600, 400);
  fill(0);

  //nevada dot
  circle(140, 100, 10);

  //pennsylvania dot
  circle(420, 100, 10);

  //georgia dot
  circle(390, 180, 10);


  if (repVote > demVote) {
    image(repLead, 500, 275, 300, 250);
  }

  //animation of biden and trump talking
  if (counter % 2 == 0) {
    image(biden, 100, 275, 300, 250);
    image(trump2, 500, 275, 300, 250);
  }

  if (counter % 2 == 1) {
    image(biden2, 100, 275, 300, 250);
    image(trump, 500, 275, 300, 250);
  }

  //rep electoral votes display
  fill(179, 82, 64);
  text(repVote, width - 90, 100);

  //dem electoral votes display
  fill(75, 108, 199);
  text(demVote, 10, 100);

  counter++;

  electionWin(); //function that displays election winner when they reach 270 votes
  }


function mouseClicked() {
  mouseCount++;
  vNV.update(); //updates votes for Nevada
  vPA.update(); //updates votes for Pennsylvania
  vGA.update(); //updates votes for Georgia
}


function vState(stateNo) { //defines object
  let w = {
    state: stateNo,

    update: function() {
      if (this.state == 0)
        updateNV();
      else if (this.state == 1)
        updatePA();
      else if (this.state == 2)
        updateGA();
      else
        print(state);
    }

  }
  return w;
}


function confetti(x, y, dx, c) { //draws confetti
  fill(c);
  ellipse(x, y, 20, 20);
}


function updateNV() {
  if (mouseX > 110 & mouseX < 160 && mouseY > 80 && mouseY < 130) {
    var originalRep = 232;
    var originalDem = 264;
    mouseCountNV++;

    if (mouseCountNV % 3 == 0) {
      fill(220);
      rect(110, 70, 50, 80);
      image(mapUs, 275, 150, 600, 400);
      demVote = demVote - 6;
      updateVotes(); //updates electoral vote display
    }

    // 1 is turning state red
    if (mouseCountNV % 3 == 1) {
      fill(199, 102, 84);
      rect(110, 70, 50, 80);
      image(mapUs, 275, 150, 600, 400);

      repVote = repVote + 6;

      updateVotes();
    }

    //2 is turning state blue
    if (mouseCountNV % 3 == 2) {
      fill(95, 128, 219);
      rect(110, 70, 50, 80);
      image(mapUs, 275, 150, 600, 400);


      demVote = demVote + 6;
      repVote = repVote - 6;

      updateVotes();

    }
    showLead(mouseCountNV); //shows marks for whoever won the state
  }

}

function updatePA() {
  if (mouseX > 390 & mouseX < 450 && mouseY > 80 && mouseY < 130) {
    mouseCountPA++;

    if (mouseCountPA % 3 == 0) {
      fill(220);
      rect(400, 80, 50, 40);
      image(mapUs, 275, 150, 600, 400);
      demVote = demVote - 20;

      updateVotes();
    }

    // 1 is turn state red
    if (mouseCountPA % 3 == 1) {
      fill(199, 102, 84);
      rect(400, 80, 50, 40);
      image(mapUs, 275, 150, 600, 400);

      repVote = repVote + 20;

      updateVotes();
    }

    //2 is turn state blue
    if (mouseCountPA % 3 == 2) {
      fill(95, 128, 219);
      rect(400, 80, 50, 40);
      image(mapUs, 275, 150, 600, 400);

      demVote = demVote + 20;
      repVote = repVote - 20;

      updateVotes();
    }
    showLead(mouseCountPA);
  }


}

function updateGA() {
  if (mouseX > 370 & mouseX < 420 && mouseY > 150 && mouseY < 210) {
    mouseCountGA++;

    if (mouseCountGA % 3 == 0) {
      fill(220);
      rect(360, 150, 60, 60);
      image(mapUs, 275, 150, 600, 400);
      demVote = demVote - 16;

      updateVotes();
    }

    // 1 is red
    if (mouseCountGA % 3 == 1) {
      fill(199, 102, 84);
      rect(360, 150, 60, 60);
      image(mapUs, 275, 150, 600, 400);

      repVote = repVote + 16;

      updateVotes();
    }

    //2 is blue
    if (mouseCountGA % 3 == 2) {
      fill(95, 128, 219);
      rect(360, 150, 60, 60);
      image(mapUs, 275, 150, 600, 400);

      demVote = demVote + 16;
      repVote = repVote - 16;

      updateVotes();
    }
  }
  showLead(mouseCountGA);
}

function updateVotes() {
  push();
  fill(220);
  rect(width - 100, 70, 70, 40);
  pop();

  //republican electoral vote
  fill(179, 82, 64);
  text(repVote, width - 90, 100);

  push();
  fill(220);
  rect(0, 70, 70, 40);
  pop();

  //democrat electoral vote
  fill(75, 108, 199);
  text(demVote, 10, 100);
}

function showLead(state) { //displays mark for whoever won the state
  if (state % 3 == 1) {
    image(repLead, 500, 275, 300, 250);
  }
  if (state % 3 == 2) {
    image(demLead, 100, 275, 300, 250);
  }
}

function electionWin() { //displays whoever wins the election
  if (demVote >= 270) { //biden displayed
      background(0, 0, 0, 100);

      background(75, 108, 199);
      for (i = 0; i < 104; i++) {
        confetti(dx[i], dy[i], ddx[i], dc[i]);
        dx[i] += ddx[i];
        if (dx[i] > width || dx[i] < 0) {
          ddx[i] = -ddx[i];
        }
      }

      image(bidenWin, 300, 200, 500, 400);

    }
    if (repVote >= 270) { //trump displayed
      background(0, 0, 0, 100);
      background(179, 82, 64);
      for (i = 0; i < 104; i++) {
        confetti(rx[i], ry[i], rdx[i], rc[i]);
        rx[i] += rdx[i];
        if (rx[i] > width || rx[i] < 0) {
          rdx[i] = -rdx[i];
        }
      }
      image(trumpWin, 300, 200, 500, 400);
    }
}

Alyssa Song

My program is an electoral map of the last few swing states in the 2020 election. You can test the electoral map and use it to see who can win the election based on who wins which swing states, and try different permutations and combinations of states.

For example:

Click Nevada once to turn the state red, and add 6 electoral votes to the republican count.

Next, click Pennsylvania once to turn the state red, which adds 20 electoral votes to the republican count.

Finally, click Georgia once to turn the state red. You should see an image with Trump 2020. Winning Georgia would put Trump over 270 electoral votes, so he would win the election.

To replay the program, refresh the page. Double click on any state to turn the state blue and make Biden win the election.

To use the program, you can click on the dot on the key swing states that are originally grey on the map. Clicking the dot once will turn the state red and add the respective amount of electoral votes to the Republican electoral count on the right, and clicking the dot twice will turn the state blue and do the same thing for the Democratic electoral count on the left.

Final Project: Covid Clicker

Our program is an interactive fight the coronavirus game. Within this game the player must tap on the coronavirus particles attacking the hospital in order to try to create and distribute the vaccine. As the players score increases the
particles spawn at a higher rate making the game harder to win. Once the screen and player are about to be overtaken by the virus the screen will start to flash red indicating the player is close to losing. Once there are 30 or more corona
virus particles on the screen the player has become infected and loses. Losing triggers the game to bring the player to the loser page. In order to win the game the player must click on 100 individual particles filling up the bar on the right side of the game. Once this occurs the player has created and distributed the vaccine bringing them to the winner page. If we had more experience in code we would have liked to have been able to make the virus particles more complex and life like while having the mouse pressed function work on only the virus. With more time and knowledge this might have been accomplished.

sketchDownload
var counter = 0;
var viruses = [];
var newVirusLikelihood = 0.05;
var cars = [];


function setup() {
    createCanvas(480, 480);
    frameRate(10);
}

function draw() {
    push();
    background1();
    pop();
    //gives a flashing warning if there are more than 20 objects
    //Lucas and Anthony
    if(viruses.length > 20){
        if(frameCount % 4 == 0){
            background(255, 0, 0, 100);
        }
        else{
            push();
            background1();
            pop();
        }
    }
    //The following if statements increase the spawn rate at certain scores
    //(Lucas)
    if(counter == 5){
        newVirusLikelihood = .07
    }
    if(counter == 10){
        newVirusLikelihood = .12
    }
    if(counter == 25){
        newVirusLikelihood = .17
    }
    if(counter == 50){
        newVirusLikelihood = .23
    }
    //Creates a progress bar to a vaccine (Lucas)
    fill(0, 255, 0);
    rect(width - 10, 0, 10, counter * height / 100);

    fill(255);
    //displays how many viruses have been "cleansed" (Lucas)
    text("Score = " + counter.toString(), 10, 10, 70, 80);
    updateAndDisplayViruses();
    bounceViruses();
    addNewVirusesWithSomeRandomProbability();
    print(counter.toString());
    //End Screen if the player loses (Lucas)
    if(viruses.length >= 30){
        //erase();
        background(0);
        textAlign(CENTER);
        textSize(26);
        text("You Lose: COVID-19 Has Taken Over", width / 2, height / 2)
        noLoop();
    }
    //End Screen if the player wins (Lucas)
    if(counter == 100){
        background(255);
        push();
        fill(0);
        textAlign(CENTER);
        textSize(26);
        text("You Win: A Vaccine Has Been Distributed", width / 2, height / 2)
        pop();
        noLoop();

    }
}

//The following code was done by Lucas until indicated
function updateAndDisplayViruses(){
    // Update the virus positions, and display them.
    for (var i = 0; i < viruses.length; i++){
        viruses[i].move();
        viruses[i].display();
    }
}
//makes the viruses bounce off the edges of the canvas
function bounceViruses(){
    for(var i = 0; i < viruses.length; i++){
        //determines if a virus is on the left or right and switches direction
        //accordingly
        if(viruses[i].x + viruses[i].breadth / 2 >= width ||
        viruses[i].x - viruses[i].breadth / 2 <= 0){
            viruses[i].speedX = -viruses[i].speedX
        }
        //determines if a virus is on the top or bottom and switches direction
        //accordingly
        if(viruses[i].y + viruses[i].breadth / 2 >= height ||
        viruses[i].y - viruses[i].breadth / 2 <= 0){
            viruses[i].speedY = -viruses[i].speedY
        }
    }
}


function addNewVirusesWithSomeRandomProbability() {
    // Adds a virus based upon a probability
    if (random(0,1) < newVirusLikelihood) {
        viruses.push(makeVirus(random(20, width - 20),
        random(20, height - 20)));
    }
}

// method to update position of virus every frame
function virusMove() {
    this.x += this.speedX;
    this.y += this.speedY;
}

function virusDisplay() {
    //colors the viruses randomly
    push();
    fill(this.clr);
    push();
    translate(this.x, this.y);
    circle(0, 0, this.breadth);
    pop();
    pop();
}

function makeVirus(startLocationX, startLocationY){
    var virus = {x: startLocationX,
               y: startLocationY,
               breadth: random(20, 80), //size of virus
               //random color of each virus
               clr: color(random(255), random(255), random(255)),
               //random speeds of virus
               speedX: random(-5, 5),
               speedY: random(-5, 5),
               move: virusMove,
               display: virusDisplay}
    return virus;
}

function mousePressed(){
    var vBefore = [];
    var vAfter = [];
    var vFinal = [];
    var v = viruses;
    for(var i = 0; i < viruses.length; i++){
        //conditions for mouse to be inside a virus
        if(mouseX > viruses[i].x - viruses[i].breadth / 2 & mouseX <
            viruses[i].x + viruses[i].breadth/2 && mouseY < viruses[i].y +
            viruses[i].breadth / 2 && mouseY > viruses[i].y -
            viruses[i].breadth / 2){
                //viruses up until the clicked object
                vBefore = viruses.slice(0, i);
                //viruses after the clicked object
                vAfter = v.slice(i + 1);
                //combines the two arrays of objects (eliminating the clicked
                //one)
                vFinal = vBefore.concat(vAfter);
                counter += 1
                viruses = vFinal
        }
    }
}
//The following code was done by Anthony
function background1(){   //joining background helper functions into one
  background(135,206,235);
  push()
  hospital();
  pop()
  push()
  updateAndDisplayCars();
  removeCarsThatHaveSlippedOutOfView();
  addNewCarsWithSomeRandomProbability();
  pop()
}

function hospital(){
  translate(0,-50);
  rect(100,250,100,230);    //creating the hospital building
  rect(200,200,200,280);
  rect(240,150,120,50);
  push();
  noStroke();
  fill(255,0,0);    //red cross on the top
  rect(295,160,10,30);
  rect(285,170,30,10)
  pop();
  push();
  fill(0,0,255);
  for(x=115;x<185;x+=30){   //windows
    for(y=255;y<460;y+=30){
      square(x,y,15);
    }
  }
  for(x=215;x<390;x+=30){
    for(y=210;y<400;y+=30){
      square(x,y,15);
    }
  }
  rect(300,450,20,30);    //doors
  rect(280,450,20,30);
  pop();
  push()
  fill(64);
  rect(0,480,480,50);   //street
  pop()
}

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

function removeCarsThatHaveSlippedOutOfView(){
    //defines if a car is off the canvas, recreates the array to keep
    //cars still on canvas and remove ones that have moved off
    var carsToKeep = [];
    for (var i = 0; i < cars.length; i++){
        if (cars[i].x + cars[i].breadth > 0) {
            carsToKeep.push(cars[i]);
        }
    }
    cars = carsToKeep;
}


function addNewCarsWithSomeRandomProbability() {
    // Adds a car based upon a probability
    var newCarLikelihood = 0.02;
    if (random(0,1) < newCarLikelihood) {
        cars.push(makeCar(width));
    }
}


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

function carDisplay() {
    //colors the car randomly
    fill(this.clr);
    push();
    translate(this.x, 440);
    //body of the car
    rect(0, 0, this.breadth, 30);
    //windows as roof of the car
    fill(255, 255, 255, 50);
    quad(15, 0, this.breadth*.25, -20, this.breadth*.75,
         -20, this.breadth-5, 0);
    //wheels
    fill(0);
    circle(20, 25, 25);
    circle(80, 25, 25);
    pop();
}

function makeCar(startLocationX){
    var car = {x: startLocationX,
               breadth: 100, // length of car
               //random color of each car
               clr: color(random(255), random(255), random(255)),
               //random speeds of cars
               speed: random(-5, -10),
               move: carMove,
               display: carDisplay}
    return car;
}

Fight the Corona virus final project

I worked on this project with Lucas Bittig. Our program is an interactive fight the coronavirus game. Within this game the player must tap on the coronavirus particles attacking the hospital in order to try to create and distribute the vaccine. As the players score increases the particles spawn at a higher rate making the game harder to win. Once the screen and player are about to be overtaken by the virus the screen will start to flash red indicating the player is close to losing. Once there are 30 or more corona virus particles on the screen the player has become infected and loses. Losing triggers the game to bring the player to the loser page. In order to win the game the player must click on 100 individual particles filling up the bar on the right side of the game. Once this occurs the player has created and distributed the vaccine bringing them to the winner page. If we had more experience in code we would have liked to have been able to make the virus particles more complex and life like while having the mouse pressed function work on only the virus. With more time and knowledge this might have been accomplished.

sketchDownload
var counter = 0;
var viruses = [];
var newVirusLikelihood = 0.05;
var cars = [];


function setup() {
    createCanvas(480, 480);
    frameRate(10);
}

function draw() {
    push();
    background1();
    pop();
    //gives a flashing warning if there are more than 20 objects
    //Lucas and Anthony
    if(viruses.length > 20){
        if(frameCount % 4 == 0){
            background(255, 0, 0, 100);
        }
        else{
            push();
            background1();
            pop();
        }
    }
    //The following if statements increase the spawn rate at certain scores
    //(Lucas)
    if(counter == 5){
        newVirusLikelihood = .07
    }
    if(counter == 10){
        newVirusLikelihood = .12
    }
    if(counter == 25){
        newVirusLikelihood = .17
    }
    if(counter == 50){
        newVirusLikelihood = .23
    }
    //Creates a progress bar to a vaccine (Lucas)
    fill(0, 255, 0);
    rect(width - 10, 0, 10, counter * height / 100);

    fill(255);
    //displays how many viruses have been "cleansed" (Lucas)
    text("Score = " + counter.toString(), 10, 10, 70, 80);
    updateAndDisplayViruses();
    bounceViruses();
    addNewVirusesWithSomeRandomProbability();
    print(counter.toString());
    //End Screen if the player loses (Lucas)
    if(viruses.length >= 30){
        //erase();
        background(0);
        textAlign(CENTER);
        textSize(26);
        text("You Lose: COVID-19 Has Taken Over", width / 2, height / 2)
        noLoop();
    }
    //End Screen if the player wins (Lucas)
    if(counter == 100){
        background(255);
        push();
        fill(0);
        textAlign(CENTER);
        textSize(26);
        text("You Win: A Vaccine Has Been Distributed", width / 2, height / 2)
        pop();
        noLoop();

    }
}

//The following code was done by Lucas until indicated
function updateAndDisplayViruses(){
    // Update the virus positions, and display them.
    for (var i = 0; i < viruses.length; i++){
        viruses[i].move();
        viruses[i].display();
    }
}
//makes the viruses bounce off the edges of the canvas
function bounceViruses(){
    for(var i = 0; i < viruses.length; i++){
        //determines if a virus is on the left or right and switches direction
        //accordingly
        if(viruses[i].x + viruses[i].breadth / 2 >= width ||
        viruses[i].x - viruses[i].breadth / 2 <= 0){
            viruses[i].speedX = -viruses[i].speedX
        }
        //determines if a virus is on the top or bottom and switches direction
        //accordingly
        if(viruses[i].y + viruses[i].breadth / 2 >= height ||
        viruses[i].y - viruses[i].breadth / 2 <= 0){
            viruses[i].speedY = -viruses[i].speedY
        }
    }
}


function addNewVirusesWithSomeRandomProbability() {
    // Adds a virus based upon a probability
    if (random(0,1) < newVirusLikelihood) {
        viruses.push(makeVirus(random(20, width - 20),
        random(20, height - 20)));
    }
}

// method to update position of virus every frame
function virusMove() {
    this.x += this.speedX;
    this.y += this.speedY;
}

function virusDisplay() {
    //colors the viruses randomly
    push();
    fill(this.clr);
    push();
    translate(this.x, this.y);
    circle(0, 0, this.breadth);
    pop();
    pop();
}

function makeVirus(startLocationX, startLocationY){
    var virus = {x: startLocationX,
               y: startLocationY,
               breadth: random(20, 80), //size of virus
               //random color of each virus
               clr: color(random(255), random(255), random(255)),
               //random speeds of virus
               speedX: random(-5, 5),
               speedY: random(-5, 5),
               move: virusMove,
               display: virusDisplay}
    return virus;
}

function mousePressed(){
    var vBefore = [];
    var vAfter = [];
    var vFinal = [];
    var v = viruses;
    for(var i = 0; i < viruses.length; i++){
        //conditions for mouse to be inside a virus
        if(mouseX > viruses[i].x - viruses[i].breadth / 2 & mouseX <
            viruses[i].x + viruses[i].breadth/2 && mouseY < viruses[i].y +
            viruses[i].breadth / 2 && mouseY > viruses[i].y -
            viruses[i].breadth / 2){
                //viruses up until the clicked object
                vBefore = viruses.slice(0, i);
                //viruses after the clicked object
                vAfter = v.slice(i + 1);
                //combines the two arrays of objects (eliminating the clicked
                //one)
                vFinal = vBefore.concat(vAfter);
                counter += 1
                viruses = vFinal
        }
    }
}
//The following code was done by Anthony
function background1(){   //joining background helper functions into one
  background(135,206,235);
  push()
  hospital();
  pop()
  push()
  updateAndDisplayCars();
  removeCarsThatHaveSlippedOutOfView();
  addNewCarsWithSomeRandomProbability();
  pop()
}

function hospital(){
  translate(0,-50);
  rect(100,250,100,230);    //creating the hospital building
  rect(200,200,200,280);
  rect(240,150,120,50);
  push();
  noStroke();
  fill(255,0,0);    //red cross on the top
  rect(295,160,10,30);
  rect(285,170,30,10)
  pop();
  push();
  fill(0,0,255);
  for(x=115;x<185;x+=30){   //windows
    for(y=255;y<460;y+=30){
      square(x,y,15);
    }
  }
  for(x=215;x<390;x+=30){
    for(y=210;y<400;y+=30){
      square(x,y,15);
    }
  }
  rect(300,450,20,30);    //doors
  rect(280,450,20,30);
  pop();
  push()
  fill(64);
  rect(0,480,480,50);   //street
  pop()
}

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

function removeCarsThatHaveSlippedOutOfView(){
    //defines if a car is off the canvas, recreates the array to keep
    //cars still on canvas and remove ones that have moved off
    var carsToKeep = [];
    for (var i = 0; i < cars.length; i++){
        if (cars[i].x + cars[i].breadth > 0) {
            carsToKeep.push(cars[i]);
        }
    }
    cars = carsToKeep;
}


function addNewCarsWithSomeRandomProbability() {
    // Adds a car based upon a probability
    var newCarLikelihood = 0.02;
    if (random(0,1) < newCarLikelihood) {
        cars.push(makeCar(width));
    }
}


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

function carDisplay() {
    //colors the car randomly
    fill(this.clr);
    push();
    translate(this.x, 440);
    //body of the car
    rect(0, 0, this.breadth, 30);
    //windows as roof of the car
    fill(255, 255, 255, 50);
    quad(15, 0, this.breadth*.25, -20, this.breadth*.75,
         -20, this.breadth-5, 0);
    //wheels
    fill(0);
    circle(20, 25, 25);
    circle(80, 25, 25);
    pop();
}

function makeCar(startLocationX){
    var car = {x: startLocationX,
               breadth: 100, // length of car
               //random color of each car
               clr: color(random(255), random(255), random(255)),
               //random speeds of cars
               speed: random(-5, -10),
               move: carMove,
               display: carDisplay}
    return car;
}

Week 15: Final Project

sketch
/*
15-104
FINAL PROJECT
*/

/*
COLLABORATORS:
NICHOLAS WONG
SECTION A 
nwong1@andrew.cmu.edu

RACHEL KIM
SECTION C
rachelki@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();
		}

	}
}




For the final project, we wanted to create a side-scrolling game that related to Covid-19. In order to start the game, the only thing that the user needs to do is press the space bar in order for the player to jump. This type of game presents a screen that continuously scrolls while the player jumps to avoid obstacles. Two obstacles that the player faces are Covid-19 particles and platforms. The more obstacles the player overcomes, the speed of the game also increases as well. Once the player fails to avoid the Covid-19 particles or overcome the platforms, the player loses the game, and the “Game Over” screen would show up. In order to restart the game, the user would have to press the space bar. Overall, we both thought it would be fun to create a side-scrolling game for the final project of this course.

Throughout the process of this project, we faced a few challenges such as dynamic collision detection and graphical elements. Therefore, with time constraints, we were not able to play-test the game as much as we wanted to. Although there are a couple of flaws to the game, we had fun being able to create a side-scrolling game with colorful visuals. If we had more time, we would have refined the dynamic collision detection system, added in a more specific algorithm for creating obstacles and platforms, and fix the colors of the graphical elements. Additionally, we would also think about incorporating power-ups (masks, hand sanitizer, etc.) and sound as well.

Final Project: An Animated Rant

For my final project I was inspired by the Facebook page Zoom memes for self quarantines. Over the course of the past semester I’ve found posts that I really resonated with. Although it is a meme page – there are a lot of references to mental health and how the current pandemic and other social issues are affecting our lives beyond the Zoom classroom stress. My project uses mainly black and white colors to reflect the seriousness of the issue and to address topics of funny conversations as something bigger than that and in dire need of attention.

Beyond being a student, I also work full-time so life was getting difficult to balance. So I also found aspects of this rant to encompass elements of work from home life as well and that I do understand both sides of the story.

Now to get into how the program works. It is an interactive “flip book” where you can interact with certain pages with your cursor. Simply moving the cursor along the x and y axis of certain pages reveals new elements or changes existing one. Each of the interactions are in place to put emphasis on certain aspects of the text components but some are only animations. If I had more time to flush out some more details – I would have liked to add flame element to the last page. I think that additional interaction would have also made it more engaging.

Please feel free to interact with it below 🙂

sketch

//Helen Cheng
//helenc1@andrew.cmu.edu
//Final Project
//Section C

// text verses
var page1 = ["i'm tired.", "school is hard.", " navigating life", "during a pandemic", "is hard."]
var page2 = ["staring at a screen from ", "morning to night is hard on my eyes.",
"my vision is becoming fuzzy"];
var page3 = ["paying attention during a Zoom lecture is hard.",
"i already couldn't pay attention in person."]
var page4 = ["doing homework is hard.", "i'm not procrastinating",
"i have 3 homeworks,", "an exam,", "and a project,", "all due on the same day",
"i have to choose which one i don't want to", "'procrastinate on this time.'"];
var page5 = ["it feels like", "i'm overwhelmed"];
var page6 = ["you might feel the same way too.", "so let's all just be kind"]
var page7 = ["has anyone stopped to ask us how we feel?"]
var page8 = ["i'm burnt out."];

// global variables
var pageTracker = 0;
var sentenceTracker = 0;

//for text avoidance function
var minMouseDist = 1000;

//var for helper functions
var floater = [];

function setup() {
    createCanvas(500, 500);
    background(0);
    frameRate(1);
    textAlign(LEFT);
    textFont("serif", 20);
    imageMode(CENTER);

    //setup for page 4 - mouse repelling letters
    //characters into array
    points = new Array(page4[1].length);
    for (var i = 0; i < points.length; i++) {
        points[i] = new Array(2);
    }
    var textW = textWidth(page4[1]);
    var s2 = "";
    // logs location of characters
    for (var i = 0; i < page4[1].length; i++){
        var charPosn = textWidth(s2);
        points[i][0] = createVector((width - textW) / 2 + textWidth(s2), height / 2);
        s2 = s2 + page4[1].charAt(i);
        console.log("s2: " + s2);
    }
    console.log(points);

    //setup for floaters
    for (var i = 0; i < 100; i++) {
        floater.push(makeFloaters(random(width), random(height), 
            random(30), color(random(255), 0, 0), random(-5, 5), random(-5, 5)));
    }
}


function draw() {
    background(0);
    fill(255);

    // starting screen with instructions
    if (pageTracker == 0) {
        textSize(42);
        text("new frustrations", 200, 250);
        textSize(20);
        text("an interactive rant: flip through with arrow keys", 50, 400);
        text("interact by moving your mouse", 50, 450);
        text(concat(str(pageTracker), "/8"), 450, 450);
    }

    //auto displays all strings in a simple animation
    else if (pageTracker == 1) {
        background(0);
        textSize(42);
        text(page1[sentenceTracker], 50, 250);
        textSize(20);
        text(concat(str(pageTracker), "/8"), 450, 450);
    
        if (sentenceTracker < 4) {
            sentenceTracker += 1;
        } 
   }
   //red floaters mimic tired eyes
   else if (pageTracker == 2) {
        frameRate(10);
        animation2();
        for (var i = 0; i < 100; i++) {
            floater[i].drawFunction();
            floater[i].moveFunction();
        }
   }
   //flashing letters makes text harder to read and references attention issues
   else if (pageTracker == 3) {
        animation3();
        fill(255);
        text(concat(str(pageTracker), "/8"), 450, 450);
   }
   //red text avoids cursor to represent procrastination
   else if (pageTracker == 4) {
        animation4();
        fill(255);
        text(concat(str(pageTracker), "/8"), 450, 450);
   }
   //mouseY affects text size
   else if (pageTracker ==5) {
        animation5();
        textSize(20);
        text(concat(str(pageTracker), "/8"), 450, 450);
   }
   //mouseX reveals two sides
   else if (pageTracker == 6)  {
        animation6();
        fill(255);
        text(concat(str(pageTracker), "/8"), 450, 450);
   }
   //mouseY turns a smile upside down
   else if (pageTracker == 7) {
        animation7();
        text(concat(str(pageTracker), "/8"), 450, 450);
   }
   //flashing red text simulates emergency or error text above toaster
   else if(pageTracker == 8) {
        animation8();
        textSize(20);
        fill(255);
        text(concat(str(pageTracker), "/8"), 450, 450);
   }

}

// the page turner 
function keyPressed() {
    background(0);
    if (keyCode === LEFT_ARROW) {
        pageTracker -= 1;
    }
    else if (keyCode === RIGHT_ARROW) {
        pageTracker += 1;
    }

}

//page 5 helper functions
function makeFloaters(x, y, s, c, dx, dy) {
    var floater = new Object();
    floater.x = x;
    floater.y = y;
    floater.size = s;
    floater.c = c;
    floater.dx = dx;
    floater.dy = dy;
    floater.drawFunction = drawFloaters;
    floater.moveFunction = moveFloaters;
    return floater;
}

function moveFloaters() {
    this.x += this.dx;
    this.y += this.dy; 
}

function drawFloaters() {
    fill(this.c);
    ellipse(this.x, this.y, this.size);
}

//page 2: random circles float across the screen to mimic tired eyes
function animation2() {
    fill(255);

    textFont("serif", 20);

    text(page2[0], 100, height/4);
    text(page2[1], 200, height/2);
    text(page2[2], 100, 3*height/4);

    text(concat(str(pageTracker), "/9"), 450, 450);
}


//page 3: moving in and out of focus mimics attention disorders
function animation3() {
    strokeWeight(0);

    fill(128 + sin(frameCount*0.2) * 128);

    text(page3[0], 50, height/3);
    text(page3[1], 50, height/2);
}

//page 4: all text displayed at once but is repelled by cursor
//to symbolize avoidance/procrastination
function animation4() {
    background(0);
    text(page4[0], 50, 50);
    for (var i = 2; i < 8; i++){
        if (i < 5) {
            text(page4[i], 50, 50*i);
        }
        else {
            text(page4[i], 50, 400+50*(i - 6));
        }
    }
    //repels text from cursor
    for(var i = 0; i < points.length; i++){
        var p = points[i][0];
        var p2 = createVector(0, 0);
        var mouseDist = dist(p.x, p.y, mouseX, mouseY);
    
        if(mouseDist < minMouseDist){
            p2 = createVector(p.x - mouseX, p.y - mouseY);   
            var distDifference = minMouseDist - mouseDist;
            p2.setMag(sqrt(distDifference));
    }
    points[i][1] = p2;
    //draws text
    fill(255, 0, 0);
    text(page4[1].charAt(i), p.x + p2.x, p.y + p2.y);
    }   
}

//page 5: text grows in size with mouse position
function animation5() {
    text(page5[0], 100, height/3);
    textSize(mouseY/4);
    text(page5[1], 100, height/2);
}

//page 6: text reveals to show the two sides/perspectives
function animation6() {
    fill(255);
    rect(0, 0, mouseX/2, 500);
    rect(500, height, mouseX/2, 500);
    fill(255);
    text(page6[0], 100, height/3);
    fill(0);
    text(page6[1], 100, height/2);
}

//page 7: smiley face turns from smile to frown
function animation7() {
    ellipse(200, 200, 50, 70);
    ellipse(300, 200, 50, 70);
    //smiles at top half, frowns at bottom half of canvas
    noFill();
    strokeWeight(5);
    stroke(255);
    if (mouseY < 250) {
        arc(250, 300, 100, 50+mouseY/5, 0, PI);
    }
    else {
        arc(250, 300, 100, mouseY/5, PI, 2*PI);
    }
    strokeWeight(0);
    fill(255);
    text(page7[0], 80, 100);
}

//page 8: toaster
function animation8() {
    rectMode(CENTER);
    var toaster = 300;
    //toaster side view
    fill(220);
    rect(width/2, height/2, 200, 100);
    ellipse(170, 210, 50, 30);
    ellipse(330, 210, 50, 30);
    rect(width/2, 300, 220, 20);
    rect(350, 230, 20, 10);
    fill(128 + sin(frameCount*0.2) * 128, 0, 0);
    
    textSize(40);
    text(page8[0], 140, 100);
}

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