Yoo Jin Shin- Final Project

Final

// Yoo Jin Shin
// yoojins@andrew.cmu.edu
// Section D
// Final Project

// All scenes global variables
var yaxis = 1;
var xaxis = 2;
var frames = []; 
var frameCounts = 0;
var textSpeed = 3;
var slider;
var sliderValue;

// Yeosu global variables
var c1, c2, c3, c4;
var terrainSpeed1 = 0.0001; 
var terrainDetail1 = 0.003;
var terrainSpeed2 = 0.00012;
var terrainDetail2 = 0.0045;
var terrainSpeed3 = 0.00007;
var terrainDetail3 = 0.0006;
var clouds = []; 
var trees = [];
var textX = 1;
var sunMouse; 
var birdLoad;
var bird1;
var birds = [];

// Grand Canyon global variables
var terrainSpeed4 = 0.00003;
var terrainDetail4 = 0.0005;
var terrainSpeed5 = 0.00012;
var terrainDetail5 = 0.007;
var terrainSpeed6 = 0.00007;
var terrainDetail6 = 0.0065;
var textX3 = 1;
var c9;

// Las Vegas global variables
var c5, c6, c7, c8;
var buildings = [];
var snowflakes = [];
var drops = [];
var textX2 = 1;
var buildingMouse;
var carLoad;
var car1;
var cars = [];

function preload(){
    // Loading sprite sheet for girl character via direct links from imgur
    // Creds to https://www.gameart2d.com/freebies.html
    var filenames = [];
      filenames[0] = "https://i.imgur.com/oEJGbCm.png";
      filenames[1] = "https://i.imgur.com/QsZoWMJ.png";
      filenames[2] = "https://i.imgur.com/kyo4lhi.png";
      filenames[3] = "https://i.imgur.com/XmPYK4a.png";
      filenames[4] = "https://i.imgur.com/w80hQ6A.png";
      filenames[5] = "https://i.imgur.com/0BiNaBy.png";
      filenames[6] = "https://i.imgur.com/WL7kjhR.png";
      filenames[7] = "https://i.imgur.com/z6agkKq.png";
      filenames[8] = "https://i.imgur.com/Vxi5Eu6.png";
      filenames[9] = "https://i.imgur.com/mrjcctG.png";
      filenames[10] = "https://i.imgur.com/oDP8zsr.png";
      filenames[11] = "https://i.imgur.com/DsNFucK.png";
      filenames[12] = "https://i.imgur.com/8Y3e8BW.png";
      filenames[13] = "https://i.imgur.com/aQUjC1v.png";
      filenames[14] = "https://i.imgur.com/6yQMDLO.png";
      filenames[15] = "https://i.imgur.com/fJZPSul.png";
      filenames[16] = "https://i.imgur.com/vghvvNP.png";
      filenames[17] = "https://i.imgur.com/oh2WsXz.png";
      filenames[18] = "https://i.imgur.com/yPh4Upu.png";
      filenames[19] = "https://i.imgur.com/k0wd9HK.png";

    for (var i = 0; i < filenames.length; i++) {
        frames.push(loadImage(filenames[i]));
    }

    // Loading bird and car images created using illustrator
    birdLoad1 = "https://i.imgur.com/RQSUNmm.png";
    bird1 = loadImage(birdLoad1);

    carLoad1 = "https://i.imgur.com/yKCei98.png";
    car1 = loadImage(carLoad1);
}

function setup() {
  createCanvas(480, 480);
  drawSlider();

  // Yeosu: Define gradient colors
  c1 = color(225, 217, 199); // sky top color - grey
  c2 = color(254, 180, 144); // sky bottom color - orange
  c3 = color(50, 50, 2); // ground left - lighter green
  c4 = color(27, 20, 2); // ground right - dark green

  // Yeosu: Initialize clouds
  for (var i = 0; i < 3; i++) {
      var cloudX = random(width); 
      clouds[i] = drawClouds(cloudX);
  }

  // Yeosu: Initialize trees
  for (var i = 0; i < 7; i++) {
    var treeX = random(width);
    var t = drawTrees(treeX);
    trees[i] = t;
  }

  // Yeosu: Initialize birds
  for (var i = 0; i < 7; i++) {
    var birdX = random(width);
    birds[i] = drawBird(birdX);
  }

  // Las Vegas: Define gradient colors
  c5 = color(0, 0, 0); // sky top color - black
  c6 = color(61, 48, 52); // sky bottom color - purpley

  // Las Vegas: Initialize buildings
  for (var i = 0; i < 6; i++) {
      var rx = random(width);
      buildings[i] = drawBuilding(rx);
  }  

  // Las Vegas: Initialize cars
  for (var i = 0; i < 10; i++) {
    var carX = random(width);
    cars[i] = drawCar(carX);
  }
    imageMode(CENTER);
}

function drawSlider() {
  slider = createSlider(5, 60, 30);
  slider.style(200, '100px');
  slider.position(20, 450);
}

function draw() {
  // Set slider to adjust frameRate
  var frameRateSpeed = slider.value();
  frameRate(frameRateSpeed);
  
  // Change scene every 160 frames, then loop
  // Loop: Yeosu - GrandCanyon1 - LasVegas - GrandCanyon2
  if (frameCounts <= 160) { // 160
      drawYeosu();
  }
  else if (frameCounts >= 160 & frameCounts < 320) {
      drawGrandCanyon(); // transition: light to dark sky
  } 
  else if (frameCounts >= 320 & frameCounts < 480) {
    drawLasVegas();
  }
  else if (frameCounts >= 480 & frameCounts < 640) {
    drawGrandCanyon2(); // transition: dark to light sky
  }
  else if (frameCounts === 640) {
    frameCounts = 0;
  }  
  frameCounts++;
}

// =====================================================================
// ==============================YEOSU==================================
// =====================================================================

function drawYeosu() {
  setGradient(0, 0, width, height / 2 + 70, c1, c2, yaxis); // sky
  drawSun();
  drawMountain1();
  drawMountain2();
  drawOcean();
  drawSunReflection();
  updateClouds();
  removeClouds();
  addClouds();
  setGradient(0, 390, width, 480, c3, c4, xaxis); // ground
  updateTrees();
  removeTrees();
  addTrees();
  drawMe();
  drawFog();
  updateBird();
  removeBird();
  addBird();
  writeText();
}

function setGradient(x, y, w, h, c1, c2, axis) {
  // Top to bottom gradient
  if (axis == yaxis) { 
    for (var i = y; i <= y + h; i++) {
      var inter = map(i, y, y + h, 0, 1);
      var c = lerpColor(c1, c2, inter);
      stroke(c);
      line(x, i, x + w, i);
    }
  }
  // Left to right gradient
  else if (axis == xaxis) {
    for (var i = x; i <= x + w; i++) {
      var inter = map(i, x, x + w, 0, 1);
      var c = lerpColor(c1, c2, inter);
      stroke(c);
      line(i, y, i, y + h);
    }
  }
}

function drawMountain1(){
  noStroke();
  fill(204, 157, 135); 
  beginShape(); 
  for (var x = 0; x < width; x++) {
    var t = (x * terrainDetail1) + (millis() * terrainSpeed1);
    var y = map(noise(t), 0, 1.8, height / 4 - 10, height);
    vertex(x, y); 
  }
  vertex(width, height);
  vertex(0, height);
  endShape();
}

function drawFog() { 
  for (var y = 200; y < height + 5; y++) {
    var f = map(y, height / 2 - 40, 550, 0, 100);
    stroke(255, f);
    line(0, y, width, y);
  }
}

function drawMountain2(){
  fill(147, 126, 115); 
    noStroke();
    beginShape(); 
      for (var x = 0; x < width; x++) {
            var t = (x * terrainDetail2) + (millis() * terrainSpeed2);
            var y = map(noise(t), 0, 2, height / 4 + 60, height);
            vertex(x, y); 
      }
      vertex(width,height);
      vertex(0,height);
    endShape();
}

function drawOcean() {
    fill(170, 146, 121); 
    noStroke();
    beginShape(); 
      for (var x = 0; x < width; x++) {
            var t = (x * terrainDetail3) + (millis() * terrainSpeed3);
            var y = map(noise(t), 0, 2, height - 230, height);
            vertex(x, y); 
      }
      vertex(width, height);
      vertex(0, height);
    endShape();
}

function drawSun() {
	// All sun parts based on mouseY
  	sunMouse = constrain(mouseY, 0, height / 3 + 30);
    noStroke();
    // Sunglow
    // Color less intense and size smaller as sun goes farther up
    fill(253, 254 - sunMouse, 221 - sunMouse, 20 - sunMouse*0.02);
    ellipse(width / 3, sunMouse + 40, sunMouse - 10, sunMouse - 10);
    fill(253, 254 - sunMouse, 221 - sunMouse, 20 - sunMouse*0.03);
    ellipse(width / 3, sunMouse + 40, sunMouse*1.1, sunMouse*1.1);
    fill(253, 254 - sunMouse, 221 - sunMouse, 20 - sunMouse*0.05);
    ellipse(width / 3, sunMouse + 40, sunMouse*1.2 + 10, sunMouse*1.2 + 10);
    // Sunrays
    fill(253, 254, 221, 30);
    triangle(width / 3, sunMouse + 20, width / 3 - 40, height / 3 + 90, width / 3 - 10, height /3 + 80); // left big
    triangle(width / 3, sunMouse + 20, width / 3 + 40, height / 3 + 80, width / 3 + 10, height /3 + 70); // right big
    triangle(width / 3, sunMouse + 20, width / 3 - 50, height / 3 + 90, width / 3 - 30, height /3 + 80); // left small
    triangle(width / 3, sunMouse + 20, width / 3 + 50, height / 3 + 80, width / 3 + 30, height /3 + 70); // right small
    triangle(width / 3, sunMouse + 20, width / 3 - 70, height / 3 + 70, width / 3 - 80, height /3 + 70); // left small2
    triangle(width / 3, sunMouse + 20, width / 3 + 70, height / 3 + 90, width / 3 + 80, height /3 + 80); // right small2
    // Sun
    fill(253, 254, 221, sunMouse + 30);
    ellipse(width / 3, sunMouse + 40, sunMouse - 20, sunMouse - 20);
}

function drawSunReflection() { 
	// Size of reflection on ocean corresponds to sun size/distance away
    var x = 10;
    var y = 47;
    var w = sunMouse;
    var h = 10;
    noStroke();
    // Outer darker glow
    fill(248, 172, 137, 100);
    push();
    rectMode(CENTER);
    rect(width / 3, 2 * height / 3 + y, w, h, 10);
    rect(width / 3, 2 * height / 3 + y - 13, w * 0.8, h, 10);
    rect(width / 3, 2 * height / 3 + y - 26, w * 0.6, h, 10);
    // Inner lighter glow
    fill(253, 254, 221, 50);
    rect(width / 3, 2 * height / 3 + y - 4, w * 0.9, h * 0.8, 10);
    rect(width / 3, 2 * height / 3 + y - 17, w * 0.7, h * 0.8, 10);
    rect(width / 3, 2 * height / 3 + y - 30, w * 0.5, h * 0.8, 10);
    pop();
}

function updateClouds(){
  for (var i = 0; i < clouds.length; i++) {
    clouds[i].move();
    clouds[i].display();
  }
}

function removeClouds(){
  var keepClouds = [];
  for (var i = 0; i < clouds.length; i++) {
      if (clouds[i].x - this.width / 2 < width) {
        keepClouds.push(clouds[i]);
      }
  }
  clouds = keepClouds;
}

function addClouds(){
  var newCloud = 0.01;
  if (random(0, 1) < newCloud) {
    clouds.push(drawClouds(random(width)))
  }
}

function moveClouds(){
  this.x += this.speed;
}

function displayClouds(){
  var b = random(165, 180);
  fill(255, 240, 240, 30);
  ellipse(this.x, this.y, this.width, this.height);
  ellipse(this.x + 50, this.y + 10, this.width - 20, this.height - 70);
  ellipse(this.x - 50, this.y - 5, this.width - 70, this.height - 10);
}

function drawClouds(newCloudX) {
  var cloud = {
    x: newCloudX,
    y: random(30, height / 2),
    width: random(150, 250), 
    height: random(20, 50),
    speed: random(0.5, 1.5),
    move: moveClouds,
    display: displayClouds
  }
  return cloud;          
}

function updateTrees() {
  for (var i = 0; i < trees.length; i++) { 
    trees[i].move();
    trees[i].display();
  }
}

function removeTrees() {
  var keepTrees = [];
  for (var i = 0; i < trees.length; i++) {
    if (trees[i].x < width) {
      keepTrees.push(trees[i]);
    }
  }
  trees = keepTrees;
}

function addTrees() {
  var newTree = 0.02;
  if (random(0, 1) < newTree) {
    trees.push(drawTrees(random(width)));
  }
}

function moveTrees() {
  this.x += this.speed;
}

function displayTrees() {
  // Tree height based on mouseY, mapped to a reasonable extent
  var treeMouse = map(mouseY, 0, height, height / 3, 0);
  var treeMouseCon = constrain(treeMouse, 0, height)
  // Trunk
  stroke(c4);
  strokeWeight(4);
  line(this.x, this.y + 20 - treeMouseCon, this.x, this.y + 40);
  // Leaves
  fill(c3, 20);
  stroke(c3);
  strokeWeight(7);
  strokeJoin(ROUND);
  triangle(this.x, this.y - treeMouseCon, this.x + 20, this.y + 25, this.x - 20, this.y + 25);
  // Add snow if on Grand Canyon scene
  if (frameCounts >= 160 & frameCounts < 320 || frameCounts >= 480 && frameCounts < 640) {
    fill(250);

This project was inspired by my love of taking photos, especially of nature and cityscapes. I tried recreating the feel and weather of three shots below in a looping generative landscape. Follow me! You can speed up or slow my pace using the slider and control objects like the sun and buildings using the mouse.

Scene 1 – Sunrise at Yeosu (Javascript, my photo, sketch)
Scene 2 – Snowy Grand Canyon
Scene 3 – Rainy Las Vegas

Since this doesn’t load properly on WP, access zip file here!

Leave a Reply