// 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.
![](wp-content/uploads/2018/12/Artboard-8-1024x274.png)
![](wp-content/uploads/2018/12/Artboard-10-1024x278.png)
![](wp-content/uploads/2018/12/Artboard-6-1024x281.png)
Since this doesn’t load properly on WP, access zip file here!