This is the concept sketch of my generative landscape. I wanted to create a road with hills in the background and cars driving across the road. If I had more time with the project, I would’ve added more randomized details to the hills like stripes or grass texture patterns.
My process was pretty simple. I created objects for the different elements that I would be randomizing. For example, I made an array of objects for the hills, the roads, and the cars. I would repeat the process of creating the different functions for the various elements—with minor adjustments to the movement and randomness of each element.
//Anthony Pan
//Section C
//objects to create:
//hills
//cars
//road
//hold hills
var hillshowing = [];
//object for hills
var hills;
//hold road1
var road1showing = [];
//object for road1
var road1;
var road2;
var road2showing = [];
//car object
var car;
//array holding car object
var carShowing = [];
//car2 object
var car2;
//array holding car2 objects
var car2Showing = [];
//frame counter
var counter = 0;
function setup() {
createCanvas(480, 300);
//create hills
for(var i = 0; i < 20; i++) {
hills = makeHills(i*30, 245);
hillshowing.push(hills);
}
//create road1
for(var j = 0; j<10; j++) {
road1 = makeRoad1(j*10, 280);
road1showing.push(road1);
}
//create road2
for(var k = 0; k<10; k++) {
road2 = makeRoad2(k*10, 250);
road2showing.push(road2);
}
//create cars on road1
for(var h = 0; h < 5; h++) {
car = makeCar(0, round(random(270, 290)), random(2,4));
carShowing.push(car);
}
//create cars on road2
for(var c = 0; c < 5; c++) {
car2 = makeCar2(width, round(random(240, 255)), random(-4,-2));
car2Showing.push(car2);
}
}
function draw() {
//sky
background(135, 221, 255);
//sun
drawSun();
//hills
updateandDrawhills();
removeHillsOffScreen();
addNewHill();
//roads2 / upper roads
fill(156, 117, 95);
rect(0, 245, width, 40);
updateandDrawRoad2();
removeRoad2offScreen();
addNewRoad2();
//roads lower/ road1
fill(0);
rect(0, 270, width, 40);
updateandDrawRoad1();
removeRoad1offScreen();
addNewRoad1();
//draw cars on road2
updateandDrawCar2();
removeCars2OffScreen();
addCar2();
//draw cars
updateandDrawCar();
removeCarsOffScreen();
addNewCar();
}
//draw sun
function drawSun() {
fill("lightyellow");
noStroke();
circle(90,80, 40);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//MAKE Car2 Functions
//car 2 constructor
function makeCar2(cx, cy, zoom) {
var car2 = {x: cx, y:cy,
speed:zoom,
r: random(255),
g: random(255),
b: random(255),
move: car2Move,
draw: drawCar2 }
return car2;
}
//draw car2 object
function drawCar2() {
fill(this.r, this.g, this.b);
rect(this.x, this.y, 20, 10);
fill(0);
ellipse(3+this.x, 10+this.y, 4, 4);
ellipse(this.x + 17, this.y +10, 4, 4);
}
//update and draw car2
function updateandDrawCar2() {
for(var i = 0; i < car2Showing.length; i++) {
car2Showing[i].move();
car2Showing[i].draw();
}
}
//move car2
function car2Move() {
this.x += this.speed;
}
//remove car2s that are off screen
function removeCars2OffScreen() {
var cars2ToKeep = [];
for (var i = 0; i < car2Showing.length; i++){
if (car2Showing[i].x > 0) {
cars2ToKeep.push(car2Showing[i]);
}
}
car2Showing = cars2ToKeep; // remember the showing cars
}
//make new car2 based on probability
function addCar2() {
var newcarlikelihood = 0.03;
if(random(0,1) < newcarlikelihood) {
car2Showing.push(makeCar2(width, round(random(240, 255)), random(-4,-2)));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//MAKE Car Functions
//car constructor
function makeCar(cx, cy, zoom) {
var car = {x: cx, y:cy,
speed:zoom,
r: random(255),
g: random(255),
b: random(255),
move: carMove,
draw: drawCar }
return car;
}
//draw car object
function drawCar() {
fill(this.r, this.g, this.b);
rect(this.x, this.y, 20, 10);
fill(0);
ellipse(3+this.x, 10+this.y, 4, 4);
ellipse(this.x + 17, this.y +10, 4, 4);
}
//update car position and draw car
function updateandDrawCar() {
for(var i = 0; i < carShowing.length; i++) {
carShowing[i].move();
carShowing[i].draw();
}
}
//move car
function carMove() {
this.x += this.speed;
}
//remove cars that are off screen
function removeCarsOffScreen() {
var carsToKeep = [];
for (var i = 0; i < carShowing.length; i++){
if (carShowing[i].x < width) {
carsToKeep.push(carShowing[i]);
}
}
carShowing = carsToKeep; // remember the showing cars
}
//make new car every 100 frames
function addNewCar() {
counter +=1;
if (counter % 100== 0){
carShowing.push(makeCar(0, round(random(270, 290)), random(2,4)));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//MAKE ROAD2 Functions
//constructor for road2
function makeRoad2(rx, ry) {
var road2 = {x:rx, y:ry,
speed: -0.7,
move: road2Move,
draw: drawRoad2 }
return road2;
}
//draw road2
function drawRoad2() {
fill(120);
rect(this.x, this.y, width, 40);
for(var i = 0; i < 50; i++) {
var dx = i * 10;
fill("yellow");
rect(this.x + dx, this.y + 10, 6, 2);
}
}
//update road2 position and draw
function updateandDrawRoad2() {
for(var i = 0; i < road2showing.length; i++) {
road2showing[i].move();
road2showing[i].draw();
}
}
function road2Move() {
this.x += this.speed;
}
//remove roads off the screen
function removeRoad2offScreen() {
var road2ToKeep = [];
for (var i = 0; i < road2showing.length; i++){
if (road2showing[i].x + width > 0) {
road2ToKeep.push(road2showing[i]);
}
}
road2showing = road2ToKeep; // remember the showing roads
}
function addNewRoad2() {
counter +=1;
if (counter % 17 == 0){
road2showing.push(makeRoad2(width,250));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//MAKE ROAD1 FUNCTIONS
//constructor for road1
function makeRoad1(rx, ry) {
var road1 = {x:rx, y:ry,
speed: -0.5,
move: road1Move,
draw: drawRoad1 }
return road1;
}
//draw road
function drawRoad1() {
fill(120);
rect(this.x, this.y, width, 40);
for(var i = 0; i < 50; i++) {
var dx = i * 10;
fill("yellow");
rect(this.x + dx, this.y + 10, 6, 2);
}
}
//update road1 position and draw
function updateandDrawRoad1() {
for(var i = 0; i < road1showing.length; i++) {
road1showing[i].move();
road1showing[i].draw();
}
}
function road1Move() {
this.x += this.speed;
}
//remove roads off the screen
function removeRoad1offScreen() {
var road1ToKeep = [];
for (var i = 0; i < road1showing.length; i++){
if (road1showing[i].x + width > 0) {
road1ToKeep.push(road1showing[i]);
}
}
road1showing = road1ToKeep; // remember the showing roads
}
function addNewRoad1() {
counter +=1;
if (counter % 25 == 0){
road1showing.push(makeRoad1(width,280));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//MAKE HILLS FUNCTIONS
//update hill position and draw hill
function updateandDrawhills() {
for(var i =0; i < hillshowing.length; i++){
hillshowing[i].move();
hillshowing[i].draw();
}
}
//remove hills that have left the screen
function removeHillsOffScreen(){
var hillsToKeep = [];
for (var i = 0; i < hillshowing.length; i++){
if (hillshowing[i].x +20 > 0) {
hillsToKeep.push(hillshowing[i]);
}
}
hillshowing = hillsToKeep; // remember the showing hills
}
//make new hill from right side of canvas
function addNewHill() {
counter +=1;
if (counter % 25 == 0){
hillshowing.push(makeHills(width+20,245));
}
}
//hill constructor
function makeHills(hx, hy) {
var hills = {x:hx, y:hy,
width:random(40, 70),
height:random(100, 300),
r:0, g:random(115,200), b: random(15, 35),
speed: -1.0,
move: hillsMove,
draw: drawHills }
return hills;
}
//draw hills
function drawHills() {
fill(this.r, this.g, this.b);
ellipse(this.x, this.y, this.width, this.height);
}
//move hill to left
function hillsMove() {
this.x += this.speed;
}