creyes1 Project-10 (Generative Landscape)
//Christopher Reyes
//Section D
//creyes1@andrew.cmu.edu
//Project-10 (Generative Landscape)
//Colors
var green1 = [152, 186, 157];
var green2 = [169, 200, 172];
var green3 = [122, 153, 126];
//Shape Arrays
var orbs = [];
var cords = [];
var clouds = [];
var landlines = [];
var inc = 0; //Value for noise command
function setup() {
createCanvas(480, 480);
background(green1);
noStroke();
angleMode(DEGREES);
//Generates random land form
for (var x = 0; x < width; x++) {
landlines.push(makeLandscape(x, 1));
}
//Draws initial set of orbs
for (var i = 0; i < 5; i++) {
var rx = random(width);
var ry = random(height);
orbs[i] = makeOrb(rx, ry);
}
//Adds cord properties to array
for (var i = 0; i < 10; i++) {
cords.push(makeCord());
}
}
function draw() {
background(green1);
//Lighter background shapes
fill(green2);
noStroke();
ellipse(width/2, height/2, 100, 300);
ellipse(width/2 + 120, height/2, 75, 200);
ellipse(width/2 - 120, height/2, 75, 200);
//Renders and moves landscape
for (var x = 0; x < landlines.length; x++) {
landlines[x].display();
landlines[x].move();
}
//Removes first in the array, or the line that goes off-canvas
landlines.shift();
//Increases increment by 1, pushes a new land line onto array
inc += 1;
landlines.push(makeLandscape(width-1, inc));
//Layers lines and orbs for depth
for (var i = 0; i < 7; i++) {
cords[i].display();
}
updatePositions();
for (var i = 7; i < 10; i++) {
cords[i].display();
}
addOrb();
addCloud();
}
//GENERAL FUNCTIONS-------------------------------------------------------------
function updatePositions() {
//Update orb position and display
for (var i = 0; i < orbs.length; i++) {
orbs[i].move();
orbs[i].display();
}
//Update cloud position and display
for (var i = 0; i < clouds.length; i++) {
clouds[i].move();
clouds[i].display();
}
}
//Removes orbs and clouds after passing edge of canvas
function removeFalloff() {
var orbsToKeep = [];
for (var i = 0; i < orbs.length; i++) {
if (orbs[i].x + orb[i].breadth > 0) {
orbsToKeep.push(orbs[i]);
}
}
var cloudsToKeep = [];
for (var i = 0; i < clouds.length; i++) {
if (clouds[i].x) {
cloudsToKeep.push(clouds[i]);
}
}
}
//ORB FUNCTIONS-----------------------------------------------------------------
//Orb & orb properties
function makeOrb(spawnPositionX, spawnPositionY) {
var orb = {x: spawnPositionX,
y: spawnPositionY,
breadth: 216 * this.scale,
scale: random(.25, 1),
speed: random(-.75, -.15),
angle: random(0, 360),
move: orbMove,
display: displayOrb}
return orb;
}
//Base orb drawing, capabable of scaling and rotation
function displayOrb() {
var orbSize = 216 * this.scale;
var px = this.x-(orbSize/2);
var py = this.y-(orbSize/2);
//center position 108, 108
//Inside pink shell rim
fill(216, 154, 196);
push();
translate(px, py);
rotate(this.angle);
beginShape();
vertex((53.8 * this.scale), (15.2 * this.scale));
bezierVertex((1.781 * this.scale), (45.703 * this.scale),
-(15.078 * this.scale), (112.01 * this.scale),
(15.42 * this.scale), (163.31 * this.scale));
bezierVertex((45.919 * this.scale), (214.601 * this.scale),
(112.226 * this.scale), (231.46 * this.scale),
(163.52 * this.scale), (200.96 * this.scale));
bezierVertex((214.817 * this.scale), (170.462 * this.scale),
(231.676 * this.scale), (104.155 * this.scale),
(201.18 * this.scale), (52.86 * this.scale));
bezierVertex((170.679 * this.scale), (1.564 * this.scale),
(104.372 * this.scale), -(15.295 * this.scale),
(53.8 * this.scale), (15.2 * this.scale));
endShape();
//Inside purple
fill(158, 90, 146);
beginShape();
vertex(134.1 * this.scale, 40.76 * this.scale);
bezierVertex(97.698 * this.scale, 46.405 * this.scale,
62.946 * this.scale, 83.298 * this.scale,
56.3 * this.scale, 126.13 * this.scale);
bezierVertex(49.074 * this.scale, 172.708 * this.scale,
77.436 * this.scale, 207.524 * this.scale,
119.85 * this.scale, 200.15 * this.scale);
bezierVertex(161.836 * this.scale, 192.853 * this.scale,
196.48 * this.scale, 147.78 * this.scale,
197.52 * this.scale, 103.01 * this.scale);
bezierVertex(198.488 * this.scale, 61.779 * this.scale,
170.188 * this.scale, 35.198 * this.scale,
134.1 * this.scale, 40.76 * this.scale);
endShape();
//Inside purple shadow
rectMode(CENTER);
fill(116, 55, 107);
push();
translate((83.78 * this.scale), (93.85 * this.scale));
rotate(30);
rect(0, 0, 35 * this.scale, 175 * this.scale);
pop();
push();
translate((108.09 * this.scale), (108.64 * this.scale));
rotate(30);
rect(0, 0, 6.5 * this.scale, 175 * this.scale);
pop();
//Large pink shell, counter-clockwise winding
fill(194, 112, 173);
beginShape();
vertex((53.8 * this.scale), (15.2 * this.scale));
bezierVertex((1.781 * this.scale), (45.703 * this.scale),
-(15.078 * this.scale), (112.01 * this.scale),
(15.42 * this.scale), (163.31 * this.scale));
bezierVertex((45.919 * this.scale), (214.601 * this.scale),
(112.226 * this.scale), (231.46 * this.scale),
(163.52 * this.scale), (200.96 * this.scale));
bezierVertex((214.817 * this.scale), (170.462 * this.scale),
(231.676 * this.scale), (104.155 * this.scale),
(201.18 * this.scale), (52.86 * this.scale));
bezierVertex((170.679 * this.scale), (1.564 * this.scale),
(104.372 * this.scale), -(15.295 * this.scale),
(53.8 * this.scale), (15.2 * this.scale));
//Ellipsoid cutout, clockwise winding
beginContour();
vertex((175.65 * this.scale), (50.62 * this.scale));
bezierVertex((209.531 * this.scale), (65.455 * this.scale),
(222.219 * this.scale), (111.235 * this.scale),
(203.99 * this.scale), (152.87 * this.scale));
bezierVertex((185.753 * this.scale), (194.502 * this.scale),
(143.504 * this.scale), (216.223 * this.scale),
(109.62 * this.scale), (201.38 * this.scale));
bezierVertex((75.736 * this.scale), (186.544 * this.scale),
(63.049 * this.scale), (140.764 * this.scale),
(81.28 * this.scale), (99.13 * this.scale));
bezierVertex((99.515 * this.scale), (57.497 * this.scale),
(141.764 * this.scale), (35.776 * this.scale),
(175.65 * this.scale), (50.62 * this.scale));
endContour();
endShape(CLOSE);
//Shine
fill(218, 179, 212);
push();
translate( + (174.49 * this.scale), + (117.35 * this.scale));
rotate(25);
ellipse(0, 0, 7 * this.scale, 30 * this.scale);
pop();
push();
translate( + (172.35 * this.scale), + (140.86 * this.scale));
rotate(25);
ellipse(0, 0, 4 * this.scale, 17 * this.scale);
pop();
pop();
}
function orbMove() {
this.x += this.speed;
}
//Occasionally adds an additional orb to the array
function addOrb() {
var spawnChance = 0.005;
if (random(0, 1) < spawnChance) {
orbs.push(makeOrb(width*1.5, random(height)));
}
}
//CORD FUNCTIONS----------------------------------------------------------------
//Line properties
function makeCord() {
var cord = {x1: 0,
x2: width,
y1: randomGaussian(height*(2/3), 40),
y2: randomGaussian(height*(2/3), 40),
col: [218, 179, 212],
weight: 2,
display: drawCord}
return cord;
}
//Draws line
function drawCord() {
stroke(this.col);
strokeWeight(this.weight);
line(this.x1, this.y1, this.x2, this.y2);
noStroke();
}
//CLOUD FUNCTIONS---------------------------------------------------------------
//Cloud properties
function makeCloud() {
var cloud = {
x: width*1.5,
y: random(height),
h: random(3*4, 12*4),
w: random(40*4, 85*4),
move: cloudMove,
speed: random(-.5, -.1),
col: [255, 255, 255, 100],
display: drawCloud}
return cloud;
}
//Draws cloud
function drawCloud() {
noStroke();
fill(this.col);
ellipse(this.x, this.y, this.w, this.h);
//ellipse(this.x + this.w*1.3, this.y - this.h*.25, this.w*.33, this.h*.33);
}
//Cloud movement
function cloudMove() {
this.x += this.speed;
}
//Occasionally adds cloud to array
function addCloud() {
var spawnChance = 0.004;
if (random(0, 1) < spawnChance) {
clouds.push(makeCloud());
}
}
//LAND FUNCTIONS----------------------------------------------------------------
//Landscape properties
function makeLandscape(x, i) {
var noiseScale = 0.002;
var noiseVal = noise((x+i)*noiseScale);
var landline = {x: x,
y1: height - 50 - noiseVal*100,
y2: height,
col: green3,
weight: 1,
speed: -1,
move: panLand,
display: drawLandscape}
return landline;
}
//Draws individual lines for landscape
function drawLandscape() {
stroke(this.col);
strokeWeight(this.weight);
line(this.x, this.y1, this.x, this.y2);
}
//Moves landmass
function panLand() {
this.x += this.speed;
}
I wound up running into more difficulty than usual with this assignment, although it was definitely an interesting process when it came to problem-solving. I kept the main components of the program fairly simple – objects with random properties moving across the page. However, I really wanted to try to figure out how the landscape in the Flags assignment work, and after a lot of trial and error made a variation of it using moving vertical lines to piece together that far-off hillside. While the main objects weren’t so difficult to implement, the landscape took up a sizable chunk of my time, but I’m still happy with the result, plus it forced me to really understand the order in which functions were performed, as well as the little nuances of arrays and objects.
Analog & Digital Sketches: