//Julia Nishizaki
//Section B
//jnishiza@andrew.cmu.edu
//Project 11 - Generative Landscape
var landscapeScale = 0.005; //detail in hills
var landscapeSpeed = 0.00075; //speed of hills going by
var hillColor = '#92CA6D'; //light green
var houses = []; //array for houses
var trees = []; //array for trees
var train = { ////train variables
wY: 200, //Y of windows
wW: 325, //width of windows
wH: 275, //height of windows
corners: 30, //roundness of window corners
wWeight: 25, //stroke weight of light gray
backgroundColor: 255, //white
mainColor: '#475AA8', //light blue
wColor: '#2A357A', //dark blue, color of window and seats
divXL: 61, //X coordinate of left divider
divXR: 419, //X coordinate of right divider
}
function setup() {
createCanvas(480, 480);
for (var i = 0; i < 5; i ++) { //first houses
var rx = random(width);
houses[i] = makeHouses(rx);
}
for (var i = 0; i < 3; i ++) { //first trees
var tx = random(width);
trees[i] = makeTrees(tx);
}
frameRate(30);
}
function draw() {
background('#8ED9EF'); //blue sky
//creates hills in the background
stroke(hillColor);
for (var x = 0; x < width; x ++) {
var l = (x * landscapeScale) + (millis() * landscapeSpeed);
var y = map(noise(l), 0, 1, 100, 230); //constrains hills
line(x, y, x, height); //creates vertical lines, forming a solid shape
}
displayHouses(); //houses
removeOldHouses();
addHouses();
displayTrees(); //trees
removeOldTrees();
addTrees();
drawTrain(); //train
}
function displayHouses() { //displays and updates house location
for (var i = 0; i < houses.length; i ++) {
houses[i].move();
houses[i].draw();
}
}
function removeOldHouses() { //gets rid of old houses, puts the houses that are still on the canvas in a new array
var housesToKeep = [];
for (var i = 0; i < houses.length; i ++) {
if (houses[i].x + houses[i].breadth > 0) {
housesToKeep.push(houses[i]);
}
}
houses = housesToKeep;
}
function addHouses() { //adds new houses into the array
if (random(0, 1) < 0.02) {
houses.push(makeHouses(width));
}
}
function moveHouses() { //moves the houses
this.x += this.speed;
if (this.x < -this.breadth) {
this.x == width + this.breadth;
}
}
function drawHouses() { //draws the houses
noStroke();
rectMode(CORNER);
fill(this.r, this.g, this.b); //randomizes color
push();
translate(this.x, this.y);
rect(0, -this.height, this.breadth, this.height); //house rectangle
//roof
fill(255);
triangle(-2, -this.height + 1, this.breadth + 2, -this.height + 1, this.breadth / 2, -this.height - this.roofH);
//door
rect(this.doorX, - this.doorH, this.doorW, this.doorH);
pop();
}
function makeHouses(locationX) { //house variables
var hse = {x: locationX,
y: random(225, 275),
r: random(255),
g: random(255),
b: random(255),
roofH: round(random(10, 25)),
height: round(random(25, 50)),
breadth: round(random(30, 60)),
doorX: random(10, 20),
doorW: 10,
doorH: 15,
speed: -6.0,
move: moveHouses,
draw: drawHouses}
return hse;
}
//trees
function displayTrees() { //dispays and updates tree locations
for (var i = 0; i < trees.length; i ++) {
trees[i].movet();
trees[i].drawt();
}
}
function removeOldTrees() { //gets rid of old trees
var treesToKeep = [];
for (var i = 0; i < trees.length; i ++) {
if (trees[i].xt + trees[i].breadtht > 0) {
treesToKeep.push(trees[i]);
}
}
trees = treesToKeep;
}
function addTrees() { //adds new trees
if (random(0, 1) < 0.1) {
trees.push(makeTrees(width));
}
}
function moveTrees() { //moves trees
this.xt += this.speedt;
if (this.xt < -this.breadtht) {
this.xt == width + this.breadtht;
}
}
function drawTrees() { //draws trees
noStroke();
rectMode(CORNER);
colorMode(HSB, 100); //switches color mode to HSB to assist with random colors
fill(this.ht, 55, this.bt); //random colors between yellow-green to green
push();
translate(this.xt, height * 3 / 4);
rect(0, -this.heightt, this.breadtht, this.heightt, 50, 50, 0, 0);
pop();
}
function makeTrees(locationX) { //tree variables
var trs = {xt: locationX,
bt: random(50, 85),
ht: random(17, 25),
heightt: round(random(50, 160)),
breadtht: round(random(100, 130)),
speedt: -10.0,
movet: moveTrees,
drawt: drawTrees}
return trs;
}
//train
function drawTrain() {
colorMode(RGB);
drawWindow(width / 2); //draws center window
drawWindow(-118); //draws left window
drawWindow(width + 118); //draws right window
//light blue panels
noStroke();
rectMode(CORNER);
fill(train.mainColor);
rect(0, 0, width, train.wY - (train.wH / 2) - 10); //top panel
rect(0, train.wY + (train.wH / 2) + 10, width, height - (train.wY + (train.wH / 2)) - 10); //bottom panel
//seats
drawSeats(train.divXL, 0, 0, 40); //left seat
drawSeats(train.divXR, width - 200, 40, 0); //right seat
//table
rectMode(CENTER);
rect(width / 2, height - 105, 150, 20, 5, 5, 5, 5);
//section dividers, light gray
drawDividers(train.divXL);
drawDividers(train.divXR);
}
function drawWindow(x) { //creates center window
rectMode(CENTER);
noFill();
stroke(train.backgroundColor); //creates light gray area around the windows
strokeWeight(train.wWeight);
rect(x, train.wY, train.wW + train.wWeight, train.wH + train.wWeight, train.corners, train.corners, train.corners, train.corners);
stroke(train.wColor); //creates blue window border
strokeWeight(10);
rect(x, train.wY, train.wW, train.wH, train.corners, train.corners, train.corners, train.corners);
}
function drawSeats(x1, x2, UL, UR) {
fill(train.wColor);
rect(x1 - 45, height - 200, 90, 200, 30, 30, 0, 0); //seat back
rect(x2, height - 50, 200, 50, UL, UR, 0, 0); //left seat cushions
}
function drawDividers(x) {
strokeWeight(5);
stroke(200);
line(x, train.wY - (train.wH / 2) - 7.5, x, height); //line dividing sections
}
For this project, I wanted to create a landscape outside of a train window. I decided to use three layers, some bushes or trees in the foreground, houses in the middle ground, and hills in the background. I tried to change the speeds of the different layers, with the tree layer the fastest and the hill layer the slowest, in order to give the illusion of perspective, and that you’re looking out of a window as everything flies by.