Final Project

I wanted to raise awareness about melting icebergs due to global warming so I created a game where a polar bear must jump on multiple floating icebergs to reach a safer large iceberg. I was inspired by games like frogger and crossy road and wanted to create an interactive easy game that would help users understand global warming better. To play the game user must press the space button to continue and press up to navigate. Land on the iceberg and you will be safe, if you land in the ocean, you will die. Make sure to move up before you drift off into the ocean. Also note that there are some weak icebergs that will break if you are unlucky. If I had more time I would work on creating levels with more iceberg rows and increasing speed of the icebergs, and maybe add more obstacles like a sea lion or natural predators of polar bears.

sketch

//code for screen changes
var currentScreen = "start";

//for the icebergs
var icebergs1 = [];
var icebergs2 = [];
var icebergs3 = [];
var icebergs4 = [];
var icebergs5 = [];
var x;

//for the movement of the game
var py = 0;
var count = 0;
var safe = true;

//for the melting icebergs
var beginIceberg = [];
var noiseParam = 0;
var noiseStep= 0.05;
var endingIceberg = [];
var noiseParam = 0;
var noiseStep= 0.05;

//for the baby polar bear location
var positionX = 250;
var positionY = 450;


function setup() {
    createCanvas(500, 500);
    text("p5.js vers 0.9.0 test.", 10, 15);
    start();
    //the initial icebergs
      for (var i = 0; i < 5; i++){
        x = 100*i;
        y = -50;
       icebergs1[i]=makeIceberg(x,y); 
      }
      for (var i = 0; i < 5; i++){
        x = 100*i;
        y = 50;
       icebergs2[i]=makeIceberg(x,y); 
      }
      for (var i = 0; i < 5; i++){
        x = 100*i;
        y = 150;
       icebergs3[i]=makeIceberg(x,y); 
      }
      for (var i = 0; i < 5; i++){
        x = 100*i;
        y = 250;
       icebergs4[i]=makeIceberg(x,y); 
      }
       
      for (var i = 0; i < 5; i++){
        x = 100*i;
        y = 350;
       icebergs5[i]=makeIceberg(x,y); 
      }
    //for the starting iceberg
      for (var i=0; i < width/5; i++){
        n=noise(noiseParam);
        value = map(n,0,1,400,450);
        beginIceberg.push(value);
        noiseParam += noiseStep;
    }

    //for the ending iceberg
     for (var i=0; i < width/5; i++){
      n=noise(noiseParam);
      value = map(n,0,1,-150,-100);
      endingIceberg.push(value);
      noiseParam += noiseStep;
    }
    
    frameRate(10);
}

function draw() {
  translate(0,py);
  //the blue ocean
  background(0,0,200);

  //the start screen
  if (currentScreen == "start"){
    start();
    if (keyIsPressed){
      currentScreen = "game";
    }
  }
  
  //plays the game screen
  else if (currentScreen == "game"){
    gameScreen();
  }
  
  //plays the lose screen
  else if (currentScreen == "lose"){
    elimination();
  }
  
  //playes the win screen
  else if (currentScreen == "win"){
    win();
  }
  

}

//Game Scene 

function gameScreen(){
  //the starting scene of the melting large iceberg
  meltingIceberg();
  
  //the icebergs
  updateAndDisplayIceberg();
  addNewIcebergs(); 
  
  //the movement of the game - to continuosly check if its on an iceberg
  if (count == 1){
      for (var i = 0; i < icebergs1.length; i++){
        if (positionX >= icebergs1[i].x & positionX + 20 <= icebergs1[i].x + icebergs1[i].width){
          positionX += 3;
          safe = true;
          break;;
        }
      }
    }
  if (count == 2){
      for (var i = 0; i < icebergs2.length; i++){
        if (positionX >= icebergs2[i].x & positionX + 20 <= icebergs2[i].x + icebergs2[i].width){
          positionX += 3;
          safe = true;
          break;
        }
      }
    }
  if (count == 3){
      for (var i = 0; i < icebergs3.length; i++){
        if (positionX >= icebergs3[i].x & positionX + 20 <= icebergs3[i].x + icebergs3[i].width){
          positionX += 3;
          safe = true;
          break;
        }
      }
    }
  if (count == 4){
      for (var i = 0; i < icebergs4.length; i++){
        if (positionX >= icebergs4[i].x & positionX + 20 <= icebergs4[i].x + icebergs4[i].width){
          positionX += 3;
          safe = true;
          break;
        }
      }
    }
  if (count == 5){
      for (var i = 0; i < icebergs5.length; i++){
        if (positionX >= icebergs5[i].x & positionX + 20 <= icebergs5[i].x + icebergs5[i].width){
          positionX += 3;
          safe = true;
          break;
        }
      }
    }
    
  if (positionX+20 > width){
    safe = false;
  }
    
  
    //if safe = false - game over
    if (safe == false){
      currentScreen = "lose";
      //noLoop()
    }
   
  //endgame
  if (count == 6){
    //display winning scene
    currentScreen = "win";
  }
 meltingIceberg2();
 
  //the baby polar bear 
  babyPolarBear();
}

//The large icebergs

function meltingIceberg(){
  fill("white");
  stroke("white");
  beginShape();
  vertex(0,height);
  
  for(i=0; i<width/5;i++){
    vertex(i*5,beginIceberg[i]);
  }
  
  vertex(width+50,height);
  endShape(CLOSE); 
  n=noise(noiseParam);
  value = map(n,0,1,400,450);
  beginIceberg.shift();
  beginIceberg.push(value);
  noiseParam += noiseStep;
}

function meltingIceberg2(){
 //The ending scene is a melting iceberg with the mother polar bear
  fill("white");
  stroke("white");
  beginShape();
  vertex(0,-600);
  
  for(i=0; i<width/5;i++){
    vertex(i*5,endingIceberg[i]);
  }
  
  vertex(width+50,-600);
  endShape(CLOSE); 
  n=noise(noiseParam);
  value = map(n,0,1,-150,-100);
  endingIceberg.shift();
  endingIceberg.push(value);
  noiseParam += noiseStep;
}


//code to do the jumps

//to draw baby polar bear and its respective movements (initally just a square, will later create details) 

function babyPolarBear(){
  fill("red");
  rect(positionX, positionY, 20,20); //might need to fix size later 
}

function keyPressed(){
  if (keyCode == UP_ARROW & currentScreen == "game"){
      py+=100;
      positionY -= 100;
      count++;
      safe = false;
      gameScreen();
    }
}

//object creation of the icebergs

function makeIceberg(x,y){
  var ice = {
    x,
    y,
    height: 25,
    width: floor(random(40,60)),
    speed: 3, 
    display: displayIceberg,
    move:moveIceberg
  }
  return ice;  
  }
 
 function displayIceberg(x,y){
   fill("white");
   rect(this.x,this.y,this.width,this.height);
 }   
 
 function moveIceberg(x){
   this.x+=this.speed;
 } 
 
 function updateAndDisplayIceberg(){
   for(var i = 0; i < icebergs1.length; i++){
     icebergs1[i].move();
     icebergs1[i].display();
   }
   for(var i = 0; i < icebergs2.length; i++){
     icebergs2[i].move();
     icebergs2[i].display();
   }
   for(var i = 0; i < icebergs3.length; i++){
     icebergs3[i].move();
     icebergs3[i].display();
   }
   for(var i = 0; i < icebergs4.length; i++){
     icebergs4[i].move();
     icebergs4[i].display();
   }
   for(var i = 0; i < icebergs5.length; i++){
     icebergs5[i].move();
     icebergs5[i].display();
   }
 }
   
 function addNewIcebergs(){ //should I change this to different logic?
   var newIcebergLikelihood = 0.05;
   var x = -40;
   if (random(0,1) < newIcebergLikelihood){
     icebergs1.push(makeIceberg(x,350));
   }
   if (random(0,1) < newIcebergLikelihood){
     icebergs2.push(makeIceberg(x,250));
   }
   if (random(0,1) < newIcebergLikelihood){
     icebergs3.push(makeIceberg(x,150));
   }
   if (random(0,1) < newIcebergLikelihood){
     icebergs4.push(makeIceberg(x,50));
   }
   if (random(0,1) < newIcebergLikelihood){
     icebergs5.push(makeIceberg(x,-50));
   }
 }
 

//Code to implement width

function icebergWidth(){
  return this.x + this.width;
}



//starting scene - instructions stuff - press space to continue
function start(){
  fill("green");
  rect(0,0,width,height);
  textSize(15);
  fill("white");
  text("Welcome to Save the POLAR BEAR from Global Warming", 50 ,200);
  textSize(15);
  fill("white");
  text("Press Space to Continue", 50,260);
  textSize(15);
  fill("white");
  let word = 'Instructions: Press the up key to move the polar bear (the red square) forward. Land on the iceberg and you will be safe, if you land in the ocean, you will die. Make sure to move up before you drift off into the ocean. Also note that there are some icebergs that are hidden if you are lucky and some weak icebergs that will break if you are unlucky. Can you reach the safe iceberg?'
  text(word,50,280, 400,200);
}

//The winning scene
function win(){
  fill("yellow");
  rect(0,0 - 100* count,width,height);
  textSize(50);
  fill("black");
  text("You have Won", 50 ,250 - 100* count);
  textSize(20);
  fill("black");
  text("Reload page to play again", 250,290 - 100* count);
}

// elimination scene 

function elimination(){
  fill("black");
  rect(0 ,0 - 100* count,width,height);
  textSize(50);
  fill("white");
  text("You have LOST", 50 ,250 - 100* count);
  textSize(20);
  fill("white");
  text("Reload page to play again", 250,290 - 100* count);
  
}


Final Project

sketch

var lines = []; // array of lines
var PGHannualAvg = [50.0, 50.4, 51.7, 49.0, 51.9, 53.8, 53.6, 52.6, 54.2, 54.5, 53.2, 52.3, 54.2, 51.2, 52.9, 54.1, 51.7, 53.4, 54.1, 53.8, 52.1, 51.6, 54.5, 52.3, 53.3, 53.3, 54.6, 53.6, 54.7, 52.6, 53.2, 52.9, 51.2, 52.0, 52.8, 50.7, 53.2, 52.2, 51.9, 53.7, 50.9, 53.6, 51.7, 52.0, 51.9, 49.3, 52.7, 53.3, 51.4, 55.4, 52.6, 50.3, 52.4, 50.8, 52.8, 51.6, 51.7, 53.1, 54.7, 53.5, 53.6, 52.6, 52.1, 51.0, 51.0, 53.0, 52.8, 49.6, 52.3, 51.6, 50.7, 52.0, 51.6, 53.6, 51.4, 52.4, 54.2, 51.1, 52.3, 52.9, 53.0, 51.8, 51.7, 51.0, 51.5, 48.8, 51.8, 49.1, 50.0, 49.4, 48.2, 51.1, 50.4, 50.1, 50.3, 49.1, 49.7, 50.7, 50.8, 49.9, 52.5, 51.4, 51.1, 48.0, 49.3, 49.7, 49.4, 49.5, 49.1, 50.4, 50.5, 50.4, 50.6, 51.7, 52.3, 51.0, 50.2, 53.3, 54.2, 50.9, 51.8, 51.6, 51.8, 50.3, 50.0, 54.0, 52.0, 50.8, 52.2, 52.6, 50.3, 51.6, 51.6, 52.3, 52.0, 50.9, 51.0, 51.9, 52.8, 54.2, 51.5, 50.0, 52.5, 54.2, 53.6, 52.3, 52.4, 53.3]
var Year = [];
var numLines = PGHannualAvg.length; // number of lines total
var lineWidth = 800/numLines; // width of lines

function preload() { // loads font info
    helveticaBold = loadFont('HelveticaNeueBold.ttf');
    helveticaUltraLight = loadFont('HelveticaNeueUltraLight.ttf');
    helveticaUltraLightObl = loadFont('HelveticaNeueUltraLightItal.ttf');
    helveticaLight = loadFont('HelveticaNeueLight.ttf');
    for (var i = 0; i < numLines; i++) { // pushes consecutive year info to year array
        Year.push(1872 + i);
    }
}

function setup() {
    createCanvas(800, 400);
    background(220);
    useSound();
}

function soundSetup() { // oscillator setup
    osc = new p5.Oscillator();
    osc.amp(0.25);
    osc.setType(sin);
    osc.start();
}

function makeLines() { // line object constructor
    for (i = 0; i < numLines; i++) {
        lines[i] = { x: i*lineWidth, y: height,
        temp: PGHannualAvg[i], draw: drawLines, c: chooseColor }
    }
}

function drawLines(line) { // function to draw lines
    noStroke();
    fill(this.c());
    rect(this.x, 0, lineWidth, this.y);
}

function chooseColor() { // if statements choosing colors based on temp array value
    if (this.temp <= 49.0) {
        return (color(0, 116, 255));
    }
    if (this.temp > 49.0 & this.temp <= 49.5) {
        return (color(5, 4, 254));
    }
    if (this.temp > 49.5 & this.temp <= 50.0) {
        return (color(82, 82, 254));
    }
    if (this.temp > 50.0 & this.temp <= 50.5) {
        return (color(126, 125, 253));
    }
    if (this.temp > 50.5 & this.temp <= 51.0) {
        return (color(183, 183, 255));
    }
    if (this.temp > 51.0 & this.temp <= 51.5) {
        return (color(251, 245, 133));
    }
    if (this.temp > 51.5 & this.temp <= 52.0) {
        return (color(249, 221, 13));
    }
    if (this.temp > 52.0 & this.temp <= 52.5) {
        return (color(254, 202, 5));
    }
    if (this.temp > 52.5 & this.temp <= 53.0) {
        return (color(254, 88, 2));
    }
    if (this.temp > 53.0 & this.temp <= 53.5) {
        return (color(234, 2, 0));
    }
    if (this.temp > 53.5) {
        return (color(133, 0, 0));
    }
}

function playSound() { // chooses oscillator frequency based on mouse index line
    var mInd = int(mouseX / lineWidth);
    osc.freq(chooseSound(PGHannualAvg[mind]));
}

function chooseSound(temp) { // if statements based on temperature index
    if (temp <= 49.0) {
        return (70);
    }
    if (temp > 49.0 & temp <= 49.5) {
        return (80);
    }
    if (temp > 49.5 & temp <= 50.0) {
        return (120);
    }
    if (temp > 50.0 & temp <= 50.5) {
        return (160);
    }
    if (temp > 50.5 & temp <= 51.0) {
        return (200);
    }
    if (temp > 51.0 & temp <= 51.5) {
        return (240);
    }
    if (temp > 51.5 & temp <= 52.0) {
        return (280);
    }
    if (temp > 52.0 & temp <= 52.5) {
        return (320);
    }
    if (temp > 52.5 & temp <= 53.0) {
        return (360);
    }
    if (temp > 53.0 & temp <= 53.5) {
        return (400);
    }
    if (temp > 53.5) {
        return (440);
    } 
}

function drawTitle() { // draws black bar and title text
    rect(0, 325, 800, 100);
    fill(255);
    textSize(18);
    textFont(helveticaBold);
    text("1872", 10, 350);
    text("2020", 748, 350);
    stroke(255);
    line(61, 343, 738, 343);
    line(732, 337, 738, 343);
    line(732, 349, 738, 343);
    noStroke();
    text("Annual Average Temperatures: Pittsburgh", 235, 375);
}

function showMouseInfo() { // black hover rectangle with bar info
    var mInd = int(mouseX / lineWidth);
    noStroke();
    fill(255);
    if ((mouseY < 325) & (mouseX > 0) && (mouseX < width) && (mouseY > 0)) {
        noFill();
        stroke(255);
        strokeWeight(2);
        rect(mInd*lineWidth, 0, lineWidth, 325);
        if (mouseX < 725) {
            noStroke();
            fill(0);
            rect(mouseX + 20, mouseY, 65, 40);
            fill(255);
            textFont(helveticaBold);
            text(Year[mInd], mouseX+25, mouseY+18);
            textFont(helveticaLight);
            text(PGHannualAvg[mInd]+"°F", mouseX+25, mouseY+34);
        }
        else {
            noStroke();
            fill(0);
            rect(mouseX - 70, mouseY, 65, 40);
            fill(255);
            textFont(helveticaBold);
            text(Year[mInd], mouseX- 65, mouseY+18);
            textFont(helveticaLight);
            text(PGHannualAvg[mInd]+"°F", mouseX-65, mouseY+34);            
        }
    }
}

function draw() { // main draw function
    background(0);
    noStroke();
    makeLines();
    for (i = 0; i < numLines; i++) {
        lines[i].draw();
        fill(0);
    }
    drawTitle();
    showMouseInfo();
    var mInd = int(mouseX / lineWidth);
    osc.freq(chooseSound(PGHannualAvg[mInd]));
}

My program is a data visualization of Pittsburgh’s fluctuating average annual temperatures over time. I took data from the historical records of the Pittsburgh International Airport weather station from 1872 through 2020. Each of the colored bars represent a year and its average temperature. The colors represent the temperatures–the warmer the color, the hotter the temperature, and vice versa. The user can use their mouse cursor to hover over the bars and view information for that particular one–the year and temperature from that year. There is also an aspect of sound–the temperatures relate to a frequency level that plays when the user hovers over the bar. The higher the temperature, the higher the frequency that is played.

Note: I used external fonts uploaded via local files and displayed using a local server, but I’m not sure how to upload those so that WordPress can run them. I tried Imgur but they don’t support TrueType font files.

Final Project

sketch

//jlococo
//Jacky Lococo

var xp = 0;
var yp = 40;
var dxp = 5;
var bird = [ ];
var xcir = 350;
var ycir = 200;
var angle = 0;
var smoke = [ ];
var cloud = [ ];
var tree = [ ];
function setup() {
    createCanvas(700, 400);

    for (var i = 0; i <5; i++){ //for loop for the bird array
        bird[i] = new Object();
        bird[i].x = width;
        bird[i].y  = random(100, 200);
        bird[i].dx = random(-2, -4.5);
        bird[i].c = color(21, 76, 114);
    }

    for (var i = 0; i < 11; i++){ //for loop for the smoke array
        smoke[i] = new Object();
        smoke[i].x = random(40, 140);
        smoke[i].y  = random(0, 100);
        smoke[i].dx = 4;
        smoke[i].s = random(20, 35);
        smoke[i].c = 150;
    }

    for (var i = 0; i < 9; i++){ //for loop for the clouds
        cloud[i] = new Object();
        cloud[i].x = random(width/2 + 60, width);
        cloud[i].y  = random(0, height/2 - 30);
        cloud[i].dx = 4;
        cloud[i].s = random(70, 120);
        cloud[i].c = 230;
    }

    for (var i = 0; i < 20; i++){ //for loop for the trees
        tree[i] = new Object();
        tree[i].x = random(width/2 + 60, width);
        tree[i].y  = random(height/2 + 135, height);
        tree[i].s = random(70, 120);
    }

    frameRate(15);
}



function draw() {
    background(230);
 
 //------------------ CITY ------------------
    //background of city
    noStroke();
    fill(230);
    beginShape();
    vertex(0,0);
    vertex(0, height);
    vertex(width/2-20, height);
    vertex(width/2+20, 0);
    endShape();

    //smokestacks
    fill(200);
    rect(50, 100, 25, 300);
    rect(100, 100, 25, 300);

    //drawing the smoke
    for (var i = 0; i < 11; i++){
        draw_smoke(smoke[i]);
    }

    //2nd row of buildings
    fill(170);
    rect(50, 220, 100, 300);
    rect(140, 200, 100, 300);
    rect()

    //buildings front row
    noStroke()
    fill(90);
    rect(0, 200, 100, 420);
    rect(100, 240, 75, 420);
    rect(175, 180, 45, 300);
    rect(220, 200, 50, 300);
    rect(260, 300, 80, 200);

    //windows
    if(mouseX < width/2){ //makes the lights turn on and off
        fill(241, 216, 3, 150);
    } else {
        fill(230); //fills them with the background when mouse is on right
    }
    rect(220, 220, 10, 20);
    rect(247, 270, 10, 20);
    rect(220, 340, 10, 20);
    rect(150, 300, 10, 20);
    rect(110, 275, 10, 20);
    rect(45, 370, 10, 20);
    rect(33, 230, 10, 20);


    //moving plane in the background
    airPlane(xp, yp, dxp);
    xp +=dxp;


//--------------- FOREST -------------------
    //background of forest
    noStroke();
    fill(185, 220, 236);
    beginShape();
    vertex(width/2-20, height);
    vertex(width/2+20, 0);
    vertex(width, 0);
    vertex(width, height);
    endShape();

    //clouds
    for (var i = 0; i < 9; i++){
        draw_cloud(cloud[i]);
    }

    //MOUNTAINS
    fill(137, 184, 206);
    //first larger shape
    beginShape();
    vertex(width/2+30, height);
    vertex(550, 150);
    vertex(600, 150);
    vertex(700, 300);
    vertex(700, height);
    endShape();
    //second shape shorter mountain
    beginShape();
    vertex(width/2-20, height);
    vertex(430, 240);
    vertex(480, 240);
    vertex(550, height);
    endShape();
    //circles rounding mountains
    ellipse(575, 161, 54, 54);
    ellipse(455, 250, 53, 52);

    //HILL behind - darker shade
    beginShape()
    fill(88, 106, 36);
    vertex(width/2-20, height);
    vertex(width/2-10, 280);
    vertex(600, 400)
    endShape()

    //HILL - quarter of circle
    fill(127, 148, 68);
    ellipse(670, height+70, 730, 350);

    //trees
    for (var i = 0; i < 20; i++){ //for loop for the trees
        draw_tree(tree[i]);
    }

    //birds
    for (var i = 0; i < 5; i++) {
        draw_bird(bird[i]);
        if (bird[i].x < width/2){ //changing bird location after they reach midpoint
            bird[i].x = width +100;
        }
        bird[i].x += bird[i].dx; //making birds move

        if (mouseX < width/2){ //making the birds stop when mouse is on city half
            bird[i].dx = 0
        }else{
            bird[i].dx = random(-1, -4.5);
        }
        if(mouseIsPressed & dist(mouseX, mouseY, xcir, ycir) < 30){ //making birds stop with circle pressed
            bird[i].dx = 0;
        }
    }

//------------------

    //FOREST OPACITY FILLS
    if(mouseX < width/2){
        noStroke();
        fill(0, 100);
        beginShape();
        vertex(width/2-20, height);
        vertex(width/2+20, 0);
        vertex(width, 0);
        vertex(width, height);
        endShape();
    }

    //masking shape
    fill(230);
    beginShape();
    vertex(width/2+10, 80);
    vertex(width/2-5, 230);
    vertex(300, 230);
    vertex(300, 80);
    endShape();

    //OPACITY FILLS CITY AND VELOCITY STOPS
    if(mouseX > width/2){
        noStroke();
        fill(0, 100);
        beginShape();
        vertex(0,0);
        vertex(0, height);
        vertex(width/2-20, height);
        vertex(width/2+20, 0);
        endShape();
        dxp = 0;
    } else {
        dxp = 5;
    }
    if(xp > width/2 +30){
        xp = 0 - 50;
    }


    //Lines and circle
    fill(100, 150);
    stroke(255);
    strokeWeight(4);
    line(width/2+20, 0, width/2-20, 400);
    ellipse(xcir, ycir, 60, 60);
    noStroke();
    fill(255);
    textSize(10);
    text('P R E S S', xcir-23, ycir+4);


    //CURSOR - icons following the mouse
    if(mouseX > width/2){ //mouse is flower on forest section
        noStroke();
        flower();
    } else { //mouse is three little grey smoke dots
        noStroke();
        fill(50, 100);
        ellipse(mouseX + 9, mouseY +5, 11, 11);
        ellipse(mouseX - 9, mouseY+5, 11, 11);
        ellipse(mouseX, mouseY - 8, 11, 11);
    }

    //CIRCLE MOUSE PRESSED - if mouse is pressed on cirlce fact shows up
    if(mouseIsPressed & dist(mouseX, mouseY, xcir, ycir) < 30){
        fill(0, 150);
        rect(0, 0, 700, 400);
        dxp = 0;
    fill(255)
        textSize(15)
        text('Urban areas and urbanization is a major contributor of climate change,', 140, 100)
        text('making up baout 75% of CO2 emissions from global energy use.', 150, 130)
    }
}



//------------ FUNCTIONS -----------
function flower(){ //creates cursor flower
    fill(233, 199, 10, 200);
    ellipse(mouseX, mouseY, 15, 15);
    fill(255, 154, 154, 200);
    ellipse(mouseX+10, mouseY, 8, 8);
    ellipse(mouseX-10, mouseY, 8, 8);
    ellipse(mouseX, mouseY-10, 8, 8);
    ellipse(mouseX, mouseY+10, 8, 8);
    ellipse(mouseX+7, mouseY+7, 8, 8);
    ellipse(mouseX-7, mouseY-7, 8, 8);
    ellipse(mouseX-7, mouseY+7, 8, 8);
    ellipse(mouseX+7, mouseY-7, 8, 8);
}

function airPlane(xp, yp, dxp){ //creates airplane moving in the background
    fill(200);
    rect(xp, yp, 40, 10);
    ellipse(xp+40, yp+5, 15,10);
    ellipse(xp, yp, 5, 20);
    fill(175);
    ellipse(xp+ 15, yp+7, 23, 5);
    strokeWeight(2);
    stroke(220, 180);
    line(xp, yp+10, xp-150, yp+10);
}

function draw_tree(t){
    fill(0);
    rect(t.x, t.y, 5, 10);
    fill(63, 111, 85);
    triangle(t.x +2, t.y-10, t.x - 5, t.y+5, t.x+10, t.y+5);
}

function draw_bird(b){
    fill(b.c);
    ellipse(b.x, b.y, 10, 10);
    fill(214, 216, 3);
    ellipse(b.x -6, b.y, 4, 4);
    fill(13, 39, 56);
    ellipse(b.x + 4, b.y, 7, 5);
}

function draw_smoke(s){
    fill(s.c, 160);
    circle(s.x, s.y, s.s);
}

function draw_cloud(c){
    fill(c.c, 150);
    circle(c.x, c.y, c.s);
}


    







``

14 – Final Project

sketch

//bgoeke Sec. B Final Project

var gravity = 0.3;   // downward acceleration
var spring = 0.7; // how much velocity is retained after bounce
var drag = 0.0001;    // drag causes particles to slow down
var np = 0;      // how many particles
var rpx = [];
var rpy = [];
var rpc = 10000;
var count = 0;

function preload() {
	gas = loadImage("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/12/greenhousegas.png")
	plant = loadImage("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/12/plant1.png")
	bin = loadImage("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/12/rcbin2.png")

}
 
function particleStep() {
    this.age++;
    this.x += this.dx;
    this.y += this.dy;
    if (this.x > width - 80 & this.y > height - 100) { // bounce off right wall
        this.x = (width - 80) - (this.x - (width-80));
        this.dx = 0;
    } else if (this.x < 0) { // bounce off left wall
        this.x = -this.x;
        this.dx = -this.dx * spring;
    }

    if (this.x < width - 180 & this.y > height - 100) { // bounce off right wall
        this.x = (width) - (this.x - (width));
        this.dx = 0;
    }


    if (this.y > height-20) { // bounce off bottom
        this.y = (height-20) - (this.y - (height-20));
        this.dy = 0;
    } else if (this.y < 0) { // bounce off top
        this.y = -this.y;
        this.dy = -this.dy * spring;
    }

    //deals with repeler
    var rpx = mouseX
    var rpy = mouseY
    	var dp = dist(this.x, this.y, rpx, rpy);
    	var f = rpc / (Math.pow(dp , 2));
    	var dirx = (this.x - rpx) / dp;
    	var diry = (this.y - rpy) / dp;
    	this.x += f * dirx;
    	this.y += f * diry;

    	this.dy = this.dy + gravity; // force of gravity
    // drag is proportional to velocity squared
    // which is the sum of the squares of dx and dy
    var vs = Math.pow(this.dx, 2) + Math.pow(this.dy, 2);
    // d is the ratio of old velocty to new velocity
    var d = vs * drag;
    // d goes up with velocity squared but can never be
    // so high that the velocity reverses, so limit d to 1
    d = min(d, 1);
    // scale dx and dy to include drag effect
    this.dx *= (1 - d);
    this.dy *= (1 - d);
}


 
 
function particleDraw() {
    image(bin,180,290,210,120);
    image(gas, this.x, this.y, 40, 40);
}
 
 
// create a "Particle" object with position and velocity
function makeParticle(px, py, pdx, pdy) {
    p = {x: px, y: py,
         dx: pdx, dy: pdy,
         age: 0,
         stepFunction: particleStep,
         drawFunction: particleDraw
        }
    return p;
}




    function countParticle() {
        count ++
        //count = (count);
    }

    function gameOver() {
        if (int(count/1000) > 80) {
            rect(width/2, height/2, width, height);
            textSize(60);
            text('YOU WIN !', 10, height/2)
            textSize(40);
            text(int((millis())/1000), 100, 250);
            text('seconds', 155, 250);
            noLoop();
    }

    }



 
var particles = [];
 
 
function setup() {
    createCanvas(400, 400);
    frameRate(10);

}
 
 
// draw all particles in the particles array
//
function draw() {
    background('lightblue');
    noStroke();
    fill(80);
    ellipse(80,100,160,50);
    ellipse(250,20,350,60);
    ellipse(100,100,100,50);
    stroke(0);
    strokeWeight(1);
    fill(255,10,5);
    textSize(15);
    text('How Fast Can You Get Rid Of The Gas?', 120,20)
    fill(0,255,0);
    rectMode(CENTER);
    textSize(50);
    text(int(count/1000), 10, height/2);

    image(plant,mouseX,mouseY,80,80);
    var newp = makeParticle(50, 50,
                                random(-10, 10), random(-10, 0));
        particles.push(newp);

    stroke(0);
    strokeWeight(10);
    newParticles = [];


    //if (mouseIsPressed) {
        //var newp = makeParticle(mouseX, mouseY,
                                //random(-10, 10), random(-10, 0));
        //particles.push(newp);
    //}
 
    // newParticles will hold all the particles that we want to
    // retain for the next call to draw() -- we will retain particles
    // if the age is < 200 (frames). Initially, newParticle is empty
    // because we have not found any "young" particles yet.

    for (var i = 0; i < particles.length; i++) { // for each particle
        var p = particles[i];
        p.stepFunction();
        p.drawFunction();

        if (p.y > height - 80 & p.x > width-180 && p.x < width-80) {
            newParticles.push(p);
            countParticle()
        }

        // since we are "looking" at every particle in order to
        // draw it, let's use the opportunity to see if particle[i]
        // is younger than 200 frames. If so, we'll push it onto the
        // end of newParticles.
        if (p.age < 3000) {
            newParticles.push(p);
        }
    }

    gameOver();
   
    // now, newParticles has EVERY particle with an age < 200 frames.
    // these are the particles we want to draw next time, so assign
    // particles to this new array. The old value of particles, i.e.
    // the entire array, is simply "lost" -- Javascript will reclaim
    // and reuse the memory since that array is no longer needed.
    particles = newParticles;



}

For my program I wanted to create a falling game where you can manipulate multiple objects to get them in some sort of cup or final destination. In this game you use the plant as a repeler to direct the bad greenhouse gasses into the recycling bin. The goal is to get the counter to eighty and there’s some bonuses when you use the plant to bounce the gas around quicker. At eighty the game stops and gives you the time it took to finish the game. The ultimate competition in the game is to get the time as quickly as you can. The best time I got was 15 seconds. If I had some more time I wanted to make it so the recycling bin actually gets filled up with gases and overfills. I would’ve also liked to make more levels where there are existing obstacles that you have to get around with the plant.

14 – Final Project

sketch

//bgoeke Sec. B Final Project

var gravity = 0.3;   // downward acceleration
var spring = 0.7; // how much velocity is retained after bounce
var drag = 0.0001;    // drag causes particles to slow down
var np = 0;      // how many particles
var rpx = [];
var rpy = [];
var rpc = 10000;
var count = 0;

function preload() {
	gas = loadImage("http://localhost:8080/greenhousegas.png")
	plant = loadImage("http://localhost:8080/plant1.png")
	bin = loadImage("http://localhost:8080/rcbin2.png")

}
 
function particleStep() {
    this.age++;
    this.x += this.dx;
    this.y += this.dy;
    if (this.x > width - 80 & this.y > height - 100) { // bounce off right wall
        this.x = (width - 80) - (this.x - (width-80));
        this.dx = 0;
    } else if (this.x < 0) { // bounce off left wall
        this.x = -this.x;
        this.dx = -this.dx * spring;
    }

    if (this.x < width - 180 & this.y > height - 100) { // bounce off right wall
        this.x = (width) - (this.x - (width));
        this.dx = 0;
    }


    if (this.y > height-20) { // bounce off bottom
        this.y = (height-20) - (this.y - (height-20));
        this.dy = 0;
    } else if (this.y < 0) { // bounce off top
        this.y = -this.y;
        this.dy = -this.dy * spring;
    }

    //deals with repeler
    var rpx = mouseX
    var rpy = mouseY
    	var dp = dist(this.x, this.y, rpx, rpy);
    	var f = rpc / (Math.pow(dp , 2));
    	var dirx = (this.x - rpx) / dp;
    	var diry = (this.y - rpy) / dp;
    	this.x += f * dirx;
    	this.y += f * diry;

    	this.dy = this.dy + gravity; // force of gravity
    // drag is proportional to velocity squared
    // which is the sum of the squares of dx and dy
    var vs = Math.pow(this.dx, 2) + Math.pow(this.dy, 2);
    // d is the ratio of old velocty to new velocity
    var d = vs * drag;
    // d goes up with velocity squared but can never be
    // so high that the velocity reverses, so limit d to 1
    d = min(d, 1);
    // scale dx and dy to include drag effect
    this.dx *= (1 - d);
    this.dy *= (1 - d);
}


 
 
function particleDraw() {
    image(bin,180,290,210,120);
    image(gas, this.x, this.y, 40, 40);
}
 
 
// create a "Particle" object with position and velocity
function makeParticle(px, py, pdx, pdy) {
    p = {x: px, y: py,
         dx: pdx, dy: pdy,
         age: 0,
         stepFunction: particleStep,
         drawFunction: particleDraw
        }
    return p;
}




    function countParticle() {
        count ++
        //count = (count);
    }

    function gameOver() {
        if (int(count/1000) > 80) {
            rect(width/2, height/2, width, height);
            textSize(60);
            text('YOU WIN !', 10, height/2)
            textSize(40);
            text(int((millis())/1000), 100, 250);
            text('seconds', 155, 250);
            noLoop();
    }

    }



 
var particles = [];
 
 
function setup() {
    createCanvas(400, 400);
    frameRate(10);

}
 
 
// draw all particles in the particles array
//
function draw() {
    background('lightblue');
    noStroke();
    fill(80);
    ellipse(80,100,160,50);
    ellipse(250,20,350,60);
    ellipse(100,100,100,50);
    stroke(0);
    strokeWeight(1);
    fill(255,10,5);
    textSize(15);
    text('How Fast Can You Get Rid Of The Gas?', 120,20)
    fill(0,255,0);
    rectMode(CENTER);
    textSize(50);
    text(int(count/1000), 10, height/2);

    image(plant,mouseX,mouseY,80,80);
    var newp = makeParticle(50, 50,
                                random(-10, 10), random(-10, 0));
        particles.push(newp);

    stroke(0);
    strokeWeight(10);
    newParticles = [];


    //if (mouseIsPressed) {
        //var newp = makeParticle(mouseX, mouseY,
                                //random(-10, 10), random(-10, 0));
        //particles.push(newp);
    //}
 
    // newParticles will hold all the particles that we want to
    // retain for the next call to draw() -- we will retain particles
    // if the age is < 200 (frames). Initially, newParticle is empty
    // because we have not found any "young" particles yet.

    for (var i = 0; i < particles.length; i++) { // for each particle
        var p = particles[i];
        p.stepFunction();
        p.drawFunction();

        if (p.y > height - 80 & p.x > width-180 && p.x < width-80) {
            newParticles.push(p);
            countParticle()
        }

        // since we are "looking" at every particle in order to
        // draw it, let's use the opportunity to see if particle[i]
        // is younger than 200 frames. If so, we'll push it onto the
        // end of newParticles.
        if (p.age < 3000) {
            newParticles.push(p);
        }
    }

    gameOver();
   
    // now, newParticles has EVERY particle with an age < 200 frames.
    // these are the particles we want to draw next time, so assign
    // particles to this new array. The old value of particles, i.e.
    // the entire array, is simply "lost" -- Javascript will reclaim
    // and reuse the memory since that array is no longer needed.
    particles = newParticles;



}

For my program I wanted to create a falling game where you can manipulate multiple objects to get them in some sort of cup or final destination. In this game you use the plant as a repeler to direct the bad greenhouse gasses into the recycling bin. The goal is to get the counter to eighty and there’s some bonuses when you use the plant to bounce the gas around quicker. At eighty the game stops and gives you the time it took to finish the game. The ultimate competition in the game is to get the time as quickly as you can. The best time I got was 15 seconds. If I had some more time I wanted to make it so the recycling bin actually gets filled up with gases and overfills. I would’ve also liked to make more levels where there are existing obstacles that you have to get around with the plant.

Final project

sketch

var x= 30;
var xPos = 0;
var y = 60
var r = [55, 98, 145, 195] //radius of visualization 1
var angle =10
var cycle = 1; //cycle through the different visualizations
var transparent =100 //used for key
var value = 0
var yr = 1980

//precipitation data
var precip1 = [39.46, 37.5, 32.01, 41.41, 35.32, 38.51, 37.4, 39.2, 
            27.09, 42.51]

var precip2 = [52.24, 32.02, 36.65, 38.26, 41.34, 28.89, 45.47, 34.21,
            36.21, 40.12]

var precip3 = [35.73, 32.33, 41.04, 57.41, 41.23, 34.90,40.70, 39.69, 32.84, 
            37.85]

var precip4 = [44.24, 41.74, 36.65, 36.84, 40.56, 35.01, 42.15, 57.83, 52.46, 39.33]
//used for text in vizualization 1
precipData = [39.46, 37.5, 32.01, 41.41, 35.32, 38.51, 37.4, 39.2, 
            27.09, 42.51, 52.24, 32.02, 36.65, 38.26, 41.34, 28.89, 45.47, 34.21,
            36.21, 40.12,35.73, 32.33, 41.04, 57.41, 41.23, 34.90,40.70, 39.69, 32.84, 
            37.85, 44.24, 41.74, 36.65, 36.84, 40.56, 35.01, 42.15, 57.83, 52.46, 39.33]

var precipitation = []
var precipitation2 = []
var precipitation3 = []
var precipitation4 = []

//temperature data
var temp = [49.5, 49.1, 50.4, 50.5, 50.4, 50.6, 51.7, 52.3, 51.0, 50.2, 53.3, 54.2, 50.9, 
            51.8, 51.6, 51.8, 50.3, 50, 54, 52, 50.8, 52.2, 52.6, 50.3, 51.6, 51.6, 52.3,
            52, 50.9, 51, 51.9, 52.8, 54.2, 51.5, 50, 52.5, 54.2, 53.6, 52.3, 52.4, 53.3 ]

//images
var skyline;
var backdrop;
var buildings;

var snow = []

function preload() {
    skyline = loadImage("https://i.imgur.com/U7UJvXu.png")
    backdrop = loadImage("https://i.imgur.com/vShIEDi.png")
    buildings = loadImage("https://i.imgur.com/dfPYkth.png")
}

function setup() {
    createCanvas(480, 480);
    background(220);

     for (var i = 0; i < 10; i++) {
        precipitation[i] = new Object();
        precipitation[i].x = r[0] * sin(angle);
        precipitation[i].y = r[0] * cos(angle);
    }

    for (var i = 0; i < 10; i++) {
        precipitation2[i] = new Object();
        precipitation2[i].x = r[1] * sin(angle);
        precipitation2[i].y = r[1] * cos(angle);
    }

     for (var i = 0; i < 10; i++) {
        precipitation3[i] = new Object();
        precipitation3[i].x = r[2] * sin(angle);
        precipitation3[i].y = r[2] * cos(angle);
    }

     for (var i = 0; i < 10; i++) {
        precipitation4[i] = new Object();
        precipitation4[i].x = r[3] * sin(angle);
        precipitation4[i].y = r[3] * cos(angle);
    }

       for (var i = 0; i < 500; i++) {
        snow[i] = new Object();
        snow[i].x = random(30, width-30)
        snow[i].y = random(60, 300)
        snow[i].dy = 1;
    }

}

function draw() { //cycles through the different climate patterns
    if (cycle == 1) {
        introduction()
    } else if (cycle == 2) {
        drawPrecipitation()
    } else if (cycle ==3) {
        drawTemp()
    } else if (cycle == 4) {
        drawSnowRecord()
    } else {
         cycle = 1
    }
}
function introduction() { //first slide
    background(0)
    fill(255)
    textSize(15)
    text("Data Visualizations on Climate Patterns in Pittsburgh", 10, height/2)
    textSize(12)
    text("Click mouse to change data", 10, height/2+20)
}
function drawPrecipitation() {
    background(255, 229, 227)
    fill(0)
    textSize(15)
    text("Average Precipitation in Pittsburgh (1980-2020)", 10, 25)
    frameRate(int(1.5))
    noStroke()

//bottom left key
    fill(214, 132, 84, 100)
    rect(10, 420, 30, 10)

    fill(214, 132, 84, 100-15)
    rect(10, 431, 30, 10)

    fill(214, 132, 84, 100-30)
    rect(10, 442, 30, 10)

    fill(214, 132, 84, 100-45)
    rect(10, 453, 30, 10)
       
    textSize(8)
    fill(0)
    text("1980-1990", 45, 427)
    text("1990-2000", 45, 427+11)
    text("2000-2010", 45, 427+22)
    text("2010-2020", 45, 427+33)

    translate(width/2, height/2+15)

    fill(214, 132, 84, 60)
    noStroke()
    circle(0, 0, 150)
    circle(0, 0, 240)
    circle(0, 0, 337)
    circle(0, 0, 440)
    fill(214, 132, 84, 50)
    circle(0, 0, 70)


//ring of ellipses
    for (var i=0; i<precip1.length; i++) {
        noStroke()
        fill(0, 255-precip1[i]*3, precip1[i]*4)
        rotate(radians(360/10))
        circle(precipitation[i].x, precipitation[i].y, precip1[i]/1.4)
    }

      for (var i=0; i<precip2.length; i++) {
        var x = r[1] * sin(angle);
        var y = r[1] * cos(angle);
        noStroke()
        fill(0, 255-precip2[i]*3, precip2[i]*4)
        rotate(radians(360/10))
        circle(precipitation2[i].x, precipitation2[i].y, precip2[i]/1.4) //change to object
    }

      for (var i=0; i<precip3.length; i++) {
        var x = r[2] * sin(angle);
        var y = r[2] * cos(angle);
        noStroke()
        fill(0, 255-precip3[i]*3, precip3[i]*4)
        rotate(radians(360/10))
        circle(precipitation3[i].x, precipitation3[i].y, precip3[i]/1.4)
    }

      for (var i=0; i<precip4.length; i++) {
        var x = r[3] * sin(angle);
        var y = r[3] * cos(angle);
        noStroke()
        fill(0, 255-precip4[i]*3, precip4[i]*4)
        rotate(radians(360/10))
        circle(precipitation4[i].x, precipitation4[i].y, precip4[i]/1.4)
    }

    
    textSize(10)
    text(precipData[value], -10, 10)
    value+=1

    if (value>40) {
        value=0
    }
    textSize(15)
    text(yr, -15, 0)
    yr+=1

    if (yr >2020) {
        yr=1980
    }
}


function drawTemp() {
    background(235, 88, 52)
    textSize(15)
    fill(0)
    text("Average Temperature in Pittsburgh (1980-2020)", 10, 25)
    frameRate(25)

    translate(width/2,height/2)
    //background circles
    fill(255, 255, 255, 70)
    circle(0, 0, 400, 400)
    fill(235, 88, 52)
    circle(0, 0, 150, 150)
    //rotating circle data
    for (var i =0; i<temp.length; i++) {
        rotate(radians(angle))
        // xPos=(300/2 * cos(temp[i]))
        fill(temp[i]*3,0,0, 80)
        circle(xPos, 100, temp[i]/2)
        angle+=.01
    }
}


function drawSnowRecord() {
    background(10,31,50)
    fill(255)
    text("Greatest Snowfall in One Day in Pittsburgh", 10, 25)
    push()
    textSize(10)
    text("Hover over the snowballs", 10, 40)
    pop()

    image(backdrop, 20, 92)
    circle(420, 290, 60)
    image(skyline, 30, 150)
    fill(250, 250, 250)
    circle(260, 300, 40)
    circle(150, 305, 30)
    image(buildings, 30, 272)
    circle(80, 300, 50)
    circle(330, 290, 80)
    pop()
    //data appears when hovering over snowballs

      if ((dist(330, 290, mouseX, mouseY) < 80/2)) {
        text("March 13, 1993: 23.6 inches of snow", 130, 400)
    }

      if ((dist(420, 290, mouseX, mouseY) < 60/2)) {
        text("December 17, 1890: 22 inches of snow", 130, 400)
    }

      if ((dist(80, 300, mouseX, mouseY) < 50/2)) {
        text("January 8, 1884: 16.5 inches of snow", 130, 400)
    }

      if ((dist(260, 300, mouseX, mouseY) < 40/2)) {
        text("March 3, 1942: 16.3 inches of snow", 130, 400)
    }

      if ((dist(150, 305, mouseX, mouseY) < 30/2)) {
        text("March 5, 1902: 15 inches of snow", 130, 400)
    }
    //snow
      for (var i=0; i<500; i++) {
        noStroke()
        fill(255)
        circle(snow[i].x, snow[i].y, 2)
    }


}


function mousePressed() { //changes visualzation when mouse clicked
    cycle += 1;
}


        
    






   

sketch
//Amalia Kutin
//15-104 B
var bergSize;
var polar;
var pieces = [];
var afterNoon;
var skyColor;
var clouds = [];
var skyOrb;
var skyOrbColor;


function setup() {
    createCanvas(500, 500);
    background(158, 198, 255);
    bergSize = 400;
    skyColor = 125;
    skyOrb = 0;
    skyOrbColor = false;
    noStroke();
    polar = {x: 250, y: 350, dx: 0};
    for(let i = 0; i < 10; i++) clouds[i] = {x: random()*500, y: random()*180};
}

function draw() {
    background(158, 198, 255);
    fill(61, 120, 204);
    rect(0, 200, 500, 300);
    fill(143, 185, 191);
    beginShape();
    vertex(250-(bergSize/2), 350);
    vertex(250-(bergSize/4), 350-(bergSize/4));
    vertex(250+(bergSize/4), 350-(bergSize/4));
    vertex(250+(bergSize/2), 350);
    vertex(250+(bergSize/4), 350+(bergSize/4));
    vertex(250-(bergSize/4), 350+(bergSize/4));
    endShape(CLOSE);
    for(let i = 0; i < pieces.length; i++) drawIce(pieces[i]);
    drawSky();
    for(let i = 0; i < clouds.length; i++) drawClouds(clouds[i]);
    drawBear(polar);
}

function drawBear(b) {
    fill(255);
    beginShape();
    vertex(b.x-20, b.y-20);
    vertex(b.x+10, b.y-30);
    vertex(b.x+20, b.y-25);
    vertex(b.x+15, b.y-10);
    vertex(b.x+20, b.y+10);
    vertex(b.x+10, b.y+10);
    vertex(b.x, b.y);
    vertex(b.x-10, b.y+5);
    vertex(b.x-10, b.y+10);
    vertex(b.x-20, b.y+10);
    vertex(b.x-30, b.y+5);
    vertex(b.x-35, b.y-5);
    endShape(CLOSE);
    fill(156, 96, 114);
    circle(b.x+20, b.y-25, 5);
    fill(0);
    circle(b.x+10, b.y-22, 5);
    circle(b.x+13, b.y-27, 5);
    b.x += random()*6 - 3;
    b.y += random()*6 - 3;
    if(b.x < 260-bergSize/2) b.x += 10;
    if(b.x > 240+bergSize/2) b.x -= 10;
    if(b.y < 360-bergSize/4) b.y += 10;
    if(b.y > 340+bergSize/4) b.y -= 10;
}

function drawIce(i) {
    fill(143, 185, 191);
    beginShape();
    vertex(i.x-(i.s/2), i.y);
    vertex(i.x-(i.s/4), i.y-(i.s/4));
    vertex(i.x+(i.s/4), i.y-(i.s/4));
    vertex(i.x+(i.s/2), i.y);
    vertex(i.x+(i.s/4), i.y+(i.s/4));
    vertex(i.x-(i.s/4), i.y+(i.s/4));
    endShape(CLOSE);
    if(i.c % 8 < 2) i.x++;
    else if(i.c % 8 < 4) i.y++;
    else if(i.c % 8 < 6) i.x--;
    else i.y--;
    i.c++;
}

function drawSky() {
    if(afterNoon) skyColor-=0.25;
    else skyColor+=0.25;
    fill(skyColor, skyColor, 120+skyColor/2);
    rect(0, 0, 500, 200);
    if(skyColor == 200) afterNoon = true;
    if(skyColor == 50) afterNoon = false;
    if (skyOrbColor) fill(219, 252, 255);
    else fill(235, 196, 68);
    circle(skyOrb, 100, 60);
    skyOrb+=(0.25*500/150);
    if (skyOrb > 500) {
        skyOrb = 0;
        if (skyOrbColor) skyOrbColor = false;
        else skyOrbColor = true;
    }
}

function drawClouds(c) {
    fill(255);
    ellipse(c.x%500, c.y, 50, 30);
    c.x++;
}

function mousePressed() {
    if(bergSize > 150) bergSize -= 10;
    var newPiece;
    for(let i = 0; i < 20; i++) newPiece = {x: random()*500, y: 200+random()*300, s: random()*60, c: 0};
    pieces[pieces.length] = newPiece;
}

My project revolved around a polar bear and melting ice. There is an iceberg that the user melts by clicking, and a polar bear stuck on it. Small pieces of ice are generated as the main piece melts. The sky has clouds that move across the sky. There is also a sun/moon that moves across the sky as well. The polar also randomly moves around, but it’s constrained by the size of the iceberg. This project demonstrates the small scale effects of climate change.

If I had more time, I would have considered adding a second polar bear. The issue is that it would need to stay on the iceberg while also not bumping into its friend.

Final Project

For my final project, I was inspired by the capitalist need for consumption over all else. Specifically, I’ve been concerned with over-fishing (I even wrote one of my essays to apply to CMU about fishing net pollution). So, I created a game that simulates capitalist motives in regards to fishing.

In the game, your cursor becomes a fishing hook which you can use to click on the fish and catch them. This will momentarily make the screen flash green and increase the amount of money you’ve made. However, once all the fish are caught, the coral dies off and the ocean becomes much less vibrant than it was before. Finally, a message will pop up warning the player about the effects of over-fishing. However, if the player goes for a minute and a half without killing all the fish, a message will pop up to congratulate them on being a conscious consumer.

I added everything I intended for the program, but I can definitely see how I could add more aspects to make this a more complete and polished screen, like a system to replenish the fish gradually. Also, moving seaweed or bubbles might be nice. But I am happy with this outcome.

sketch

//Elise Chapman
//ejchapma
//ejchapma@andrew.cmu.edu
//Section D

f=[]; //array for the fish
fClick=[]; //array for tracking the clicked 
var sandy = []; //for the sand
var noiseParam = 5; //for the sand
var noiseStep = 0.005; //for the sand
//color variables so that the coral can turn gray
var tube1;
var tube2;
var tube3;
var brain1;
var brain2;
var gray1=125;
var gray2=100;
var moneyCount=0; //counts the money
var timer=0; //for tracking after fish die
var timerLive=0; //for tracking time for player for being good

function setup() {
    createCanvas(600, 300);
    rectMode(CENTER);
    strokeJoin(ROUND);
    textAlign(CENTER,CENTER);
    noCursor();
    frameRate(10);
    //fish setup
    for (var i=0; i<20; i+=1) {
        f[i]=new Object();
        f[i].x=random(30,width-31);
        f[i].y=random(75,height-31);
        f[i].dx=random(-10,11); //change in x
        r=int(random(0,256));
        //g=int(random(0,256));
        b=int(random(0,256));
        f[i].c=color(r,0,b); //fish color
    }

    //for the sand
    noiseSeed(87);
    for (var i=0; i<(width/5)+1; i+=1) {
        var n=noise(noiseParam);
        var value=map(n,0,1,0,height);
        sandy[i]=value;
        noiseParam+=noiseStep;
    }

    //tube colors
    tube1=color(67,87,173) //blue
    tube2=color(242,160,242); //pink
    tube3=color(239,99,81); //red
    brain1=color(97,208,149); //green
    brain2=color(249,199,132); //yellow
}

function draw() {
    if (f.length<1 & timer>90) {
        background(122,161,187); //darker ocean blue
    } else {
        background(74,225,255); //ocean blue
    }
    sandscape();
    coral();
    seaweed(15,100);
    seaweed(40,175);
    seaweed(250,200);
    seaweed(275,75);
    seaweed(300,125);
    seaweed(450,225);
    seaweed(550,175);
    seaweed(575,100);
    //fish
    for (var i=0; i<f.length; i+=1) {
        fish(f[i].x,f[i].y,f[i].dx,f[i].c);
        f[i].x+=f[i].dx;
        if (f[i].x<15 || f[i].x>width-15) {
        f[i].dx=-f[i].dx;
        }
    }
    //bad ending
    if (timer>120 & f.length<1) {
        push();
        translate(width/2,height/2)
        noStroke();
        fill(0,0,0,200);
        rect(0,0,600,300);
        strokeWeight(1);
        stroke(255);
        fill(255);
        text("You've chosen greed over the fish.\nOver-fishing is one of the greatest causes \nof devastation for our oceans.\nDoes making a quick buck make killing the coral worth it?\nI should hope not.\nAlways choose the environment."
            ,0,0);
        pop();
    }
    //money
    noStroke();
    fill(255); //white
    rect(75,30,100,50,10,10,10,10);
    strokeWeight(2);
    stroke(0,122,4); //green
    fill(0,122,4); //green
    textSize(20);
    text("$"+str(moneyCount),75,30);
    //fish hook
    if (f.length>0) {
        fishHook(mouseX,mouseY);
    }
    if (f.length<1) {
        timer++;
    }
    //good ending
    if (timerLive>6300 & f.length>1) {
        push();
        translate(width/2,height/2)
        noStroke();
        fill(0,0,0,200);
        rect(0,0,600,300);
        strokeWeight(1);
        stroke(255);
        fill(255);
        text("Congrats!\nYou've chosen to fish sustainably, or not at all.\nAs over-fishing continues to be a source of \ndevastation for our oceans, please continue\nto advocate for healthy fishing!\n:)"
            ,0,0);
        pop();
    }
    timerLive++;
}

//swimming fish
function fish(x,y,dx,c) {
    noStroke();
    fill(c);
    ellipse(x,y,40,30);
    //moving left
    if (dx<0) {
        triangle(x+15,y,x+30,y+15,x+30,y-15);
        triangle(x-20,y,x+10,y-25,x+10,y);
        triangle(x-20,y,x+10,y+25,x+10,y);
        fill(0);
        ellipse(x-7,y-3,9);
    //moving right
    } else if (dx>=0) {
        triangle(x-15,y,x-30,y+15,x-30,y-15);
        triangle(x+20,y,x-10,y-25,x-10,y);
        triangle(x+20,y,x-10,y+25,x-10,y);
        fill(0);
        ellipse(x+7,y-3,9);
    }
}

//landscape made of sand
function sandscape() {
    //sets up the sand
    strokeWeight(3);
    stroke(242,231,189); //beige
    fill(242,231,189); //beige

    //creates the sand
    push();
    translate(0,10);
    beginShape();
    vertex(0,height);
    for (var i=0; i<(width/5)+1; i+=1) {
        vertex(i*5,sandy[i]);
    }
    vertex(width,height);
    endShape();
    pop();
}

//coral reef has got to have coral
function coral() {
    //tube coral
    if (f.length<1 & timer>70) {
        fill(gray1);
        stroke(gray1);
    } else {
        fill(tube1);
        stroke(tube1);
    }
    strokeWeight(8);
    var place = 500; //easier to adjust coral placement
    quad(place,200,place+20,200,place+30,70,place,70);
    quad(place-30,210,place,210,place-10,100,place-30,100);
    quad(place-60,190,place-40,190,place-30,50,place-70,40);
    quad(place-90,200,place-60,200,place-70,130,place-80,130);
    if (f.length<1 & timer>20) {
        fill(gray1);
        stroke(gray1);
    } else {
        fill(tube2);
        stroke(tube2);
    }
    place = 150;
    quad(place-30,250,place-50,250,place-50,120,place-20,120);
    quad(place+30,260,place,260,place+10,150,place+30,150);
    quad(place+60,240,place+40,240,place+30,100,place+70,90);
    quad(place-90,250,place-60,250,place-70,180,place-80,180);

    //brain coral
    if (f.length<1 & timer>10) {
        fill(gray2);
        stroke(gray2);
    } else {
        fill(brain1);
        stroke(brain1);
    }
    ellipse(400,200,100,70);
    if (f.length<1 & timer>50) {
        fill(gray2);
        stroke(gray2);
    } else {
        fill(brain2);
        stroke(brain2);
    }
    ellipse(10,150,100,70);

    //another tube coral
    if (f.length<1 & timer>30) {
        fill(gray1);
        stroke(gray1);
    } else {
        fill(tube3);
        stroke(tube3);
    }
    place = 300;
    quad(place+30,340,place,360,place+10,200,place+30,190);
    quad(place+60,360,place+40,360,place+30,250,place+70,250);
}

//makes the cursor look a certain way
function fishHook(x,y) {
    noFill();
    stroke(255);
    strokeWeight(10);
    beginShape();
    vertex(x+40,y-50);
    vertex(x+40,y-50);
    vertex(x+40,y);
    curveVertex(x+20,y+10);
    curveVertex(x,y);
    vertex(x,y);
    endShape();
    fill(80);
    triangle(x-5,y+10,x+10,y-10,x-5,y-10);
}

//underwater has to have seaweed
function seaweed(x,height) {
    strokeWeight(5);
    stroke(0,122,4); //green
    fill(0,122,4); //still green
    triangle(x,350,x+20,350,x+10,height);
}

function mousePressed() {
    for (var i=0; i<f.length; i+=1) {
        if (dist(mouseX,mouseY, f[i].x,f[i].y)<30) {
            f.splice(i,1);
            fill(0,122,4,100); //green
            rect(width/2,height/2,600,300);
            moneyCount+=10000;
            break;
        }
    }
}

Final Project

In my final project, the user starts at the year 1900 where there’s only fish in the ocean happily floating around and the thermometer on the left is quite low. As the reader reads the message on the top of the screen, they click the mouse and the year changes to 1940 where there is now oil barrels floating in the ocean. This addition of similar pollutants (oil barrels, plastic water bottles, face masks, and plastic bags) continues one by one as the user continues clicking the mouse. In the final click, year 2100, the user ends up killing the earth.

To do this project, I did some research onto the type of ocean pollutants that become more and more common as time passes. For example, in 2020, my animation spawns face masks in the ocean, which is a reflection of what truly happened in the real world due to COVID-19. The expectation from the user is quite straightforward as they just have to click their mouse and the animation progresses.

I think if I had more time, I would have changed more elements like the number of fish in the ocean, the color of the ocean gets dirtier, and the fish would have had expressions that go from happy to sad. Although I was unable to add these features, I am quite satisfied with how my project turned out.

Download

// Yash Mittal
// Section D 
// Final Project 

var waveValue = []; //array for front wave
var waveValue2 = []; //array for back wave
var noiseParam = 0.0001;
var noiseParam2 = 0.0001;
var noiseStep = 0.01;
var noiseStep2 = 0.01;
var x = []; //x value of fish
var y = []; //y value of fish
var dx = []; //x direction of fish
var c = []; //color for fish
var count = 0; //variable to keep track of user mousePressed
var clouds = 'https://i.imgur.com/RLqcPK7.png' //cloud image
var cloudsX = 0; //x value for 1st cloud
var cloudsX1 = -160; //x value for 2nd cloud
var cloudsDx = 2; //x direction speed for 1st cloud
var cloudsDx1 = 1; //x direction speed for 2nd cloud
var oilBarrel = 'https://i.imgur.com/nHrLCul.png' //oil barrel image
var numBarrels = 5; //number of barrels that spawn
var oilBarrelList = []; //array for barrels
var waterBottles = 'https://i.imgur.com/Xxl9tDk.png' //water bottle image
var numBottles = 10; //number of plastic water bottles that spawn
var waterBottlesList = []; //array for bottles
var faceMasks = 'https://i.imgur.com/wgsNqdq.png' //face mask image
var numMasks = 10; //number of face masks that spawn
var faceMasksList = []; //array for face masks
var plasticBag = "https://i.imgur.com/L8v1yKk.png" //plastic bag image
var numBags = 10; //number of plastic bags that spawn
var plasticBagList = []; //number of plastic bags that spawn
var sun = 'https://i.imgur.com/ftQzVK5.png'; //sun image
var angle_sun = 0; //rotation angle variable for sun
var thermometer = 'https://i.imgur.com/zcV3Srl.png'; //thermometer image
var deadEarth = 'https://i.imgur.com/tAGCTqA.png'; //dead earth image

function preload() {

    pimg = loadImage (clouds);
    oilImage = loadImage (oilBarrel);
    bottleImage = loadImage (waterBottles);
    maskImage = loadImage (faceMasks);
    plasticImage = loadImage (plasticBag);
    sunImage = loadImage (sun);
    thermoImage = loadImage (thermometer);
    earthImage = loadImage (deadEarth);

}

function setup () {

    createCanvas (600, 400);
    frameRate (15); 

    makeOil();

    makeBottle();

    makeMask();

    makeBag();

    for (var i = 0; i < 50; i ++) { //loop for fish value

        x [i] = random (25, width - 25);
        dx [i] = random (-5, 5);
        c [i] = color (random (0, 130), random (0, 130), random (0,130));
    }
}

function draw () {

    background (220);

    sunRotate(); //rotating circle

    cloudsP (); //drawing clouds

    timelineBar ();

    drawWaves1 ();

    for (i = 0; i < 20; i = i + 1) { //loop for fish value

        fill (c[i]);
        fish (x [i], waveValue [i] + 110, dx [i]); //making y value same as waveValue [i]
        x [i] = x [i] + dx [i];
        if (x [i] >= width - 25 || x [i] < 25 ) {
            dx [i] = - dx [i];

        }
   }

    highlightRect ();

    if (count >= 1) {

        for (var i = 0; i < numBarrels; i++) {
            updateOil(i); //moves oil barrels
            showOil (); //displays oil barrels
        }

        fill ("red");
        rect (17, 194, 8, 6); //increasing avg temp
    }

    if (count >=2) {

        for (var i = 0; i < numBottles; i++) {

            updateBottle (i);
            showBottle ();
        }

        rect (17, 185, 8, 13); //increasing avg temp
     }

     if (count >=3) {

        for (var i = 0; i < numMasks; i++) {

            updateMask (i);
            showMask ();
        }

        rect (17, 168, 8, 17); //increasing avg temp
     }

     if (count >=4) {

        for (var i = 0; i <numBags; i++) {

            updateBag (i);
            showBag ();
        }

        rect (17, 155, 8, 20); //increasing avg temp
     }

    image(thermoImage, 10, 140, 30, 80);

    drawWaves2 ();

    if (count >=5) {

        fill (0);
        rect (0, 0, width, height);
        image (earthImage, width / 2 - 240, height / 2 - 150, 250, 250);
        textSize(15);
        fill (255);
        text ("Congratulations, you killed the earth!", 330, 200);
     }  
}

function sunRotate () {

    push();
    rotate (radians(angle_sun));
    imageMode (CENTER);
    image (sunImage, 0, 0, 170, 170);
    pop();
    angle_sun = angle_sun + 2; //iterating angle for sun
}

function makeBag () {

    for (var i = 0; i < numBags; i++) {

        tx = random (10, width - 10); //random x value for bags
        ty = 0; //unassigned y value
        plasticBagList.push ({x:tx, y:ty, show:bagDraw, move: bagMove}); //create object & pushing in array
    }
}

function updateBag (i) { //function that holds y value of bottle and move function

    plasticBagList [i].y = waveValue[i] + 120; 
    plasticBagList [i].move ();
}

function showBag () { //function to display mask

    for (var i = 0; i < 10; i++) {

        plasticBagList [i].show ();
    }
}

function bagDraw() {

    image (plasticImage, this.x, this.y, 35, 35); //calling image

}

function bagMove () {

    this.x = this.x - random (0, 3);

    if (this.x < -25) { //if bags exits canvas from left, it appears on right

        this.x = width + 20;
    }
}

function makeMask () {

    for (var i = 0; i < numMasks; i++) {

        tx = random (10, width - 10); //random x value for masks
        ty = 0; //unassigned y value
        faceMasksList.push ({x:tx, y:ty, show: maskDraw, move: maskMove}); //creating object & pushing in array 
    }
}

function updateMask (i) { //function that holds y value of bottle and move function

    faceMasksList [i].y = waveValue[i] + 100;
    faceMasksList [i].move ();
}

function showMask () { //function to display mask

    for (var i = 0; i < 10; i++) {

        faceMasksList [i].show ();
    }
}

function maskDraw () {

    image (maskImage, this.x, this.y, 30, 30); //calling image
}

function maskMove () {

    this.x = this.x - random (0, 2);

    if (this.x < -25) { //if masks exits canvas from left, it appears on right

        this.x = width + 20;
    }
}

function makeBottle () {

    for (var i = 0; i < numBottles; i++) {

        tx = random (25, width - 25); //random x value for bottles
        ty = 0; //unassigned y value
        waterBottlesList.push ({x:tx, y:ty, show: bottleDraw, move: bottleMove});//creating object & pushing in array
    }
}

function updateBottle (i) { //function that holds y value of bottle and move function

    waterBottlesList [i].y = waveValue[i] + 90;
    waterBottlesList [i].move ();
}

function showBottle () { //function to display bottles

    for (var i = 0; i < 10; i++) {

        waterBottlesList [i].show ();
    }
}

function bottleDraw () {

    image (bottleImage, this.x, this.y, 30, 30); //calling the image
}

function bottleMove () {

    this.x = this.x + random (0, 2);

    if (this.x > width) { //if bottles exits canvas from right, it appears on left

        this. x = -20; 
    } 
}

function makeOil () {

    for (var i = 0; i < numBarrels; i++) {

        tx = random (25, width - 25); //random x value for barrels
        ty = 0; //unassigned y value
        oilBarrelList.push({x:tx, y:ty, show: oilDraw, move: oilMove}); //creating object & pushing in array 
    }
}

function updateOil (i) { //function that holds y value of barrel and move function

    oilBarrelList [i].y = waveValue [i] + 100; //assigning waveValue to y value 
    oilBarrelList [i].move (); //move function
}

function showOil () { //function to display oil

    for (var i = 0; i < 5; i++) { //for loop to display barrels
        oilBarrelList [i].show();
    }
}

function oilDraw (){

        image(oilImage, this.x, this.y, 35, 58); //drawing oil
}

function oilMove () { //function iterating x value of each barrel

        this.x = this.x - random (0, 2);

        if (this.x < -40) {

            this.x = 600
        } 
}

function mousePressed () {

         count = count + 1; //count increases each time mouse is pressed
    }

function cloudsP () {

    image (pimg, cloudsX, 50, 160, 160);
    image (pimg, cloudsX1, 20, 150, 150);

    cloudsX = cloudsX + cloudsDx;
    cloudsX1 = cloudsX1 + cloudsDx1;

    if (cloudsX >= width) {

        cloudsX = -160;
    }

    if (cloudsX1 >= width) {

        cloudsX1 = -160;
    }
}

function fish (x, y, dx) { //fish function

    fill (c);
    ellipse (x, y, 20, 10);

    if (dx < 0) { //if fish is going left

        triangle (x + 10, y, x + 15, y + 5, x + 15, y - 5);

    } else if (dx >= 0) { //if fish is going right

        triangle (x - 10, y, x - 15, y + 5, x - 15, y - 5);

    }
}

function highlightRect () {

    if (count == 0) { 

        fill ("green");
        rect (85, 57, 20, 40); //1900

    }  

    if (count == 1) {

        fill("green");
        rect (165, 57, 20, 40); //1940

    }  

    if (count == 2) {

        fill ("green");
        rect (245, 57, 20, 40); //1980
    }

    if (count == 3) {

        fill ("green");
        rect (325, 57, 20, 40); //2020
    }

    if (count == 4) {

        fill ("green");
        rect (405, 57, 20, 40); //2060
    }

    if (count == 5) {

        fill ("green");
        rect (485, 57, 20, 40); //2100
    }

    print(count);
}

function drawWaves1 () { // water wave 1 function

    for (var i = 0; i < width / 5 + 1; i++) {

        var n = (noise(noiseParam));

        var value = map (n, 0, 1, 80, height);

        waveValue.push(value); 

        noiseParam = noiseParam + noiseStep;
    }

    beginShape (); // drawing randomised wave

    vertex (0, height); // point 1 

    for (var i = 0; i <= width / 5; i++) { // point 2 random

        fill (116, 205, 235, 200); //water with alpha value
        noStroke();

        vertex (i * 5, waveValue [i] + 80); // randomised wave

    }

        waveValue.shift (); // making wave move by removing first element
        waveValue.push (map (noise (noiseParam), 0, 1, 80, height)); // adding random array value
        noiseParam = noiseParam + noiseStep;

        vertex (width, height); // point 3

        endShape (CLOSE);

    }

function drawWaves2 () { // water wave 2 function

        for (var i = 0; i < width / 5 + 1; i++) {

        var n1 = (noise(noiseParam2));

        var value2 = map (n1, 0, 1, 40, height);

        waveValue2.push(value2); 

        noiseParam2 = noiseParam2 + noiseStep2;
    }

    beginShape (); // drawing randomised wave

    vertex (0, height); // point 1 

    for (var i = 0; i <= width / 5; i++) { // point 2 random

        fill (116, 205, 235, 90); //water with alpha value
        noStroke();

        vertex (i * 5, waveValue2 [i] + 40); // randomised wave 2

    }

        waveValue2.shift (); // making wave move by removing first element
        waveValue2.push (map (noise (noiseParam), 0, 1, 40, height)); // adding random array value
        noiseParam2 = noiseParam2 + noiseStep2;

        vertex (width, height); // point 3

        endShape (CLOSE);

    }

function timelineBar () { //timeline function

        stroke (0);
        strokeWeight(5);
        line (20, 40, 20, 70); //left line
        line (20, 55, 580, 55); //middle line
        line (580, 40, 580, 70); //right line

        for (var a = 0; a < 6; a++) { // for loop for date rectangles 

            noFill();
            strokeWeight(1);
            rect (a * 80 + 85, 57, 20, 40);
        }

        textSize (30);
        fill (0);
        text ("Click mouse to time travel", 120, 40);

        textSize (15);
        text ("1900", 78, 115);
        text ("1940", 158, 115);
        text ("1980", 238, 115);
        text ("2020", 318, 115);
        text ("2060", 398, 115);
        text ("2100", 478, 115);

    }

Final Project – Air Pollution

his project relies on a particle system. It indicated regions with air pollution on an abstract Indian map. Hovering above the regions with your maps will lead to an info box appearing. The more red the region, the worse it is in terms of the air pollution.

class=”p5-embed” href=”https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/12/sketch-9.js”>sketch Karan Shah