Project 11 – Generative Landscape

For this project, I wanted to create a simple winter landscape, because Christmas is coming and it’s quite exciting. Take a close look at this landscape and close your eyes and imagine that you are Santa Claus on a nice warm sled on your way to California.

I used the noise function to generate the mountains, and objects to create snowflakes and buildings.

sketch
var buildings = [];
var mountains = [];
var noiseParam = 0;
var noiseStep = 0.03;
let snowflakes = [];


function setup() {
    createCanvas(400, 240); 
    
    for(var i = 0; i < width/5; i++){
        var n = noise(noiseParam);
        mountains[i];
        var value = map(n, 0, 1, 0, height);
        mountains.push(value);
        noiseParam += noiseStep;
    }
    // create an initial collection of buildings
    for (var i = 0; i < 10; i++){
        var rx = random(width);
        buildings[i] = makeBuilding(rx);
    }
    frameRate(25);
}


function draw() {
    background(23, 39, 174); 
    noStroke();
    fill(187, 223, 250);
    ellipse(200, 70, 70);
    fill(255, 30);
    cloud(40, 47, 1);
    cloud(275, 15, 0.8);
    cloud(380, 70, 1.5);

    let t = frameCount / 20; // update time

     // create a random number of snowflakes each frame
  for (let i = 0; i < random(5); i++) {
    snowflakes.push(new snowflake()); // append snowflake object
  }

  // loop through snowflakes with a for..of loop
  for (let flake of snowflakes) {
    flake.update(t); // update snowflake position
    flake.display(); // draw snowflake
  }
}

// snowflake class
function snowflake() {
  // initialize coordinates
  this.posX = 0;
  this.posY = random(-50, 0);
  this.initialangle = random(0, 2 * PI);
  this.size = random(2, 5);

  // radius of snowflake spiral
  // chosen so the snowflakes are uniformly spread out in area
  this.radius = sqrt(random(pow(width / 2, 2)));

  this.update = function(time) {
    // x position follows a circle
    let w = 0.6; // angular speed
    let angle = w * time + this.initialangle;
    this.posX = width / 2 + this.radius * sin(angle);

    // different size snowflakes fall at slightly different y speeds
    this.posY += pow(this.size, 0.5);

    // delete snowflake if past end of screen
    if (this.posY > height) {
      let index = snowflakes.indexOf(this);
      snowflakes.splice(index, 1);
    }
  };

  this.display = function() {
    ellipse(this.posX, this.posY, this.size);
  };

    //for animating the mountains
    mountains.shift();
    var n = noise(noiseParam);
    var value = map(n, 0, 1, 0, height);
    mountains.push(value);
    noiseParam += noiseStep;

    //for mountains
    beginShape();

    for(var i = 0; i < width/5; i++){
        //filling the mountain with color
        fill(44, 67, 184);
        noStroke();
        //vertex funciton to fill the mountain
        vertex((i * 5), mountains[i]); 
        vertex((i + 1) * 5, mountains[i + 1]);   
        vertex(width/2, 10000000); 
    }
    endShape(CLOSE);
   
    displayHorizon();

    updateAndDisplayBuildings();
    removeBuildingsThatHaveSlippedOutOfView();
    addNewBuildingsWithSomeRandomProbability(); 
}


function updateAndDisplayBuildings(){
    // Update the building's positions, and display them.
    for (var i = 0; i < buildings.length; i++){
        buildings[i].move();
        buildings[i].display();
    }
}


function removeBuildingsThatHaveSlippedOutOfView(){
    var buildingsToKeep = [];
    for (var i = 0; i < buildings.length; i++){
        if (buildings[i].x + buildings[i].breadth > 0) {
            buildingsToKeep.push(buildings[i]);
        }
    }
    buildings = buildingsToKeep; // remember the surviving buildings
}


function addNewBuildingsWithSomeRandomProbability() {
    // With a very tiny probability, add a new building to the end.
    var newBuildingLikelihood = 0.007; 
    if (random(0,1) < newBuildingLikelihood) {
        buildings.push(makeBuilding(width));
    }
}


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

// draw the building and some windows
function buildingDisplay() {
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight; 
    fill(105, 135, 213); 
    noStroke(); 
    push();
    translate(this.x, height - 40);
    rect(0, -bHeight, this.breadth, bHeight);
    fill(151, 186, 236);
    for (var i = 0; i < this.nFloors; i++) {
        rect(5, -15 - (i * floorHeight), this.breadth - 10, 3);
    }
    pop();
}


function makeBuilding(birthLocationX) {
    var bldg = {x: birthLocationX,
                breadth: 50,
                speed: -3.0,
                nFloors: round(random(2,8)),
                move: buildingMove,
                display: buildingDisplay}
    return bldg;
}


function displayHorizon(){
    fill(68, 91, 193);
    rect(0, height-50, width, height-50); 

}

function cloud(x, y, size) {
    fill(68, 91, 193);
    noStroke();
    arc(x, y, 25 * size, 20 * size, PI + TWO_PI, TWO_PI);
    arc(x + 10, y, 25 * size, 45 * size, PI + TWO_PI, TWO_PI);
    arc(x + 25, y, 25 * size, 35 * size, PI + TWO_PI, TWO_PI);
    arc(x + 40, y, 30 * size, 20 * size, PI + TWO_PI, TWO_PI);
}





Leave a Reply