Final Project: Survive the Particles

For my final project, I create a particle game in which the player attempts to avoid an increasing amount of particles which follow the cursor. The circular cursor is controlled by the mouse and is the direction in which all the particles move individually towards. A timer tracks the number of red particles on the screen and acts as a scoreboard which halts when the cursor makes contact with a particle. This game is based off one of my favorite iPhone apps which I discuss in my project priors and precursors.

The main source code comes from the Flock Particle Mutual Interactions example from our class notes. Overall, I was able to execute my original proposal. There were some features that I found worked better than others which was the main difference between my proposal and my final project.

//Kyle Lee
//Section C
//kdlee@andrew.cmu.edu
//Final Project

function particleUpdate() {
if (this.bFixed == false) {
this.vx *= this.damping;
this.vy *= this.damping;

this.px += this.vx;
this.py += this.vy;
}
if (this.px + particleDiameter/2 > width ||
this.px - particleDiameter/2 < 0){
this.vx = -this.vx;
}
if (this.py + particleDiameter/2 > height ||
this.py - particleDiameter/2 < 0){
this.vy = -this.vy;
}
}

var particleDiameter = 8;
function particleDraw() {
fill("#FA4E44");//red
ellipse(this.px, this.py, particleDiameter, particleDiameter);
}

// add a force to the particle using F = mA
var ax = fx / this.mass;
var ay = fy / this.mass;
this.vx += ax;
this.vy += ay;
}

// make a new particle
function makeParticle(x, y, dx, dy) {
var p = {px: x, py: y, vx: dx, vy: dy,
mass: 1.0, damping: 0.9,
bFixed: false,
update: particleUpdate,
draw: particleDraw
}
return p;
}

var seekFactor = 0.0010;
function seek(p) {
var desiredX = mouseX - p.px;
var desiredY = mouseY - p.py;
p.addForce(desiredX * seekFactor, desiredY * seekFactor);
}

//Unable to empty array and restart time
// function keyPressed() {
//     loop();
//     background();
//     time = 0;
//     myParticles.push(time);
// }

var myParticles = [];
var nParticles = 1000;
var cursorD = 30;
var x = 200;
var y = 200;
var diffx = 0;
var diffy = 0;

function setup() {
createCanvas(400, 400);
for (var i = 0; i < nParticles; i++) {
var rx = random(width);
var ry = random(height);
var p = makeParticle(rx, ry, 0, 0);
p.bElasticBoundaries = false;
p.damping = 0.99;
myParticles[i] = p;
}
frameRate(25);
noStroke();
}

function draw() {
background(250);
var time = ceil(frameCount/10);
var xConstrain = constrain(x, cursorD/2, width - cursorD/2);//mouse boundary
var yConstrain = constrain(y, cursorD/2, height - cursorD/2);//mouse boundary
for (var i = 0; i < time; i++) {
var ithParticle = myParticles[i];
ithParticle.fx = 0;
ithParticle.fy = 0;
if (follow) seek(ithParticle);
}

fill("#FA9998");
textAlign(CENTER);
textStyle(BOLD);
textSize(36);
text(time, width/2, 100);//displays time/score

fill("#2A3447");
ellipseMode(CENTER);
diffx = mouseX - x;
diffy = mouseY - y;
x = x + 0.2*diffx;
y = y + 0.2*diffy;
ellipse(xConstrain, yConstrain, cursorD, cursorD);//draws cursor/player

for (var i = 0; i < time; i++) {
var p = myParticles[i]
var length = dist(xConstrain, yConstrain, p.px, p.py);
p.update(); // update all locations
p.draw(); // draw all particles

if (length < cursorD/2){//stops game
textStyle(BOLD);
textSize(48);
fill("#FA4E44");
text("Game Over", width/2, height/2);

textStyle(NORMAL);
textSize(14);
fill(0);
text("reload to restart", width/2, height/2 + 20);
noLoop();
}
}
}

Final Project

For my final project I created an animation of a robot watching a tree grow through different seasons. I was able to create what I proposed in that the eyes watch the tree grow and there is something different about the robot in each season. I modified the tree example from lab so that it would grow at a steady rate. There is not much different between the project and my proposal except that I added a bit to summer and fall that were not mentioned. Overall some aspects of this project were harder to make than I thought, but it was a lot of fun to create.

//Rebecca Enright
//renright@andrew.cmu.edu
//Section A
//Final Project

//variables for rain/ snow/ leaves locations
var x;
var y;
//variable for ground color
var c;
//create object for umbrella
uX = 215;
uY = 240;
uR = 100;
uS = 50;
var umbrella = {locationX: uX, locationY: uY, left: uR, right: uS};

function setup() {
createCanvas(600, 400);
frameRate(10);

}

function draw() {
background(0, 220, 255);
//create variable for tree growth
var growth = 0;
growth = growth + (millis()/4000);
//create condition to stop growth
if (growth > 30) {
growth = 30;
}

//create conditionals to change scene
if (second() <= 14) {
MakeItRain();
}

if (second() > 14 & second() < 29 ) {
summerSun(growth);
}

if (second() >= 29 & second() < 44) {
autumn(growth);
}

if (second() >= 44) {
LetItSnow();
}

//call tree function
push();
translate(400, 350);
drawBranch(0, growth);
pop();
//call robot functions
drawRobot(growth);

}

//create tree
function drawBranch(depth, len) {
stroke(215, 150, 60);
line(0, 0, 0, -len);
push();
translate(0, -len);
drawTree(depth + 1, len);
stroke(0, 200, 0);
pop();

}

//create tree
function drawTree(depth, len) {
//variable for tree swaying
var angle = 5 * (noise(millis()/4000) - 0.5);
//conditional for number of branches
if (depth < 10) {
drawBranch(depth, len);
drawBranch(depth, len);
}
}

//create general draw robot function
function drawRobot(growth) {
//drawRock();
drawRobotBody();
}

//draw robot face
fill(200);
rect(200, 250, 25, 25);
//draw robot eyes
movingRobotEyes(growth);
//draw robot smile
fill(255);
arc(218, 270, 10, 10, 0, PI);
//draw robot antenna
fill(200);
rect(210, 240, 5, 10);
}

//function for robot body
function drawRobotBody() {
//draw neck
fill(200);
rect(207, 275, 10, 5);
//draw stomach
fill(200);
rect(200, 280, 20, 30);
//arm
fill(200);
rect(195, 280, 10, 20);
rect(195, 300, 30, 10);
//bolts for arm
fill(190);
ellipse(200, 285, 5, 5);
ellipse(200, 305, 5, 5);
//legs
fill(200);
rect(200, 310, 30, 10);
rect(220, 310, 10, 25);
//bolt for leg
fill(190);
ellipse(225, 315, 5, 5);
//foot
fill(200);
rect(220, 335, 15, 5);
}

//create rock function for robot to sit on
function drawRock() {
fill(175);
ellipse(200, 325, 50, 25);
}

//create snow function for winter
function LetItSnow() {
//draw ellipse
fill(255);
//variables for snowflake locations
//x location
x = 10 + random(5);
//y location
y = 0;
y = 2 * y;

//make loop for snowflakes
for (var i = 0; i < width; i++) {
sX = x * i;
sY = y + random(300);

r = random(5, 10);
ellipse(sX, sY, r, r);
}
//create snowy ground
fill(255);
rect(0, 295, 599, 104);
//draw red dot for robot antenna
fill(255, 0, 0);
ellipse(213, 240, 5, 5);
//draw scarf
scarf();
//draw rock to sit on
drawRock();
}

//create rain function for spring
function MakeItRain() {
stroke(0, 0, 255);
//reset variables for x and y locations
//x location
x = 5;
//y location
y = 0;
y = y + 1;

//make loop for rain drops
for (var i = 0; i < width; i++) {
//rain drop x and y location
rX = x * i;
rY = y + random(300);
line(rX, rY, rX + 5, rY + 5);
}
//reset stroke color
stroke(0);

//call workUmbrella to open umbrella
workUmbrella();

//create ground
fill(0, 190, 0);
rect(0, 295, 599, 104);
//draw rock to sit on
drawRock();
}

//create function for umbrella
function workUmbrella() {
fill(255, 0, 0);
arc(umbrella.locationX, umbrella.locationY, umbrella.left, umbrella.right, PI, 0);
fill(0);
ellipse(umbrella.locationX, umbrella.locationY - 25, 5, 5);
}

//create function for scarf
function scarf() {
fill(0, 190, 0);
rect(200, 275, 25, 5);
fill(200);
rect(220, 280, 5, 10);
fill(0, 190, 0);
rect(220, 290, 5, 10);
}

//create function for summer
function summerSun(growth) {//lX, lY, lS, lC, len) {
//create sun
fill(255, 255, 0);
ellipse(100, 100, 50, 50);
//create rays for sun
push();
translate(100, 100);
for (i = 0; i < 8; i++) {
//create sun rays
rotate(QUARTER_PI);
triangle(30, 30, 40, 60, 50, 50);
}
pop();
//create ground
fill(0, 227, 0);
rect(0, 295, 599, 104);

//call leaves
push();
translate(400, 350);
drawBranch2(0, growth);
pop();
//create flower for antenna
flower();
//create rock to sit on
drawRock();
}
//create second drawbranch function for green during summer
function drawBranch2(depth, len) {
stroke(0, 200, 0);
line(0, 0, 0, -len);
push();
translate(0, -len);
drawTree2(depth + 1, len);
stroke(0, 200, 0);
pop();

}

//create second drawtree for green during summer
function drawTree2(depth, len) {
//variable for tree swaying
var angle = 5 * (noise(millis()/4000) - 0.5);
//conditional for tree branches
if (depth < 12) {
drawBranch2(depth, len);
drawBranch2(depth, len);
}
}

//create function for fall
function autumn(growth) {
//create ground
fill(0, 210, 0);
rect(0, 295, 599, 104);
//create leaves on ground
var ln = 10;
ln = ln + millis()/5000;

for (i = 0; i < ln; i++) {
//set random leaf locations around base of tree
var lx = random(340, 460);
var ly = random(350, 390);
//create leaf size
var ls = 1;
ls = growth//1 + millis()/5000;
//draw leaves
fill(random(255), random(255), 0);
ellipse(lx, ly, ls/2, ls/2 + 2);
}
//create background
fallLeafBackground();
//draw  pumpkin for robot to sit on
drawPumpkin();
}

//create function for leaf background
function fallLeafBackground() {
//reassign pixel vairables so m moves by 10
//and reassign y so that it is randomized
for (var i = 0; i < width; i++) {
//leaf locations
var blx = 25;
blx = blx * i;
var bly = random(1,300);
//draw leaves
fill(random(255), random(255), 0);
ellipse(blx, bly, 5, 10);

}

}

//put flower on antenna during summer
function flower() {
//center
fill(255, 255, 0);
ellipse(215, 235, 5, 5);
//petals
push();
translate(215, 235);
for (var i = 0; i < 10; i++) {
rotate(QUARTER_PI);
fill(255);
ellipse(5, 0, 5, 5);
}
pop();
}

//create function so that robot eyes move
function movingRobotEyes(growth) {
//variable for robot pupil y location
var ey = 262;
ey = ey - (millis()/4000)/10;
//conditional to limit eye location
if (ey < 259) {
ey = 259;
}

//draw robot eyes
fill(255);
ellipse(210, 260, 10, 10);
ellipse(225, 260, 10, 10);
//pupil
fill(0);
ellipse(212, ey, 5, 5);
ellipse(227, ey, 5, 5);
}

function drawPumpkin() {
fill(255, 150, 0);
ellipse(200, 325, 50, 25);
fill(0);
//eyes
triangle(190, 325, 195, 320, 200, 325);
triangle(205, 325, 210, 320, 215, 325);
//mouth
rect(190, 330, 25, 2);
rect(195, 332, 5, 2);
rect(205, 332, 5, 2);
}

Michal Luria – Final Project

/*  Submitted by: Michal Luria
Section A: 9:00AM - 10:20AM
mluria@andrew.cmu.edu
Final-Project
*/

//variables to draw circles
var circles = []; //array of circle objects
var sentArray = []; //array for sentences
var posX = []; //the circle bases (character) X array
var posY = []; //the circle bases (character) Y array

//variables to determine most dominant character
var currentHighest = 0; //currently most sentences
var winnerIndex; //the index of the winner
var previousWinnerIndex = -1; //the index of the previous winner

//load text to strings - each part (by character) is a string

}

function setup () {

createCanvas(700,500);
frameRate(30);

//determine initial positions of characters
posX = [width/2, width/5, width/5*4, width/2, width/2, width/5, width/5*4];
posY = [height/2, height/2, height/2, height/5, height/5*4, height/5*4, height/5];

//initialize 0 for all scores
for (var k = 0; k < posX.length; k++){

scores[k] = 0;

}

//for every paragraph in the file (one string), split into sentences
for (var i = 0; i < textArray.length; i++){

//split sentences whenever one of the following chars appear: ;!?.
sentArray = splitTokens(textArray[i], ";!?.");

//The following code will do this: for every sentence a character says, create a circle object and draw it

//if VAL is talking (if the word VAL in the string)
if (textArray[i].indexOf("VAL") >= 0) {

//for every sentence VAL speaks, push a circle object into the circle array
for (var j = 1; j < sentArray.length; j++) {

/*pass the following variables for each circle object:
name
length of sentence (the size of the circle is determined by how long the sentence is)
Start frame - each circle has a frame number on which it can start drawing (using FrameCount)
The start frame is influenced by the index of the play sentences (how far is
the sentence into the play [i]), by the current index [j], and by the
length of the previous sentence, in order to give a feel of the play dynamics
Color
Index number
*/
circles.push(new Circle("VAL", sentArray[j].length,
j*i*20+(sentArray[j-1].length*2), color(247, 132, 163, 80), 0));
}

}

//The above comments are true for each one of the characters in the play below:

//if ELI is talking (found in string)
if (textArray[i].indexOf("ELI") >= 0) {

//for every sentence ELI speaks, push a circle onject into array
for (var j = 1; j < sentArray.length; j++) {

circles.push(new Circle("ELI", sentArray[j].length,
j*i*20+(sentArray[j-1].length*2), color(132, 247, 159, 80), 1));
}

}

//if CLE is talking (found in string)
if (textArray[i].indexOf("CLE") >= 0) {

//for every sentence CLE speaks, push a circle onject into array
for (var j = 1; j < sentArray.length; j++) {

circles.push(new Circle("CLE", sentArray[j].length,
j*i*20+(sentArray[j-1].length*2), color(132, 194, 247, 80), 2));
}

}

//if HAR is talking (found in string)
if (textArray[i].indexOf("HAR") >= 0) {

//for every sentence HAR speaks, push a circle onject into array
for (var j = 1; j < sentArray.length; j++) {

circles.push(new Circle("HAR", sentArray[j].length,
j*i*20+(sentArray[j-1].length*2), color(255, 246, 100, 80), 3));
}

}

//if LA FL is talking (found in string)
if (textArray[i].indexOf("LA FL") >= 0) {

//for every sentence LA FL speaks, push a circle onject into array
for (var j = 1; j < sentArray.length; j++) {

circles.push(new Circle("LA FL", sentArray[j].length,
j*i*20+(sentArray[j-1].length*2), color(205, 139, 255, 80), 4));
}

}

//if SIM is talking (found in string)
if (textArray[i].indexOf("SIM") >= 0) {

//for every sentence SIM speaks, push a circle onject into array
for (var j = 1; j < sentArray.length; j++) {

circles.push(new Circle("SIM", sentArray[j].length,
j*i*20+(sentArray[j-1].length*2), color(133, 251, 255, 80), 5));
}

}

//if FRO is talking (found in string)
if (textArray[i].indexOf("FRO") >= 0) {

//for every sentence FRO speaks, push a circle onject into array
for (var j = 1; j < sentArray.length; j++) {

circles.push(new Circle("FRO", sentArray[j].length,
j*i*20+(sentArray[j-1].length*2), color(255, 133, 255, 80), 6));
}

}

}

}

function draw () {

background(0);
stroke(0);

//draw all circle objects
for (var i = 0; i < circles.length; i++){

circles[i].draw();

}

//The follow section checks who the most dominant character (winner) is and updates their location

//check all the scores all the time (score = number of sentences a character said)
for (var j = 0; j < scores.length; j++){

//if a score is higher the current highest score
if (scores[j] > currentHighest) {

currentHighest = scores[j]; //update highest score

if (j != winnerIndex) { //if the highest score holder (character) changed

previousWinnerIndex = winnerIndex; //update the previous winner category
winnerIndex = j; //and update the new winner

}

}
}

/*Update the winner's location
The following parts check where the winner is, and move them towards the center
In parallel, the previous winner is moved in the opposite direction of the winner
in order to switch between their locations */

if (posX[winnerIndex] < width/2) {
posX[winnerIndex]++;
posX[previousWinnerIndex]--;
}

if (posY[winnerIndex] < height/2) {
posY[winnerIndex]++;
posY[previousWinnerIndex]--;
}

if (posX[winnerIndex] > width/2) {
posX[winnerIndex]--;
posX[previousWinnerIndex]++;
}

if (posY[winnerIndex] > height/2){
posY[winnerIndex]--;
posY[previousWinner]++;
}

}

//define circle object: name, sentence array, start frame, color and index
function Circle(name, sentArray,
myStartFrame, circColor, index) {

this.name = name; //name of actor
this.sent = sentArray; //length of sentence
this.index = index; // index of character
this.x = posX[this.index]; //circle X location
this.y = posY[this.index]; //circle Y location
this.siz = 0; //circle Size
this.start = myStartFrame; //the frame to start drawing the circle
this.color = circColor; //the color of the circle

this.draw = function() { //draw a circle

noStroke();

fill(this.color); //use the object's circle

/*determine circle size by sentence length (as long as the size is smaller than the sentence length * 2.5)
and only if the current frame count is bigger than the object's start frame
draw the circle*/
if (this.siz < this.sent * 2.5 & frameCount > this.start) {

this.x = posX[this.index]; //update the x position according to winner check
this.y = posY[this.index]; //update the y position according to winner check
ellipse (this.x, this.y, this.siz, this.siz); //draw the circle
this.siz++; //increase circle size
scores[this.index]++; //increase the score count for the character for each of his/her sentence circle

//write the name of the character below (also shows up and disappears according to the character on stage)
textSize(10);
text(this.name, this.index*100+40, height-50);

}

}

}

The Miser / Moliere

In my final project I wanted to do data visualization. With a background in theater, I thought it would be interesting to look at plays and show new aspects by using their data.

I used the famous play “The Miser” by Moliere, and created several aspects that would allow viewers to get a sense of the play dynamics.

Description of what you see:

1. Each circle is a sentence in the play.
2. The size of the circle represents the sentence length.
3. The circle sequence is according to the chronological order of sentences in the play.
4. The interval between sentences is in proportion to the length of the previous sentence.
5. The most dominant character in each part of the play is centered in location.

My final project visualized each sentence by a character in the play using a circle, “played” in the order of the characters text. The size of each circle visualizes the length of the sentence. The project also presents who is on stage at every given moment, and finally, the character that is most dominant in the play comes to the center of the stage.

I hope that using these aspects, it will be easy to get a sense of the pace of the play, if the dialog is quick or slow, who talks a lot and who is more quiet, when monologs occur, and who dominates the play dynamics. I hope that the visualization will allow looking at a famous masterpiece in a new light.

Project 3 – Alison Hoffman

//Alison Hoffman
//Section D
//achoffma@andrew.cmu.edu
//Project 3

//*This Program is a dynamic drawing that responds to the mouseX and mouseY position
function setup() {
createCanvas(640,480);
}

function draw() {
background("lavender");
noStroke();
rectMode(CENTER);

var boxColor = map(mouseX,0,width,0,180);
var boxTrans = map(mouseX,0,width,100,255);
//top row
fill(boxColor);
push();
translate(width*.15,100);
rect(0,0,50,50);
pop();
push();
translate(width*.38,100);
rect(0,0,50,50);
pop();
push();
translate(width*.62,100);
rect(0,0,50,50);
pop();
push();
translate(width*.85,100);
rect(0,0,50,50);
pop();

//middle row
fill(255,255,255,boxTrans);
push();
translate(width*.12,height/2);
scale(1 + mouseY/80);
rect(0,0,25,25);
pop();
push();
translate(width*.30,height/2);
scale(1 - mouseY/80);
rect(0,0,25,25);
pop();
push();
translate(width*.50,height/2);
scale(1 + mouseY/80);
rect(0,0,25,25);
pop();
push();
translate(width*.70,height/2);
scale(1 - mouseY/80);
rect(0,0,25,25);
pop();
push();
translate(width*.88,height/2);
scale(1 + mouseY/80);
rect(0,0,25,25);
pop();
//rect(width*.25,height/2,25,25);
//rect(width*.47,height/2,25,25);
//rect(width*.69,height/2,25,25);
//rect(width*.86,height/2,25,25);

//bottom row
fill(boxColor);
push();
translate(width*.15,380);
rect(0,0,50,50);
pop();
push();
translate(width*.38,380);
rect(0,0,50,50);
pop();
push();
translate(width*.62,380);
rect(0,0,50,50);
pop();
push();
translate(width*.85,380);
rect(0,0,50,50);
pop();

}

For this project I focused on making the mouseX & mouseY interaction feel intuitive. As you move mouseX left to right, the boxes in the first and third row rotate alternatively based on the mouseX position. The shade of the boxes also get lighter as you increase mouseX. The transparency of the the smaller white boxes in the middle row also decrease as mouseX decreases. MouseY controls the scale of the middle boxes as well.

Diana Connolly – Final Project

For my final project, I created a simple computer game. Going into the assignment, I knew that I wanted to create a game in which you simply were flying and avoiding hitting cliffs above and below you. My game turned into a jetpacker game in which you are going deeper and deeper into a cave.

Please click on the canvas to be able to use the key commands. Press ‘S’ first to start the game and get everything moving. Then, you can use ‘J’ to ignite your jetpack, and to jump upwards. I recommend you hold down ‘J’ for longer strides instead of using short, jerky jump motions. Either way, try to stay alive as long as possible, measured by the seconds alive listed in the top left corner and the background cave color changing as you go deeper into the cave.

var topRocks = [];
var bottomRocks = [];
var count = 0; //will keep track of where on the noise curve we are
var jetPackY; //character's Y location, from top

var flameImg; //character image with flame
var noFlameImg; //character
var monsterImg; //flying monster character

var notPaused = false; //game is paused
var gameOver = false; //game is in play

var initialTime = 0; //time counter variables
var elapsed;
var timeAtDeath = 0;

var colR = 255; //initial background color
var colG = 161;
var colB = 105;

}

function setup() {
monsterX = width + 1000;
monsterY = height / 2 - 30;
createCanvas(600, 400);
frameRate(40);
jetPackY = height / 2;
// pushes in noise values into top and bottom rock arrays
while (count < width + 1) {
topRocks.push(height - noise(count * 0.01) * height / 3);
bottomRocks.push(noise(width + count * 0.01) * height / 3);
count++;
}
}

function draw() {
background(colR, colG, colB);

drawBottomRocks();
drawTopRocks();

//prints time alive
fill(255);
textSize(15);
textStyle(BOLD);
textAlign(LEFT);
textFont("Helvetica");
if (!notPaused) {
elapsed = 0;
} else if (gameOver) {
elapsed = timeAtDeath;
} else {
var elapsed = getElapsed();
}
text("Seconds alive: " + elapsed, 15, 25);

//moving background and jetpacker
if (notPaused & !gameOver) {
timeAtDeath = getElapsed();
monsterX -= 3;
updateBackgroundColor(elapsed);
println("lik");
if (keyIsDown(74)) {
jetPackY -= 5; //start moving jetPack w/ pressing "J"
} else {
jetPackY += 3; //jetPack falls otherwise
}
}

//draw jetPack
var jetPackX = width / 3;
if (keyIsDown(74)) {
image(flameImg, jetPackX, jetPackY, 30, 40);
} else {
image(noFlameImg, jetPackX, jetPackY, 30, 40);
}

if (!notPaused & !gameOver) { //starting page
fill(0);
textSize(20);
textStyle(BOLD);
textAlign(CENTER);
textFont("Helvetica");
text("Press 'S' to start game", width / 2, height / 2 - 10);
text("Hold down 'J' to move up", width / 2, height / 2 + 50);
}

//checks for hitting bottom rocks
var tallestBottomPoint = bottomRocks[jetPackX];
for (var j = jetPackX; j < jetPackX + 30; j++) {
tallestBottomPoint = max(bottomRocks[j], tallestBottomPoint);
}
if (jetPackY + 30 >= height - tallestBottomPoint) {
gameOver = true;
textAlign(CENTER);
textSize(60);
textFont("Helvetica");
fill(255, 0, 0);
text("GAME OVER", width / 2, height / 2);
textSize(20);
fill(0);
text("Press 'R' to start again", width / 2, height / 2 + 40);
}

//checks for hitting top rocks
var tallestTopPoint = height - topRocks[jetPackX];
for (var k = jetPackX; k < jetPackX + 30; k++) {
tallestTopPoint = max(height - topRocks[k], tallestTopPoint);
}
if (jetPackY + 10 <= tallestTopPoint) {
gameOver = true;
textAlign(CENTER);
textSize(60);
textFont("Helvetica");
fill(255, 0, 0);
text("GAME OVER", width / 2, height / 2);
textSize(20);
fill(0);
text("Press 'R' to start again", width / 2, height / 2 + 40);
}

//restart game
if (keyIsPressed) {
if (key == 'r' || key == 'R') {
jetPackY = height / 2;
notPaused = false;
gameOver = false;
}
}

}

function keyPressed() {
// if you press S, start and reset start time
if (key == 's' || key == 'S') {
initialTime = getSecondsToday();
notPaused = true;
}
}

// ----------------------------------------------------------------------------------------
// FUNCTIONS CALLED FROM ABOVE

function drawBottomRocks() {
beginShape();
noStroke();
fill(31, 19, 79);
vertex(0, height);
for (var i = 0; i < bottomRocks.length; i++) {
vertex(i, height - bottomRocks[i]);
}
vertex(width, height);
endShape(CLOSE);
}

function drawTopRocks() {
beginShape();
noStroke();
fill(31, 19, 79);
vertex(0, 0);
for (var i = 0; i < topRocks.length; i++) {
vertex(i, height - topRocks[i]);
}
vertex(width, 0);
endShape(CLOSE);
}

//shifts over mountains based on noise plots
for (var i = 0; i < 5; i++) {
bottomRocks.shift();
topRocks.shift();
count++;
topRocks.push(height - noise(count * 0.01) * height / 2);
bottomRocks.push(noise(width + count * 0.01) * height / 2);
}
}

function getSecondsToday() {
// returns seconds since midnight today
var h = hour();
var m = minute();
var s = second();
return (s) + (m * 60) + (h * 60 * 60);
}

function getElapsed() {
// responsible for returning seconds since game started
return getSecondsToday() - initialTime;
}

function updateBackgroundColor(elapsed) {
//shifts background color
colR = map(elapsed, 0, 20, 255, 227);
colG = map(elapsed, 0, 20, 161, 167);
colB = map(elapsed, 0, 20, 105, 193);
}