Lanna Lang – Project 11 – Landscape

sketch

//Lanna Lang
//Section D
//lannal@andrew.cmu.edu
//Project 11 - Landscape

//variables for the gradients;
var yAxis = 1;
var c1, c2, c3, c4, c5; //background colors

//variables to draw the clouds
var cloudX = [500, 700, 1200];
var cloudY = [150, 120, 190];
var cloudDist = 5; //the distance the cloud moves

//arrays for the tree and house objects
var trees = [];
var houses = [];

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

    c1 = color('#9a99d3'); //background sky lavender
    c2 = color('#ff829f'); //background sky pink
    c3 = color('#f6944d'); //background sky orange
    c4 = color('#a29078'); //train color 1
    c5 = color('#f2f2f4'); //train color 2

    //create an initial collection of trees
    for (var i = 0; i < 10; i++) {
        var rtx = random(width);
        var rty = random(281, 330);
        trees[i] = makeTree(rtx, rty);
    }
    //create an initial collection of houses
    for (var i = 0; i < 10; i++) {
        var rhx = random(width);
        var rhy = random(300, 350);
        houses[i] = makeHouse(rhx, rhy);
    }
}

function draw() {
    drawBackground();
    drawClouds();
    drawLandscape();

    UandDTrees();
    removeTrees();
    addNewTrees();
    
    UandDHouses();
    removeHouses();
    addNewHouses();

    drawTrain();
}

//function to draw the background and 
//the canvas for the train
function drawBackground() {
    //rectangle around full canvas
    drawGradDGtoG(0, 0, width, height, c4, c5, yAxis);

    //draw the sky with gradients
    drawGradPtoP(35, 100, 400, 80, c1, c2, yAxis);
    drawGradPtoO(35, 181, 400, 105, c2, c3, yAxis);
}

//draw the landscape inside the train windows
function drawLandscape() {
    var mtnSpeed = 0.0005;
    var mtnDetail = 0.01;

    //draw the moutains
    stroke('#445c3c');
    for (var x = 35; x <= 435; x++) {
        var t = (x * mtnDetail) + (millis() * mtnSpeed);
        var y = map(noise(t), 0, 1, 170, 300);
        line(x, y, x, 380);
    }

    //draw the grass/horizon
    noStroke();
    fill('#798f44');
    rect(35, 281, 400, 107);
}

//draw the clouds
function drawClouds() {
    for (var i = 0; i < cloudX.length; i++) {
        cloudX[i] -= cloudDist; //the clouds move 5 pixels to the left
        //draw the 3 clouds
        noStroke();
        fill('#faa3b1');
        ellipse(cloudX[i], cloudY[i] + 10, 100, 8);
        ellipse(cloudX[i] - 24, cloudY[i] + 1, 30, 20);
        ellipse(cloudX[i] + 3, cloudY[i], 40, 22);
        ellipse(cloudX[i] - 5, cloudY[i] - 10, 40, 20);
        ellipse(cloudX[i] + 22, cloudY[i], 30, 18);
        //when the clouds reach the end of the canvas, 
        //they will reset back at the other side of the canvas
        //at a random x postion between 500 and 1300
        if (cloudX[i] < 0) {
            cloudX[i] = random(500, 1300);
        }
    }
}

//function to draw gradient from purple to pink
function drawGradPtoP(x, y, w, h, c1, c2, axis) {
    noFill();
    if (axis == yAxis) {
        for (var i = y; i <= y + h; i++) {
            var inter = map(i, y, y + h, 0, 1);
            var cPtoP = lerpColor(c1, c2, inter);
            stroke(cPtoP); 
            line(x, i, x + w, i);
        }
    }
}

//function to draw gradient from pink to orange
function drawGradPtoO (x, y, w, h, c2, c3, axis) {
    noFill();
    if (axis == yAxis) {
        for(var i = y; i <= y + h; i++) {
            var inter = map(i, y, y + h, 0 , 1);
            var cPtoO = lerpColor(c2, c3, inter);
            stroke(cPtoO);
            line(x, i, x + w, i);
        }
    }
}

//function to draw gradient from tan to light grey
function drawGradDGtoG (x, y, w, h, c4, c5, axis) {
    noFill();
    if (axis == yAxis) {
        for(var i = y; i <= y + h; i++) {
            var inter = map(i, y, y + h, 0 , 1);
            var cDGtoG = lerpColor(c4, c5, inter);
            stroke(cDGtoG);
            line(x, i, x + w, i);
        }
    }
}

//function to draw the train
function drawTrain() {
    //redraw the very left and right sides of the train
    //because of the clouds moving
    drawGradDGtoG(0, 0, 35, height, c4, c5, yAxis);
    drawGradDGtoG(435, 0, 490, height, c4, c5, yAxis);
    
    //rectangle to separate the sky gradient into two windows
    drawGradDGtoG(210, 0, 60, height, c4, c5, yAxis);
   
    //dark brown line in the middle
    noStroke();
    fill('#2e2423');
    rect(235, 0, 10, height); 

    //black rect sign under windows
    fill(0);
    rect(280, 400, 140, 20); 
    rect(50, 400, 140, 20);
    
    //dark brown window frames
    strokeWeight(2);
    stroke('#2e2423');
    noFill();
    rect(30, 85, 185, 310);
    rect(265, 85, 175, 310);

    //sign under windowa that says "Do not lean on train door"
    fill(224);
    textSize(11);
    textStyle(BOLD);
    text("Do not lean on train door", 284, 413);
    text("Do not lean on train door", 54, 413);
    
    //draw the door handles on the train doors
    stroke(193);
    fill(220);
    rect(180, 440, 35, 70);
    rect(265, 440, 35, 70);
    //draw the insides of the door handles
    fill(130);
    rect(190, 450, 15, 70);
    rect(275, 450, 15, 70);

    //draw the train handles
    for (var j = 0; j < width + 50; j += 150) {
        stroke(200);
        strokeWeight(13);
        noFill();
        line(j, 0, j, 70);
        line(j, 70, j + 33, 130);
        line(j, 70, j - 30, 130);
        line(j - 30, 130, j + 33, 130);
    }
}

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

//if a tree has dropped off the left edge,
//remove it from the array
function removeTrees() {
    var treesToKeep = [];
    for (var i = 0; i < trees.length; i++) {
        if (trees[i].x + trees[i].tw > 0 & 
            trees[i].y + trees[i].th > 0) {
            treesToKeep.push(trees[i]);
        }
    }
    trees = treesToKeep; //remember the surviving trees
}

//with a very tiny probability, add a new tree to the end
function addNewTrees() {
    var newTreeChance = 0.01;
    if (random(0.1) < newTreeChance) {
        trees.push(makeTree(width, random(281, 330)));
    }
}

//update position of the tree at every frame
function moveTree() {
    this.x += this.speed;
}

//draw the tree and tree trunk
function drawTree() {
    noStroke();
    fill('#c39a2b');
    push();
    translate(this.x, this.y);
    triangle(0, -this.th, 0 - this.tw / 2, 0, 
            0 + this.tw / 2, 0);
    pop();

    fill('#512a17');
    push(); 
    translate(this.x, this.y);
    rect(-3, 0, 4, 5);
    pop();
}

//this function accepts parameters and uses the values
//of those parameters to initialize fields in the tree object
function makeTree(birthLocationX, birthLocationY) {
    var mktr = {x: birthLocationX,
                y: birthLocationY,
                tw: random(5, 15),
                speed: -5.0,
                th: random(15, 30),
                move: moveTree,
                draw: drawTree}
    return mktr;
}

//update the house's positions, and display them
function UandDHouses() {
    for (var i = 0; i < houses.length; i++) {
        houses[i].move();
        houses[i].draw();
    }
}

//if a house has dropped off the left edge,
//remove it from the array
function removeHouses() {
    var housesToKeep = [];
    for (var i = 0; i < houses.length; i++) {
        if (houses[i].x2 + houses[i].hw > 0 &
            houses[i].y2 + houses[i].hh > 0) {
            housesToKeep.push(houses[i]);
        }
    }
    houses = housesToKeep; //remember the surviving houses
}

//with a very tiny probability, add a new house to the end
function addNewHouses() {
    var newHouseChance = 0.003;
    if (random(0.1) < newHouseChance) {
        houses.push(makeHouse(width, random(300, 350)));
    }
}

//update position of the tree at every frame
function moveHouse() {
    this.x2 += this.speed2;
}

//draw the house and the house roof
function drawHouse() {
    noStroke();
    fill('#e7d2a0');
    push();
    translate(this.x2, this.y2);
    rect(-10, 0, 20, 10);
    pop();

    fill('#95221b');
    push();
    translate(this.x2, this.y2);
    triangle(0, -this.hh / 2, 0 - this.hw / 2, 0, 
            0 + this.hw / 2, 0);
    pop();
}

//this function accepts parameters and uses the values
//of those parameters to initialize fields in the house object
function makeHouse(birthLocationX2, birthLocationY2) {
    var mkh = {x2: birthLocationX2,
                y2: birthLocationY2,
                hw: random(10, 40),
                speed2: -5.0,
                hh: random(10, 30),
                move: moveHouse,
                draw: drawHouse}
    return mkh;
}

When I first read this prompt, what came up to my mind immediately was creating a landscape that mimics what I see when sitting on a high-speed train. My favorite sceneries are usually what I see when I pass by complete cities in just a few hours on those trains. I had a lot of fun creating this landscape, but it was also very challenging for me. It definitely took me more than a couple of hours, but it was worth it.

My sketch

Leave a Reply