Generative Landscape
I struggled a lot with this project. There were so many little things I wanted to do but didn’t know how to execute. I wanted to create a calming lake and mountains landscape with the sun in the background and used a purple color scheme and gradients to achieve this. The starter code helped me a lot with the clouds. The most difficult part, I think, was creating the reflections in the water – I used the noise() function to create them and used a similar code to the mountains. In the end, I used fog image to spice things up and create atmosphere.
// Tiffany Lai
// 15-104, Section A
// thlai@andrew.cmu.edu
// Project 10 - Landsape
var clouds = []; // array for clouds
var waterX = []; // array for x position of reflection lines
var waterY = []; // array for y position of reflection lines
var speed1 = 0.0002; // for mountain1
var peaks1 = 0.03; // for mountain1
var speed2 = 0.0005; // for mountain2
var peaks2 = 0.03; // for mountain2
var boatX = 250; // x coordinates of boat
var img; // variable to store fog filter
function preload() {
img = loadImage("https://i.imgur.com/aoZ4YwF.png"); // fog image
}
function setup() {
createCanvas(480, 480);
// initial collection of clouds
for (var i = 0; i < 5; i++) {
var rx = random(width);
clouds[i] = makeClouds(rx);
}
for (var i = 0; i < 50; i++) {
var sparkleX = random(0, width);
var sparkleY = random(height * 2 / 3, height);
waterX.push(sparkleX);
waterY.push(sparkleY);
}
}
function draw() {
var num = height; // number of lines for gradient bg
// gradient background
for (var i = 0; i < num; i++) {
strokeWeight(2);
stroke(100 + 1.2 * i, 50 + i, 100 + 0.7 * i);
line(0, i, width, i);
}
sun(); // draw sun
updateClouds(); // update and display clouds
removeClouds(); // remove clouds that have slippsed out of view
addClouds(); // add new clouds with random probability
mountain1(); // draw first mountains
mountain2(); // draw second mountains
water(); // draw water and reflections
boat(boatX); // draw boat
boatX -= 0.5; // boat speed
if (boatX < -50) { // if boat exits left, make it come in right
boatX = width;
}
image(img, 0, 0, width, height); // load fog
}
function sun() { // sun and rays
noStroke();
fill(255, 200);
ellipse(width / 3, height / 3, 170, 170); // sun
for (var i = 0; i < 55; i++) { // sun rays
strokeWeight(1);
stroke(color(220 + 2 * i, 120 + i, 130 + 1 * i, 100)); // gradient
noFill();
ellipse(width / 3, height / 3, 170 + i * i * 0.2, 170 + i * i * 0.2); // distance between circles
}
}
function updateClouds() {
for (var i = 0; i < clouds.length; i++) {
clouds[i].move();
clouds[i].display();
}
}
function removeClouds() {
var keepClouds = [];
for (var i = 0; i < clouds.length; i++) {
if (clouds[i].x + clouds[i].breadth > 0) {
keepClouds.push(clouds[i]);
}
}
clouds = keepClouds;
}
function addClouds() {
// probability of cloud appearing
var cloudChance = 0.007;
if (random(0, 1) < cloudChance) {
clouds.push(makeClouds(width));
}
}
function moveClouds() { // speed of clouds
this.x += this.speed;
}
function displayClouds() {
fill(255, 50);
noStroke();
ellipse(this.x, this.y, this.width, this.height);
ellipse(this.x + 10, this.y + 10, this.width - 10, this.height - 10);
ellipse(this.x + 20, this.y - 10, this.width / 2, this.height / 2);
ellipse(this.x - 20, this.y, this.width - 20, this.height - 10);
}
function makeClouds(cloudX) {
var cloud = {
x: cloudX,
y: random(0, height / 2 - 100),
speed: random(-1, -0.1),
width: random(40, 100),
height: random(20, 50),
breadth: 50,
move: moveClouds,
display: displayClouds,
}
return cloud;
}
function mountain1() { // background mountains
noStroke();
fill(135, 86, 110);
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * peaks1) + (millis() * speed1);
var y = map(noise(t), 0, 1, height / 5, height / 2);
vertex(x, y);
}
vertex(width, height);
vertex(0, height);
endShape();
}
function mountain2() { // middleground mountains
// noStroke();
stroke(70, 63, 86);
strokeWeight(1);
// beginShape();
for (var x = 0; x < width; x++) {
var t = (x * peaks2) + (millis() * speed2);
var y = map(noise(t), 0, 2, height / 2, height / 3);
line(x, 330 + y / 2, x, 330 - y / 2);
}
}
function water() { // water and reflections
noStroke();
fill(170, 120, 126, 100);
rect(0, height - height / 3, width, height);
for (var i = 0; i < 15; i++) {
var t = (i * peaks2) + (millis() * speed2);
var widthChange = (map(noise(t), 0, 1, 0, 100));
stroke(255, 70);
line(waterX[i] - widthChange, waterY[i], waterX[i] + widthChange, waterY[i]);
}
}
function boat(boatX) { // make boat
noStroke();
fill(50, 43, 76);
triangle(boatX + 31, 367, boatX + 31, 393, boatX + 16, 393);
triangle(boatX + 33, 374, boatX + 34, 393, boatX + 47, 393);
quad(boatX + 15, 396, boatX + 23, 405, boatX + 40, 405, boatX + 47, 396);
stroke(255, 50);
line(boatX + 15, 405, boatX + 45, 405);
}