{"id":69224,"date":"2021-11-30T16:16:08","date_gmt":"2021-11-30T21:16:08","guid":{"rendered":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/?p=69224"},"modified":"2021-11-30T16:16:08","modified_gmt":"2021-11-30T21:16:08","slug":"final-project","status":"publish","type":"post","link":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/2021\/11\/30\/final-project\/","title":{"rendered":"Final Project"},"content":{"rendered":"<!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD HTML 4.0 Transitional\/\/EN\" \"http:\/\/www.w3.org\/TR\/REC-html40\/loose.dtd\">\n<html><body><p><a class=\"p5_sketch_link\" data-width=\"600\" data-height=\"600\" href=\"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-content\/uploads\/2021\/11\/sketch-66.js\">sketch<\/a>\n\n\n\n<iframe src=\"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-content\/plugins\/p5-embedder\/p5_iframe.html\" class=\"p5_exampleFrame\" width=\"600\" height=\"600\"><\/iframe><pre class=\"language-javascript\"><code class=\"p5_editor language-javascript\">\/\/Alana Wu\n\/\/ID: alanawu\n\/\/Final Project\n\nvar buildings = [];\nvar buildings2 = [];\nvar buildings3 = [];\nvar counts = 0;\nvar fireCount = 0;\nvar myParticles = [];\nvar nParticles = 800; \nvar group = true;\n\nfunction setup()\n{\n    createCanvas(600, 600);\n    rectMode(CENTER);\n    ellipseMode(CENTER);\n    frameRate(10);\n    for (var i = 0; i &lt; 10; i++) \/\/makes original buildings in 1st layer\n    {\n        var rx = random(width);\n        buildings[i] = makeBuilding(rx);\n    }\n    for (var j = 0; j &lt; 8; j++) \/\/makes original buildings in 2nd layer\n    {\n        var ax = random(width);\n        buildings2[j] = makeBuilding2(ax);\n    }\n    for (var k = 0; k &lt; 8; k++)\/\/makes original buildings in 3rd layer\n    {\n        var bx = random(width);\n        buildings3[k] = makeBuilding3(bx);\n    }\n\n    for (var i = 0; i &lt; nParticles; i++) \/\/makes original particles\n    {\n        var rx = random(width);\n        var ry = random(230, 280);\n        var p = makeParticle(rx, ry, 0, 0);\n        p.bHardBoundaries = true;\n        p.damping = 0.99;\n        myParticles[i] = p;\n    }\n}\n\nvar desiredSeparation = 50;\nvar separationFactor = 0.01;\nfunction separate(p) \/\/applies force that separates particles\n{ \n    \/\/ rule applies if separation is &lt; desired separation, \n    \/\/ apply an opposing force to achieve greater separation\n    \/\/ opposing force grows as the separation becomes less\n    for (var i = 0; i &lt; myParticles.length; i++)\n    {\n        var boid = myParticles[i]; \/\/ get each other particle\n        var d = dist(p.px, p.py, boid.px, boid.py);\n        if (d &gt; 1 & d < desiredSeparation)\n        {\n            \/\/ divide by distance so that the total force is 1\n            var fx = (p.px - boid.px) \/ d;\n            var fy = (p.py - boid.py) \/ d;\n            \/\/ scale force by (desiredSeparation - d), which\n            \/\/ is 0 at desiredSeparation and grows as distance\n            \/\/ becomes less\n            var factor = (desiredSeparation - d) * separationFactor;\n            p.addForce(fx * factor, fy * factor);\n        }\n    }\n}\n\nfunction draw()\n{\n    background(0, 0, counts*5);\n    fill (150, 0, 0, 200);\n    rect (300, 240, width, 80); \/\/red rect behind 1st layer of buildings\n    fill (75, 0, 0, 200);\n    rect(300, 175, width, 50); \/\/red rect behind 2nd layer of buildings\n    updateAndDisplayBuildings();\n    removeBuildingsThatHaveSlippedOutOfView();\n    addNewBuildingsWithSomeRandomProbability(); \n    fill (100, 0, 0);\n    rect (300, 450, width, 400);\n    for (var i = 0; i &lt; myParticles.length; i++) \/\/applies separate to the particles\n    {\n        var ithParticle = myParticles[i];\n        ithParticle.fx = 0;\n        ithParticle.fy = 0;\n        separate(ithParticle);\n    }\n \n    for (var i = 0; i &lt; myParticles.length; i++)\n    {\n        var p = myParticles[i]\n        p.update(); \/\/ update all locations\n        p.draw(); \/\/ draw all particles\n    }\n\n    oilRig(200, 400); \/\/draws oil rig in foreground\n    smokeClouds(110, 90, 30, 25, 240); \/\/draws smoke clouds coming out of oil rig chimneys\n    smokeClouds(170, 90, 30, 25, 230);\n    smokeClouds(230, 90, 30, 25, 220);\n    smokeClouds(140, 90, 30, 25, 200);\n    smokeClouds(200, 90, 30, 25, 140);\n    if (fireCount &gt; 1) \/\/draws fires in different spots on oil rig as you click the mouse\n    {\n        push();\n        translate (180, 200);\n        fire (100, 100, 1);\n        pop();\n    }\n    if (fireCount &gt; 2)\n    {\n        push();\n        translate (0, 320);\n        fire(100, 100, 1);\n        pop();\n    }\n    if (fireCount &gt; 3)\n    {\n        push();\n        translate (20, 230);\n        fire(100, 100, 1);\n        pop();\n    }\n    if (fireCount &gt; 4)\n    {\n        push();\n        translate (250, 260);\n        fire(100, 100, 1);\n        pop();\n    }\n    if (fireCount &gt; 5)\n    {\n        push();\n        translate (110, 240);\n        fire(100, 100, 1);\n        pop();\n    }\n    if (fireCount &gt; 6)\n    {\n        push();\n        translate (150, 290);\n        fire(100, 100, 1);\n        pop();\n    }\n    if (fireCount &gt; 7)\n    {\n        push();\n        translate (-70, 290);\n        fire(100, 100, 1);\n        pop();\n    }\n    if (fireCount &gt; 8)\n    {\n        push();\n        translate (235, 330);\n        fire(100, 100, 1);\n        pop();\n    }\n    if (fireCount &gt; 9)\n    {\n        push();\n        translate (-400, 100);\n        fire(100, 100, 5);\n        pop();\n    }\n    if (fireCount &gt; 10)\n    {\n        push();\n        translate (-200, 100);\n        fire(100, 100, 5);\n        pop();\n    }\n    if (fireCount &gt; 11)\n    {\n        push();\n        translate (0, 100);\n        fire(100, 100, 5);\n        pop();\n    }\n    drawButton();\n    if (fireCount &gt; 12) \/\/world goes boom once you click enough times. Draws final screen\n    {\n        fill(255, 0, 0);\n        rect(300, 300, width, height);\n        textSize(140);\n        stroke(255);\n        fill(0);\n        strokeWeight(8);\n        text(\"BOOM\", 85, 300);\n        textSize(12);\n        noStroke();\n        text(\"RIP humanity.\", 15, 580);\n    }\n}\n\nfunction fire(x, y, size)\n{\n    fill (255, 0, 0); \/\/red flame\n    beginShape();\n    vertex((x + 10)*size, y*size);\n    vertex((x + 20)*size, (y - 20)*size);\n    vertex((x + 23)*size, (y - 50)*size);\n    vertex(x*size, (y - 100)*size);\n    vertex((x - 4)*size, (y - 60)*size);\n    vertex((x - 12)*size, (y - 80)*size);\n    vertex((x - 24)*size, (y - 50)*size);\n    vertex((x - 16)*size, (y - 20)*size);\n    endShape();\n\n    push(); \/\/orange flame\n    fill (255, 130, 0);\n    translate(size*32, size*28);\n    beginShape();\n    vertex((x + 10)*size*.7, y*size*.7);\n    vertex((x + 20)*size*.7, (y - 20)*size*.7);\n    vertex((x + 23)*size*.7, (y - 50)*size*.7);\n    vertex(x*size*.7, (y - 100)*size*.7);\n    vertex((x - 4)*size*.7, (y - 60)*size*.7);\n    vertex((x - 12)*size*.7, (y - 80)*size)*.7;\n    vertex((x - 24)*size*.7, (y - 50)*size*.7);\n    vertex((x - 16)*size*.7, (y - 20)*size*.7);\n    endShape();\n    pop();\n\n    push(); \/\/yellow flame\n    fill (255, 255, 0);\n    translate(size*65, size*55);\n    beginShape();\n    vertex((x + 10)*size*.4, y*size*.4);\n    vertex((x + 20)*size*.4, (y - 20)*size*.4);\n    vertex((x + 23)*size*.4, (y - 50)*size*.4);\n    vertex(x*size*.4, (y - 100)*size*.4);\n    vertex((x - 4)*size*.4, (y - 60)*size*.4);\n    vertex((x - 12)*size*.4, (y - 80)*size)*.4;\n    vertex((x - 24)*size*.4, (y - 50)*size*.4);\n    vertex((x - 16)*size*.4, (y - 20)*size*.4);\n    endShape();\n    pop();\n\n}\n\nfunction smokeClouds(x, y, w, h, col)\n{\n    fill (col);\n    ellipse (x + 35, y - 40, w*1.5, h*1.5);\n    ellipse (x + 20, y - 45, w*1.5, h*1.5);\n    ellipse (x + 50, y - 55, w*1.5, h*1.5);\n    ellipse (x + 25, y - 60, w*1.5, h*1.5);\n\n    ellipse (x, y, w, h);\n    ellipse (x + 10, y, w, h);\n    ellipse (x, y + 10, w, h);\n    ellipse (x - 12, y, w, h);\n    ellipse (x - 5, y - 12, w - 10, h - 10);\n\n    ellipse (x - 20, y + 40, w\/2, h\/2);\n    ellipse (x - 23, y + 35, w\/2, h\/2);\n    ellipse (x - 15, y + 35, w\/2, h\/2);\n\n}\n\nfunction updateAndDisplayBuildings()\/\/moves the buildings and redraws them\n{\n    \n    for (var i = 0; i &lt; buildings3.length; i++)\n    {\n        buildings3[i].move();\n        buildings3[i].display();\n    }\n    for (var i = 0; i &lt; buildings2.length; i++)\n    {\n    buildings2[i].move();\n    buildings2[i].display();\n    }\n    for (var i = 0; i &lt; buildings.length; i++)\n    {\n        buildings[i].move();\n        buildings[i].display();\n    }\n}\n\n\nfunction removeBuildingsThatHaveSlippedOutOfView() \/\/gets rid of building objects we no longer can see\n{\n    var buildingsToKeep = [];\n    for (var i = 0; i &lt; buildings.length; i++)\n    {\n        if (buildings[i].x + buildings[i].breadth &gt; 0)\n        {\n            buildingsToKeep.push(buildings[i]);\n        }\n    }\n    buildings = buildingsToKeep;\n\n    var buildings2ToKeep = [];\n    for (var i = 0; i &lt; buildings2.length; i++)\n    {\n        if (buildings2[i].x + buildings2[i].breadth &gt; 0)\n        {\n            buildings2ToKeep.push(buildings2[i]);\n        }\n    }\n    buildings2 = buildings2ToKeep;\n\n    var buildings3ToKeep = [];\n    for (var i = 0; i &lt; buildings3.length; i++)\n    {\n        if (buildings3[i].x + buildings3[i].breadth &gt; 0)\n        {\n            buildings3ToKeep.push(buildings3[i]);\n        }\n    }\n    buildings3 = buildings3ToKeep;\n}\n\n\nfunction addNewBuildingsWithSomeRandomProbability()\n{\n    var newBuildingLikelihood = 0.02; \n    if (random(0,1) &lt; newBuildingLikelihood)\n    {\n        buildings.push(makeBuilding(width));\n        buildings2.push(makeBuilding2(0));\n        buildings3.push(makeBuilding3(width));\n    }\n}\n\nfunction buildingMove()\n{\n    this.x += this.speed;\n}\n    \nfunction buildingDisplay()\n{\n    if (this.color == 0)\n    {\n        fill (255, 0, 255, this.opacity); \/\/light green\n    }\n    else if (this.color == 1)\n    {\n        fill(255, 255, 0, this.opacity); \/\/yellow\n    }\n    else if (this.color == 2)\n    {\n        fill(255, 0, 0, this.opacity); \/\/red\n    }\n    else if (this.color == 3)\n    {\n        fill(0, 0, 255, this.opacity); \/\/blue\n    }\n    else if (this.color == 4)\n    {\n        fill (255, 0, 120, this.opacity); \/\/orange\n    }\n    else if (this.color == 5)\n    {\n        fill (0, 255, 0, this.opacity); \/\/green\n    }\n    push();\n    translate(this.x, this.layer);\n    rect(0, -this.bHeight\/2, this.breadth, this.bHeight);\n    pop();\n}\n\n\nfunction makeBuilding(birthLocationX)\n{\n    var bldg = {x: birthLocationX,\n                breadth: random(30, 80),\n                speed: -1.0,\n                color: int(random(6)),\n                opacity: 250,\n                bHeight: random(30, 150),\n                layer: 250,\n                move: buildingMove,\n                display: buildingDisplay}\n    return bldg;\n}\n\nfunction makeBuilding2(birthLocationX)\n{\n    var bldg2 = {x: birthLocationX,\n                breadth: random(30, 80),\n                speed: 1.0,\n                color: int(random(5)),\n                opacity: 155,\n                bHeight: random(50, 150),\n                layer: 200,\n                move: buildingMove,\n                display: buildingDisplay}\n    return bldg2;\n}\n\n\nfunction makeBuilding3(birthLocationX)\n{\n    var bldg3 = {x: birthLocationX,\n                breadth: random(30, 80),\n                speed: -1.0,\n                color: int(random(5)),\n                opacity: 100,\n                bHeight: random(50, 150),\n                layer: 150,\n                move: buildingMove,\n                display: buildingDisplay}\n    return bldg3;\n}\n\n\nfunction oilRig (x, y) \/\/all dirty colors\n{\n    var bounce = 0;\n    var dy = -1;\n    fill (200);\n    noStroke();\n    rect (x - 120, y + 100, 50, 80); \/\/base columns\n    rect (x + 120, y + 100, 50, 80);\n\n    push();\n    translate (0, bounce);\n    bounce += dy;\n    if (bounce &gt; 5 || bounce &lt; -5)\n    {\n        dy*= -1;\n    }\n    fill (130);\n    for (var j = 0; j &lt; 5; j++)\n    {\n        rect (x + 100 - j*30, y - 75 - j*20, 100, 40);\n    }\n    fill (200);\n    var diff = -110;\n    for (var i = 0; i &lt; 5; i++)\n    {\n        rect (x + diff, y - 160, 15, 200);\n        diff += 30;\n    }\n    fill (60);\n    rect (x - 90, y - 110, 100, 120);\n    fill (80);\n    rect (x + 30, y - 90, 100, 70);\n    fill (150);\n    rect (x - 120, y + 50, 30, 20);\n    rect (x + 120, y + 50, 30, 20);   \n    fill (100);\n    rect (x, y, 350, 100); \/\/big rectangle\n    rect (x - 60, y - 80, 100, 60);\n    fill (50);\n    rect (x - 100, y + 15, 280, 50);\n    rect (x + 100, y - 40, 250, 40);\n    rect (x + 100, y - 100, 20, 80);\n    rect (x + 60, y - 100, 20, 80);\n    rect (x + 20, y - 100, 20, 80);\n    fill (80);\n    rect(x, y - 20, 400, 25);\n    fill (150);\n    rect (x, y, 400, 10);\n    pop();\n}\n\nfunction drawButton() \/\/click here button in bottom right corner\n{\n    fill(0);\n    rect (530, 550, 90, 40);\n    fill(255);\n    text(\"CLICK HERE\", 493, 553);\n    noStroke();\n}\n\nfunction mousePressed() \/\/counts for background color and fires drawn\n{\n    counts ++;\n\n    if (mouseX &gt; 485 & mouseX < 575 && mouseY > 530 && mouseY < 570)\n    {\n        fireCount ++;\n    }\n}\n\n\/\/ Update the position based on force and velocity\nfunction particleUpdate()\n{\n    if (this.bFixed == false) {\n        this.vx *= this.damping;\n        this.vy *= this.damping;\n  \n        this.limitVelocities();\n        this.handleBoundaries();\n        this.px += this.vx;\n        this.py += this.vy;\n    }\n}\n\n\n\/\/ Prevent particle velocity from exceeding maxSpeed\nfunction particleLimitVelocities()\n{\n    if (this.bLimitVelocities) {\n        var speed = sqrt(this.vx * this.vx + this.vy * this.vy);\n        var maxSpeed = 14;\n        if (speed &gt; maxSpeed) {\n            this.vx *= maxSpeed \/ speed;\n            this.vy *= maxSpeed \/ speed;\n        }\n    }\n}\n\n\n\/\/ do boundary processing if enabled\nfunction particleHandleBoundaries()\n{\n    if (this.bPeriodicBoundaries)\n    {\n        if (this.px &gt; width) this.px -= width;\n        if (this.px &lt; 0) this.px += width;\n        if (this.py &gt; 280) this.py -= height;\n        if (this.py &lt; 230) this.py += height;\n    } else if (this.bHardBoundaries)\n    {\n        if (this.px &gt;= width)\n        {\n            this.vx = -abs(this.vx);\n        }\n        if (this.px &lt;= 0)\n        {\n            this.vx = abs(this.vx);\n        }\n        if (this.py &gt;= 280)\n        {\n            this.vy = -abs(this.vy);\n        }\n        if (this.py &lt;= 230)\n        {\n            this.vy = abs(this.vy);\n        }\n    }\n}\n\n\n\/\/ draws particles as circles\nfunction particleDraw()\n{\n    fill(200, 200, 200, 100);\n    noStroke();\n    ellipse(this.px, this.py, 18, 18);\n}\n\n\n\/\/ add a force to the particle using F = mA\nfunction particleAddForce(fx, fy)\n{\n    var ax = fx \/ this.mass;\n    var ay = fy \/ this.mass;\n    this.vx += ax;\n    this.vy += ay;\n}\n\n\n\/\/ make a new particle\nfunction makeParticle(x, y, dx, dy)\n{\n    var p = {px: x, py: y, vx: dx, vy: dy,\n             mass: 1.0, damping: 0.9,\n             bFixed: false,\n             bLimitVelocities: true,\n             bPeriodicBoundaries: false,\n             bHardBoundaries: true,\n             addForce: particleAddForce,\n             update: particleUpdate,\n             limitVelocities: particleLimitVelocities,\n             handleBoundaries: particleHandleBoundaries,\n             draw: particleDraw\n            }\n    return p;\n}\n\n\n\n\n<\/code><\/pre><\/p><p>For this program, I started with the idea of the ruins of human cities. Originally, I wanted to do something with skylines, but in the final project, I instead have three layers of simple buildings moving across the landscape background.<br>In the midground, I modified the particles program that we went through during class to create an effect that looks like roiling fog.<br>In the foreground, I drew a large oil rig in various shades of gray to contrast with the bright and colorful background.<br>As the user clicks the &ldquo;click me&rdquo; button, small fires appear on the oil rig. After enough clicks, huge fires appear on the screen, ending with a screen that says BOOM after the oil rig explodes.<\/p>\n\n\n\n<p>I wanted to refrain from using images, so the program has more of a game-like appearance, making a climate apocalypse seem like a &ldquo;game over&rdquo;.<\/p><\/body><\/html>\n","protected":false},"excerpt":{"rendered":"<p>For this program, I started with the idea of the ruins of human cities. Originally, I wanted to do something with skylines, but in the final project, I instead have three layers of simple buildings moving across the landscape background.In the midground, I modified the particles program that we went through during class to create &hellip; <a href=\"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/2021\/11\/30\/final-project\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Final Project&#8221;<\/span><\/a><\/p>\n","protected":false},"author":677,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[116,57],"tags":[],"_links":{"self":[{"href":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-json\/wp\/v2\/posts\/69224"}],"collection":[{"href":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-json\/wp\/v2\/users\/677"}],"replies":[{"embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-json\/wp\/v2\/comments?post=69224"}],"version-history":[{"count":1,"href":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-json\/wp\/v2\/posts\/69224\/revisions"}],"predecessor-version":[{"id":69226,"href":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-json\/wp\/v2\/posts\/69224\/revisions\/69226"}],"wp:attachment":[{"href":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-json\/wp\/v2\/media?parent=69224"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-json\/wp\/v2\/categories?post=69224"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/15-104\/f2021\/wp-json\/wp\/v2\/tags?post=69224"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}