Project 11: Generative Landscape

For my project, I decided to create a relaxing underwater scene. Although it was a bit challenging to figure out how to execute my ideas, I had fun making my landscape and adjusting properties to make it more interesting. To create my landscape, I combined concepts that we learned in the past, such as arrays, objects, loops, noise, images, and functions. I randomized properties such as the x/y positions, sizes, colors, and speeds of my objects.

landscape-cb
var terrain = [];
var coral;
var bubbles = [];
var fish = [];

var noiseParam = 0;
var noiseStep = 0.05;

function preload() {
    coral = loadImage("https://i.imgur.com/S5HGpZa.png");
}

function setup() {
    createCanvas(480, 300);
    //setup noise for terrain
    for(var i=0; i<=width/5; i++) {
        var n = noise(noiseParam);
        var value = map(n, 0, 1, 0, height);
        terrain.push(value);
        noiseParam += noiseStep;
    }
    //setup for fish
    for (var i = 0; i < 15; i++) {
        fishx = random(width);
        fish[i] = makeFish(fishx);
    }
    //setup for bubbles
    for (var i = 0; i < 10; i++) {
        bubblex = random(width);
        bubbley = random(height);
        bubbles[i] = makeBubble(bubblex, bubbley);
    }
    frameRate(10);
}

function draw() {
    background(0, 180, 200);

    noStroke();
    fill(0, 230, 255, 90);
    ellipse(240, 0, 600, 200);

    blueTerrain();
    
    updateAndDisplayFish();
    removeFish();
    addNewFish();
    
    displayBubbles();
}

//background terrain
function blueTerrain() {
    terrain.shift();
    var n = noise(noiseParam);
    var value = map(n, 0, 1, 0, height);
    terrain.push(value);
    noiseParam += noiseStep;
    
    //blue terrain
    noStroke();
    fill(0, 66, 115);
    beginShape();
    vertex(0, height);
    for(var i=0; i<width/4; i++) {
        vertex(i*5, terrain[i]);
        //placement of coral on terrain
        if(terrain[i] < terrain[i-1] & terrain[i] < terrain[i+1]) {
            drawCoral(i*5, terrain[i]);
        }
    }
    vertex(width, height);
    endShape(CLOSE);
}

//draws coral on terrain
function drawCoral(x, y) {
    imageMode(CENTER);
    image(coral, x, y-10, 65, 80);
}

//update the fish positions and display them
function updateAndDisplayFish() {
    for (var i = 0; i < fish.length; i++) {
        fish[i].move();
        fish[i].draw();
    }
}

//remove fish that are off the canvas from the array
function removeFish() {
    var fishToKeep = [];
    for (var i = 0; i < fish.length; i++) {
        if (fish[i].x + fish[i].w > 0) {
            fishToKeep.push(fish[i]);
        }
    }
    fish = fishToKeep;
}

//with a small probability, add a new fish to end of the array
function addNewFish() {
    var newFishLikelihood = 0.3;
    if (random(0,1) < newFishLikelihood) {
        fish.push(makeFish(width+20));
    }
}

function moveFish() {
    this.x += this.speed;
}

function drawFish() {
    push();
    translate(this.x, this.y);
    fill(this.color);
    ellipse(0, 0, this.w, this.h);
    strokeWeight(1.5);
    stroke(240);
    fill(50);
    ellipse(-15, -4, 8, 8);
    noStroke();
    fill(this.fincolor);
    triangle(0, -4, 0, 4, 15, 0);
    noFill();
    push();
    fill(this.color);
    triangle(this.w/2+20, -8, this.w/2+20, 8, (this.w/2)-2, 0);
    pop();
    pop();
}

//fish constructor
function makeFish(fishx) {
    var f = {x: fishx, y: random(height),
            w: random(40, 80), h: random(10, 45),
            color: color(random(100, 255), random(100, 255), random(100, 255)),
            fincolor: color(random(50, 200), random(50, 200), random(50, 200)),
            speed: random(-10, -20),
            move: moveFish,
            draw: drawFish
    }
    return f;
}

function displayBubbles() {
    for (var i = 0; i < bubbles.length; i++) {
        bubbles[i].move();
        bubbles[i].draw();
    }
}

//bubbles float upwards
function moveBubbles() {
    this.x += this.speed;
    this.y += this.speed;
    if (this.x <= 0) {
        this.x = width;
    }
    if (this.y <= 0) {
        this.y = height;
    }
}

function drawBubbles() {
    push();
    strokeWeight(1);
    stroke(255, 255, 255, 80);
    fill(100, 255, 255, 60);
    ellipse(this.x, this.y, this.size, this.size);
    noFill();
    strokeWeight(2);
    arc(this.x - this.size/12, this.y - this.size/12, 15, 15, PI, PI + HALF_PI);
    pop();
}

//bubbles constructor
function makeBubble(bubblex, bubbley) {
    var b = {x: bubblex, y: bubbley,
            size: random(20, 40),
            speed: random(-1, -6),
            move: moveBubbles,
            draw: drawBubbles
    }
    return b;
}

Leave a Reply