Erin Fuller – Generative Landscape

//Erin Fuller
//SectionA
//efuller@andrew.cmu.edu
//Project 10

var terrainSpeed1 = 0.00009; //background mountain speed
var terrainDetail1 = 0.006; //background mountain detail

var terrainSpeed2 = 0.00025; //foreground mountain speed
var terrainDetail2 = 0.005; //foreground mountain detail

var terrainSpeed3 = 0.00025; //foreground plane speed
var terrainDetail3 = 0.0015; //foreground plane detail

var img;
var gFrameCount = 0; 

function preload() {
    img = loadImage("https://i.imgur.com/mO1FDPJ.png"); //preload image
}

function setup() {
    createCanvas(480, 480);
    frameRate(10);
}

function draw() {
//sky
    colorMode(HSB);
    var s = 55; // saturation 55
    var b = 100; //brightness 100

    gFrameCount = gFrameCount + 1;
    if (gFrameCount > 600) {
        gFrameCount = 0;
    } //add frame count, restart after 600

    if (gFrameCount > 300) {
        var s = map(gFrameCount, 300, 600, 85, 55);
        var b = map(gFrameCount, 300, 600, 25, 100);
        var m = map(gFrameCount, 300, 600, 25, 65);
    } else {
        var s = map(gFrameCount, 0, 300, 55, 85);
        var b = map(gFrameCount, 0, 300, 100, 25);
        var m = map(gFrameCount, 0, 300, 65, 25);        
    } //changes sky background + mountains to night
    background(214, s, b); 

//sun & moon
    var centerx = width / 2; 
    var centery = 170;
    var radius = 120;
    var d = 45 + random(-2, 2); //makes sun and moon more fun
    var rAngle = map(frameCount, 0, 600, 0, 360) + 45; //
    
    noStroke();
    line(centerx, centery, centerx + x, centery - y); //rotating line w circles at end

    var sX = cos(radians(rAngle)) * radius;
    var sY = sin(radians(rAngle)) * radius;

    ellipseMode(CENTER);
    fill('yellow');
    ellipse(centerx + sX, centery - sY, d, d); //sun

    var mX = cos(radians(-rAngle)) * radius; //neagtive to go in opposite of sun
    var mY = sin(radians(-rAngle)) * radius;

    fill('white');
    ellipse(centerx + mX, centery - mY, d, d); //moon

//background-mountain
    noStroke(); 
    fill(32, 60, m - 5);
    beginShape(); 
    vertex(0, height);
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail1) + (millis() * terrainSpeed1);
        var y = map(noise(t), 0, 1, height / 12, height / 3);
        vertex(x, y); 
    }
    vertex(width, height);
    endShape();

//foreground-mountain
    fill(32, 45, m); 
    beginShape(); 
    vertex(0, height);
    for (var z = 0; z < width; z++) {
        var f = (z * terrainDetail2) + (millis() * terrainSpeed2);
        var y = map(noise(f), 0, 1, height / 12, height / 2);
        vertex(z, y); 
    }
    vertex(width, height);
    endShape();

//foreground-plane
    fill(32, 30, m + 20); 
    beginShape(); 
    vertex(0, height);
    for (var z = 0; z < width; z++) {
        var p = (z * terrainDetail3) + (millis() * terrainSpeed3);
        var y = map(noise(p), 0, 1, height / 2, height * .75);
        vertex(z, y); 
    }
    vertex(width, height);
    endShape();
 
//foreground-train
    fill(10); 
    beginShape(); // clockwise

    vertex(0, 480);
    vertex(0, 0);
    vertex(480, 0);
    vertex(480, 480);

    var a = 20;
    var b = 40;
    var c = 60

    beginContour(); // counter clockwise
    vertex(b, a); //left-up
    bezierVertex(a, a, a, a, a, b);
    vertex(a, height - b - c); //left-down
    bezierVertex(a, height - a - c, a, height - a - c, b, height - a - c);
    vertex(width - b, height - a - c); //right-down
    bezierVertex(width - a, height - a - c, width - a, height - a - c, width - a, height - b - c);
    vertex(width - a, b); //right up
    bezierVertex(width - a, a, width - a, a, width - b, a);  

    endContour();
    endShape(CLOSE);

    rect(0, 115, width, 5);
    rect(0, 210, width, 5);
    rect(0, 305, width, 5);
    
    noFill(); 
    colorMode(RGB, 225);
    stroke(139, 186, 213, 130);
    strokeWeight(10);
    
    line(60, 100, 120, 40); //"window glares"
    line(62, 73, 93, 42);
    line(95, 95, 130, 59);

    line(426, 322, 387, 361); //"window glares"
    line(443, 328, 390, 381);
    line(451, 344, 412, 382);

//foreground cowboy
    image(img, -90, 140, img.width * .25, img.height * .25);
}

I generated a landscape that both travels through space and time. The cowboy is watching the desert pass by from the train, as well as the day change to night and back.

Jamie Dorst Project 10

sketch

/*
Jamie Dorst
jdorst@andrew.cmu.edu
Section A
Project-10
*/

var trees = [];
// noise variables
var terrainSpeed1 = 0.0005;
var terrainDetail1 = 0.002;
var terrainSpeed2 = 0.0003;
var terrainDetail2 = 0.004;
var terrainSpeed3 = 0.0001;
var terrainDetail3 = 0.006;

function setup() {
    createCanvas(480, 480);
    // create an initial collection of trees
    for (var i = 0; i < 7; i++){
        var rx = random(width);
        trees[i] = makeTree(rx);
    }
    frameRate(10);
}

function draw() {
    background('#E0F7FA');
    // draw sun
    fill('gold');
    noStroke();
    ellipse(100, 100, 100, 100);
    // draw clouds
    fill(255);
    ellipse(340, 80, 50, 50);
    ellipse(360, 90, 60, 60);
    ellipse(380, 70, 75, 75);
    ellipse(400, 80, 50, 50);

    ellipse(220, 200, 50, 50);
    ellipse(250, 210, 60, 60);
    ellipse(260, 190, 75, 75);
    ellipse(280, 200, 50, 50);

    drawHills();
    updateAndDisplayTrees();
    removeTreesThatHaveSlippedOutOfView();
    addNewTreesWithSomeRandomProbability(); 
}

function drawHills() {
    // blue hills
    beginShape(); 
    stroke('#3949AB');
    for (var q = 0; q < width; q++) {
        var t = (q * terrainDetail3) + (millis() * terrainSpeed3);
        var y = map(noise(t), 0,1, 25, height)
        line(q, y, q, height); 
    }
    endShape();
    // pink hills
    beginShape(); 
    stroke('#E91E63');
    for (var a = 0; a < width; a++) {
        var t = (a * terrainDetail2) + (millis() * terrainSpeed2);
        var y = map(noise(t), 0,1, height / 2, height)
        line(a, y, a, height); 
    }
    endShape();

    // yellow hills
    beginShape(); 
    stroke('#FFEB3B');
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail1) + (millis() * terrainSpeed1);
        var y = map(noise(t), 0,1, 2 * height / 3, height)
        line(x, y, x, height); 
    }
    endShape();
}

function updateAndDisplayTrees() {
    // update the trees' positions and display them
    for (var i = 0; i < trees.length; i++){
        trees[i].move();
        trees[i].display();
    }
}

function removeTreesThatHaveSlippedOutOfView() {
    // if a tree has dropped off the left edge remove it from the array
    // copy all the trees we want to keep into a new array
    var treesToKeep = [];
    for (var i = 0; i < trees.length; i++){
        if (trees[i].x + trees[i].breadth > 0) {
            treesToKeep.push(trees[i]);
        }
    }
    trees = treesToKeep;
}

function addNewTreesWithSomeRandomProbability() {
    // add a new tree to the end, 20% chance
    var newTreeLikelihood = 0.2; 
    if (random(0,1) < newTreeLikelihood) {
        trees.push(makeTree(width));
    }
}

// draw the tree
function treeDisplay() {
    if (this.colors < 0.5) {
        var fillColor = 255;
        var strokeColor = 0;
    } else {
        fillColor = 0;
        strokeColor = 255;
    }
    fill(fillColor);
    noStroke();
    ellipseMode(CENTER);
    ellipse(this.x, height - this.trunkHeight, this.treeSize, this.treeSize);
    stroke(strokeColor);
    strokeWeight(3);
    line(this.x, height - this.trunkHeight - 5, this.x, height);
    line(this.x, height - this.trunkHeight + 5, this.x - 7, height - this.trunkHeight - 2);
    line(this.x, height - this.trunkHeight + 10, this.x + 7, height - this.trunkHeight + 3);
}

function makeTree(birthLocationX) {
    var tree = {
        trunkHeight: random(40, 80),
        treeSize: random(30, 50),
        colors: random(0, 1),
        x: birthLocationX,
        sizes: 50,
        breadth: 50,
        speed: -20.0,
        move: treeMove,
        display: treeDisplay
    }
    return tree;
}

// method to update position of building every frame
function treeMove() {
    this.x += this.speed;
}

For this project, I just wanted to make a fun landscape and then have a lot of contrasting colors, which is why I made the trees randomize to be black with white or white with black. I had a lot of trouble at the beginning figuring out how to get the trees to stay on the page, and then later, move. I also struggled with getting the hills to be different heights, but when I figured it out it was a pretty simple change. I think that overall though I ended up learning a lot more about objects, and I’m happy with how it turned out.

Min Jun Kim- Project 10

Look for a while to see all the details!

/*
Min Jun Kim
15104
Project 10
This program draws a highway setting with randomly made objects
*/

var terrainSpeed = 0.0001;
var terrainDetail = 0.0005;
var terrainmapx = [];
var terrainmapy = [];
var dec = 0; //counter for time
var cars = []; //array of cars

function setup() {
	//sets up canvas and initial 3 cars 
    createCanvas(640, 400);
    for (var i = 0; i < 3; i++) {
    	var rx = random(width);
    	cars[i] = makeCar(rx);
    }

    
}
 


function draw() {
    background(0);    
    fill(0); 
    stroke(0);
    
    beginShape(); 
    for (var x = -30; x < width; x++) {
        var t = (x * terrainDetail) + (millis() * terrainSpeed);
        var y = map(noise(t), 0,1, 0, height)+100;
        
        //draws the wavey terrain background 
        vertex(0,height);
        vertex(width/2, height);
        vertex(width, height);
        vertex(x, y); 

        //index the values for access
        terrainmapx[x]=x; 
        terrainmapy[x]= y;

    }
    endShape();
    //specifications of drawing future items
    stroke(100);
    rectMode(CENTER);
    //when the array gets too full erase the old values
    for (i = 0; i < terrainmapx.length; i+=1) {
    	if(terrainmapx.length > 700) {
        	terrainmapx.pop();
        	terrainmapy.pop();
        }
       	
       	//draws the highway
        stroke(50);
        fill(50);
        rect(i, terrainmapy[i]-65,30,110); 
        fill(100);
        stroke(100);
        rect(i, terrainmapy[i],30,20);
        rect(i, terrainmapy[i]-130,20,20);



    }
    //draws the while center line of the highway
    for (i = 0; i < width+55; i += 50) {
    	fill(240);
    	rect(i+20, terrainmapy[i]-60, 30, 7);
    }
    //calls functions for the car
    DisplaynUpdateCars();
    addCarWithSomeRandomProbability();
    
    //draw the car going right that stays on the canvas
    push();
    translate(150, terrainmapy[150]-30);
    rotate(degrees((atan2(terrainmapy[640]-terrainmapy[150]-30,640-150))+360%360))
    fill(250,240,95,80);
    noStroke();
    triangle(15,0,100,40,100,-40);
    fill(0);
    rect(0,0, 60, 30);
    fill(240,0,0);
    rect(0,0, 30, 30);
    pop()
    

    //draws the moon
    fill(250,240,95);
    ellipse(50, terrainmapy[50]-300, 50,50);
    fill(0);
    ellipse(62, terrainmapy[50]-300, 30,30);

    //draws the raindrops
    for (var y = 5; y <= 480; y+=20) {
		for (var x = 5; x <= 640; x += 10) {
			stroke(0,40,50,80);
			line(x,y,x,y+random(0,20));
		}
	}
    
}

function carMove() {
	//updates the speed and location of the car
	if (oldspeed > this.speed) {
		this.speed = this.speed+ 10;
	}
	var oldspeed = this.speed;
	this.x += this.speed;


}

function DisplaynUpdateCars() {
	//calls the display and update function
	for (var i = 0; i < cars.length; i++) {
		cars[i].display();
		cars[i].move();
	}
}

function carsDisplay() {
	//draws the car itself
	noStroke();
	var heighty= terrainmapy[round(this.x)];
	
	push();

	for (i=0; i<10; i++) {
		fill(250,240,95,10);
		triangle(this.x, heighty-85, this.x-this.sizeX, heighty-85-40,this.x-this.sizeX,heighty-85+40);
		fill(this.colory,100,100);
		rect(this.x, heighty-85, this.sizeX, this.sizeX/2);
		push();
		fill(200);
		rect(this.x, heighty-85, this.sizeX/2, this.sizeX/2);
		pop()
	}
	
	pop();
	
}




function addCarWithSomeRandomProbability() {
	//probability of a car increases over time, which guarentees 
	//that there won't be too long of a gap between cars
    dec += 1;
    if (random(0,1) < dec/500) {
        cars.push(makeCar(width));
        dec = 0;
    }
}

function makeCar(birthLocationX) {
	//specifications of the car
	var car = {x: birthLocationX,
		sizeX: random(60,120),
		colory: random(250),
		speed: random(-20,-15),
		move: carMove,
		display: carsDisplay


	}
	return car;
}




I wanted to make a program that draws on uniquely created terrain, so I studied the way of using noise to create new terrain. Then I made it such that the terrain appears to be smooth and wavy. I indexed the values for later use, and made it such that it disappears when reaching a certain limit- This helped improve the speed of the animation and reduced the need for indexing the x value. I then made it such that random cars appear on both sides, but it looked unrealistic (physics wise) so I made one car stay in the same spot. To make things more moody, I changed it to a night-setting with transparent headlights, a moon and the rain. One problem that I had was that sometimes, the car would overlap when initially starting out, and I tried to go around this problem by changing the range of the speed and adding a counter to the probability of making a new car. I really liked how this project turned out and it taught me well about object programming.

Initial sketch. Some elements were left out.

Kevin Thies – Project 10

mountain roads

// Kevin Thies
// Section C
// kthies@andrew.cmu.edu
// Project 10 - Generative Landscape

// initiate containers for mountains, trees, and posts
var mountains = [];
var trees = [];
var posts = [];

// keeps track of time for post spawning
var timer = 0;

// preset y values to act as "layers"
var layer = [470, 435, 400, 380, 320, 290];


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

    // add starting mountains
    for(var i = 0; i < 15; i++) {
        var randomX = random(width);
        mountains[i] = makeMountain(randomX, 5);
    }

    // add starting trees
    for(var i = 0; i < 100; i++) {
        var randomX = random(width);
        trees[i] = makeTree(randomX, 5);
    }

    // add closer starting trees with different speed and color
    for(var i = 100; i < 200; i++) {
        var randomX = random(width);
        var newTree = makeTree(randomX, 4);
        newTree.color = color(10,0,29);
        newTree.speed = 0.9;
        trees[i] = newTree;
    }
}

function draw() {

    // background
    background(12,24,68);
    strokeWeight(3);
    backgroundGradient();
    strokeWeight(0);

    // sun
    strokeWeight(0);
    fill("lemonchiffon");
    ellipse(width / 2, layer[5], 100, 100);

    // ground
    fill(12,24,68);
    rectMode(CORNERS);
    rect(0, layer[5], width, height);
    fill(10,0,29);
    rect(0, layer[4], width, height);

    // mountains
    strokeWeight(0);
    updateAndDisplayMountains();
    removeOffscreenMountains();
    addNewMountains();

    // trees at base of mountain
    updateAndDisplayTrees();
    removeOffscreenTrees();
    addNewTrees();
    addNewCloserTrees();

    // highway railing
      // posts
    updateAndDisplayPosts();
    removeOffscreenPosts();
    addNewPosts();

      // solid barrier part of the rail
    fill(40,37,31);
    rect(0, layer[2], width, layer[0]);
    stroke(98,87,93);
    strokeWeight(3);
    line(0, layer[2], width, layer[2]);
    strokeWeight(0);
    rectMode(CENTER);
    fill(24,12,14);
    rect(width/2, layer[1], width, 40)
}

// POSTS //////////////////////////////////////////////////////////////////

// moves the existing posts
function updateAndDisplayPosts() {
    for(var i = 0; i < posts.length; i++) {
        posts[i].move();
        posts[i].display();
    }
}

// removes the posts that are offscreen
function removeOffscreenPosts() {
    // if posts are offscreen, don't re-add them to posts[]
    var postsToKeep = [];
    for(var i = 0; i < posts.length; i++) {
        if (posts[i].x + 40 > 0) {
            postsToKeep.push(posts[i]);
        }
    }
    posts = postsToKeep;
}

// adds the new posts
function addNewPosts() {
    // every 40 frames, shoot in a new post
    timer ++;
    if(timer == 40) {
        timer = 0;
        posts.push(makePost(width))
    }
}

// how posts are made
function makePost(px) {
    var post = {x: px,
                speed: 12,
                display: postDisplay,
                color: color(98,87,93),
                color2: color(40,37,31),
                move: postMove,
    }
    return post;
}

// is how to move the posts
function postMove() {
    this.x -= this.speed;
}

// builds the posts from the this.x coordinate
function postDisplay() {
    stroke(this.color);
    strokeWeight(3);
    //       |      part of post
    line(this.x, height, this.x, layer[2] - 20);
    //      / /     part of post
    line(this.x, layer[2] - 20, this.x - 10, layer[2] - 10);
    line(this.x - 20, layer[2] - 20, this.x - 30, layer[2] - 10);
    //       -      part of post
    line(this.x - 5, layer[2] - 15, this.x - 25, layer[2] - 15);
    strokeWeight(0);
}

// TREES //////////////////////////////////////////////////////////////////

// how trees are made
function makeTree(tx, layer) {
    var tree = {x: tx,
                layer: layer,
                speed: 0.7,
                display: treeDisplay,
                color: color(12,24,68),
                move: treeMove,
                scale: random(0.5, 1)};
    return tree;
}

// how the trees are moved
function treeMove() {
    this.x -= this.speed;
}

// builds the far trees from an x coordinate
function treeDisplay() {
    fill(this.color);
    ellipse(this.x, layer[this.layer], 20 * this.scale, 20 * this.scale);
}

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

// removes trees that are offscreen
function removeOffscreenTrees() {
    // if tree is offscreen, don't re-add it to trees[]
    var treesToKeep = [];
    for(var i = 0; i < trees.length; i++) {
        if (trees[i].x + 20 > 0) {
            treesToKeep.push(trees[i]);
        }
    }
    trees = treesToKeep;
}

// random chance generates a new tree on layer 5
function addNewTrees() {
    var newTreeChance = 0.1;
    if(random(0,1) < newTreeChance) {
        trees.push(makeTree(width, 5))
    }
}

// random chance generates a new tree on layer 4 with fitting color and speed
function addNewCloserTrees() {
    var newTreeChance = 0.1;
    if(random(0,1) < newTreeChance) {
        var newTree = makeTree(width, 4);
        newTree.color = color(10,0,29);
        newTree.speed = 0.9;
        trees.push(newTree);
    }
}

// BACKGROUND //////////////////////////////////////////////////////////////

// makes the gradient seen in the background from y = 0 to layer 5
function backgroundGradient() {
    for(var i = 0; i < layer[5]; i++) {
        var g = map(i, 0, layer[5], 0, 140);
        stroke(255, g, 0);
        line(0, i, width, i);
    }
}

// MOUNTAINS //////////////////////////////////////////////////////////////

// moves existing mountains (so strong)
function updateAndDisplayMountains() {
    for(var i = 0; i < mountains.length; i++) {
        mountains[i].move();
        mountains[i].display();
    }
}

// removes mountains that are offscreen
function removeOffscreenMountains() {
    // if mountain is offscreen, don't re-add it to mountains[]
    var mountainsToKeep = [];
    for(var i = 0; i < mountains.length; i++) {
        if (mountains[i].x + (200 * mountains[i].scale) > 0) {
            mountainsToKeep.push(mountains[i]);
        }
    }
    mountains = mountainsToKeep;
}

// random chance generates a new mountain
function addNewMountains() {
    var newMountainChance = 0.01;
    if(random(0,1) < newMountainChance) {
        mountains.push(makeMountain(width, 5))
    }
}

// how mountains are made
function makeMountain(mx, layer) {
    var mountain = {x: mx,
                    layer: layer,
                    speed: 0.5,
                    display: mountainDisplay,
                    color: color(85,54,86),
                    color2: color(85, 54, 106),
                    move: mountainMove,
                    scale: random(0.5, 1)};
    return mountain;
}

// how mountains are moved
function mountainMove() {
    this.x -= this.speed;
}

// actually builds the moutain based off an x coordinate
function mountainDisplay() {
    fill(this.color);
    triangle(this.x, layer[this.layer],
         this.x + (200 * this.scale), layer[this.layer],
         this.x + (100 * this.scale), layer[this.layer] - (180 * this.scale));
    fill(this.color2);
    triangle(this.x + (170 * this.scale), layer[this.layer],
              this.x + (200 * this.scale), layer[this.layer],
              this.x + (100 * this.scale), layer[this.layer] - (180 * this.scale));
}

// Congradulations, you made it to the end! *confetti emoji*

At first when I was thinking about what to do, I thought about long car rides through the mountains. I sketched up an idea that involved cars going different directions, but after implementing the moving mountains, I realized I had to simplify my idea. I kept the most important part of that, the mountains, and rebuilt from there. I think having all the layers helps add some measurable scale to the mountains and trees in the background. I’m also just really with how it turned out, and although making the objects got tedious, once I had one and understood how the pieces fit together, it really sped up from there.

My plan involving mountains, roads, and layers

Judy Li-Project-10-Landscape

judyli: Landscape Project 10

/*
Judy Li
Section A
judyli@andrew.cmu.edu
Project-10
*/

var terrainSpeed = 0.0005;
var terrainDetail = 0.002;
var terrainDetail1 = 0.00125;
var terrainDetail2 = 0.001;
var terrainDetail3 = 0.0005;
var yaxis = 1;
var c;
var c1;
var c2;
var star = [];

function setup() {
    createCanvas(480, 480);
    frameRate(10);
    c2 = color(179, 77, 37);
    c1 = color(64, 40, 74);
    c = color(247, 222, 85);

    star.push(drawStar());
}

function wave1() {
	beginShape();
	stroke(26, 20, 95);
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail) + (millis() * terrainSpeed);
        var y = map(noise(t), 0, 5, 0, height / 4);
        line(x, y + (height / 2), x, height); 
    }
    endShape();
}

function wave2() {
	beginShape();
	stroke(26, 40, 95);
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail1) + (millis() * terrainSpeed);
        var y = map(noise(t), 0, 4, 0, height / 2);
        line(x, y + 15 + (height / 2), x, height); 
    }
    endShape();
}

function wave3() {
	beginShape();
	stroke(26, 60, 95);
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail2) + (millis() * terrainSpeed);
        var y = map(noise(t), 0, 3.5, 0, height);
        line(x, y + 25 + (height / 2), x, height); 
    }
    endShape();
}

function wave4() {
	beginShape();
	stroke(26, 70, 95);
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail3) + (millis() * terrainSpeed);
        var y = map(noise(t), 0, 3, 0, height);
        line(x, y + 50 + (height / 2), x, height); 
    }
    endShape();
}

 
function draw() {
    background("white");
    nStar();
    nPosition();
    nArray();
    setGradient(0, 0, width, height / 3, c1, c2, yaxis);
    setGradient(0, height / 3, width, 2 * (height / 3), c2, c, yaxis);

    fill(247, 222, 125);
    ellipse(width / 2, 25 + (height / 2), 50, 50);

    push();
    strokeWeight(1.5);
    stroke(255, 255, 255, 100);
    ellipse(width - 50, 50, 50, 50);
    fill(247, 222, 200);
    ellipse(width - 50, 50, 49, 49);
    pop(); 

    for (var i = 0; i < star.length; i++) {
        star[i].display();
    }

    push();
    wave1();
    wave2();
    wave3();
    wave4();
    noFill();
    rect(0, 0, width, height);
    pop();
}

function nStar() {
    if (random(0, 250) < 50) {
        star.push(drawStar());
    }
}

function nPosition() {
    for (var i = 0; i < star.length; i++) {
        star[i].move();
    }
}

function nArray() {
    var ogStar = [];
    for (var i = 0; i < star.length; i++) {
        if (star[i].x > 0) {
            ogStar.push(star[i]);
        }
    }
    star = ogStar;
}

function moveStar() {
    this.x -= this.speed;
}

function seeStar() {
    stroke(255, 255, 255, 250);
    strokeWeight(random(1, 5));
    point(this.x, this.y);
}

function drawStar() {
    var star = {x: width,
        pdist: 100,
        speed: 5,
        starsize: round(random(0, 5)),
        y: round(random(0, height / 4)),
        move: moveStar,
        display: seeStar
        }
    return star;
}

function setGradient(x, y, w, h, c1, c2, axis) {
    noFill();
    if (axis == yaxis) {  // Top to bottom gradient
	    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);
		}
	}
}

For this project, I wanted to mimic the moment of a sunset on the horizons of an ocean. I used four waves to create a different movement between the others. I also included stars slowly throughout to capture the day to night lapse. And to make it a little fun on the part of the sun, the stroke weights were in a random order so that it captures the movement of the disappearing sun. I had a lot of fun with this project, but I struggled a bit in the beginning with the details of the wave. But I think that the templates on the course page helped a lot with my other objects.

initial idea sketch