Project 11 – Generative Landscape

sketch
/*
 * Eric Zhao
 * ezhao2@andrew.cmu.edu
 *
 * Generative ladnscape 
 *
 */

var hillHeights = [];
var mountainHeights = [];
//arrays for foreground and background
var noiseParam = 0;
var noiseParam2 = 0;
var noiseStep = 0.01;
var numpoints = 80;
//bottom 4 used as placemarkers and attempts
//to make the hobbit holes not disappear on screen
var xInc;
var circleRad; 
var breadth = 25;
var marginRatio = (numpoints+breadth)/numpoints;

function drawMountain(hill, numpoints){
    //draws a perlin noise mountain
    beginShape();
    vertex(width - width*marginRatio, height);
    vertex(width - width*marginRatio, height);
    for(let i = -breadth; i <= numpoints+breadth; i++){
        vertex(i * xInc, hill[i]);
    }
    vertex(width*marginRatio, height);
    vertex(width*marginRatio, height);   

    endShape();
}

function stepMountain(param, step, hill, numpoints){
    //generates array of perlin values used for mountain and trees
    hill.shift();
    for(let i = -breadth; i <= numpoints+breadth; i++){
        var n = noise(param);
        var value = map(n, 0, 1, 0, height);
        hill.push(value);
        param += step;
    }
    noiseParam = param;
}

function drawHole(circleRad){
    //hobbit hole draw function
    fill(22, 98, 71);
    ellipse(0, 0, circleRad, circleRad);
    fill(random(0, 360), 94, 25);
    ellipse(0, 0, circleRad*0.8, circleRad*0.8);
    stroke(0);
    noFill();
    for(var i = 0; i <= 8; i ++){
        arc(0, 0, circleRad*0.8, circleRad*0.8, i*(PI/8), -i*(PI/8), CHORD);
    }
    fill(50, 80, 90);
    ellipse(0, 0, max(10, circleRad*0.1), max(10, circleRad*0.1));
}

function setup() {
    createCanvas(600, 400);
    colorMode(HSB);
    frameRate(30);
    noStroke();
    strokeWeight(2);
    stepMountain(noiseParam, noiseStep, hillHeights);
}

function draw() {
    xInc = width/numpoints;
    background(183, 33, 95);
    //draws background/dark green mountain
    fill(120, 100, 20);
    stepMountain(noiseParam2, 0.4, mountainHeights, 320)
    drawMountain(mountainHeights, 320);
    //draws foreground scenery
    fill(110, 64, 52);
    stepMountain(noiseParam, noiseStep, hillHeights, numpoints);
    drawMountain(hillHeights, numpoints);
    push();
    translate(0, 20);
    fill(42, 30, 90);
    drawMountain(hillHeights, numpoints);
    //at peaks of hill, add a hobbit hole
    for(let i = -breadth; i <= numpoints+breadth; i++){
            if(i != -breadth & i !=numpoints+breadth){
                if (hillHeights[i] < hillHeights[i-1] &&
                hillHeights[i] < hillHeights[i+1]){
                    push();
                    fill(0);
                    translate(i * xInc, (height + hillHeights[i])/2);
                    drawHole((height-hillHeights[i])/1.5);
                    pop();              
                }

            }
        }
    pop();

}

My idea was to generate a rolling hill and place hobbit holes at random locations or peaks under the hill, with their basic shape looking something like this:

Unfortunately, I realized too late that the program I wrote didn’t utilize objects and made changing variables about the holes (ex. colors and varying designs) very difficult without restructuring the program significantly.

Leave a Reply