LO-11 (focus on women practitioners)

Karolina Sobecka is an artist, and researcher that operates in the intersection of art, science, technology, and activism. Her most recent work is a series called ‘Matter of Air’ in which she explores environmental activism through art and technology, including a project in which she creates, with a group of folks, a pseudo weather controlling machine. However, for this LO I’ll be discussing  one of her older interactive installations. This project is called stability. The project entails having a user interact with a cube and a screen that supposedly shows a small room with a person inside the cube. Every time you shake up the room, the person rearranges the room and records the “disaster” in its disaster journal. The interesting thing is that every single arrangement created by this person is unique. This perhaps can be interpreted as pseudo Automated Intelligence, as the person is actively “creating” a new layout every time. But, this could perhaps just an illusion coded by the creator.

http://cargocollective.com/karolinasobecka/Stability

Project 11: Generative Landscape

For my project, I decided to create a relaxing underwater scene. Although it was a bit challenging to figure out how to execute my ideas, I had fun making my landscape and adjusting properties to make it more interesting. To create my landscape, I combined concepts that we learned in the past, such as arrays, objects, loops, noise, images, and functions. I randomized properties such as the x/y positions, sizes, colors, and speeds of my objects.

landscape-cb
var terrain = [];
var coral;
var bubbles = [];
var fish = [];

var noiseParam = 0;
var noiseStep = 0.05;

function preload() {
    coral = loadImage("https://i.imgur.com/S5HGpZa.png");
}

function setup() {
    createCanvas(480, 300);
    //setup noise for terrain
    for(var i=0; i<=width/5; i++) {
        var n = noise(noiseParam);
        var value = map(n, 0, 1, 0, height);
        terrain.push(value);
        noiseParam += noiseStep;
    }
    //setup for fish
    for (var i = 0; i < 15; i++) {
        fishx = random(width);
        fish[i] = makeFish(fishx);
    }
    //setup for bubbles
    for (var i = 0; i < 10; i++) {
        bubblex = random(width);
        bubbley = random(height);
        bubbles[i] = makeBubble(bubblex, bubbley);
    }
    frameRate(10);
}

function draw() {
    background(0, 180, 200);

    noStroke();
    fill(0, 230, 255, 90);
    ellipse(240, 0, 600, 200);

    blueTerrain();
    
    updateAndDisplayFish();
    removeFish();
    addNewFish();
    
    displayBubbles();
}

//background terrain
function blueTerrain() {
    terrain.shift();
    var n = noise(noiseParam);
    var value = map(n, 0, 1, 0, height);
    terrain.push(value);
    noiseParam += noiseStep;
    
    //blue terrain
    noStroke();
    fill(0, 66, 115);
    beginShape();
    vertex(0, height);
    for(var i=0; i<width/4; i++) {
        vertex(i*5, terrain[i]);
        //placement of coral on terrain
        if(terrain[i] < terrain[i-1] & terrain[i] < terrain[i+1]) {
            drawCoral(i*5, terrain[i]);
        }
    }
    vertex(width, height);
    endShape(CLOSE);
}

//draws coral on terrain
function drawCoral(x, y) {
    imageMode(CENTER);
    image(coral, x, y-10, 65, 80);
}

//update the fish positions and display them
function updateAndDisplayFish() {
    for (var i = 0; i < fish.length; i++) {
        fish[i].move();
        fish[i].draw();
    }
}

//remove fish that are off the canvas from the array
function removeFish() {
    var fishToKeep = [];
    for (var i = 0; i < fish.length; i++) {
        if (fish[i].x + fish[i].w > 0) {
            fishToKeep.push(fish[i]);
        }
    }
    fish = fishToKeep;
}

//with a small probability, add a new fish to end of the array
function addNewFish() {
    var newFishLikelihood = 0.3;
    if (random(0,1) < newFishLikelihood) {
        fish.push(makeFish(width+20));
    }
}

function moveFish() {
    this.x += this.speed;
}

function drawFish() {
    push();
    translate(this.x, this.y);
    fill(this.color);
    ellipse(0, 0, this.w, this.h);
    strokeWeight(1.5);
    stroke(240);
    fill(50);
    ellipse(-15, -4, 8, 8);
    noStroke();
    fill(this.fincolor);
    triangle(0, -4, 0, 4, 15, 0);
    noFill();
    push();
    fill(this.color);
    triangle(this.w/2+20, -8, this.w/2+20, 8, (this.w/2)-2, 0);
    pop();
    pop();
}

//fish constructor
function makeFish(fishx) {
    var f = {x: fishx, y: random(height),
            w: random(40, 80), h: random(10, 45),
            color: color(random(100, 255), random(100, 255), random(100, 255)),
            fincolor: color(random(50, 200), random(50, 200), random(50, 200)),
            speed: random(-10, -20),
            move: moveFish,
            draw: drawFish
    }
    return f;
}

function displayBubbles() {
    for (var i = 0; i < bubbles.length; i++) {
        bubbles[i].move();
        bubbles[i].draw();
    }
}

//bubbles float upwards
function moveBubbles() {
    this.x += this.speed;
    this.y += this.speed;
    if (this.x <= 0) {
        this.x = width;
    }
    if (this.y <= 0) {
        this.y = height;
    }
}

function drawBubbles() {
    push();
    strokeWeight(1);
    stroke(255, 255, 255, 80);
    fill(100, 255, 255, 60);
    ellipse(this.x, this.y, this.size, this.size);
    noFill();
    strokeWeight(2);
    arc(this.x - this.size/12, this.y - this.size/12, 15, 15, PI, PI + HALF_PI);
    pop();
}

//bubbles constructor
function makeBubble(bubblex, bubbley) {
    var b = {x: bubblex, y: bubbley,
            size: random(20, 40),
            speed: random(-1, -6),
            move: moveBubbles,
            draw: drawBubbles
    }
    return b;
}

Project 11: Generative Landscape

For this week’s project, I decided to visualize an NYC subway line I used often (pre-pandemic) and the views of the skyline you can see passing by when the subway tracks are outdoors. I first roughly sketched out the scene on paper and then used Professor Cortina’s sample code as a baseline and customized it further to meet my vision. I displayed the scene to be at night since that’s the time of day I liked most when watching the skyline. Also, although nighttime, the lights would always be on in the buildings, so I decided to have lit up windows on all the buildings as well as the light reflections.

sketch
var frontBuildings = [];
var backBuildings = [];
var moonAndStars;

function preload(){
  moonAndStars = loadImage("https://i.imgur.com/0JJlsGR.png");
}

function setup() {
  createCanvas(480, 270);
  // make initial array of buildings
  for(var i = 0; i < 20; i++) {
    var x = random(width);
    backBuildings[i] = makeBackBuilding(x);
  }
  for(var i = 0; i < 10; i++) {
    var x = random(width);
    frontBuildings[i] = makeFrontBuilding(x);
  }
  frameRate(50);
}

function draw() {
  // gradient night background
  setGradient(color("#655BCE"), color("#1A1449"));
  // moon
  image(moonAndStars, 0, 0, 480, 350);

  updateAndDisplayBuildings();
  removeBuildingsThatHaveSlippedOutOfView();
  addNewBuildingsWithSomeRandomProbability(); 
  // tracks
  drawTrack();
  // train
  drawTrain();

}

function drawTrain() {
  strokeWeight(1);
  stroke("#4A4954");
  // train body
  fill("#65656D");
  rect(0, 180, 220, 80);
  strokeWeight(5);
  line(0, 240, 218, 240);
  strokeWeight(2);
  line(0, 245, 218, 245);
  strokeWeight(5);
  line(0, 190, 218, 190);
  strokeWeight(2);
  line(0, 196, 218, 195);
  noStroke();
  // doors
  fill("#5D5C66");
  rect(10, 200, 36, 60);
  rect(130, 200, 36, 60);
  // windows
  fill("#383664");
  rect(12, 202, 32, 30);
  rect(132, 202, 32, 30);
  rect(58, 200, 60, 30);
  rect(200, 200, 20, 40);
  // train number
  fill("purple");
  circle(182, 220, 25);
  fill(255);
  textSize(20);
  text("7", 177, 227);
}

function drawTrack() {
  fill(20);
  rect(0, 220, width, 100);
  fill("#8F8F91");
  rect(0, 220, width, 30);
  fill("#F0D933");
  rect(0, 240, width, 5);
}

function removeBuildingsThatHaveSlippedOutOfView(){
  // If a building has dropped off the left edge,
  // remove it from the array.  This is quite tricky, but
  // we've seen something like this before with particles.
  // The easy part is scanning the array to find buildings
  // to remove. The tricky part is if we remove them
  // immediately, we'll alter the array, and our plan to
  // step through each item in the array might not work.
  //     Our solution is to just copy all the buildings
  // we want to keep into a new array.
  var frontBuildingsToKeep = [];
  var backBuildingsToKeep = [];
  for (var i = 0; i < frontBuildings.length; i++){
      if (frontBuildings[i].x + frontBuildings[i].width > 0) {
          frontBuildingsToKeep.push(frontBuildings[i]);
      }
  }
  for (var i = 0; i < backBuildings.length; i++){
      if (backBuildings[i].x + backBuildings[i].width > 0) {
          backBuildingsToKeep.push(backBuildings[i]);
      }
  }
  frontBuildings = frontBuildingsToKeep; // remember the surviving buildings
  backBuildings = backBuildingsToKeep;
}


function addNewBuildingsWithSomeRandomProbability() {
  // With a very tiny probability, add a new building to the end.
  var newBuildingLikelihood = 0.08; 
  if (random(0,1) < newBuildingLikelihood) {
      backBuildings.push(makeBackBuilding(width));
      frontBuildings.push(makeFrontBuilding(width));
  }
}

function updateAndDisplayBuildings(){
  // Update the building's positions, and display them.
  for (var i = 0; i < backBuildings.length; i++){
      backBuildings[i].move();
      backBuildings[i].display();
  }
  for (var i = 0; i < frontBuildings.length; i++){
      frontBuildings[i].move();
      frontBuildings[i].display();
  }
    
}

// method to update position of building every frame
function frontBuildingMove() {
    this.x += this.speed;
}
    
// draw the building and some windows
function frontBuildingDisplay() {
  noStroke();
  // building
  fill(this.color);
  var y = 220 - this.height;
  rect(this.x, y, this.width, this.height);
  // windows
  fill("#FFE9AD");
  for(var i = 0; i < 5; i ++) {
    rect(this.x + 5, y + 10 + 15*i, this.width/6, 8);
    rect(this.x + 20, y + 10 + 15*i, this.width/6, 8);
    rect(this.x + 35, y + 10 + 15*i, this.width/6, 8);
  }
}

function makeFrontBuilding(xlocation) {
  var building = {x: xlocation, 
                  width: random(40, 50), 
                  height: random(80, 120),
                  color: color(random(20, 70), random(20, 70), 130),
                  speed: -3,
                  move: frontBuildingMove, 
                  display: frontBuildingDisplay}
  return building;
}


// method to update position of building every frame
function backBuildingMove() {
  this.x += this.speed;
}
    
// draw the back building and some windows
function backBuildingDisplay() {
  noStroke();
  var y = 220 - this.height;
  // light reflections
  fill(255, 243, 180, 20);
  ellipse(this.x + this.width/2, y + 20, this.width*2);
  // building
  fill(this.color);
  rect(this.x, y, this.width, this.height);
  // windows
  fill("#FFE9AD");
  for(var i = 0; i < 8; i ++) {
    rect(this.x + 5, y + 10 + 15*i, this.width/6, 8);
    rect(this.x + 20, y + 10 + 15*i, this.width/6, 8);
    rect(this.x + 35, y + 10 + 15*i, this.width/6, 8);
  }
}

function makeBackBuilding(xlocation) {
  var building = {x: xlocation, 
                  width: random(40, 50), 
                  height: random(130, 160),
                  color: color(random(60, 80), random(60, 80), 180),
                  speed: -3,
                  move: backBuildingMove, 
                  display: backBuildingDisplay}
  return building;
}

// code from https://editor.p5js.org/REAS/sketches/S1TNUPzim
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);
  }
}



LO-11: Women in Computational Design

The project I chose for this week is SOMEONE by Lauren Lee McCarthy. This project interested me since its focus was on reimagining home intelligence systems as actual people rather than AI. SOMEONE is primarily a human version of Amazon Alexa. For 2 months, the homes of 4 participants had custom-designed smart devices installed. A command center was installed in NYC where visitors were able to look into the participants’ homes through laptops and control their networked devices. Participants would call out for “someone” in which the visitors respond to their needs as Alexa does.

Lauren Lee McCarthy is an artist whose work focuses on social relationships in the era of surveillance, automatic, and algorithmic living. She received a BS in Computer Science and Art and Design from MIT and an MFA from UCLA. She is also the creator of p5.js!

Command Center at 205 Hudson Gallery in NYC
Example view of visitors at Command Center

PROJECT-10 (generative landscape)

sketch
// 15-104
// SEAN CHEN

var bgbuildings = [];
var forebuildings = [];
var sidewalk = [];
var dash = [];
var light, bgCloud, foreCloud;
var frames = [];
var run = [];

function preload() {
    light = loadImage('https://i.imgur.com/147kNrs.png');
    bgCloud = loadImage('https://i.imgur.com/Fn6e7H6.png');
    foreCloud = loadImage('https://i.imgur.com/PNyKohG.png');
    frames[0] = loadImage('https://i.imgur.com/xxj2N5D.png');
    frames[1] = loadImage('https://i.imgur.com/ju233XV.png');
    frames[2] = loadImage('https://i.imgur.com/En4Sjg2.png');
    frames[3] = loadImage('https://i.imgur.com/KXPlTB9.png');
    frames[4] = loadImage('https://i.imgur.com/Ya0obgN.png');
    frames[5] = loadImage('https://i.imgur.com/wFN72zO.png');
    frames[6] = loadImage('https://i.imgur.com/DtMtZEq.png');
    frames[7] = loadImage('https://i.imgur.com/oEUisa6.png');
}

// update scene objects
function sceneUpdate(){
    for (var i = 0; i < bgbuildings.length; i++){
        bgbuildings[i].move();
        bgbuildings[i].display();
    }
    for (var i = 0; i < forebuildings.length; i++) {
        forebuildings[i].move();
        forebuildings[i].display();
    }
    for (var i = 0; i < dash.length; i++) {
        dash[i].move();
        dash[i].display();
    }
    for (var i = 0; i < run.length; i++) {
        run[i].move();
        run[i].display();
    }
    for (var i = 0; i < sidewalk.length; i++) {
        sidewalk[i].move();
        sidewalk[i].display();
    }
}

// adding and deleting excess objects
function shiftScene() {
    var buildingsToKeep = [];
    for (var i = 0; i < bgbuildings.length; i++) {
        if (bgbuildings[i].x + bgbuildings[i].breadth > 0) {
            buildingsToKeep.push(bgbuildings[i]);
        }
    }
    bgbuildings = buildingsToKeep;
    for (var i = 0; i < forebuildings.length; i++) {
        if (forebuildings[0].x + forebuildings[0].width < 0) {
            forebuildings.push(makeBuildingFore((forebuildings.length-1)*95));
            forebuildings.shift();
        }
    }
    for (var i = 0; i < sidewalk.length; i++) {
        if (sidewalk[0].x + 50 < 0) {
            sidewalk.push(makeSidewalk(width + width/7));
            sidewalk.shift();
        }
    }
    for (var i = 0; i < dash.length; i++) {
        if (dash[0].x + width/7 < 0) {
            dash.push(makeDash(width));
            dash.shift();
        }
    }
}

// randomly adding background buildings
function bldgProb() {
    var newBuildingLikelihood = 2.5; 
    if (random(0,100) < newBuildingLikelihood) {
        bgbuildings.push(makeBuilding(width));
    }
}

// method to update position of objects every frame
function buildingMove() {
    this.x += this.speed;
}

// draw background building and windows
function buildingDisplay() {
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight; 
    fill(53); 
    stroke(0); 
    push();
    translate(this.x, height - 60);
    rect(0, -bHeight, this.breadth, bHeight);
    for (var i = 0; i < this.nFloors; i++) {
        for (var j = 0; j < this.breadth/20; j++) {
            fill(155, 133, 38);
            circle(j*15+10, -10-(i * floorHeight), 10);
        }
    }
    pop();
}

function makeBuilding(birthLocationX) {
    var bldg = {x: birthLocationX,
                breadth: 50,
                speed: -1,
                nFloors: round(random(6,10)),
                move: buildingMove,
                display: buildingDisplay}
    return bldg;
}

// drawing foreground buildings with long windows
function buildingDisplayFore() {
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight;
    fill(120);
    stroke(0);
    push();
    translate(this.x, height - 60);
    rect(0, -bHeight, this.width, bHeight+10);
    for (var i = 0; i < this.nFloors; i++) {
        fill(155, 133, 38);
        rect(5, -10-(i*floorHeight), this.width-10, floorHeight-10, 5);
    }
    pop();
}

function makeBuildingFore(birthLocationX) {
    var bldg = {x: birthLocationX,
                width: 90,
                speed: -2,
                nFloors: round(random(3, 6)),
                move: buildingMove,
                display: buildingDisplayFore
                }
    return bldg;
}

// adding street lights
function sidewalkDisplay() {
    image(light, this.x, height-85, 57, 50);
}

function makeSidewalk(birthLocationX) {
    var swalk = {x: birthLocationX,
                 speed: -2.5,
                 width: width/4,
                 move: buildingMove,
                 display: sidewalkDisplay
                }
    return swalk;
}

// adding street dashes
function dashDisplay() {
    stroke(144, 133, 0);
    line(this.x, height-20, this.x + width/14, height-20);
}

function makeDash(birthLocationX) {
    var d = {x: birthLocationX,
             speed: -2.5,
             width: width/7,
             move: buildingMove,
             display: dashDisplay
            }
    return d;
}

// adding running dude
function charDisplay() {
    image(frames[this.frame], this.x, 243, 30, 27);
}

function frameMove() {
    if (this.frame == 7 & this.step%3 == 0) {
        this.frame = 0;
    } else if (this.step%3 == 0) {
        this.frame++;
    }
    this.step++;
}

function makeChar(birthLocationX) {
    var c = {x: birthLocationX,
             frame: 0,
             step: 0,
             move: frameMove,
             display: charDisplay
            }
    return c;
}

function setup() {
    createCanvas(450, 300);
    background(5, 5, 45);
    // create an initial collection of buildings
    for (var i = 0; i < 7; i++){
        var rx = random(width);
        bgbuildings[i] = makeBuilding(rx);
        forebuildings[i] = makeBuildingFore(i * 95);
        dash[i] = makeDash(i * width/6);
    }
    for (var i = 0; i < 5; i++) {
        sidewalk[i] = makeSidewalk(i * width/4);
    }
    for (var i = 0; i < frames.length; i++) {
        run[i] = makeChar(10);
    }
    frameRate(30);
}

function draw() {
    background(5, 5, 45);
    //backgournd cloud
    image(bgCloud, 0, 0, 600, 100);
    // road and sidewalk
    fill(0);
    rect(0, height-50, width, 60);
    fill(66);
    rect(0, height-60, width, 20);
    // updatinga and displaying scene objects
    sceneUpdate();
    shiftScene();
    bldgProb(); 
    push();
    // layering transparent clounds
    tint(255, 127);
    image(foreCloud, 0, 0, 600, 100);
    pop();
}

Beach Landscape

When I saw the prompt for the project this week, I immediately thought of doing something with a noise function. I felt as though mountains wouldn’t allow for enough variability, so I decided to do a beach. I laid out the very basic sand, water, and sky, and then added embellishing elements to try to create a drive by beach scene.

beach
var boats = [];     //arrays to hold respective objects
var clouds = [];
var umbrellas = [];
var planes = []; 
var buildings = [];
var railings = [];
var people = [];
var towels = [];
var landscape = [];     //array that creates slope of shoreline
var noiseParam = 0;     
var noiseStep = 0.005;      //defines extremity of shoreline slope


function setup() {
    createCanvas(480,300); 
    
    for (var i = 0; i < 3; i++){        //make a certain amount of (object) to start out, at random locations within a constraint
        var rx = random(width);
        var ry = random(80,150)
            boats[i] = makeBoat(rx,ry);
    }

    for (var i = 0; i < 3; i++){
        var Cx = random(width);
        var Cy = random(0,60)
            clouds[i] = makeCloud(Cx,Cy);
    }

    for (var i = 0; i < people.length; i++){
        var Tx = random(width);
        var Ty = random(250,300)
            towels[i] = makeTowel(Tx,Ty);
    }
    for (var i = 0; i < people.length; i++){
        var Px = random(width);
        var Py = random(250,300)
            people[i] = makePerson(Px,Py);
    }

    for (var i = 0; i < 5; i++){
        var Ux = random(width);
        var Uy = random(250,300)
            umbrellas[i] = makeUmbrella(Ux,Uy);
    }
    
    for (var i = 0; i < 15; i++){
        var Bx = random(width);
            buildings[i] = makeBuilding(Bx);
    }

    for (var i = 0; i < 0.9; i++){
        var Px = random(width);
        var Py = random(0,20)
            planes[i] = makePlane(Px,Py);
   }
    

    for(var i=0;i<=width/5;i++){    
        var n= noise(noiseParam);       //picks value 0-1
        var value = map(n,0,1,50,height);        //scales it to the canvas size

            landscape.push(value);      //adds to array
            noiseParam+=noiseStep;      //moves to the right for the next point in the array
   }
    
    frameRate(5);
}



function draw() {
    background(3,220,245);

    fill(13,66,212,230);    //dark blue
        rect(0,height/4,width,height);      //body of water   
    fill(227,232,164,175);  //pale beige
        rect(0,height/4-7,width,7);    //distant shoreline

                    //call the functions to spawn and despawn respective obejcts
    removeBoat();         
    newBoat(); 

    removeCloud();
    newCloud();

    removeUmbrella();

    removePlane();
    newPlane();

    removeBuilding();
    newBuilding();

    removeRailing();
    newRailing();

    removePerson();

    removeTowel();
  
   
                                                //call the move and show functions to continually draw and redraw objects after updated coordinates
    for (var i = 0; i < clouds.length; i++){
        clouds[i].move();
        clouds[i].show();
    }

    for (var i = 0; i < buildings.length; i++){
        buildings[i].move();
        buildings[i].show();
     }

    for (var i = 0; i < boats.length; i++){
        boats[i].move();
        boats[i].show();
    }
   

    displayHorizon();

     for (var i = 0; i < towels.length; i++){
        towels[i].move();
        towels[i].show();
    }

    for (var i = 0; i < people.length; i++){
        people[i].move();
        people[i].show();
    }

    for (var i = 0; i < umbrellas.length; i++){
        umbrellas[i].move();
        umbrellas[i].show();
    }


    for (var i = 0; i < planes.length; i++){
       planes[i].move();
       planes[i].show();
     }

    fill(159,159,159);
        rect(0,height-50,width,40);
    fill(110,110,110);
        rect(0,height-45,width,30);


    for (var i = 0; i < railings.length; i++){
       railings[i].move();
       railings[i].show();
     }    
}

                        //functions to remove an object from a displayed array once "out of sight"
function removeBoat(){
    
    var boatsToKeep = [];    //the boats that should still be displayed
    for (var i = 0; i < boats.length; i++){
        if (boats[i].x + boats[i].breadth > 0) {    //if the boat is closer than it's width to the edge
            boatsToKeep.push(boats[i]);     //add this boat to the boats that will be displayed
        }
    }
    boats = boatsToKeep; // only display the baots currently being kept
}

function removeCloud(){
    var cloudsToKeep = [];
    for (var i = 0; i < clouds.length; i++){
        if (clouds[i].x + clouds[i].breadth > 0) {
           cloudsToKeep.push(clouds[i]);
        }
   }
    clouds = cloudsToKeep; 
}

function removeUmbrella(){
    var umbrellasToKeep = [];
    for (var i = 0; i < umbrellas.length; i++){
        if (umbrellas[i].x + umbrellas[i].breadth > 0) {
           umbrellasToKeep.push(umbrellas[i]);
        }
    }
    umbrellas = umbrellasToKeep; 
}

function removePlane(){
    var planesToKeep = [];
    for (var i = 0; i < planes.length; i++){
        if (planes[i].x + 150 > 0) {
           planesToKeep.push(planes[i]);
        }
   }
    planes = planesToKeep; 
}

function removeBuilding(){
    var buildingsToKeep = [];
        for (var i = 0; i < buildings.length; i++){
            if (buildings[i].x > 0) {
                buildingsToKeep.push(buildings[i]);
        }
   }
    buildings = buildingsToKeep; 
}

function removeRailing(){
    var railingsToKeep = [];
        for (var i = 0; i < railings.length; i++){
            if (railings[i].x > 0) {
                railingsToKeep.push(railings[i]);
        }
   }
    railings = railingsToKeep; 
}

function removePerson(){
    var peopleToKeep = [];
        for (var i = 0; i < people.length; i++){
            if (people[i].x > 0) {
               peopleToKeep.push(people[i]);
        }
   }
    people = peopleToKeep; 
}

function removeTowel(){
    var towelsToKeep = [];
        for (var i = 0; i < towels.length; i++){
            if (towels[i].x > 0) {
               towelsToKeep.push(towels[i]);
        }
   }
    towels = towelsToKeep; 
}

                    //functions to create new objects that come into sight

function newBoat() {

    var newBoatChance = 0.009;      //the chance that a new boat will appear
    if (random(0,1) < newBoatChance) {      //activate probability
        boats.push(makeBoat(width,random(100,150)));        //add a new boat if the porbability condition is met
    }
}
function newCloud() {

    var newCloudChance = 0.001; 
    if (random(0,1) < newCloudChance) {
        clouds.push(makeCloud(width,random(0,60)));
    }
}


function newPlane() {

    var newPlaneChance = 0.003; 
    if (random(0,1) < newPlaneChance) {
        planes.push(makePlane(width, random(0,50)));
   }
}

function newBuilding() {

    var newBuildingChance = 0.1; 
    if (random(0,1) < newBuildingChance) {
        buildings.push(makeBuilding(width));
   }
}

function newRailing() {

    var newRailingChance = 0.8; 
    if (frameCount % 2 == 0 & random(0,1)

Yael Braha

Eamonn Burke

This is Yael Braha’s “Tree of Changes”, an interactive sculpture which utilizes metalwork, voice recognition and algorithms, LED lights, and a custom Max/MSP software. It allows a user to speak a “wish” into a microphone, watch it travel up the tree, and become a glowing leaf on the branches.

What I really admire about this project is interactivity, and especially how intimate that interactivity is. It shows the power of computational design as a way to connect to people and make them feel special. Not only is a user able to alter the sculpture, but they are able to do it in a way that feels personal to them, which is the epitome of user experience design. In addition to this, the tree itself looks very elegant despite being made from metal, which is quite a feat.

Yael Braha studied Graphic Design at the European Institute of Design in Rome. She then immigrated to the US to study film at San Francisco State University. She now works in Canada, and works mainly with large computational and architectural installations, but also creates fine hand art such as jewelry and ceramics.

Project 11 – Generative Landscape

For this project, I wanted to create a bustling city environment. I created an iPhone in the middle with someone pressing the record button, imagining that they are in a driving car and want to take in the city.

sketch
/* 
 * Amy Lee 
 * amyl2
 * Section B 
 */ 

// Variables for people 
var px = [];
var py = [];
var pdx = [];
var pc = [];
var skin = []; 
var pWidth = []; 
var pHeight = []; 

// Variables for clouds 
var cx = [];
var cy = [];
var cdx = [];
var cWandH = []; 

var buildings = [];
var houses = []; 

function preload() {
    // loading image files 
    finger = loadImage("https://i.imgur.com/DPWPwwe.png"); 
    police = loadImage("https://i.imgur.com/9xYWNnM.png"); 
    taxi = loadImage("https://i.imgur.com/ywwvyoP.png")
} 

function setup() {
    createCanvas(480,480); 
    frameRate(20); 

    // Finger 
    fin = new Object(); 
    fin.image = finger; 
    fin.x = 200;
    fin.y = 460; 
    fin.dx = 1; 
    fin.dy = 1; 
    fin.width = 290; 
    fin.height = 200; 
    fin.move = fingerMove; 
    fin.draw = fingerDraw;

    pol = new Object(); 
    pol.image = police; 
    pol.x = 700; 
    pol.y = 255; 
    pol.dx = 15; 
    pol.width = 240; 
    pol.height = 240; 
    pol.move = polMove; 
    pol.draw = polDraw; 

    tax = new Object(); 
    tax.image = taxi; 
    tax.x = 900; 
    tax.y = 275; 
    tax.dx = 10; 
    tax.width = 230
    tax.height = 230 
    tax.move = taxiMove; 
    tax.draw = taxiDraw; 

    // People
    for (var i = 0; i < 10; i ++){
        px[i] = random(25, width - 25); 
        py[i] = 350; 
        pdx[i] = random(1,3); 
        pc[i] = color(random(255), random(255), random(255));
        skin[i] = color(random(55,200), 80, 90); 
        pWidth[i] = random(20,50); 
        pHeight[i] = random(30,80); 
    }

    // Clouds 
    for (var i = 0; i < 5; i ++){
        cx[i] = random(20,460); 
        cy[i] = random(30,90); 
        cdx[i] = 2; 
        // cloud width and height 
        cWandH[i] = random(20,30); 
    }

    // Building 
    for (var j = 0; j < 5; j ++){
        var bx = random(width); 
        buildings[j] = makeBuildings(bx); 
    }

    // House 
    for (var k = 0; k < 3; k ++){
        var hx = random(width); 
        houses[k] = makeHouses(hx); 
    }

    frameRate(10); 
} 

function draw() {
//  background(130,208,218); 
    background(200,241,208);

    sidewalk(); 
    road(); 

    // Draw clouds, make them move right, and reappear if they move off canvas 
    for (var i = 0; i < 5; i++){
       cloud(cx[i], cy[i], cdx[i], cWandH[i], cWandH[i]);
       cx[i] += cdx[i]; 

       if (cx[i] > width + 10){
           cx[i] = -40; 
       }
   }

    updateAndDisplayBuildings();
    removeBuildingsThatHaveSlippedOutOfView();
    addNewBuildingsWithSomeRandomProbability(); 

    updateAndDisplayHouses();
    removeHousesThatHaveSlippedOutOfView();
    addNewHousesWithSomeRandomProbability(); 

    // Make buildings reappear if they go off the right side of the canvas 
    // Reappear on the left side 
    for (var j = 0; j < buildings.length; j++){
        if (buildings[j].x > width + 20) {
           buildings[j].x = -60; 
       }
   }

    // Make houses reappear if they go off the right side of the canvas 
    // Reappear on the left side 
    for (var k = 0; k < houses.length; k ++){
        if (houses[k].x > width + 20) {
            houses[k].x = -100; 
        }
    }

    // Make people reappear if they go off the right side of the canvas 
    // Reappear on the left side     
    for (var i = 0; i < 10; i ++){
        people(px[i], py[i], pdx[i], pc[i],skin[i],pWidth[i], pHeight[i]); 
        px[i] += pdx[i]; 

        if(px[i] > width+50){
           px[i] = -50; 
        }
    }

    pol.draw(); 
    pol.move(); 

    tax.draw(); 
    tax.move();  

    drawiPhone();  
    fin.draw(); 
    fin.move(); 

    if (frameCount >= 60){
    record(); 
    }

}

 function people(px, py, pdx, pc,skin, pWidth, pHeight){
    fill(pc); 
    noStroke(); 
    // Shirt 
    ellipse(px, py, pWidth, pHeight); 
    // Head 
    fill(skin); 
    ellipse(px,py-25,20,20); 
 }


function fingerDraw(){
    image(finger, this.x, this.y, this.width, this.height); 
}

// Move finger to record button 
function fingerMove(){ 
    if (fin.x > 142 & this.y > 378){
    this.x -= this.dx; 
    this.y -= this.dy; 
    }
}

function polDraw(){
    image(police, this.x, this.y, this.width, this.height); 
}

function polMove(){
    this.x -= this.dx; 
    if (this.x <= -800){
        this.x = 500; 
    }
}

function taxiDraw(){
    image(taxi, this.x, this.y, this.width, this.height); 
}

function taxiMove(){
    this.x -= this.dx; 
    if (this.x <= -1000){
        this.x = 500; 
    }
}

//              BUILDINGS                   //
function updateAndDisplayBuildings(){
    // Update the building's positions, and display them.
    for (var j = 0; j < buildings.length; j++){
        buildings[j].move();
        buildings[j].display();
    }
}

function removeBuildingsThatHaveSlippedOutOfView(){
    var buildingsToKeep = [];
    for (var j = 0; j < buildings.length; j++){
        if (buildings[j].x + buildings[j].breadth > 0) {
            buildingsToKeep.push(buildings[j]);
        }
    }
    buildings = buildingsToKeep; // remember the surviving buildings
}

function addNewBuildingsWithSomeRandomProbability() {
    // With a very tiny probability, add a new building to the end.
    var newBuildingsLikelihood = .0006; 
    if (random(0,1) < newBuildingsLikelihood) {
        buildings.push(makeBuildings(width));
    }
}

// Make buildings move to right 
function buildingsMove() {
    this.x += this.speed;

}

function buildingsDisplay() {
    var floorHeight = 30;
    var bHeight = this.nFloors * floorHeight; 
    push();
    noStroke(); 
    fill(this.col); 
    translate(this.x, height - 40);
    // Drawing the actual buildings
    rect(0, -bHeight-110, this.breadth, bHeight);
//    fill(18, 126, 190);  
    // Windows 
    for (var i = 0; i < this.nFloors; i++) {
        fill(18, 126, 190);  
        rect(5, -130 - (i * floorHeight), this.breadth - 10, 10);
    }
    // Building antennae 
    stroke(18,126,190); 
    strokeWeight(2); 
    line(5,-bHeight-110,5,-bHeight-120); 
    line(10,-bHeight-110,10, -bHeight-130); 
    noStroke(); 
    pop();
}

function makeBuildings(birthLocationX) {
    var bldg = {x: birthLocationX,
                breadth: 60,
                speed: 4.0,
                col: color(121,204,221),
                nFloors: round(random(5,10)),
                move: buildingsMove,
                display: buildingsDisplay}
    return bldg;
}

//              HOUSES                   //
function updateAndDisplayHouses(){
    for (var k = 0; k < houses.length; k++){
        houses[k].move(); 
        houses[k].display(); 
    }
}

function makeHouses(birthLocationX){
    var houses = {x: birthLocationX,
                 breadth: 100,
                 speed: 4.0, 
                 col1: color(232,175,104),
                 col2: color(182,110,125),
                 nFloors: round(random(2,4)), 
                 move: housesMove, 
                 display: housesDisplay}
    return houses; 
}

function removeHousesThatHaveSlippedOutOfView() {
    var housesToKeep = []; 
    for (var k = 0; k < houses.length; k++){
        if (houses[k].x + houses[k].breadth > 0) {
            housesToKeep.push(houses[k]); 
        }
    }
    houses = housesToKeep; 
}


function addNewHousesWithSomeRandomProbability() {
    var newHousesLikelihood = .0001; 
    if (random(0,1) < newHousesLikelihood) {
        houses.push(makeHouses(width)); 
    }
}

function housesMove() {
    this.x += this.speed; 
}

function housesDisplay() {
    var floorHeight = 20; 
    var hHeight = this.nFloors * floorHeight; 
    push(); 
    noStroke(); 
    fill(this.col1); 
    translate(this.x, height-30); 
    rect(0, -hHeight - 110, this.breadth, hHeight); 
    fill(this.col2); 
    triangle(0, -hHeight - 110, this.breadth, -hHeight - 110, this.breadth/2, -hHeight - 140); 
    rect(30, -hHeight - 90, this.breadth - 60, hHeight - 20); 
    fill(252, 197, 132); 
    ellipse(50, -hHeight - 110 , 8, 8); 
    pop(); 
}

function cloud(cx, cy, cdx, cWandH, cWandH){
    push(); 
    stroke(255); 
    strokeWeight(20); 
    line(cx, cy, cx+30, cy); 
    pop(); 
    fill(255);
    ellipse(cx,cy,cWandH, cWandH); 
    ellipse(cx+10,cy-10,cWandH, cWandH); 
    ellipse(cx+20,cy,cWandH, cWandH); 
}

function drawiPhone(){
    fill(0); 
    // top rectangle
    rect(130,40,200,60); 
    // left side 
    rect(130,40,20,400); 
    // right side 
    rect(330,40,20,400); 
    // bottom rectangle 
    rect(130,380,200,60) 
    // home button 
    fill(255); 
    ellipse(236,416,31,31); 
    fill(33);
    ellipse(240,416,33,33);  
    // small rectangle at top 
    fill(58); 
    rect(215,65,50,10); 
    // glass shine 
    push(); 
    stroke(255); 
    strokeWeight(10); 
    line(160,140,200,110); 
    line(160,170,240,110); 
    line(240,360,310,305); 
    line(272,370,315,336); 
    pop(); 
} 

function sidewalk(){
    noStroke(); 
    fill(236,205,158); 
    rect(0,330,480,70); 
    fill(132,64,64); 
    rect(0,390,480,10); 
}

function road(){
    fill(180,145,126); 
    rect(0,400,480,80); 
}

// REC button on iPhone 
function record(){
    fill(255,0,0); 
    ellipse(270,124,13,13); 
    textSize(20);     
    text("REC", 280, 130); 
}

















Project 11: Landscape

peachsketch
var Stars = [];
var Planets = [];
var asteroids = [];
var terrain = [];
var noiseParam = 0;
var noiseStep = 0.007;

function setup() {
    createCanvas(480, 300); 
    // create an initial collection of stars, planets, and asteroids
    for (var i = 0; i < 100; i++){
        var rx = random(width);
        var ry = random(height);
        Stars[i] = makeStar(rx, ry);
    }
    for (var i = 0; i < 5; i++){
        var rx = random(width);
        var ry = random(height);
        Planets[i] = makePlanet(rx, ry);
    }
    for (var i = 0; i < 2; i++){
        var rx = random(width);
        var ry = random(height);
        asteroids[i] = makePlanet(rx, ry);
    }
//set up noise function to create scrolling planet terrain
  for (i = 0; i<=width/5; i++){
    var n = noise(noiseParam);
    var value = map(n, 0,1,height/2, height)
    terrain.push(value)
    noiseParam+= noiseStep
  }

    frameRate(20);
}

function draw() {
    background(0); 

    updateStars();
    removeStars();
    addNewStars(); 

    updatePlanets();
    removePlanets();
    addNewPlanets(); 

    updateasteroids();
    removeasteroids();
    addNewasteroids(); 

mars();
insideSpaceship();
astronaut();
}

function updateStars(){
    // Update the Star's positions, and display them.
    for (var i = 0; i < Stars.length; i++){
        Stars[i].move();
        Stars[i].display();
    }
}

function removeStars(){
    var StarsToKeep = [];
    for (var i = 0; i < Stars.length; i++){
        if (Stars[i].x + Stars[i].breadth > 0) {
            StarsToKeep.push(Stars[i]);
        }
    }
    Stars = StarsToKeep; 
}


function addNewStars() {
    var newStarLikelihood = 0.2; 
    if (random(0,1) < newStarLikelihood) {
        Stars.push(makeStar(width, random(height)));
    }
}

// method to update position of Star every frame
function StarMove() {
    this.x += this.speed;
}
    
// draw Stars
function StarDisplay() {
    fill(255);  
    push();
    translate(this.x, this.y);
    ellipse(0, this.breadth, this.nsize)
    pop();
}

function makeStar(birthLocationX, birthLocationY) {
    var star = {x: birthLocationX,
                breadth: 50,
                y:birthLocationY,
                speed: -2.0,
                nsize: round(random(1,8)),
                move: StarMove,
                display: StarDisplay}
    return star;
}

//view scrolling landscape from inside spaceship
function insideSpaceship(){
	noStroke()
fill(151, 163, 194)
	rect(0, height/9*7, width, height);
	rect(0,0, width, height/9);
	rect(0,0, width/9, height)
	rect(width/9*8, 0, width, height);
noFill();
strokeWeight(10);
stroke(61, 81, 133)
beginShape();
	vertex(width/9, height/9);
	vertex(width/9*8, height/9);
	vertex(width/9*8, height/9*7);
	vertex(width/9, height/9*7);
	vertex(width/9, height/9);
endShape();
strokeWeight(2);
var lx = 80;
var ly = 10;
var pt = 15
for (i=0; i<4; i++){
	line(lx, 0, lx, height/9)
	line(lx, height/9*7, lx, height)
	lx+=110
	line(0, ly, width, ly)
	ly += 250
	}
line(0, 120, width/9, 120)
line(width/9*8, 120, width, 120)
strokeWeight(7)
	point(width/9 + 10, height/9 +10)
	point(width/9 + 10, height/9*7 - 10)
	point(width/9*8-10, height/9 +10)
	point(width/9*8-10, height/9*7 - 10)
noStroke();
}

//draw astronaut looking out spaceship window
function astronaut(){
fill(255)
	ellipse(70, 230, 100);
	rect(30, 240, 80,100)
fill(143, 150, 168)
	ellipse(85,225, 60)
stroke(143, 150, 168)
strokeWeight(4);
	line(85, 270, 85, height)
noFill()
stroke(181, 199, 247)
	ellipse(85,225, 60)
noStroke();
}

function updatePlanets(){
    for (var i = 0; i < Planets.length; i++){
        Planets[i].move();
        Planets[i].display();
    }
}

function removePlanets(){
    var PlanetsToKeep = [];
    for (var i = 0; i < Planets.length; i++){
        if (Planets[i].x + Planets[i].breadth > 0) {
            PlanetsToKeep.push(Planets[i]);
        }
    }
    Planets = PlanetsToKeep; 
}

function addNewPlanets() {
    var newPlanetLikelihood = 0.01; 
    if (random(0,1) < newPlanetLikelihood) {
        Planets.push(makePlanet(width, random(height)));
    }
}

function PlanetMove() {
    this.x += this.speed;
}
    
function PlanetDisplay() {
    fill(this.clr);  
    push();
    translate(this.x, this.y);
    ellipse(0, this.breadth, this.nsize)
    pop();
}

function makePlanet(birthLocationX, birthLocationY) {
    var Planet = {x: birthLocationX,
                breadth: 50,
                y:birthLocationY,
                clr: color(random(1, 255), random(1, 255), random(1, 255)),
                speed: -1.0,
                nsize: round(random(10,50)),
                move: PlanetMove,
                display: PlanetDisplay}
    return Planet;

}

function updateasteroids(){
    for (var i = 0; i < asteroids.length; i++){
        asteroids[i].move();
        asteroids[i].display();
    }
}

function removeasteroids(){
    var asteroidsToKeep = [];
    for (var i = 0; i < asteroids.length; i++){
        if (asteroids[i].x + asteroids[i].breadth > 0) {
            asteroidsToKeep.push(asteroids[i]);
        }
    }
    asteroids = asteroidsToKeep;
}

//asteroids appear the least frequently - "surprise element"
function addNewasteroids() {
    var newasteroidLikelihood = 0.005; 
    if (random(0,1) < newasteroidLikelihood) {
        asteroids.push(makeasteroid(width, random(height)));
    }
}

//make the asteroid move in both x direction and y direction
function asteroidMove() { 
    this.x += this.speed;
    this.y += this.speedy;
}
    
// draw asteroids
function asteroidDisplay() {
    fill(random(255), random(255), random(255));  
    push();
    translate(this.x, this.y);
    ellipse(0, 5, this.nsize)
    beginShape();
    	vertex(5,5);
    	vertex(15,5);
    	vertex(9,7);
    	vertex(15,10);
    	vertex(9,13);
    	vertex(10,15);
    	vertex(5,15);
    endShape();
    pop();
}

function makeasteroid(birthLocationX, birthLocationY) {
    var asteroid = {x: birthLocationX,
                breadth: 50,
                y:birthLocationY,
                speed: -5.0,
                speedy: -1.0,
                nsize: 10,
                move: asteroidMove,
                display: asteroidDisplay}
    return asteroid;
}
//generate landscape of planet in foreground, placed low on screen so low frequency of apearance
function mars (){
    var n = noise(noiseParam);
    var value = map(n, 0,1,height/5*3, height)
    terrain.push(value)
    terrain.shift();
    noiseParam+= noiseStep
  for (i = 0; i<=width/5; i++){
    noStroke();
    fill(222, 106, 11)
    beginShape();
    vertex(0, height)
    vertex(width, height)
    vertex(i*5, terrain[i])  
    endShape();
  if (terrain[i] < terrain[i+1] & terrain[i] < terrain[i-1]){
  drawAlien(i)
  }
}
}

  function drawAlien(i){ 
  fill(0,255,0)

  ellipse(i*5, terrain[i]-10, 10);
  stroke(0,255,0)
  strokeWeight(2);
    line(i*5,terrain[i]-20, i*5, terrain[i]-10)
   strokeWeight(10)
    ellipse(i*5, terrain[i]-5, 5)
   noStroke()
    fill(255)
   ellipse(i*5, terrain[i]-5, 8)
   fill(0)
     ellipse(i*5, terrain[i]-5, 5)

}

For this assignment, I had a lot of fun deciding what I wanted my landscape to be. However, I found that there were a lot of components that I wanted to introduce, but wasn’t able to efficiently generate them in a concise amount of code. I ended up utilizing methods from different classes to generate different aspects of my landscape – for example, objects in the background similar to what was provided in the sample code, as well as usage of the noise function for objects in the foreground. I was partially inspired by the game Among Us as well as a music video called “Where the Sea Sleeps.”

Looking Outwards – 11

One project that I admire is “Bot Party,” helmed by Phoenix Perry and aided by Freida Abtan, both women artists. The project is a game that requires the players to help the robots communicate with each other through audio interaction. They utilize a ‘bot to skin and skin to bot’ communication protocol – the user physically connects the bots so that they may send encoded messages to each other. I admire that the project is both thoughtful in its simplistic message, while simultaneously is efficient as well as aesthetically pleasing. It also utilizes robots for a considerably unique purpose. Phoenix Perry amusingly calls herself a cultural engineer, game designer, instigator, as well as “feminist killjoy.” She was educated at NYU Tandon. I admire her in that while she has evidently found personal success, she has used that success to help others – she founded the Code Liberation Institute, which teaches women how to program games, as well as Dozen Eyes Games, a studio aimed at games and installations that generate social change. She also gives lectures, and in general, her active pursuit of positive change in the world of a male dominated profession is really inspiring.