Final Project

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

*Systems & Keys

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

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

*Goal

Score at least 5 points by throwing out flammable objects

*Attention

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

sketch copy
//Final Project

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Final Project

Virus Run

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

Some Screenshots of what the full canvas looks like:


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

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


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

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

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

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

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

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

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

}



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

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

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

    } else { 

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

        createNewMask();
        displayMask();

        createNewHandSan();
        displayHandSan();

        checkIfGameOver();
    
        score += 1; 

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

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

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

}

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

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


function checkIfGameOver (){

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

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

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


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


// BEGIN CODE FOR MASK OBSTACLES



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

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

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

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

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

// BEGIN CODE FOR HAND SANITIZER OBSTACLES

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

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

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

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

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


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

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


FinalProject-wildFire

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


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

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

//koala
var koalaImg;
var koala;

//var counter
var counter = 5;


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

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

}

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

    koala = koalaMake(45,420);
       
}   


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

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

    //counter

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

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

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

    //fire

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

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

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

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

        }

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


 
    }   

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

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

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

    particles = newParticles;

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

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

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

    //game ending, win or loose

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

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

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

        noLoop();
        }
    }



}


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


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

    }

}

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

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

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


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

}

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

function drawFire(){

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

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



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

}


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

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

    pop();
}


//particles

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

}

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


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

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

//koala

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

function koalaDraw(){

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

}

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

}

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

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

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

Final Project – Simple Virus Simulator

For my final project, I wanted to create a simple virus simulation where one infected particle infects a population of healthy particles. The particles move across the canvas at random speeds and directions and bounce off the edges of the canvas. I wanted to show how quickly disease can spread within a population if you don’t take preventative measures such as wearing a mask and social distancing.

  1. Your mouse is a social distancing particle that repels all other particles that comes within its’ social distancing radius.
  2. Healthy particles that come within range of a sick particles’ “infection radius” will be infected.
  3. If you press any key on the keyboard, more healthy particles will be added to the screen (but will quickly be infected by the population of sick particles).
  4. If you click the “RETURN” key, the sick particles will all reset to healthy and the process of infection begins again. 
  5. In the upper left corner, there is a counter for the number of sick particles.
Covid Simulation
//Maggie Ma
//Section D
//Final Project Virus Simulator

var dots = [];
var infectionRadius = 20; //light red infection radius 
var rpc = 19000; //repelling constant


function setup() {

    createCanvas(600, 600);
 	for (i = 0; i < 100; i++) { //create 100 healthy dots
		var p = new dot();
		dots.push(p);
	}
	frameRate(20);
}

function draw() {
	background(255);

	for (var i = 0; i< dots.length; i++) { //draw uninfected dots
		dots[i].update();
		dots[i].show();
	}
	if (frameCount ==100){
		dots[9].infected = true; //after 100 frameCount, one dot becomes sick
	}
	//dots infect eachother if come in contact in the "infectionRadius"
	for (var m = 0; m<dots.length; m++) {
		for (var i = 0; i < dots.length; i++) {
			if (dist(dots[m].x, dots[m].y,
		dots[i].x, dots[i].y) <= infectionRadius) {
				if (dots[m].infected == true) {
						dots[i].infected = true;
			}
		}
		}
	}
	//Social Distance dot that repels all infected dots
	ellipseMode(CENTER);
	noStroke();
	fill(0,0,0,100);
	ellipse(mouseX,mouseY,100,100);
	fill(0);
	ellipse(mouseX,mouseY,25,25);

	var sickcounter = 0;
	//var healthycounter = 100;

	for (var i = 0; i < dots.length; i ++) {
		if(dots[i].infected ==true) {
			sickcounter++;
			//healthycounter--;
		}
	}
	noStroke();
	fill(200);
	textSize(12);
	text("You are the social distancing particle.", 10, 25);
	text("Press any key to add healthy particles.", 10, 50);
	fill(200);
	text("Press 'Return' key to reset.", 10, 75);
	text("Sick Particles:", 10,100);
	text(sickcounter, 130,100);

	
}

//add new uninfected dots by pressing key
function keyPressed() {
	dots.push(new dot(mouseX, mouseY));
	//healthycounter++;

	//if click "Return key" simulation resets.
	if (keyCode === RETURN) {
		for (var m = 0; m<dots.length; m++) {
			for (var i = 0; i < dots.length; i++) {
				if(dots[i].infected == true) {
					dots[i].infected = false;
					dots[9].infected = true;
					sickcounter = 0;
			}
		}
		}
	}
}

class dot { 

	constructor() { 
		this.x =random(3.5, width-3.5);
		this.y =random(3.5,height-3.5);
		this.dx =random(-10,7);
		this.dy =random(-10,7);
		this.infected = false
		this.history = [];
	}

	update() { 
		//move black dots
		this.x+= this.dx; 
		this.y+=this.dy;

		//bounce off the edges of the canvas
		if (this.x > width) { //bounce off right wall
			this.x = width - (this.x - width);
			this.dx = -this.dx
		} else if (this.x < 0) { //bounce off left wall
			this.x = -this.x;
			this.dx = -this.dx
		}
		if (this.y > height) { // bounce off bottom
       		this.y = height - (this.y - height);
        	this.dy = -this.dy; 
    	} else if (this.y < 0) { // bounce off top
        	this.y = -this.y;
        	this.dy = -this.dy;
		}

		//create the particle trail
		var v = createVector(this.x, this.y);
		this.history.push(v);
		if (this.history.length>15) { //trail is 15 ellipses long
			this.history.splice(0,1); //splice out the trail circle at index 0
		}

		//effect of the social distancing repeller
		var dp = dist(this.x, this.y, mouseX, mouseY);
    	var f = rpc /(Math.pow(dp, 2)); //Math.pow is exponent w/ base dp
    	var dirx = (this.x - mouseX)/dp;
   		var diry = (this.y - mouseY)/dp;
    	this.x += f*dirx;
    	this.y += f*diry;
	}	

	show() { 
		//if dot is infected, color red
		if (this.infected ==true) {
			noStroke();

			//creating dot "tail"
			for (var i = 0; i < this.history.length; i++) {
				var pos = this.history[i];
				fill('red');
				ellipse(pos.x,pos.y, i*.15, i*.15) 
			}
			//drawing red dot
			fill(255,0,0,100);
			ellipse(this.x, this.y, 30,30);
			fill('red');
			ellipse(this.x,this.y,10,10);

		//else if dot is uninfected, color black dot
		} else {
			noStroke();
			//creating dot "tail"
			for (var i = 0; i < this.history.length; i++) {
				var pos = this.history[i];
				fill(0);
				ellipse(pos.x,pos.y, i*.15, i*.15) 
			}
			fill(0);
			ellipse(this.x,this.y, 10,10); 
		}
	}
}

Final Project

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

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

sketch

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


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

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

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

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

Looking Outwards 11

The female artist I found inspirational is Mary Frank. She is an artist and
computational designer that works in immersive and real-time media. One of her artworks, “As Machines Shine” is a beautiful installation piece of liquid
colonies of light in addition to motion-triggered motion composition that flows
with the movement of the installation. This piece responds to another artist,
Kadet Kuhne’s interactive audio called “Abstracted Reflection”. The sculpture
digitally fabricated with wood and acrylic for its membranous qualities, while
the projected illusion is imagery that resembles water. The installation
suggests organisms and movement on a microscopic scale. The projection is real-time and is inspired by spatial algorithms. I find it fascinating that the
machine is able to generate something so organic and random in a way that
can only be found in nature.

Project 11

sketchDownload
var hills = [];
var noiseParam = 0;
var noiseStep = 0.03;
var xTree = [];
var yTree = [];
var car;

function preload() {
    car = loadImage("https://i.imgur.com/dk31naF.png");
}

function setup() {
    createCanvas(400, 250);
    for (var i = 0; i <= width/5; i ++) {
        var n = noise(noiseParam);
        var value = map(n, 0, 1, 0 ,height);
        print(n);
        hills.push(value);
        noiseParam += noiseStep;
    }
    frameRate(10);
    imageMode(CENTER);
}

function draw() {
    background(0, 59, 107); //dark sky
    hills.shift();
    var n = noise(noiseParam);
    var value = map(n, 0, 1, 0 ,height);
    hills.push(value);
    noiseParam += noiseStep;
    for (var i = 0; i < width/5; i ++) {
        var x = i*5;
        noStroke();
        fill(22, 105, 120);
        beginShape(); //drawing the hills
        vertex(x, height);
        vertex(x, hills[i]); 
        vertex(x+5, hills[i+1]);
        vertex(x+5, height);
        endShape();
        //draw tree if hillValue[i] is smaller than the points before & after
        if (hills[i] < hills[i+1] && hills[i] < hills[i-1]) {
            tree(x, hills[i]);
        }
    }
    //insert car image
    image(car, width/2, height/2, 450, 300);

}
function tree(x, hills) {
    fill(1, 120, 33)
    triangle(random(x-2, x-5), hills*1.2, random(x, x+3), 
    hills*0.8, x+5, hills*1.2);
    stroke(46, 19, 19);
    strokeWeight(2);
    line(x, hills*1.2, x, hills*1.5); 
}

This animation shows a baby sitting inside a car in the middle of a long drive at night, staring out into the mountains.

Looking Outwards 11

Bot Party
2017
Jubbies Steinweh-Adler

The project, Bot Party, is an interactive game relying on sound and physical contact with another person.This game is made up of a bunch of cubes which are called bots, which communicate with other users but only when you touch someone else who is holding another Bot. This project was created to help break the ice between strangers. It requires a secret message from each bot that can only be revealed through holding hands with people and experimenting until the message is revealed. The secret messages are randomly generated through software on the main part of the game. I admire how this game uses technology to aid human connection in a playful, lighthearted way. I also think it is really interesting that this software was built to receive human touch inputs from a sensor, this is something I would like to explore with code. This project was created by Pheonix Perry. She works primarily as a game designer, but also founded the Code Liberation Foundation which teaches women between ages 16-60 how to code.


Pheonix Perry

LO 11 – Women Practitioners

Milica Zec is a VR filmmaker who focuses on creating stories to raise awareness of societal and environmental issues. Growing up in Serbia, she witnessed war, bombings, and unrest as a child. Her tumultuous childhood inspires her work, in which she hopes to preserve what is precious through creating new realities. 

Milica’s second VR film, Trees, places a viewer in the middle of a rainforest as an immobile tree that grows from a seed and eventually is destroyed by a wildfire, as the viewer watches, helpless as they cannot do anything to save the tree or forest. In a talk at the World Economic Forum, she describes how the film was so moving that many viewers came out in tears, finally understanding climate change on an innate and personal level.

I watched Trees online through a 2D youtube video. While I didn’t experience it the way it was meant to be viewed, I could immediately understand how powerful its message could be when immersing a viewer in these surroundings. I’m excited to see how her next project, Rainforest, continues this message in a more interactive way.

Project 11 – Generative Landscape

sketch
/*
 * Eric Zhao
 * ezhao2@andrew.cmu.edu
 *
 * Generative ladnscape 
 *
 */

var hillHeights = [];
var mountainHeights = [];
//arrays for foreground and background
var noiseParam = 0;
var noiseParam2 = 0;
var noiseStep = 0.01;
var numpoints = 80;
//bottom 4 used as placemarkers and attempts
//to make the hobbit holes not disappear on screen
var xInc;
var circleRad; 
var breadth = 25;
var marginRatio = (numpoints+breadth)/numpoints;

function drawMountain(hill, numpoints){
    //draws a perlin noise mountain
    beginShape();
    vertex(width - width*marginRatio, height);
    vertex(width - width*marginRatio, height);
    for(let i = -breadth; i <= numpoints+breadth; i++){
        vertex(i * xInc, hill[i]);
    }
    vertex(width*marginRatio, height);
    vertex(width*marginRatio, height);   

    endShape();
}

function stepMountain(param, step, hill, numpoints){
    //generates array of perlin values used for mountain and trees
    hill.shift();
    for(let i = -breadth; i <= numpoints+breadth; i++){
        var n = noise(param);
        var value = map(n, 0, 1, 0, height);
        hill.push(value);
        param += step;
    }
    noiseParam = param;
}

function drawHole(circleRad){
    //hobbit hole draw function
    fill(22, 98, 71);
    ellipse(0, 0, circleRad, circleRad);
    fill(random(0, 360), 94, 25);
    ellipse(0, 0, circleRad*0.8, circleRad*0.8);
    stroke(0);
    noFill();
    for(var i = 0; i <= 8; i ++){
        arc(0, 0, circleRad*0.8, circleRad*0.8, i*(PI/8), -i*(PI/8), CHORD);
    }
    fill(50, 80, 90);
    ellipse(0, 0, max(10, circleRad*0.1), max(10, circleRad*0.1));
}

function setup() {
    createCanvas(600, 400);
    colorMode(HSB);
    frameRate(30);
    noStroke();
    strokeWeight(2);
    stepMountain(noiseParam, noiseStep, hillHeights);
}

function draw() {
    xInc = width/numpoints;
    background(183, 33, 95);
    //draws background/dark green mountain
    fill(120, 100, 20);
    stepMountain(noiseParam2, 0.4, mountainHeights, 320)
    drawMountain(mountainHeights, 320);
    //draws foreground scenery
    fill(110, 64, 52);
    stepMountain(noiseParam, noiseStep, hillHeights, numpoints);
    drawMountain(hillHeights, numpoints);
    push();
    translate(0, 20);
    fill(42, 30, 90);
    drawMountain(hillHeights, numpoints);
    //at peaks of hill, add a hobbit hole
    for(let i = -breadth; i <= numpoints+breadth; i++){
            if(i != -breadth & i !=numpoints+breadth){
                if (hillHeights[i] < hillHeights[i-1] &&
                hillHeights[i] < hillHeights[i+1]){
                    push();
                    fill(0);
                    translate(i * xInc, (height + hillHeights[i])/2);
                    drawHole((height-hillHeights[i])/1.5);
                    pop();              
                }

            }
        }
    pop();

}

My idea was to generate a rolling hill and place hobbit holes at random locations or peaks under the hill, with their basic shape looking something like this:

Unfortunately, I realized too late that the program I wrote didn’t utilize objects and made changing variables about the holes (ex. colors and varying designs) very difficult without restructuring the program significantly.