//Sean B. Leo
//sleo@andrew.cmu.edu
//Section C
//Project 11 - generative landscape
var terrainSpeed = 0.0005;
var terrainDetail = 0.001;
var clouds = []; //background clouds
var clouds2 = []; //foreground clouds
var c1, c2;
function setup() {
createCanvas(480, 480);
for (var i = 0; i < 10; i++){
var rx = random(width);
clouds[i] = makeClouds(rx);
clouds2[i] = makeClouds2(rx);
}
frameRate(30);
}
function draw() {
//background gradient colors
c1 = color(40, 90, 255,10);
c2 = color(250, 250, 240);
setGradient(c1, c2);
updateClouds();
removeClouds();
addRandomClouds();
}
function setGradient(c1, c2) {
noFill();
for (var y = 0; y < height; y++) {
var inter = map(y, 0, height, 0, 1);
var c = lerpColor(c1, c2, inter);
stroke(c);
line(0, y, width, y);
}
}
function updateClouds(){
// Update the cloud positions
for (var i = 0; i < clouds.length; i++){
clouds[i].move();
clouds[i].display();
}
for (var i = 0; i < clouds2.length; i++){
clouds2[i].move();
clouds2[i].display();
}
}
function removeClouds(){
var cloudsToKeep = [];
var cloudsToKeep2 = [];
for (var i = 0; i < clouds.length; i++){
if (clouds[i].x + clouds[i].breadth > 0) {
cloudsToKeep.push(clouds[i]);
}
}
clouds = cloudsToKeep;
for (var i = 0; i < clouds2.length; i++){
if (clouds2[i].x + clouds2[i].breadth > 0) {
cloudsToKeep2.push(clouds2[i]);
}
}
clouds2 = cloudsToKeep2;
}
function addRandomClouds() {
// probability of new cloud
var newCloudLikelihood = 0.01;
if (random(0,1) < newCloudLikelihood) {
clouds.push(makeClouds(width));
clouds2.push(makeClouds2(width));
}
}
//cloud positions
function cloudMove() {
this.x += this.speed;
}
//draw clouds
function cloudDisplay() {
//var bHeight = this.x;
fill(230, 230, 230, 155);
noStroke();
push();
translate(this.x, this.y+20);
ellipse(0, 0, this.d/2, this.d/3);
fill(220, 220, 220, 155);
noStroke();
ellipse(0 - 10, 0 + 5, this.d*2, this.d* 1.3);
fill(240, 240, 240, 190);
noStroke();
ellipse(0 + 15, 0, this.d*1.2, this.d/2);
pop();
}
function cloudDisplay2() {
//var bHeight = this.x;
fill(255, 255, 255, 200);
noStroke();
push();
translate(this.x, this.y+20);
ellipse(0, 0, this.d*1.1, this.d/1.2);
fill(245, 245, 245, 200);
noStroke();
ellipse(0 - 10, 0 + 5, this.d*3, this.d/ 1.3);
fill(255, 255, 255, 200);
noStroke();
ellipse(0 + 15, 0, this.d*1.2, this.d/2);
pop();
}
function makeClouds(birthLocationX) {
var cloud = {x: birthLocationX,
y: random(0, height / 2),
d: random(20, 80),
breadth: 100,
speed: -.1,
move: cloudMove,
display: cloudDisplay}
return cloud;
}
function makeClouds2(birthLocationX) {
var cloud2 = {x: birthLocationX,
y: random(0, height / 2),
d: random(20, 80),
breadth: 100,
speed: -.1,
move: cloudMove,
display: cloudDisplay2}
return cloud2;
}
Category: SectionC
Jasmine Lee – Project 11 – Landscape
//Jasmine Lee
//jasmine4@andrew.cmu.edu
//Section C
//Project 11 (Generative Landscape)
var waterSpeed = 0.0002;
var waterDetailL1 = 0.0005; //controls amplitude of left side of waterfall
var waterDetailL2 = 0.0001;
var waterDetailL3 = 0.00025;
var waterDetailL4 = 0.00075;
var waterDetailR1 = 0.0001; //controls amplitude of right side of waterfall
var waterDetailR2 = 0.00025;
var waterDetailR3 = 0.0005;
var waterDetailR4 = 0.00075;
var waterDetailH1 = 0.0005; //controls amplitude of horizontal waves
var waterDetailH2 = 0.00095;
var waterDetailH3 = 0.00075;
var fish = [];
var newFishLikelihood = 2.9;
function setup() {
createCanvas(480, 480);
frameRate(20);
//makes fish and places them in random x and y positions
for (var i = 0; i < 8; i ++) {
fish.push(makeFish(floor(random(240, 480)), floor(random(300, 360))));
}
//displays the fish properly
for (var i = 0; i < fish.length; i ++) {
updateAndDisplayFish();
}
}
function draw() {
background(138, 212, 227); //teal
noFill();
stroke(255, 255, 255, 100); //transparent white
//LEFT SIDE OF WATERFALL---------------------------------------------
//1st line of waterfall
for (var y = 0; y < 240; y++) {
//t determines how far away the line is from x = 0 at y
//millis() * waterSpeed slows down how fast the line is traveling)
var t = ((y * waterDetailL1) + millis() * waterSpeed);
var x = map(noise(t), 0, 1, 0, 220);
line(x, y, (t - width), y);
}
//2nd line of waterfall
for (var y = 0; y < 240; y++) {
var t = ((y * waterDetailL2) + millis() * waterSpeed);
var x = map(noise(t), 0, 1, 10, 235);
line(x, y, (t - width), y);
}
//3rd line of waterfall
for (var y = 0; y < 240; y++) {
var t = ((y * waterDetailL3) + millis() * waterSpeed);
var x = map(noise(t), 0, 1, 20, 250);
line(x, y, (t - width), y);
}
//4th line of waterfall
for (var y = 0; y < 240; y++) {
var t = ((y * waterDetailL4) + millis() * waterSpeed);
var x = map(noise(t), 0, 1, 50, 220);
line(x, y, (t - width), y);
}
//RIGHT SIDE OF WATERFALL---------------------------------------------
//1st line of waterfall
for (var a = 0; a < 240; a ++) {
//c gives us how far away the line is from x = 0 at y
//millis() * waterSpeed slows down how fast the line is traveling)
var c = ((a * waterDetailR1) + millis() * waterSpeed);
var b = map(noise(c), 0, 1, 240, 480);
line(b, a, ((width + 60) - c), a);
}
//2nd line of waterfall
for (var a = 0; a < 240; a ++) {
var c = ((a * waterDetailR2) + millis() * waterSpeed);
var b = map(noise(c), 0, 1, 220, 480);
line(b, a, ((width + 60) - c), a);
}
//3rd line of waterfall
for (var a = 0; a < 240; a ++) {
var c = ((a * waterDetailR3) + millis() * waterSpeed);
var b = map(noise(c), 0, 1, 200, 480);
line(b, a, ((width + 60) - c), a);
}
//4th line of waterfall
for (var a = 0; a < 240; a ++) {
var c = ((a * waterDetailR4) + millis() * waterSpeed);
var b = map(noise(c), 0, 1, 300, 480);
line(b, a, ((width + 60) - c), a);
}
//HORIZONTAL WAVES--------------------------------------------
noFill();
stroke(41, 152, 217, 100);
//1st wave
for (var x = 0; x < width; x ++) {
//c gives us how far away the line is from x = 0 at y
//millis() * waterSpeed slows down how fast the line is traveling)
var t = ((x * waterDetailH1) + millis() * waterSpeed);
var y = map(noise(t), 0, 1, 210, 240);
line(x, y, x, height);
}
//2nd wave
for (var x = 0; x < width; x ++) {
var t = ((x * waterDetailH2) + millis() * waterSpeed);
var y = map(noise(t), 0, 1, 220, 250);
line(x, y, x, height);
}
//3rd wave
for (var x = 0; x < width; x ++) {
var t = ((x * waterDetailH3) + millis() * waterSpeed);
var y = map(noise(t), 0, 1, 240, 300);
line(x, y, x, height);
}
//functions used to display and control the fish
updateAndDisplayFish();
removeFish();
}
function updateAndDisplayFish() {
//update the fish position and display
for (var i = 0; i < fish.length; i ++) {
fish[i].move();
fish[i].displayF();
}
}
function removeFish() {
//Copy all fish we want to keep into a new array
var fishToKeep = [];
for (var i = 0; i < fish.length; i++) {
if (fish[i].x + fish[i].fishWidth > 0) {
fishToKeep.push(fish[i]);
}
}
fish = fishToKeep; //stores the surviving fish
}
function fishMove() {
//controls fish movement
this.x += this.speed;
//makes fish start back at right end of canvas once they reach the left
if (this.x < 0) {
this.x = width;
}
}
function fishDisplay() {
//fish body
fill(237, 175, 69, 100); //fish body
noStroke();
ellipse(this.x, this.y, this.fishWidth, this.fishHeight);
//fish tail
triangle(this.x + (this.fishWidth / 2) , this.y, this.x + 20, this.y + 5, this.x + 20, this.y - 5);
}
//creates fish object
function makeFish(birthLocationX, birthLocationY) {
var fs = {x: birthLocationX,
y: birthLocationY,
fishWidth: random(15, 30),
speed: -2.0,
fishHeight: random(7, 10),
move: fishMove,
displayF: fishDisplay}
return fs;
}
For my landscape, I wanted to depict a peaceful waterfall scene. Using different noise functions, I was able to create gently flowing water, and subtle waves. The fish in the freshwater loop continuously, as if they were swimming around in the water and looping back where we could not see them turn. The most difficult part was this project was creating the objects. I had trouble with getting the correct amount of fish to show up, and with keeping the fish on the page. Over time, the waterfall changes position until it seems as if there are two waterfalls. Each time the landscape is refreshed, the fish sizes and positions are randomized.
![](../../../../wp-content/uploads/2019/11/IMG_1716.jpg)
Ammar Hassonjee – Project 11 – Generative Landscape
/* Ammar Hassonjee
ahassonj@andrew.cmu.edu
Section C
Project 11
*/
// global variables and arrays declared to hold objects
var traintracks = [];
var tracky = 0; //position of train tracks
var oases = []; // array for oases objects
var trees = []; // array for tree objects
function setup() {
createCanvas(480, 480);
// for loop that pushed train track objects to array
for (var i = 0; i < 480; i += 20) {
traintracks.push(makeTrainTracks(210, i));
// creates a random amount of oases to add to the oases array each time
// the program is loaded
if (i % 240 === 0) { //random iteration
// variables initialized to pass as parameters for making the oases objects
var xloc = int(random(width / 4));
var yloc = int(random(height));
var shade = int(random(200, 255));
var xsize = int(random(60, 100));
var ysize = int(random(100, 150));
oases.push(makeOasis(xloc, yloc, shade, xsize, ysize));
}
}
frameRate(20);
}
function draw() {
background(250, 245, 200);
fill(97, 74, 66);
rect(200, 0, 10, height); // train track boundaries
rect(270, 0, 10, height); // train track boundaries
strokeWeight(1);
// calling the track functions to continously move the tracks and add oases objects to canvas
updateTracks();
removeTracks();
addTracks();
// function called for drawing the train object
drawTrain();
}
// updating the position of each track and oases in each of the arrays
function updateTracks() {
// for loop that calls train track objects and moves/displays them
for (var i = 0; i < traintracks.length; i++) {
traintracks[i].move();
traintracks[i].display();
}
// for loop that calls oases objects and moves/displays them
for (var j = 0; j < oases.length; j++) {
oases[j].move();
oases[j].display();
}
// for loop that calls tree objects and moves/displays them
for (var k = 0; k < trees.length; k++) {
trees[k].move();
trees[k].display();
}
}
function addTracks() {
var position = traintracks[traintracks.length - 1].y; // initializing traintracks position
traintracks.push(makeTrainTracks(210, position + 20)); // adding a traintracks object to the end of the array
var chance = int(random(0, 40)); // making sure the chance of appending an oases object is low
if (chance === 2) {
// variables declared as parameters to pass to the oases object
var xloc = int(random(width / 4));
var yloc = height;
var shade = int(random(200, 255));
var xsize = int(random(40, 60));
var ysize = int(random(100, 400));
oases.push(makeOasis(xloc, yloc, shade, xsize, ysize));
}
// varying the chance of the trees appearing
var chance2 = int(random(0, 25));
if (chance2 === 4) { // making sure the trees appear on both sides of the tracks
var xpo = int(random(180)); // xvariable for first half of the canvas
var ypo = height;
var treeColor = int(random(100, 255));
var treeSize = int(random(20, 40));
trees.push(makeTree(xpo, ypo, treeSize, treeColor));
} else if (chance === 6) {
var xpo = int(random(300, width)); // x variable for second half of the canvas
var ypo = height;
var treeColor = int(random(100, 255));
var treeSize = int(random(20, 30));
trees.push(makeTree(xpo, ypo, treeSize, treeColor));
}
}
function removeTracks() {
// creating a duplicate array to keep track objects that are within the canvas
var trackKeep = [];
for (var i = 0; i < traintracks.length; i++) {
if (traintracks[i].y > -10) {
trackKeep.push(traintracks[i]);
}
}
traintracks = trackKeep; // reassigning the tracks array to the duplicate array
// creating a duplicate array to keep track objects that are within the canvas
var oasesKeep = [];
for (var i = 0; i < oases.length; i++) {
if (oases[i].y > -40) {
oasesKeep.push(oases[i]);
}
}
oases = oasesKeep; // reassigning the oases array to the duplicate array
// creating a duplicate array to keep track objects that are within the canvas
var treeKeep = [];
for (var i = 0; i < trees.length; i++) {
if (trees[i].y > -40) {
treeKeep.push(trees[i]);
}
}
trees = treeKeep; // reassigning the trees array to the duplicate array
}
function trackMove() { // moving the position of each track and oases object
this.y -= 10;
}
function trackDisplay() { // displaying each track object with rectangles
strokeWeight(1);
fill(97, 74, 66);
rect(this.x, this.y, 60, 10);
}
function makeTrainTracks(xpos, ypos) { //object for making traintrack
var trck = {x: xpos, y: ypos, move: trackMove,
display: trackDisplay}
return trck;
}
function makeOasis(xco, yco, color, xscale, yscale) { //object for making oases
var oasis = {x: xco, y: yco, move: trackMove,
display: oasisDisplay, tone: color,
size1: xscale, size2: yscale};
return oasis;
}
function oasisDisplay() { // displaying the oases objects as an ellipse
fill(0, this.tone, this.tone);
noStroke();
ellipse(this.x, this.y, this.size1, this.size2);
strokeWeight(1);
stroke(0);
}
function makeTree(xp, yp, xsize, colour) { //function for making tree objects
var tree1 = {x: xp, y: yp, move: trackMove, display: treeDisplay,
tone: colour, size1: xsize};
return tree1;
}
function treeDisplay() { // displaying the tree objects by drawing from parameters
noStroke();
fill(0, this.tone, 0);
ellipse(this.x, this.y, this.size1 * 1.5);
fill(0, this.tone - 50, 0);
ellipse(this.x, this.y, this.size1);
}
function drawTrain() { // drawing the train object as a static image
noStroke();
fill(200, 100, 100);
rect(207, 220, 67, 160);
rect(207, 390, 67, 160);
strokeWeight(4);
stroke(0);
noFill()
rect(230, 382, 20, 7);
strokeWeight(2);
rect(220, 230, 40, 120);
rect(220, 410, 40, 120);
}
For this project, I chose to animate an aerial view over a train moving across a desert. I’ve always been interested in Wild West type scenes, so the image of a train moving past oases and small little cacti is one that stood out to me. I attached a sketch of my thought process at the bottom.
![](../../../../wp-content/uploads/2019/11/IMG_0104-1024x768.jpg)
Kimberlyn Cho- Project 11- Landscape
/* Kimberlyn Cho
Section C
ycho2@andrew.cmu.edu
Project 11 */
var gifts = [];
function setup() {
createCanvas(480, 300);
//gifts already on conveyor at start
for (var i = 0; i < 10; i++) {
var rx = random(width);
gifts[i] = makeGifts(rx);
}
frameRate(15);
}
function draw() {
background(240);
//draw gifts
updateGifts();
addGifts();
removeGifts();
//draw conveyor
drawConveyor();
}
//update gift location
function updateGifts() {
for (var i = 0; i < gifts.length; i++) {
gifts[i].move();
gifts[i].display();
}
}
//remove gifts after conveyor from array
function removeGifts() {
var giftsToKeep = [];
for (var i = 0; i < gifts.length; i++) {
if (gifts[i].x + gifts[i].breadth > 0) {
giftsToKeep.push(gifts[i]);
}
}
gifts = giftsToKeep;
}
//add new gifts to array
function addGifts() {
var newGiftLikelihood = 0.04;
if (random(0,1) < newGiftLikelihood) {
gifts.push(makeGifts(width));
}
}
//move gifts per frame
function giftMove() {
this.x += this.speed;
}
//draw each gift
function giftDisplay() {
//giftbox
var py = 150;
noStroke();
fill(this.r, this.g, this.b);
rect(this.x, py, this.breadth, this.h);
//ribbons
fill(255);
rect(this.x + this.breadth / 4, py, this.ribbon, this.h);
rect(this.x, py + this.h / 2, this.breadth, this.ribbon);
}
//gift Object
function makeGifts(birthLocationX) {
var gift = {x: birthLocationX,
h: -random(10, 40),
ribbon: random(1, 5),
r: random(100, 255),
g: random(100, 255),
b: random(100, 255),
breadth: random(20, 80),
speed: -1.0,
move: giftMove,
display: giftDisplay}
return gift;
}
function drawConveyor() {
//conveyor
strokeWeight(0);
fill(220);
rect(0, height / 2, width, 30, 25);
strokeWeight(2);
stroke(255);
rect(4, (height / 2) + 4, width - 8, 30 - 8, 25);
//conveyor gears
for (var y = 0; y < 18; y++) {
var ny = 15 + y * 20;
strokeWeight(2);
stroke(200);
noFill();
ellipse(ny, height / 2 + 15, 18);
strokeWeight(0);
fill(255);
ellipse(ny, height / 2 + 15, 8);
}
//ground
fill(150);
strokeWeight(0);
rect(0, height * 4 / 5, width, height / 5);
//legs
strokeWeight(0);
fill(190);
rect(100, height / 2 + 30, 12, 80);
rect(88, height / 2 + 110, 35, 15, 2);
//scanning machine
rect(350, 145, 200, 130, 8);
rect(350, 50, 10, 110, 8);
rect(350, 50, 135, 15, 8);
fill(255, 0, 0, 50);
rect(360, 65, 130, 80);
}
For this project, I was interested in the purpose of a conveyor belt and how it is able to move a group of objects at a set rate. I used objects to randomize the size and color of gifts that would pass through the conveyor belt. I kept the background graphics to a grayscale to emphasize the gifts that pass through the screen. I found this assignment to be very helpful in understanding how objects work since we had to create our own objects as opposed to being given an object and just using it in the draw function.
![](../../../../wp-content/uploads/2019/11/IMG_1793-1024x768.jpg)
Ammar Hassonjee – Looking Outwards 11
![](../../../../wp-content/uploads/2019/11/Capture.png)
For this post, I chose to focus on the work of an artist named Claudia Hart. She uses technology to make explorations with the recurring theme of “identity art”, in which her work explores body issues, perception, and the relationship between nature and technology. She studied art history at NYU and a Masters of Architecture from Columbia, and then taught 3D art exploration at the School of Art Institute in Chicago. She currently works out of New York and Chicago.
A project of hers that I chose to focus on is her exploration of a series of Augmented Reality wallpapers that display captivating images of art. Over these wallpapers, viewers can use their smartphones to overlay different images and animations over the wallpapers. The animations themselves are embedded in code in the app that activates when the camera moves over the wallpaper. A link to her project can be found here.
Looking Outwards – 11 – Joanne Chui
![](../../../../wp-content/uploads/2019/11/Screen-Shot-2019-11-08-at-1.23.19-PM.png)
Neri Oxman is an architect, designer, inventor, and a professor at the MIT Media Lab. Her research is focused on how computation design, digital fabrication, material science, and biology intersect, thus coining the term Material Ecology.
I was interested in this project, Mushtari, which is a 3D printed wearable sculpture that supports the flow of cyanobacteria that converts sunlight into sucrose. It’s both indexical and symbolic of the digestive tract, in which it looks and functions as an organ system for absorbing nutrients, digesting biomass, and expelling waste.
https://neri.media.mit.edu/projects/details/mushtari.html#prettyPhoto
lee chu – looking outwards 11
phonelovesyoutoo: database by Kate Hollenbach displays the feed of both the front and rear-facing cameras. The recordings are displayed at the original time of day, depicting a glimpse of the relationship between human, device, time, and space. This collection of videos really highlights the information we essentially give for free just by owning a device with so many sensors and recording devices.
Kate Hollenbach is an artist, programmer, and educator based in Chicago and Los Angeles. She explores interactive systems and technologies involving body, gesture, and physical space.
Project 11 – Landscape – Joanne Chui
/*
Joanne Chui
Section C
Project 11
*/
var terrainSpeed = 0.0001;
var terrainDetail = 0.005;
var riverDetail = 0.0005
var birds = [];
var c1, c2;
function setup() {
createCanvas(480, 240);
frameRate(10);
for(i = 0; i < 10; i++){
var rx = random(width);
var ry = random(height);
birds[i] = makeBird(rx, ry);
}
}
function draw() {
// background(220, 220, 230);
c1 = color(170, 170, 190);
c2 = color(240, 190, 120);
setGradient(c1, c2);
//sun
noStroke();
fill(210, 100, 40);
ellipse(width/2, 160, 170, 170);
//call landscape and birds
drawMountain();
updateBird();
addBird();
removeBird();
}
//background gradient
function setGradient(c1, c2){
noFill();
for(i = 0; i < height; i++){
var inter = map(i, 0, height, 0, 1);
var c = lerpColor(c1, c2, inter);
stroke(c);
line(0, i, width, i);
}
}
function drawMountain(){
//furthest mountain
fill(55, 63, 82);
noStroke();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail) + (millis() * terrainSpeed);
var y = map(noise(t), 0,1, 0, height);
vertex(x, y);
}
vertex(width, height);
vertex(0, height);
endShape();
//middle river
fill(220, 180, 150);
noStroke();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * riverDetail) + (millis() * terrainSpeed);
var y = map(noise(t), 0,1, height/2, height);
vertex(x, y);
}
vertex(width, height);
vertex(0, height);
endShape();
//closest mountain
fill(170, 120, 40);
noStroke();
beginShape();
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail) + (millis() * terrainSpeed*4);
var y = map(noise(t), 0,2, 0, height);
vertex(x, y*3);
}
vertex(width, height);
vertex(0, height);
endShape();
}
function makeBird(birdX, birdY){
var bird = {
x: birdX,
y: birdY,
speed: random(5, 20),
size: random(5, 20),
color: random(0, 100),
move: birdMove,
display: displayBird
}
return bird;
}
function birdMove(){
this.x += this.speed;
this.y -= this.speed / 5;
}
function displayBird(){
strokeWeight(2);
stroke(this.color);
noFill();
push();
translate(this.x, this.y);
arc(0, 0, this.size, this.size, PI + QUARTER_PI, 0);
arc(this.size, 0, this.size, this.size, PI, 0 - QUARTER_PI);
pop();
}
function updateBird(){
for(i = 0; i < birds.length; i++){
birds[i].move();
birds[i].display();
}
}
//adding birds with a random probability
function addBird(){
var newBird = random(1);
if(newBird < 0.2){
var birdX = 0;
var birdY = random(height);
birds.push(makeBird(birdX, birdY));
}
}
//removing birds from the array once they fall off the canvas
function removeBird(){
var keepBird = [];
for(i = 0; i < birds.length; i++){
if(birds[i].x + birds[i].size > 0){
keepBird.push(birds[i]);
}
}
birds = keepBird;
}
I was interested in creating a landscape with many layers to show depth. I was interested in creating birds because i felt that they would add a dynamic movement in the landscape.
![](../../../../wp-content/uploads/2019/11/IMG_4508-1024x768.jpg)
lee chu – project 11
// lee chu
// section c
// lrchu@andrew.cmu.edu
// project - 11
var islands = [];
var hills = [];
var x; // cloud x
// colors
var navajo = '#FFE4A3';
var lPink = '#FFAFBA';
var peachOrange = '#EDD397';
var mauve = '#E8A0A9';
var peach = '#FFEAB7';
var taupe = '#544244';
var puce = '#4C3C3E';
var middleYellow = '#F4B086';
function setup() {
createCanvas(480, 300);
// create an initial collection of islands
for (var i = 0; i < 2; i++){
var rx = random(40, width - 40);
islands[i] = makeIsland(rx);
}
for (var i = 0; i < 3; i++){
var rx2 = random(40, width - 40);
hills[i] = makeHill(rx2);
}
frameRate(10);
x = random(40, width - 40);
}
function draw() {
sky();
horizon();
// sun
fill(peachOrange);
ellipse(width / 2, height / 2, 100);
// islands
updateAndDisplayIslands();
removeIsland();
addIsland();
// cloud
cloud(x, 80);
x += 1;
if (x - 50 > width - 40) {
x = -10;
}
// hills
updateHills();
removeHill();
addHill();
// window
fill(0, 0, 50);
windowFrame(40, 60);
fill(75, 75, 100);
windowFrame(28, 55);
}
function cloud(x, y) {
strokeWeight(0);
fill(255);
rect(x, y, 20, 10);
rect(x + 10, y + 10, 20, 10);
rect(x - 10, y + 10, 20, 10);
rect(x + 20, y + 20, 20, 10);
rect(x - 10, y + 20, 20, 10);
rect(x - 30, y + 20, 20, 10);
rect(x - 30, y + 30, 20, 10);
rect(x - 50, y + 30, 20, 10);
rect(x - 20, y + 30, 20, 10);
rect(x + 10, y + 30, 20, 10);
rect(x + 30, y + 30, 20, 10);
rect(x - 20, y + 40, 30, 10);
}
function makeIsland(birthLocationX) {
var island = {x: birthLocationX, breadth: round(random(25, 50)),
speed: -1,
height: round(random(80, 150)),
move: islandMove,
display: islandDisplay}
return island;
}
function islandMove() {
this.x += this.speed;
}
function islandDisplay() {
// face
fill(middleYellow);
push();
translate(this.x, height - 150);
beginShape();
vertex(0.4 * this.breadth, -this.height / 2);
vertex(0.6 * this.breadth, -this.height / 2);
vertex(this.breadth, this.height / 2);
vertex(0.8 * this.breadth, this.height / 2 * 1.2);
vertex(0.4 * this.breadth, this.height / 2 * 1.2);
vertex(0.1 * this.breadth, this.height / 2);
endShape(CLOSE);
// shadow
fill(taupe);
beginShape();
vertex(0.4 * this.breadth, -this.height / 2);
vertex(0.1 * this.breadth, this.height / 2);
vertex(0.4 * this.breadth, this.height / 2 * 1.2);
vertex(0.35 * this.breadth, this.height / 2);
endShape(CLOSE);
pop();
}
function updateAndDisplayIslands() {
for (var i = 0; i < islands.length; i ++) {
islands[i].move();
islands[i].display();
}
}
function removeIsland() {
var islandsToKeep = [];
for (var j = 0; j < islands.length; j ++) {
if (islands[j].x + islands[j].breadth > 40) {
islandsToKeep.push(islands[j]);
}
}
islands = islandsToKeep;
}
function addIsland() {
var likelihood = 0.007;
if (random(1) < likelihood) {
islands.push(makeIsland(width));
}
}
function makeHill(x) {
h = round(random(150, 200));
var spike = {x: x, breadth: round(random(25, 50)),
speed: -3,
height: round(random(200, 250)),
move: hillMove,
display: hillDisplay}
return spike;
}
function hillMove() {
this.x += this.speed;
}
function hillDisplay() {
fill(peach);
push();
translate(this.x, height - 50);
beginShape();
vertex(0, 0);
vertex(this.breadth, 0);
vertex(0.9 * this.breadth, -this.height * 0.25);
vertex(0.7 * this.breadth, -this.height / 2);
vertex(0.6 * this.breadth, -this.height);
vertex(0.4 * this.breadth, -this.height);
vertex(0.2 * this.breadth, -this.height / 2);
endShape(CLOSE);
pop();
}
function updateHills() {
for (var i = 0; i < hills.length; i ++) {
hills[i].move();
hills[i].display();
}
}
function removeHill() {
var hillsToKeep = [];
for (var j = 0; j < hills.length; j ++) {
if (hills[j].x + hills[j].breadth > 40) {
hillsToKeep.push(hills[j]);
}
}
hills = hillsToKeep;
}
function addHill() {
var likelihood = 0.01;
if (random(1) < likelihood) {
hills.push(makeHill(width));
}
}
function windowFrame(r, f) {
strokeWeight(0);
// top left
beginShape();
vertex(0, 0);
vertex(100, 0);
vertex(100, r);
bezierVertex(f, r, r, f, r, 100);
vertex(0, 100);
endShape(CLOSE);
rect(100, 0, width - 200, r);
// top right
beginShape();
vertex(0, height);
vertex(100, height);
vertex(100, height - r);
bezierVertex(f, height - r, r, height - f, r, height - 100);
vertex(0, height - 100);
endShape(CLOSE);
rect(width - r, 100, r, height - 200);
// bottom right
beginShape();
vertex(width, 0);
vertex(width - 100, 0);
vertex(width - 100, r);
bezierVertex(width - f, r, width - r, f, width - r, 100);
vertex(width, 100);
endShape(CLOSE);
rect(100, height - r, width - 200, r);
// bottom left
beginShape();
vertex(width, height);
vertex(width - 100, height);
vertex(width - 100, height - r);
bezierVertex(width - f, height - r, width - r, height - f, width - r, height - 100);
vertex(width, height - 100);
endShape(CLOSE);
rect(0, 100, r, height - 200);
// lines
stroke(0);
strokeWeight(0.5);
line(0, height - 20, width, height - 20);
strokeWeight(0.25);
}
function sky() {
for (var y = 40; y < height - 69; y ++) {
var interval = map(y, 40, height - 69, 0, 1);
var c = lerpColor(color(mauve), color(peachOrange), interval);
strokeWeight(1);
stroke(c);
line(0, y, width, y);
}
}
function horizon(){
strokeWeight(0);
fill(navajo);
beginShape();
vertex(0, height - 70);
vertex(width, height - 70);
vertex(width, height);
vertex(0, height);
endShape(CLOSE);
}
I aimed to emulate the view from inside of a train outwards into a scene with floating islands.
Jai Sawkar – Looking Outwards – 11
![](../../../../wp-content/uploads/2019/11/perfectcity_05-1024x640.jpg)
Mary Flanagan is an inventor, artist, writer, and designer that creates games, installations, poetry, and essays. Perfect.city an exploration of the South Korean city of Songdo, a planned international metropolis developed by Gale International. Mary’s goal for the city is that it be designed perfectly. Mary modeled the city in the video game, Sims 2. She then conducted a series renders, along with the video below showcasing the design.
While I do think it is smart to use software to model the city, I do believe that making it through Sims does limit the possibilities due to its constraints. Nonetheless, the project was quite interesting, and I look forward to seeing her future work!