Generative Beach Landscape

When I saw the prompt for the project this week, I immediately thought of doing something with a noise function. I felt as though mountains wouldn’t allow for enough variability, so I decided to do a beach. I laid out the very basic sand, water, and sky, and then added embellishing elements to try to create a drive by beach scene.

Beach
var boats = [];     //arrays to hold respective objects
var clouds = [];
var umbrellas = [];
var planes = []; 
var buildings = [];
var railings = [];
var people = [];
var towels = [];
var landscape = [];     //array that creates slope of shoreline
var noiseParam = 0;     
var noiseStep = 0.005;      //defines extremity of shoreline slope


function setup() {
    createCanvas(480,300); 
    
    for (var i = 0; i < 3; i++){        //make a certain amount of (object) to start out, at random locations within a constraint
        var rx = random(width);
        var ry = random(80,150)
            boats[i] = makeBoat(rx,ry);
    }

    for (var i = 0; i < 3; i++){
        var Cx = random(width);
        var Cy = random(0,60)
            clouds[i] = makeCloud(Cx,Cy);
    }

    for (var i = 0; i < people.length; i++){
        var Tx = random(width);
        var Ty = random(250,300)
            towels[i] = makeTowel(Tx,Ty);
    }
    for (var i = 0; i < people.length; i++){
        var Px = random(width);
        var Py = random(250,300)
            people[i] = makePerson(Px,Py);
    }

    for (var i = 0; i < 5; i++){
        var Ux = random(width);
        var Uy = random(250,300)
            umbrellas[i] = makeUmbrella(Ux,Uy);
    }
    
    for (var i = 0; i < 15; i++){
        var Bx = random(width);
            buildings[i] = makeBuilding(Bx);
    }

    for (var i = 0; i < 0.9; i++){
        var Px = random(width);
        var Py = random(0,20)
            planes[i] = makePlane(Px,Py);
   }
    

    for(var i = 0;i <= width / 5;i++){    
        var n = noise(noiseParam);       //picks value 0-1
        var value = map(n,0,1,50,height);        //scales it to the canvas size

            landscape.push(value);      //adds to array
            noiseParam += noiseStep;      //moves to the right for the next point in the array
   }
    
    frameRate(5);
}



function draw() {
    background(3,220,245);

    fill(13,66,212,230);    //dark blue
        rect(0,height / 4,width,height);      //body of water   
    fill(227,232,164,175);  //pale beige
        rect(0,height / 4-7,width,7);    //distant shoreline

                    //call the functions to spawn and despawn respective obejcts
    removeBoat();         
    newBoat(); 

    removeCloud();
    newCloud();

    removeUmbrella();

    removePlane();
    newPlane();

    removeBuilding();
    newBuilding();

    removeRailing();
    newRailing();

    removePerson();

    removeTowel();
  
   
                                                //call the move and show functions to continually draw and redraw objects after updated coordinates
    for (var i = 0; i < clouds.length; i++){
        clouds[i].move();
        clouds[i].show();
    }

    for (var i = 0; i < buildings.length; i++){
        buildings[i].move();
        buildings[i].show();
     }

    for (var i = 0; i < boats.length; i++){
        boats[i].move();
        boats[i].show();
    }
   

    displayHorizon();

     for (var i = 0; i < towels.length; i++){
        towels[i].move();
        towels[i].show();
    }

    for (var i = 0; i < people.length; i++){
        people[i].move();
        people[i].show();
    }

    for (var i = 0; i < umbrellas.length; i++){
        umbrellas[i].move();
        umbrellas[i].show();
    }


    for (var i = 0; i < planes.length; i++){
       planes[i].move();
       planes[i].show();
     }

    fill(159,159,159);
        rect(0,height-50,width,40);
    fill(110,110,110);
        rect(0,height-45,width,30);


    for (var i = 0; i < railings.length; i++){
       railings[i].move();
       railings[i].show();
     }    
}

                        //functions to remove an object from a displayed array once "out of sight"
function removeBoat(){
    
    var boatsToKeep = [];    //the boats that should still be displayed
    for (var i = 0; i < boats.length; i++){
        if (boats[i].x + boats[i].breadth > 0) {    //if the boat is closer than it's width to the edge
            boatsToKeep.push(boats[i]);     //add this boat to the boats that will be displayed
        }
    }
    boats = boatsToKeep; // only display the baots currently being kept
}

function removeCloud(){
    var cloudsToKeep = [];
    for (var i = 0; i < clouds.length; i++){
        if (clouds[i].x + clouds[i].breadth > 0) {
           cloudsToKeep.push(clouds[i]);
        }
   }
    clouds = cloudsToKeep; 
}

function removeUmbrella(){
    var umbrellasToKeep = [];
    for (var i = 0; i < umbrellas.length; i++){
        if (umbrellas[i].x + umbrellas[i].breadth > 0) {
           umbrellasToKeep.push(umbrellas[i]);
        }
    }
    umbrellas = umbrellasToKeep; 
}

function removePlane(){
    var planesToKeep = [];
    for (var i = 0; i < planes.length; i++){
        if (planes[i].x + 150 > 0) {
           planesToKeep.push(planes[i]);
        }
   }
    planes = planesToKeep; 
}

function removeBuilding(){
    var buildingsToKeep = [];
        for (var i = 0; i < buildings.length; i++){
            if (buildings[i].x > 0) {
                buildingsToKeep.push(buildings[i]);
        }
   }
    buildings = buildingsToKeep; 
}

function removeRailing(){
    var railingsToKeep = [];
        for (var i = 0; i < railings.length; i++){
            if (railings[i].x > 0) {
                railingsToKeep.push(railings[i]);
        }
   }
    railings = railingsToKeep; 
}

function removePerson(){
    var peopleToKeep = [];
        for (var i = 0; i < people.length; i++){
            if (people[i].x > 0) {
               peopleToKeep.push(people[i]);
        }
   }
    people = peopleToKeep; 
}

function removeTowel(){
    var towelsToKeep = [];
        for (var i = 0; i < towels.length; i++){
            if (towels[i].x > 0) {
               towelsToKeep.push(towels[i]);
        }
   }
    towels = towelsToKeep; 
}

                    //functions to create new objects that come into sight

function newBoat() {

    var newBoatChance = 0.009;      //the chance that a new boat will appear
    if (random(0,1) < newBoatChance) {      //activate probability
        boats.push(makeBoat(width,random(100,150)));        //add a new boat if the porbability condition is met
    }
}
function newCloud() {

    var newCloudChance = 0.001; 
    if (random(0,1) < newCloudChance) {
        clouds.push(makeCloud(width,random(0,60)));
    }
}


function newPlane() {

    var newPlaneChance = 0.003; 
    if (random(0,1) < newPlaneChance) {
        planes.push(makePlane(width, random(0,50)));
   }
}

function newBuilding() {

    var newBuildingChance = 0.1; 
    if (random(0,1) < newBuildingChance) {
        buildings.push(makeBuilding(width));
   }
}

function newRailing() {

    var newRailingChance = 0.8; 
    if (frameCount % 2 == 0 & random(0,1) < newRailingChance) {    //spawn every two frames, if probability condition is met
        railings.push(makeRailing(width));
   }
}

                        //functions to move the objects across the screen
function moveBoat() {
    this.x += this.speed;       //add a speed value to the the x position to chance it every frame
}

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

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

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

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

function movePerson(){
  this.x += this.Xspeed;
  this.y += this.Yspeed/3;       //move very slightly in Y direction
} 

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

                                //functions to show (object) by drawing it at the requested coordinates
function showBoat() {               

    var floorHeight = 10; 
    push();
    translate(this.x, this.y);      //plot the drawing at the the coordinates given
    noStroke(); 
    for (var i = 0; i < this.nFloors; i++) {
        fill(this.color,this.y*2);  //random color, with varying opacity based on y value (distance from viewer)
            rect(0, -15 - (i * floorHeight), this.breadth-10*i, 10);        //the boat levels
        if(this.nFloors == 3){
            fill(255,this.y*2);     //white, varying opacity
                rect(3,-15-(i*floorHeight), this.breadth-12*i,7)        //to make a "yacht"
    }     
        if(this.nFloors == 2){
            fill(161,227,238,this.y*2);     //light blue, varying opacity
                rect(5,-13-(floorHeight),this.windowBreadth,7);     //window
        }
        if(this.nFloors == 1){
            strokeWeight(5);
            stroke(this.color,this.y*2);        //rnadom color of boat, varying opacity
                line(7,0-(floorHeight),-6,-15-(floorHeight));   //fishing gig
            strokeWeight(2);
                line(-6,-15-(floorHeight),random(-12,-16),5-(floorHeight));     //fishing line
        }

    }
    pop();
}

function showCloud(){

    var cloudHeight = 10;       //height of a cloud
    var cHeight = this.nClouds * cloudHeight;       //height dpends on how many clouds
    fill(255,200);      //pale white
    noStroke();
    push();
    translate(this.x, this.y);      //appear at width, and random y in a constraint
        for (var i = 0; i < this.nClouds; i++) {
             ellipse(0, -15 - (i * cHeight), this.breadth-10, 30);      //draw cloud
        }
    pop();

 }

function showUmbrella(){

    var umbrellaHeight = 10; 
    noStroke();
    push();
    translate(this.x, this.y+15);       //appear at width, random y between shoreline and height(adjusted to ensure no umbrellas in water)
    noStroke(); 
        fill(255);      //white
            rect(0,0, this.breadth, this.height);       //umbrella stand
        fill(this.color);   //random color
        rotate(radians(this.angle));    //turn at different angles
            arc(0,10,40,40,180,TWO_PI);     //umbrella dome
    pop();
}

function showPlane(){
    
    push();
        translate(this.x, this.y);      //appear at width, random y within constraint
        noStroke(); 
        scale(this.scale);      //scale randomly
            fill(220,this.scale*400);       //opacity deoends on size
                ellipse(50,42.5,10,30);     //plane body and wings
                ellipse(50,50,50,15);
                ellipse(50,60,10,30);
            fill(50,this.scale*400);     //dark gray, varying opacity
                ellipse(33,47,4,4);     //cockpit window
                    
                for(var x=39;x < 55;x+=4)     //plane windows
                    ellipse(x,50,4,4);

        strokeWeight(1);    
        stroke(0,this.scale*400);      //black
            line(55,57.5,110,57.5);     //flag ropes
            line(55,42.5,110,42.5);
    fill(this.color);   //random color
    noStroke();
        rect(110,37.5,45+random(-2,2),25);  //flag, moving
    pop();
}

function showBuilding(){
    
   // var floorHeight = 2;        //height of a floor
    //var buildingHeight = this.nFloors * floorHeight;        //building height depends on how many floors
    fill(this.color);     
    
    push();
        noStroke();
        translate(this.x, 70);      //appear at width,70 (far shoreline)
            rect(0, -10, this.breadth, this.height*2);         //draw building
    pop();
    
}

function showRailing(){
    
    push();
         translate(this.x, 280);        //appear at width,280
         fill(200,200,200);     //gray
         stroke(0);     //black
             rect(0, -20,this.breadth,20);      //draw railing markers
    pop();
    
}

function showPerson(){

    push();
        translate(this.x, this.y+20);       //appear at width, and a random heught between shoreline and bottom of canvas(adjusted to ensure nobody in the water)
            fill(this.skinColor);    //random brown tone   
                ellipse(0,-5,5,5);        //head
        rectMode(CENTER);
            fill(this.shirtColor);      //random color
                rect(0,10,this.breadth,this.height);       //body
            fill(this.pantsColor);      //random color
                rect(0,25,this.breadth,this.height);       //legs 
    pop();
}

function showTowel(){

    push();
       translate(this.x, this.y+30);        //appear at width, random y between shoreline and height  
           fill(this.towelColor);       //random color
               rect(0,0,this.breadth,this.height);     //draw towel
    pop();
}

                                    //constructors for each object

function makeBoat(startX,startY) {
    var boat = {x: startX,      //where it gets translated to
                y:startY,
                breadth: round(random(20,40)),  //it's width
                windowBreadth: random(5,10),    //window width  
                speed: random(-2,-0.1),     //how fast it moves across canvas
                nFloors: round(random(1,3)),    //how many floors there are 
                color: random(150,255),     //color of boat
                move: moveBoat,     //functions to move and show the boat
                show: showBoat}
    return boat;
}

function makeCloud(startX,startY){
    var cloud = {x: startX,
                y:startY,
                breadth: round(random(60,100)),
                speed: random(-0.7,-0.3),
                nClouds: round(random(1,3)),
                move: moveCloud,
                show: showCloud}
   return cloud;
}

function makeUmbrella(startX,startY){
    var umbrella = {x: startX,
                y:startY,
                breadth: round(random(2,4)),
                speed: round(random(-5,-4.99)),
                height: random(25,30),
                color: color(random(0,255),random(0,255),random(0,255)),       //color of hood
                angle: random(-20,20),      //angle of hood rotation
                move: moveUmbrella,
                show: showUmbrella
            }
    return umbrella;
}

function makePlane(startX,startY){
    var plane = {x: startX,
                y:startY,
                scale: random(1 / 4,1),       //size of plane
                speed: random(-7,-5),
                color: color(random(0,255),random(0,255),random(0,255)),
                move: movePlane,
                show: showPlane
            }
    return plane;
}

function makeBuilding(startX){
       var building = {x: startX,
                       breadth: 10,
                       height:10,
                       speed: -1.0,
                       color: random(50,200),
                       //distance: random(100,200),
                       //nFloors: round(random(2,8)),
                       move: moveBuilding,
                       show: showBuilding
            }
    return building;
}

function makeRailing(startX){
    var railing = {x: startX,
                   breadth:10,
                   speed: -20,
                   move: moveRailing,
                   show: showRailing
            }
    return railing;
}

function makePerson(startX,startY){
      var person = {x: startX,
                    y:startY,
                    breadth: random(5,8),
                    height: random(14,17),
                    skinColor: color(random(200,250),random(100,150),random(20,100)),
                    shirtColor: color(random(0,255), random(0,255),random(0,255)),
                    pantsColor: color(random(0,255), random(0,255),random(0,255)),
                    Xspeed: random(-7,-4),
                    Yspeed: random(-0.5,0.5),
                    move: movePerson,
                    show: showPerson}
   return person;
}


function makeTowel(startX,startY){
      var towel = {x: startX,
                    y:startY,
                    breadth: random(10,20),
                    height: random(5,15),
                    towelColor: color(random(0,255), random(0,255),random(0,255)),
                    speed: -5,
                    move: moveTowel,
                    show: showTowel}
   return towel;
}




function displayHorizon(){
landscape.shift();      //removes the first array element

    n = noise(noiseParam);       //selecting a noise value
    value = map(n,0,1,50,height);       //plotting it onto the canvas by mapping

landscape.push(value);      //adding it to the lanscape array
noiseParam+=noiseStep;      //adding step to parameter

push();
    beginShape();
        noStroke();
            fill(227,232,164);        //green
                for (i=0;i<width/5; i++){
                    var newUmbrellaChance = 0.001;      //frequencies for objects
                    var newPersonChance = 0.003;
                    var newTowelChance = 0.002;
                    var r = random(0,1);     //predictor

                if (r < newUmbrellaChance){
                    umbrellas.push(makeUmbrella(width,random(landscape[i],height)));                //construct an object between slope line and the bottom of the canvas
                }
                if(r<newPersonChance){
                    people.push(makePerson(width,random(landscape[i],height)));
                }
                if(r<newTowelChance){
                    towels.push(makeTowel(width,random(landscape[i],height)));
                }
                

    curveVertex(i*5,landscape[i])       //creates slopes by connecting two points
    curveVertex((i+1)*5,landscape[i+1])   

    
}

    curveVertex(width,height+50);      //stable values that create the green fill
    curveVertex(0,height+50);
endShape(CLOSE);        //end shape and fill it
pop();
}


Leave a Reply