// 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.
Since this doesn’t load properly on WP, access zip file here!