Project-11 Landscape

landscape
var highMountain = [];
var lowMountain = [];
var cabin = [];
var trees = [];
var dogImage = [];
var dog = [];
var noiseParam = 0;
var noiseStep = 0.01;

function preload(){
    var filenames = [];
    filenames[0] = "https://i.imgur.com/KGHR8lv.png";
    filenames[1] = "https://i.imgur.com/KGHR8lv.png";
    filenames[2] = "https://i.imgur.com/unhcm3R.png";
    filenames[3] = "https://i.imgur.com/unhcm3R.png";
    filenames[4] = "https://i.imgur.com/J2pZbow.png";
    filenames[5] = "https://i.imgur.com/J2pZbow.png";
    filenames[6] = "https://i.imgur.com/unhcm3R.png";
    filenames[7] = "https://i.imgur.com/unhcm3R.png";
 
    for (var i = 0; i<filenames.length; i++) {
        dogImage[i] = loadImage(filenames[i]);
    }
}

function setup() {
    createCanvas(480, 240); 
    frameRate(24);
    imageMode(CENTER);
    //mountains
    for (var i = 0; i <= width/4; i++) {
      var value = map(noise(noiseParam), 0, 1, 0, height*1.1);
      highMountain.push(value);
      noiseParam += noiseStep;
    }
    for (var i = 0; i <= width/5; i++) {
      var value = map(noise(noiseParam), 0, 1, 0, height*1.9);
      lowMountain.push(value);
      noiseParam += noiseStep;
    }

    // create an initial collection of cabins 
    for (var i = 0; i < 10; i++){
        var rx = random(width);
        cabin[i] = makeCabin(rx);
        var r = random(width);
        trees[i] = makeTree(r);
    }

    //create three walking characters 
    var d = makeCharacter(400, 200);
    dog.push(d);
    
}

function draw() {
    background(200); 
    //sky as a gradient
    var gradPurple = color(134, 123, 198);
    var gradPink = color(240, 198, 209);
    for (var i = 0; i < height; i++){
      var gradient = map (i, 0, (height/3)*1.5, 0, 1);
      var bgColor = lerpColor(gradPurple, gradPink, gradient);
      stroke(bgColor);
      line(0, i, width, i);
    }
    //snow
    stroke(239, 241, 253);
    strokeWeight(2);
    for (var i = 0; i < 750; i++) {
      point(random(0,width), random(-0, height));
    }

    //sun 
    noStroke();
    fill(242, 226, 233, 90);
    circle(width/2, height/2-40, 60);
    fill(242, 226, 233, 75);
    circle(width/2, height/2-40, 50);
    fill(242, 226, 233, 60);
    circle(width/2, height/2-40, 40);
    fill(242, 226, 233);
    circle(width/2, height/2-40, 30);

    //clouds 
    cloud(45, 80);
    cloud(180, 130);
    cloud(360, 160);
    cloud(445, 70);

    //mountains
    drawHighMountain();
    drawLowMountain();

    //snow on the ground
    fill(239, 241, 253);
    rect(0, 180, width, 60);

    //trees
    updateAndDisplayTrees();
    removeTreesThatHaveSlippedOutOfView();
    addNewTreesWithSomeRandomProbability(); 

    //cabins
    updateAndDisplayCabins();
    removeCabinsThatHaveSlippedOutOfView();
    addNewCabinsWithSomeRandomProbability();

    //walking dog 
    for (var i = 0; i < dog.length; i++) { 
        var d = dog[i];
        d.stepFunction();
        d.drawFunction();
    }

    //fence 
    for (var x = 10; x <= width-10; x+=10) {
      stroke(198, 173, 203);
      strokeWeight(5);
      line(x, height, x, height-25);
    }
    line(0, height-15, width, height-15);

}

function drawHighMountain() {
  highMountain.shift();
  var value = map(noise(noiseParam), 0, 1, 0, height*1.1);
  highMountain.push(value);
  noiseParam += noiseStep;
  push();
  fill(170, 190, 250);
  stroke(170, 190, 250);
  beginShape(); 
  vertex(0, height);
  for (var i = 0; i < width/4; i++) {
    vertex(i*5, highMountain[i]);
    vertex((i+1)*5, highMountain[i+1]);
  }
  vertex(width, height);
  endShape();
  pop();
}
function drawLowMountain() {
  lowMountain.shift();
  var value = map(noise(noiseParam), 0, 1, 0, height*1.9);
  lowMountain.push(value);
  noiseParam += noiseStep;
  push();
  fill(193, 205, 246);
  stroke(193, 205, 246);
  beginShape(); 
  vertex(0, height);
  for (var i = 0; i < width/5; i++) {
    vertex(i*5, lowMountain[i]);
    vertex((i+1)*5, lowMountain[i+1]);
  }
  vertex(width, height);
  endShape();
  pop();
}

//cabins 
function makeCabin(birthLocationX) {
    var bldg = {x: birthLocationX,
                breadth: 70,
                speed: -5.0,
                nFloors: round(random(2,8)),
                move: cabinMove,
                display: cabinDisplay}
    return bldg;
}
// method to update position of cabin every frame
function cabinMove() {
    this.x += this.speed;
}
// draw the cabin and some windows
function cabinDisplay() {
    var floorHeight = 8;
    var cHeight = this.nFloors * floorHeight; 
    
    noStroke();
    fill(95, 124, 213);
    push();
    translate(this.x, height - 40);
    //chimmney 
    rect(this.breadth-10, -cHeight - 20, 10, 15);
    //roof
    stroke(239, 241, 253);
    triangle(-7,-cHeight,this.breadth/2,-cHeight-20,this.breadth+7,-cHeight);
    //home
    stroke(95, 124, 213); 
    rect(0, -cHeight, this.breadth, cHeight);

    fill(239, 241, 253);
    noStroke();
    circle(this.breadth/2, -cHeight - 10, 10); 
    rect(this.breadth-10, -cHeight - 20, 10, 5);
    //windows
    fill(148, 178, 249);
    stroke(95, 124, 213);
    for (var i = 0; i < this.nFloors-1; i++) {
        rect(5, -15 - (i * floorHeight), this.breadth - 10, 10);
    }
    pop();
}
function updateAndDisplayCabins(){
    // Update the cabin's positions, and display them.
    for (var i = 0; i < cabin.length; i++){
        cabin[i].move();
        cabin[i].display();
    }
}
function removeCabinsThatHaveSlippedOutOfView(){
  var cabinToKeep = [];
  for (var i = 0; i < cabin.length; i++){
    if (cabin[i].x + cabin[i].breadth > 0) {
        cabinToKeep.push(cabin[i]);
    }
  }
  cabin = cabinToKeep; // remember the surviving cabin
}
function addNewCabinsWithSomeRandomProbability() {
    // With a very tiny probability, add a new cabin to the end.
    var newCabinLikelihood = 0.01; 
    if (random(0,1) < newCabinLikelihood) {
        cabin.push(makeCabin(width));
    }
}

// dog walking character
function makeCharacter(cx, cy) {
    c = {x: cx, y: cy,
         imageNumber: 0,
         stepFunction: characterStep,
         drawFunction: characterDraw
        }
    return c;
}
function characterStep() {
    this.imageNumber++;
    if (this.imageNumber == 8) {
        this.imageNumber = 0;
    }
}
function characterDraw() {
    image(dogImage[this.imageNumber], this.x, this.y);
}

// trees 
function makeTree(birthLocationX) {
    var t = {x: birthLocationX,
                breadth: round(random(20,30)),
                speed: -5.0,
                treeHeight: round(random(30,70)),
                move: treeMove,
                display: treeDisplay}
    return t;
}
function treeMove() {
    this.x += this.speed;
}
function treeDisplay() {
    push();
    translate(this.x, height - 60);
    noStroke(); 
    fill(153, 139, 196);
    rect(-2, 0, 6, 8);
    fill(242, 198, 210); 
    triangle(0, 0, 0, -this.treeHeight, -this.breadth/2, 0);
    fill(223, 186, 209); 
    triangle(0, 0, 0, -this.treeHeight, this.breadth/2, 0);
    stroke(225);
    line(0, 0, 0, -this.treeHeight);
    pop();
}
function updateAndDisplayTrees(){
    for (var i = 0; i < trees.length; i++){
        trees[i].move();
        trees[i].display();
    }
}
function removeTreesThatHaveSlippedOutOfView(){
    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() {
    var newTreeLikelihood = 0.07; 
    if (random(0,1) < newTreeLikelihood) {
        trees.push(makeTree(width));
    }
}

function cloud(x, y) {
	fill(239, 241, 253, 50);
	arc(x, y, 60, 40, PI + TWO_PI, TWO_PI);
	arc(x + 30, y, 90, 90, PI + TWO_PI, TWO_PI);
	arc(x + 25, y, 40, 70, PI + TWO_PI, TWO_PI);
	arc(x + 50, y, 70, 40, PI + TWO_PI, TWO_PI);
}

For this project, I wanted to created a snowy landscape. I started by drawing two layers of mountains and then added the cabins, the trees, and the running dog. I feel like the cool tone color palette contrasts really well with the dog. The sun and clouds looked pretty plain so I played with the opacity of the shapes to create some visual interest. The hardest part was figuring out how to do the gradient, but I’m happy with the way that it turned out and the way it looks with the snow! I didn’t want to overcrowd the piece too much so the last thing I added was a fence.

initial hand drawn sketch

Project 11

I instantly thought of Tron bikes when I read through the assignment, so that’s what I ended up doing. I modified a version of my generative hillside from Assignment 7 (I think?) and created two types of random objects, some abstract distant vertical structures that are represented by lines, and some dystopian irregular buildings. The height of the buildings and the placement of the window sections are randomized, as well as the heights of the structures in the background. There is also a moving grid to create more sense of motion in the work.

I spent a lot of the time fiddling with the different movement rates of objects and the tonal values to get the right depth and parallax effect.

Tron movie review & film summary (1982) | Roger Ebert
The inspiration
Quick sketch for vertical grid line spacing

sketch

var buildings = [];
var lines = [];
var bottomLines =[];
var topLines =[];
let hillHeight = [];
let noiseParam = 0;
let noiseStep = 0.05;

function setup() {
    createCanvas(480, 240); 
    
    // create an initial collection of buildings
    for (var i = 0; i < 10; i++){
        var rx = random(width);
        buildings[i] = makeBuilding(rx);
    }
    //populates the grid lines
    for (var i=0; i<49;i++){
    	topLines[i]=10*i;
    	bottomLines[i]=-1200+(60*i);
    }
    frameRate(10);
    //hill values
    for (let i=0; i<=width;i+=5){
        var n= noise(noiseParam);
        var value = map(n,0,1,height/8,height/2,true);
        hillHeight.push(value);
        noiseParam += noiseStep;
    }
}


function draw() {
    background(0); 
    drawHill();
    drawGrid();
    drawBike();
    updateAndDisplayLines();
    removeLinesThatHaveSlippedOutOfView();
    addNewLineWithSomeRandomProbability();
    updateAndDisplayBuildings();
    removeBuildingsThatHaveSlippedOutOfView();
    addNewBuildingsWithSomeRandomProbability(); 
    displayHorizon();
}

//updates and draws the grid
function drawGrid(){
	strokeWeight(1);
	stroke(255);
	fill(18,49,62);
	rect(0,height-100,width,height/2);
    //vertical lines
    for (var i=0; i<49;i++){
    	line(topLines[i],height-100,bottomLines[i],height);
    	topLines[i]-=5;
    	bottomLines[i]-=30;
    	if(topLines[i]==0){
    		topLines[i]=480;
    	}
    	if(bottomLines[i]==-1200){
    		bottomLines[i]=1680;
    	}
    }
    //horizontal lines
    for(var i=0; i<10; i++){
    	line(0,height-100+pow(2,i),width,height-100+pow(2,i));
    }
}
//draws background hill
function drawHill(){
	strokeWeight(0.25);
    hillHeight.shift();
        var n= noise(noiseParam);
        var value = map(n,0,1,0,height,true);
        hillHeight.push(value);
        noiseParam+=noiseStep;
        fill(8,26,34);
    //start of the hill shape, with a buffer point off screen
        beginShape();
        curveVertex(0,height);
        curveVertex(0,height);
        curveVertex(-5,hillHeight[0]);
    //loop for drawing all vertices
    for(let j=0; j<(width/5)+1; j++){
    	 if(j!=0&hillHeight[j-1]>hillHeight[j]&&hillHeight[j+1]>hillHeight[j]){
            rect(j*5,hillHeight[j]-20,5,hillHeight[j]-20);
        }
        curveVertex(j*5,hillHeight[j]);
    }

//end of hill shape with buffer
    curveVertex(width+5,hillHeight[width/5]);
    curveVertex(width,height);
    curveVertex(width,height);
    endShape();
   }

//draws the Tron bike
function drawBike(){
	push();
	translate(100,180);
	noStroke();
	//stripe
	fill(255,190,107);
	rect(-213,9,220,15);
	//base back
	fill(182,134,44);
	beginShape();
	vertex(7,5);
	vertex(7,5);
	vertex(31,0);
	vertex(60,10);
	vertex(60,22);
	vertex(19,22);
	vertex(19,10);
	vertex(7,5);
	endShape();
	//wheels
	fill(198,128,4);
    ellipse(6,18,18,18);
    ellipse(52,18,18,18);
    fill(0);
    ellipse(6,18,12,12);
    ellipse(52,18,12,12);
    pop();
}

//buildings 


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(){
    // If a building has dropped off the left edge,
    // remove it from the array.  This is quite tricky, but
    // we've seen something like this before with particles.
    // The easy part is scanning the array to find buildings
    // to remove. The tricky part is if we remove them
    // immediately, we'll alter the array, and our plan to
    // step through each item in the array might not work.
    //     Our solution is to just copy all the buildings
    // we want to keep into a new array.
    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.12; 
    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() {
	strokeWeight(0.5);
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight; 
    fill(14,43,55); 
    stroke(255); 
    push();
    translate(this.x, height - 100);
    rect(0, -bHeight, this.breadth, bHeight);
    fill(0);
    stroke(255); 
    for (var i = 0; i < this.nFloors-1; i++) {
    	if(this.side==2){
        rect(this.breadth/2,-15 - (i * floorHeight),this.breadth-10, 10);
        }
        else{
       rect((this.breadth/2)-this.breadth,-15 - (i * floorHeight),this.breadth-10, 10);
        }
    }
    pop();
}


function makeBuilding(birthLocationX) {
    var bldg = {x: birthLocationX,
    	        side: (int(random(0,3))),
                breadth: 40,
                speed: -15.0,
                nFloors: round(random(2,8)),
                move: buildingMove,
                display: buildingDisplay}
    return bldg;
}

//lines 

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


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


function addNewLineWithSomeRandomProbability() {
    var newLineLikelihood = 1; 
    if (random(0,1) < newLineLikelihood) {
        lines.push(makeLine(width));
    }
}


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

//draw the line spikes 
function lineDisplay() {
	strokeWeight(5);
    var floorHeight = 8;
    var bHeight = this.nFloors * floorHeight;  
    stroke(80); 
    push();
    translate(this.x, height - 100);
    line(0, -bHeight, 0, 0);
    pop();
}


function makeLine(birthLocationX) {
    var ln = {x: birthLocationX,
                breadth: 40,
                speed: -10.0,
                nFloors: round(random(1,6)),
                move: lineMove,
                display: lineDisplay}
    return ln;
}


function displayHorizon(){
    stroke(255);
    line (0,height-100, width, height-100); 
}