Yiran Xuan – Project 10 – Landscape

sketch

var mountains = [];
var grass = [];
var stars = [];


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

    stars.push(makeStar());

    for(var j = 0; j < 10; j++){
    mountains.push(makeMountainPoint(width + j*80));
    }

    grass.push(makeGrass());
}


function draw() {
    background(25, 25, 112);
    drawGround();

    updatePositions(); 
    updateArrays();

    newStar(); //one star per x position
    newMountainPoint(); //one mountain point per x position
    newGrass(); //one grass per x position

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

    mountainDisplay();

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

   // textSize(32);
    //text(mountains.length, 240, 240);

}

function drawGround(){
    noStroke();
    fill('green');
    rect(0, 320, 480, 160);
    noFill();
}

function updatePositions(){
    // Update positions of stars, mountains, and grass
    for (var i = 0; i < stars.length; i++){
        stars[i].move();
    }

     for (var j = 0; j < mountains.length; j++){
        mountains[j].move();
    }

     for (var k = 0; k < grass.length; k++){
        grass[k].move();
    }
}

function updateArrays(){ //updating all arrays to delete objects that have gone offscreen
    var starsremaining = []; //temporary transfer array
    for (var i = 0; i < stars.length; i++){
        if (stars[i].x > 0) { //if the star is still in frame, put in transfer array
            starsremaining.push(stars[i]); 
        }
    }
    stars = starsremaining; //update normal array, oldest stars now deleted

    var mountainsremaining = []; //temporary transfer array
    for (var j = 0; j < mountains.length; j++){
        if (mountains[j].x > -80) { //deletes the oldest mountain point only until the second oldest point is at the border
            mountainsremaining.push(mountains[j]); 
        }
    }
    mountains = mountainsremaining; //update normal array, oldest mountain point now deleted

    var grassremaining = []; //temporary transfer array
    for (var k = 0; k < grass.length; k++){
        if (grass[k].x > 0) { //deletes the oldest mountain point only until the second oldest point is at the border
            grassremaining.push(grass[k]); 
        }
    }
    grass = grassremaining; //update normal array, oldest mountain point now deleted

}

function newMountainPoint() {
    if (mountains[6].x < 480 & mountains.length < 10) { //generates new point only if last point has passed onto the screen 
        var onebefore = mountains[mountains.length-1].x;
        mountains.push(makeMountainPoint(onebefore + 80));
    }
}

function newStar(){
    if (random(0, 100) < 10){ //makes a star at x position 10% of the time
        stars.push(makeStar());
    }
}

function newGrass(){
    if (random(0,10) < 8){ //makes a grass stalk at x position 80% of the time
        grass.push(makeGrass());
    }
}


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

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

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

// draw the building and some windows
function starDisplay() {
    stroke('white');
    strokeWeight(this.starsize);
    point(this.x, this.y);
}

function mountainDisplay(){ //displays mountain range all at once, as each line segment uses two array elements
    strokeWeight(1);
    stroke('grey');
    for(var j = 0; j < mountains.length - 1; j++){
        line(mountains[j].x, mountains[j].y, mountains[j+1].x, mountains[j+1].y);
    }
}

function grassDisplay(){
    strokeWeight(3);
    stroke('green');
    line(this.x, 320, this.x, 320 - this.stalkheight);

    if(this.flower < 1){ //grows a flower 10% of the time
        strokeWeight(8);
        stroke('yellow');
        point(this.x, 320-this.stalkheight);
    }
}


function makeStar(){
    var star = {x: width, //stars spawn at the right edge
                pointdistance: 40,
                speed: 3,
                starsize: round(random(0, 4)),
                y: round(random(0,160)),
                move: starMove,
                display: starDisplay}
    return star;
}

function makeMountainPoint(spawnpoint) {
    var mountain = {x: spawnpoint, //mountain peaks spawn past the right edge
                pointdistance: 40,
                speed: 5,
                y: round(random(160,280)), //height of the point
                move: mountainMove}
    return mountain;
}

function makeGrass(){
    var stalk = {x: 480, //grass at the right edge
                pointdistance: 40,
                speed: 7,
                stalkheight: round(random(0,30)), //height of the grass stalk
                move: grassMove,
                flower: random(0,10), //determines whether stalk grows a flower or no
                display: grassDisplay}
    return stalk;
}

This project was inspired by Tiny Wings, specifically the peaceful nighttime scene in which a starry night sky slowly drifts by. I wanted to have a green lawn foreground for extra serenity.

The stars and grass were easy to implement, but I had trouble rendering and generating new instances of the mountain peaks. Because I wanted a continuous mountain ridge, the objects being generated were points, and so the display function was an external function that processed the entire mountains array. Difficulty was also had in timing when a new mountain point would be generated; while grass and stars were generated all the time and deleted whenever they went off-screen, mountain points could only be deleted when the second oldest point started to go offscreen in order to leave no gaps. In the same vein, new mountain points needed to be generated off-screen on the other side.

Leave a Reply