It was fun to figure out how to create a whole landscape without having to define absolutely everything and making it more interesting with randomness. I added a shooting star with a very small creation probability to create a little surprise within the landscape every once in a while.
// Rachel Legg / rlegg / Section C
//have trees and stars move by
//every once in a while, a surprising shooting star
//car in the middle (moving past trees)
var stars =[];var trees =[];var shootingStars =[];var car;functionpreload(){
car =loadImage("https://i.imgur.com/C7SXV3W.png");}functionsetup(){createCanvas(450,300);frameRate(10); //initial stars and trees
for(var i =0; i <6; i++){var sx =random(width);
stars[i]=makeStar(sx);}for(var i =0; i <10; i++){var sx =random(width);
trees[i]=makeTree(sx);} //random shooting star
for(var i =0; i <1; i++){var sx =random(width);
shootingStars[i]=makeShootingStar(sx);}}functiondraw(){ //sky - dark blue
background(10,52,99); //ground
fill("darkgreen");noStroke();rect(0,240,500,75); //road
fill("gray");rect(0,260,495,10)updateAndDisplayStar();removeStarOutOfView();addNewStar();updateAndDisplayShootingStars();removeShootingStarOutOfView();addNewShootingStars();updateAndDisplayTree();removeTreeOutOfView();addNewTree(); //car stays stationary as scenery moves by
//drew out car in illustrator & uploaded to imgur
image(car, width/2-60,207,165,65);}
//stars object
functionmakeStar(starLocationX){var star ={x : starLocationX,
y :random(0,170),
starScale :random(0.1,0.5),
speed :-1,
move : moveStar,
display : displayStar}return star;}functiondisplayStar(){push();translate(this.x,this.y);fill(255);noStroke();scale(this.starScale);beginShape();vertex(50,18);vertex(61,37);vertex(83,43);vertex(69,60);vertex(71,82);vertex(50,73);vertex(29,82);vertex(31,60);vertex(17,43);vertex(39,37);endShape();pop();}
//update star positions and display
functionupdateAndDisplayStar(){for(var i =0; i < stars.length; i++){
stars[i].move();
stars[i].display();}}functionaddNewStar(){var newStarProbability =0.01;if(random(0,1)< newStarProbability){
stars.push(makeStar(width));}}function removeStarOutOfView (){ //if star goes off left edge, remove from array
var starsToKeep =[];for(var i =0; i < stars.length; i++){if(stars[i].x +50>0){
starsToKeep.push(stars[i]);}} //stars left
stars = starsToKeep;}functionmoveStar(){this.x +=this.speed;}
//trees object
functionmakeTree(treeLocationX){var tree ={xt : treeLocationX,
yt :240,
treeScale :random(0.1,0.5),
treeColor :color(0,random(75,255),0),
speedT :-3,
moveT : moveTree,
displayT : displayTree}return tree;}functiondisplayTree(){push();translate(this.xt +60,this.yt); //add 60 so transitions onto screen
fill(255);noStroke();scale(this.treeScale); //tree!
noStroke();fill("brown");rect(0,0,10,-50);rect(1,0,-10,-50);fill(this.treeColor);triangle(-60,-50,60,-50,0,-400);pop();}
//update tree positions and display
functionupdateAndDisplayTree(){for(var i =0; i < trees.length; i++){
trees[i].moveT();
trees[i].displayT();}}functionaddNewTree(){var newTreeProbability =0.04;if(random(0,1)< newTreeProbability){
trees.push(makeTree(width));}}function removeTreeOutOfView (){ //if star goes off left edge, remove from array
var treesToKeep =[];for(var i =0; i < trees.length; i++){if(trees[i].xt +100>0){
treesToKeep.push(trees[i]);}} //trees left
trees = treesToKeep;}functionmoveTree(){this.xt +=this.speedT;}
//shooting star object
functionmakeShootingStar(locationX){var shootingStar ={xs : locationX,
ys :random(75,125),
shootingStarScale :random(0.1,0.3),
speedS :-8,
moveS : moveShootingStar,
displayS : displayShootingStar}return shootingStar;}functiondisplayShootingStar(){push();translate(this.xs +60,this.ys); //add 60 so transitions onto screen
fill("yellow");noStroke();scale(this.shootingStarScale); //shooting star
beginShape();vertex(50,18);vertex(61,37);vertex(83,43);vertex(69,60);vertex(71,82);vertex(50,73);vertex(29,82);vertex(31,60);vertex(17,43);vertex(39,37);endShape();stroke("yellow");strokeWeight(2);line(60,37,100,37);line(60,47,110,47);line(60,57,120,57);pop();}
//update tree positions and display
functionupdateAndDisplayShootingStars(){for(var i =0; i < shootingStars.length; i++){
shootingStars[i].moveS();
shootingStars[i].displayS();}}functionaddNewShootingStars(){var newShootingStarsProbability =0.008;if(random(0,1)< newShootingStarsProbability){
shootingStars.push(makeShootingStar(width));}}function removeShootingStarOutOfView (){ //if star goes off left edge, remove from array
var shootingStarsToKeep =[];for(var i =0; i < shootingStars.length; i++){if(shootingStars[i].xs +100>0){
shootingStarsToKeep.push(shootingStars[i]);}} //trees left
shootingStars = shootingStarsToKeep;}functionmoveShootingStar(){this.xs +=this.speedS;}
/* Evan Stuhlfire
* estuhlfi@andrew.cmu.edu section B
* project-11-generative landscape */var hills =[];var trees =[];var chickArray =[];var imgArray =[];var farm =[];var barnImg;var cowImg;var planeObj;var flyingPlane =false;var scrollSpeed =5;functionpreload(){ // preload images
// URLs to imgur walking chick
// Chick image licensed from Adobe stock images
var filenames =[];
filenames[0]="https://i.imgur.com/kjBGzBF.png";
filenames[1]="https://i.imgur.com/hxvbkWZ.png";
filenames[2]="https://i.imgur.com/53MK7g1.png";
filenames[3]="https://i.imgur.com/6nrYJCw.png";
filenames[4]="https://i.imgur.com/XmPcBDa.png";
filenames[5]="https://i.imgur.com/3OusOsv.png";for(var i =0; i < filenames.length; i++){
imgArray[i]=loadImage(filenames[i]);
barnImg =loadImage("https://i.imgur.com/inS5Xdt.png");
cowImg =loadImage("https://i.imgur.com/8XjQyMt.png");}}
// methods
functionstepChick(){ // update the chick image to animate
if(this.imgNum < chickArray.length -2){ // increment to next image
this.imgNum++;}else{ // if at end of array reset to beginning
this.imgNum =0;}}functiondrawChick(){ // draw image
image(imgArray[this.imgNum],this.x,this.y,50,50);}functiondrawOneHill(){ // draw hill
fill(this.c);stroke(0,150,0);strokeWeight(1);ellipse(this.x,this.y,this.w,this.hi);this.x -=this.s; // decrement by speed
}functiondrawTree(){ // draw trunk
stroke(77,38,0);strokeWeight(3);line(this.x,this.y,this.x,this.y +(this.h *.8));line(this.x,this.y +this.h *.5,this.x +this.w *.2,this.y +this.h *.2);line(this.x,this.y +this.h *.7,this.x -this.w *.1,this.y +this.h *.1); // draw leaves
fill(this.c);stroke(0,100,0);strokeWeight(1);ellipse(this.x,this.y,this.w,this.h);this.x -=this.speed; // decrement by speed
}
// object constructor functions
functionnewChick(cx, cy){ // constructor to make a chick
var c ={x: cx, y: cy,
imgNum:0,
stepFunction: stepChick,
drawFunction: drawChick
}return c;}functionnewHill(hx, hy, hw, hhi, hc, hs){ // create new hill at x, y with diameter d
var h ={x: hx, y: hy, w: hw, hi: hhi,
c: hc, s: hs,
drawFunction: drawOneHill
};return h;}functionnewTree(tx, ty, tw, th, tc, ts){ // create new tree at x, y of height th, color tc
// tree width = tw, tree speed = ts
var t ={x: tx, y: ty, w: tw, h: th, c: tc,
speed: ts,
drawFunction: drawTree
};return t;}functionnewFarm(fx, fy, fi, fw, fh, fb){ // create new farm img at x, y
// use farm image fi
var f ={x: fx, y: fy, img: fi,
w: fw, h: fh,
speed: scrollSpeed,
barn: fb
};return f;}functionnewPlane(px, py, pdx, pdy){ // create plane object
var p ={x: px, y: py, dx: pdx, dy: pdy};return p;}functionsetup(){createCanvas(480,480);frameRate(10);imageMode(CENTER); // loop to create chick images
for(var i =0; i < imgArray.length; i++){
chickArray[i]=newChick(width/2, height *.7);}var onCanvas =true; // generate initial hills
var numHills =floor(random(15,20)); // onCanvas = true for first set of hills to draw on canvas
generateHills(onCanvas, numHills); // create a farm
generateFarm(); // generate initial trees
var numTrees =floor(random(1,10)); // onCanvas = true trees drawn on canvas
generateTrees(onCanvas, numTrees,1);generateTrees(onCanvas, numTrees,2);generateTrees(onCanvas, numTrees,3);}functiondraw(){ // call all the parts of the scrolling background
background(153,179,255);drawSun(); // draw hills
drawHills();removeHills();createNewHills();foreground(); // draw farm elements, barns and cows
drawFarm();removeFarm();createNewFarm(); // draw trees
drawTrees();removeTrees();createNewTrees(1);createNewTrees(2);createNewTrees(3); // animate the little chick
drawLittleChick(); // draw plane
createPlane();drawPlane();}functiondrawSun(){ // draw stationary sun
fill(255,255,77,200);stroke(255,255,26);strokeWeight(1);ellipse(width *.85, height *.1,50,50);}functionforeground(){ // draw grass
fill(0,153,51);noStroke();rect(0, height/3, width, height); // draw path
stroke(153,102,51);strokeWeight(20);line(0, height *.75, width, height *.75); // draw pebbles
// generate differnt shades of tan
stroke(random(210,250),random(125,220),random(85,220));strokeWeight(3);var y =floor(random(height *.75-10, height *.75+10));var x =floor(random(0, width));point(x, y);}functiondrawLittleChick(){ // loop through chick array call step and draw methods
for(var i =0; i < chickArray.length; i++){var currentChick = chickArray[i];
currentChick.stepFunction();
currentChick.drawFunction();}}functioncreatePlane(){ // probability of a plane
var newPlaneLikely =.0008;if(random(0,1)< newPlaneLikely &!flyingPlane){var y =floor(random(40,100));var x =0;var dx =random(2,5);var dy =random(.1,.8);
planeObj =newPlane(x, y, dx, dy);
flyingPlane =true;}}functiondrawPlane(){if(flyingPlane){stroke(230,255,255);strokeWeight(3);line(planeObj.x, planeObj.y, planeObj.x +30, planeObj.y -2); // draw wings
strokeWeight(1);line(planeObj.x +18, planeObj.y -2, planeObj.x +3,
planeObj.y +5);line(planeObj.x +18, planeObj.y -1, planeObj.x +20,
planeObj.y -10); // draw tail
line(planeObj.x, planeObj.y, planeObj.x -3, planeObj.y -8);
planeObj.x += planeObj.dx;
planeObj.y -= planeObj.dy;if(planeObj.x > width || planeObj.y <0){
flyingPlane =false;}}}functioncreateNewHills(){ // probability of a hill
var newHillLikely =.07;if(random(0,1)< newHillLikely){var numHills =floor(random(5,12));var onCanvas =false;generateHills(onCanvas, numHills);}}functionremoveHills(){ // if array has more items and hills have scrolled off screen
var keep =[];if(hills.length >=0){for(var i =0; i < hills.length; i++){if(hills[i].x + hills[i].w/2>0){
keep.push(hills[i]);}}
hills = keep;}}functiondrawHills(){ // draw hills on canvas
for(var i =0; i < hills.length; i++){var h = hills[i];
h.drawFunction();}}functiongenerateHills(onCanvas, num){ // if onCanvas = true then generate first set of hills
// on canvas, otherwise generate off canvas
// generate num number of new hills
for(var i =0; i < num; i++){ // generate hill color
var g =floor(random(50,230));var c =color(80, g,0); // generate x, y, width, and height of hill
var y =random(height/2.6, height/2);var w =random(100, width);var h =random(150,250);if(onCanvas){ // generate hills on canvas
var x =random(-w, width + w *3);var w =random(width/2, width);}else{ // generate hills off canvas
var x =random(width +(w *1.5), width *3);}var hill =newHill(x, y, w, h, c,5);
hills.push(hill);}}functioncreateNewFarm(){ // probability of a farm
var newFarmLikely =.01;if(random(0,1)< newFarmLikely){generateFarm();}}functionremoveFarm(){ // if array has more items and farms have scrolled off screen
var keep =[];if(farm.length >=0){for(var i =0; i < farm.length; i++){if(farm[i].x + farm[i].w >0){
keep.push(farm[i]);}}
farm = keep;}}functiongenerateFarm(){ // create cows on farm
var isBarn =falsevar numCows =floor(random(10,30));for(var i =0; i < numCows; i++){ // create a cow object and add it to the farm
// array for each cow
var x =random(width, width *4);var y =random(height/2.2, height/3.5);if(y < height/2.7){ // make cows smaaller, they are further away
var w =random(10,15);var h =random(10,15);}else{ // make cows bigger, they are closer
var w =random(25,30);var h =random(25,30);}var c =newFarm(x, y, cowImg, w, h, isBarn);
farm.push(c);} // randomly generate barn variables
var x =random(width + w, width *2);var y =random(height/2.6, height/3.7); // if barn is further away, draw it smaller
if(y < height/3.2){var w =random(20,40);var h =random(20,40);}else{ // close and bigger
var w =random(60,90);var h =random(50,70);}
isBarn =true;var f =newFarm(x, y, barnImg, w, h, isBarn);
farm.push(f);}functiondrawFarm(){ // draw farm on canvas
var barnArray =[];if(farm.length >0){for(var i =0; i < farm.length; i++){var f = farm[i];if(f.barn){
barnArray.push(f);}else{ // draw cows behind barns
image(f.img, f.x, f.y,
f.w, f.h);
f.x -= f.speed;}} // draw barns in their own layer on top of cows
for(var i =0; i < barnArray.length; i++){var b = barnArray[i];image(b.img, b.x, b.y, b.w, b.h);
b.x -= b.speed;}
barnArray =[];}}functioncreateNewTrees(layer){var newTreeLikely =.012;var numTrees =floor(random(2,4)); // send false to generate off canvas
var onCanvas =false;if(random(0,1)< newTreeLikely){generateTrees(onCanvas, numTrees, layer);}}functionremoveTrees(){ // if array has more items and trees have scrolled off screen
var keep =[];if(trees.length >=0){for(var i =0; i < trees.length; i++){if(trees[i].x + trees[i].w >0){
keep.push(trees[i]);}}
trees = keep;}}functiondrawTrees(){ // draw trees on canvas
if(trees.length >=0){for(var i =0; i < trees.length; i++){var t = trees[i];
t.drawFunction();}}}functiongenerateTrees(start, num, layer){ // if start = true then generate first set of trees
// on canvas, otherwise generate off canvas
// generate num number of new trees
for(var i =0; i < num; i++){ // generate tree color
var r =floor(random(70,100));var g =floor(random(80,255));var b =floor(random(80,120));if(layer ==1){var c =color(r, g, b,190); // create big trees in background
bigTrees(start, c);}elseif(layer ==2){
r =floor(random(0,150));
g =floor(random(50,150));
b =floor(random(250,255));var c =color(r, g, b,190); // create little trees in midground
littleTrees(start, c);}else{
r =floor(random(250,255));
g =floor(random(30,150));
b =floor(random(80,255));var c =color(r, g, b,200); // create shrubs in foreground
shrubs(start, c);}}}functionbigTrees(start, c){ // generate x, y, width, and height of trees
var w =random(50,70);var h =random(40,70);var y =random(height/2.6, height/2.8);if(start){ // generate trees on canvas
var x =random(5, width);}else{ // generate trees off canvas
var x =random(width + w/2, width *3);} // create tree and add to array
var tree =newTree(x, y, w, h, c,5);
trees.push(tree);}functionlittleTrees(start, c){ // generate x, y, width, and height of trees
var w =random(30,40);var h =random(15,40);var y =random(height/1.7, height/2);if(start){ // generate trees on canvas
var x =random(5, width);}else{ // generate trees off canvas
var x =random(width + w/2, width *2);} // create tree and add to array
var tree =newTree(x, y, w, h, c,5);
trees.push(tree);}functionshrubs(start, c){ // generate x, y, width, and height of trees
var w =random(20,40);var h =random(15,20);var y =random(height/1.1, height/1.3);if(start){ // generate trees on canvas
var x =random(5, width);}else{ // generate trees off canvas
var x =random(width + w/2, width *3);} // create tree and add to array
var tree =newTree(x, y, w, h, c,5);
trees.push(tree);}
//PLANET VARIABLES:
var numPlanets =4;var planet ={x:[], y:[], s:[], r:[], g:[], b:[], dx:[]};var d =[];
//STAR VARIABLES:
var numStars =100;var star ={x:[], y:[], s:[], dx:[]};
//IMG VARIABLES:
var porthole;var astroLinks =["https://i.imgur.com/FrLKzou.png","https://i.imgur.com/vdhX4kE.png","https://i.imgur.com/01Kk3J7.png"];var astroPics =[];var astro ={x:[], y:[], s:[], dx:[], e:[]};functionpreload(){for(k =0; k <3; k++){
astroPics[k]=loadImage(astroLinks[k]);}
porthole =loadImage("https://i.imgur.com/YSSOdgW.png") //made this porthole graphic myself
}functionsetup(){createCanvas(480,480);background(0);planetInitialize();starInitialize();astroInitialize();}functiondraw(){background(0);starUpdate();planetUpdate();astroUpdate();image(porthole,0,0, width, height);}functiondrawPlanetA(x, y, s, i){ //option one for planet type (moon-y)
strokeWeight(0);fill(planet.r[i], planet.g[i], planet.b[i]); //randomized color
ellipse(x, y, s, s);fill(planet.r[i]+20, planet.g[i]+20, planet.b[i]+20); //randomized color, but a little bit lighter
ellipse(x - s/10, y + s/3, s/4);ellipse(x + s/5, y - s/10, s/3);ellipse(x - s/4, y - s/5, s/7);}functiondrawPlanetB(x, y, s, i){ //option two for planet type (saturn-y)
fill(planet.r[i], planet.g[i], planet.b[i]);ellipse(x, y, s, s);strokeWeight(3);stroke(255-planet.r[i],255-planet.g[i],255-planet.b[i]);line(x - s*(2/3), y, x + s*(2/3), y);strokeWeight(0);}functionstarUpdate(){for(var j =0; j < numStars; j++){strokeWeight(0)fill(250,248,235); //creamy white
ellipse(star.x[j], star.y[j], star.s[j], star.s[j]);if(star.x[j]>= width + star.s[j]){ //if star has fully moved off screen, I reset the values
star.s[j]=random(1,10);
star.x[j]=random(-20,0-star.s[j]); //HOWEVER, I reset the values with the X position offscreen, so there appears to be a continuous scroll
star.y[j]=random(0, height);
star.dx[j]= star.s[j]/200;}else{
star.x[j]+= star.dx[j]; //if star is not offscreen, it moves to the right
}}}functionplanetUpdate(){for(var i =0; i < numPlanets; i++){if(d[i]<=1){ //selects planet type: if d is less than/equal to one, planet A is drawn, if d is greater than one, planet B is drawn
drawPlanetA(planet.x[i], planet.y[i], planet.s[i], i);}elseif(d[i]>1){drawPlanetB(planet.x[i], planet.y[i], planet.s[i], i);}if(planet.x[i]>= width + planet.s[i]+(planet.s[i]*(2/3))){ //if planet has fully moved off screen, I reset the values
planet.s[i]=random(10,150);
planet.x[i]=random(-200,0-planet.s[i]); //HOWEVER, I reset the values with the X position offscreen, so there appears to be a continuous scroll
planet.y[i]=random(0, height);
planet.r[i]=random(20,235);
planet.g[i]=random(20,235);
planet.b[i]=random(20,235);
planet.dx[i]= planet.s[i]/200;}else{
planet.x[i]+= planet.dx[i]; //if planet is not offscreen, it moves to the right
}}}functionastroUpdate(){for(var k =0; k <3; k++){image(astroPics[k], astro.x[k], astro.y[k], astro.s[k], astro.s[k]);if(astro.x[k]>= astro.e[k]){
astro.x[k]=random(-2000,-150);
astro.y[k]=random(0, height);
astro.s[k]=random(30,400);
astro.dx[k]= astro.s[k]/200;
astro.e[k]=random(height+150,2000);}else{
astro.x[k]+= astro.dx[k];}}}functionplanetInitialize(){for(var i =0; i < numPlanets; i++){
planet.x[i]=random(0, width); //x position
planet.y[i]=random(0, height); //y position
planet.s[i]=random(10,150); //size
planet.r[i]=random(20,235); //r, g, and b are randomized. I seperated these instead of creating a color variable so I could use R, G, and B to edit the details
planet.g[i]=random(20,235);
planet.b[i]=random(20,235);
planet.dx[i]= planet.s[i]/200; //dx is related to the size of the planet, if it's bigger it will appear to move quicker
d[i]=(random(0,2)); //variable d selects whether or not planet type A or B is selected
}}functionstarInitialize(){for(var j =0; j < numStars; j++){
star.x[j]=random(0, width);
star.y[j]=random(0, height);
star.s[j]=random(1,10);
star.dx[j]= star.s[j]/200; //dx is related to the size of the star, if it's bigger it will appear to move quicker
}}functionastroInitialize(){for(var k =0; k <3; k++){
astro.x[k]=random(-2000, width)
astro.y[k]=random(0, height);
astro.s[k]=random(30,150);
astro.dx[k]= astro.s[k]/200;
astro.e[k]=random(height+150,2000); //astro end: beginning/end determines where image starts/ends it's journey before reset. I made the value larger so there would be greater diversity in when astronaunts appeared
}}