Project 07: Generative Landscape

When asked to plan a generative moving landscape, I immediately thought of the game, Journey. This is a visually stunning, emotionally oriented game where you, a cloaked wanderer fly through a landscape of sand dunes, old buildings, ruins and caves.

I tried to refer to the color scheme and the my favorite structures, the posts, in this sketch. I used noise functions to render the scenery. I used a random function for the color of the posts to create a dust-wind effect.

journey_613081

 

sketch


var post = [];
var player;

function preload () {
    player = loadImage('http://i.imgur.com/5JZwRaC.png');
}

//----------------------------------
function setup() {
    createCanvas(640, 240); 
    
    //initial collection of posts
    for (var i = 0; i < 10; i ++) {
        var rx = random(width);
        var ry = random(100, 150);
        post[i] = new Post(rx, ry);
    }
}

//---------------------------------
function draw() {
    background(249, 212, 141); 
    updateAndDisplayPost();

    displayScenery();
    displayCharacter();

    removePosts();
    addPosts();
}


//----------------------------------

function updateAndDisplayPost () {
  for (var i = 0; i < post.length; i++) {
    post[i].move();
    post[i].display();
  }
}

function addPosts () {
    buildings.push(new Post (width, height));
}

function displayScenery () {
    var noiseScale = 0.02;
    var terrainDetail = 0.0005;
    var terrainSpeed = 0.0005;
    //sky bottom
    for (var x=0; x < width; x++) {
        var t = (x*terrainDetail*10) + (millis()*(terrainSpeed/4));
        var y = map(noise(t), 0, 1, 0, height);
        stroke(251, 244, 197);
        line(x, y, x, height);
    }
    //rocks
    for (var a=0; a< width; a++) {
        var b = (a*terrainDetail*10) + (millis()*terrainSpeed/2);
        var c = map(noise(b), 0, 1, 0, height);
           stroke(225, 169, 71);
           line(a, c + 30, a, height);
    }
    //sand
    for (var i=0; i< width; i++) {
        var j = (i*terrainDetail/2) + (millis()*terrainSpeed);
        var k = map(noise(j), 0, 1, 0, height);
           stroke(241, 184, 82);
           line(i, k+50, i, height);
    }
    //dunes
    for (var d=0; d< width; d++) {
        var e = (d*terrainDetail*7) + (millis()*terrainSpeed);
        var f = map(noise(e), 0, 1, 0, height);
           stroke(200, 133, 62);
           line(d, f + 100, d, height);
    }
}

function removePosts () {
    for (var i = 0; i < post.length; i++) {
        if (post[i].x < 0-post[i].width) {
            post.splice(i, 1);
        }
    }
}
function addPosts () {
    var likelihood = 0.007;
    if (random(0.1) < likelihood) {
        post.push(new Post (width, height));
    }
}

function Post (birthLocationX, birthLocationY) {
    
    this.x = birthLocationX
    this.y = birthLocationY
    this.pwidth = random(50, 80);
    this.pheight = random(5, 20);
    this.speed = -1.0
  
    this.move = function () {
        this.x += this.speed;
    }
  
    this.display = function () {
        //top structure
        var posX1 = this.x;
        var posY1 = this.y;
        var width1 = this.pwidth;
        var height1 = this.pheight;
        noStroke();
        fill(random(100));
        rect(posX1, posY1, width1, height1);
        //bottom two structures
        var posX2 = this.x + 10;
        var posY2 = this.y + height1;
        var width2 = height1;
        var height2 = width1/1.5;
        rect(posX2, posY2, width2, height2);
        rect(posX2 + posY2*(5/6), posY2, width2, height2);
    }
}

function displayCharacter () {
    var sizeX = 100;
    var sizeY = 100;
    image(player, mouseX, mouseY, sizeX, sizeY);
    
    if (mouseY >= height) { 
        sizeX = mouseX;
        sizeY = mouseY;
    }
}