Hannah Cai—Project 10—Landscape

/* Hannah Cai
Section C
hycai@andrew.cmu.edu
Project-10-Landscape
*/

var trees = []; //array for bigger trees (in the back)
var bushes = []; //array for smaller trees 
                 //I just called them bushes to make things easier
var speed = 0.00001; //leftward shift rate of mountains

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

  // create initial trees; make 5 big and 5 small trees
  for (var t = 0; t < 5; t++){
    var tx = random(width);
    trees[t] = makeTree(tx);
    var bx = random(width);
    bushes[t] = makeBush(bx);
  }
  frameRate(10); //set tree and bush frameRate to 10
}

//make tree at x
function makeTree(tx) {
  var trees = {x: tx,
              draw: treeDraw}
  return trees;
}

//make bush at x
function makeBush(bx) {
  var bushes = {x: bx,
              draw: bushDraw}
  return bushes;
}

//draw tree
function treeDraw() {
  noStroke();
  //leaves
  fill(14, 90, 117);
  triangle(this.x - 20, 398, this.x + 20, 398, this.x, 320);
  //trunk
  stroke(13, 77, 94);
  line(this.x, 330, this.x, 400);
  //movement
  this.x -= 1;

  //make new trees
  var newTree = 0.0025; //probability for new tree "birth"
  if (random(0, 1) < newTree) {
      trees.push(makeTree(width + 20)); //push new tree into trees array
  }
}

//draw bush
function bushDraw() {
  noStroke();
  //leaves
  fill(28, 65, 72);
  triangle(this.x - 15, 403, this.x + 15, 403, this.x, 330);
  //trunk
  stroke(13, 77, 94);
  line(this.x, 340, this.x, 405);
  //movement
  this.x -= 1.2;

  //make new bushes
  var newBush = 0.0025; //probability for new bush "birth"
  if (random(0, 1) < newBush) {
      bushes.push(makeBush(width + 15)); //push new bush into bushes array
  }
}

function draw() {
  background(228, 239, 242);
  noStroke();

  //orange gradient layer
  for (var y = 100; y < 400; y++) { //for this specific y interval,
    var a = map(y, 100, 400, 0, 255); //map y interval to alpha
    stroke(240, 178, 158, a); 
    line(0, y, width, y); //draw lines with mapped alphas
  }

  //sun
  fill(240, 178, 158);
  ellipse(240, 200, 25);

  //mountain layer 1
  beginShape(); 
  stroke(149, 189, 207);
  var variance1 = 0.001;
  for (i = 0; i < width; i++) {
    var t = (i * variance1) + (millis() * speed);
    var y = map(noise(t), 0, 1, 100, height);
    line(i, y, i, height); 
    }
  endShape();

  //fog layer 1
  for (var y = 200; y < 400; y++) {
    var b = map(y, 200, 400, 0, 255);
    stroke(187, 208, 214, b);
    line(0, y, width, y);
  }

  //mountain layer 2
  beginShape(); 
  stroke(85, 170, 200);
  var variance2 = 0.0015;
  for (j = 0; j < width; j++) {
    var t = (j * variance2) + (millis() * speed);
    var y = map(noise(t), 0, 1, 150, height);
    line(j, y, j, height); 
    }
  endShape();

  //fog layer 2
  for (var y = 200; y < 480; y++) {
    var b = map(y, 200, 480, 0, 255);
    stroke(187, 208, 214, b);
    line(0, y, width, y);
  }

  //draw trees using the treeDraw function
  for (var u = 0; u < trees.length; u++) {
    trees[u].draw();
  }

  //fog layer 3
  for (var y = 350; y < 480; y++) {
    var b = map(y, 350, 480, 0, 255);
    stroke(187, 208, 214, b);
    line(0, y, width, y);
  }

  //ground layers
  noStroke();
  fill(117, 144, 139);
  rect(-1, 400, width + 1, 10);
  fill(63, 84, 77);
  rect(-1, 405, width + 1, 80);

  //draw bushes using the bushDraw function
  for (var v = 0; v < bushes.length; v++) {
    bushes[v].draw();
  }

  //removes trees when they go off the left edge of the screen;
  //stores the trees still on screen in a new array
  var treesToKeep = [];
  for (var i = 0; i < trees.length; i++){
    if (trees[i].x + 20 > 0) {
      treesToKeep.push(trees[i]);
    }
  }
  trees = treesToKeep;

  //removes bushes when they go off the left edge of the screen;
  //stores the bushes still on screen in a new array
  var bushesToKeep = [];
  for (var v = 0; v < bushes.length; v++){
    if (bushes[v].x + 20 > 0) {
      bushesToKeep.push(bushes[v]);
    }
  }
  bushes = bushesToKeep;

}

I enjoyed this project, even though I initially struggled a lot with what kind of landscape I wanted to do. I wanted to make a landscape that looked believable, and since we basically all only had one terrain generation template, it was hard for me to pick a landscape I felt like I could create and be satisfied with. I ended up looking through landscape photos and using one for inspiration and reference. It was really helpful to be able to pull colors from the photo, as well as realistic landscape qualities.

I’m pretty proud with how my landscape turned out, especially with the fog (which I learned how to code alpha gradients for). I really want to try using this kind of concept to generate backgrounds that could be used for games or for open-world environments. I might explore some of that in the future (maybe for my final project?).

Catherine Coyle – Looking Outwards 10

For this week’s looking outwards, I went through the provided list of women in code, and really enjoyed the SUPERHYPERCUBE project by Heather Kelley.

A trailer and demo for the SUPERHYPERCUBE game

The project is essentially a VR arcade kind of game. It’s really simple in its idea, but the visuals are interesting and the puzzles make you work your brain which I think is cool. VR is a cool technology on its own, and it is nice to see really high quality simple concepts implemented sometimes rather than the very detailed ones. Sometimes I feel like those fall into uncanny valley territory and can be less immersive even.

Heather Kelley primarily works in game design and digital arts and media. She is very influential in the field and was named one of the five most powerful women in gaming by Inc. magazine in 2013. I couldn’t find where she went to school or what she studied online, but I did find out that she works here at CMU! I also found out that she worked on the indie game FEZ which is actually a game that I’ve played and really enjoyed so I find that very cool.

(I’m using my first LO grace day for this)

Sophia Kim – Project 10 Landscape – Sec C

sketch

// Sophia S Kim
// Section C 1:30
// sophiaki@andrew.cmu.edu 
// Project-09-Portrait

var fish = []; 

function setup() {
  createCanvas(480, 480);
  frameRate(7);
  for(var l = 0; l < 10; l++) {
    var fx = random(width);
    fish[l] = makeFish(fx);
  }
  frameRate(6);
}
 
function draw() {
  background(212, 211, 234);
  sun(); //sun in the sky 
  mountainBackground(); //mountain 
  hillInFrontofMountain(); //small hill in front of mountain
  waterRiver(); //river at the bottom 
  updateFish();
  removeFish();
  randomFish();
  fishDisplay(); 
    //randomizes fish in the "river"
}

// displays fish
function updateFish(){
    for (var i = 0; i < fish.length; i++){
        fish[i].move();
        fish[i].display();
    }
}
// fish disappear when hitting the edge
function removeFish(){
    var fishKeep = [];
    for (var q = 0; q < fish.length; q++){
        if (fish[q].x + fish[q].breadth > 0) {
            fishKeep.push(fish[q]);
        }
    }
    fish = fishKeep;
}
// randomized fish to be added to the end 
function randomFish() {
    var updatedNewFish = 0.009;
    if (random(0, 1) < updatedNewFish) {
        fish.push(makeFish(width));
    }
}

// update position of fish 
function fishMove() {
    this.x += this.speed;
}

// drawing the fish
function fishDisplay() {
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight;

    push();
    noStroke();
    translate(this.x, height - 140);
    //fish body
    fill(255, 161, 210);
    ellipse(3, bHeight+20, 35, 25);
    //fish tail
    fill(255, 161, 210);
    triangle(10, bHeight+20, 30, bHeight, 30, bHeight+40);
    pop();

}

function makeFish(birthLocationX) {
    var fhm = {x: birthLocationX,
             breadth: 5,
             speed: -3.0,
             nFloors: round(random(2,4)),
             move: fishMove,
             display: fishDisplay}
    return fhm;
}

function waterRiver() {
//makes the "river" appear 
  fill(8, 42, 102);
  rect(-1, 350, 480, 130);
}

function hillInFrontofMountain() {
//makes the hill in front of the mountain move 
  var terrainSpeed3 = 0.0001;
  var terrainDetail3 = 0.002;

  beginShape(); 
  stroke(44, 87, 181);
  for (var x3 = 0; x3 < width; x3++) {
        var p = (x3 * terrainDetail3) + (millis() * terrainSpeed3);
        var z = map(noise(p), 0, 1, 300, 200);
        line(x3, z, x3, height); 
    }
    endShape();
}

function mountainBackground() {
//makes mountains in the back
  var terrainSpeed2 = 0.0005;
  var terrainDetail2 = 0.01;
  
  stroke(99, 129, 214);
  beginShape(); 
  for (var x2 = 0; x2 < width; x2++) {
    var t = (x2 * terrainDetail2) + (millis() * terrainSpeed2);
    var y2 = map(noise(t), 0, 1, 200, 10);
    line(x2, y2, x2, height); 
    }
  endShape();
}

function sun() {
  fill(234, 119, 101); 
  noStroke(); 
  ellipse(417, 60, 80, 80);

  fill(255, 146, 128); 
  noStroke(); 
  ellipse(420, 60, 75, 75);
} 

As it gets colder in Pittsburgh, I started to miss the warm weather and my trip to Taiwan. For my landscape, I definitely wanted to make a view of mountains. This photo came to mind.

sketch of my idea
this one natural wonder in Taiwan (inspiration from this photo)

Among all the projects, this project was the hardest. I had a really hard time with making the fishes and making them move. I had a really hard time making the mountains long and keeping them consistent. Overall, I don’t really like the outcome of the final project. If I had to make changes, I would definitely add more details to the mountain.

Joanne Lee – Looking Outward 10

SUPERHYPERCUBE (2016, Heather Kelley).

The project I chose to discuss is called SUPERHYPERCUBE. It is a “VR first person puzzler” that was originally developed for PlayStationVR. In order to play this game, you must figure out how to rotate the cubes on your screen to fit the approaching wall. With each successful completion, you get more and more cubes, making it more difficult to see the shape of the wall behind you. At that point you must quickly peek around the cubes to see the shape of the wall and figure out the correct rotations.

This fascinating game was created by Heather Kelley who is a veteran game designer, digital artist, and media curator among many things. She has served as the co-chair of the IGDA’s Women in Game Development Special Interest Group for 7 years and is clearly very passionate and good at what she does. She is the co-founder of Kokoromi (an experimental game collective) and has created many creative games under her belt. I admired this game in particular because I really love puzzle games and the idea of a VR version was very interesting to me. I also admire how involved she has been in advocating women in game development and it has inspired me to try to create a small, simple game as a side project during the remainder of this semester!

Rjpark – Looking Outwards 10

Body on Screen by Claudia Hart

The woman I’ve decided to focus on is Claudia Hart and her project, Body on Screen. Claudia Hart has worked on both contemporary art and 3D animation and has taught both of those for a really long time. She’s taken classes at New York University’s Center for Advanced Digital Applications to learn Maya 3D animation software and she’s attended the School of the Art Institute of Chicago. She states that her main focus as a female artist in a high-end technology industry, is to, “subvert earlier dichotomies of woman and nature pitted against a civilized, “scientific” and masculine world of technology”. And you can clearly see that in her project, Body on Screen.

Hart was inspired by Trisha Brown, a American postmodern dancer who challenged the dance tradition that focused on formalistic beauty of the body and stylized move. Brown emphasized pedestrian movements and de-highlighted the “feminine” features of a dancer’s body. Similar to Brown, Hart portrays women in a simple way by drawing their bodies with sagging breast, rocky hairs, frozen-looking body, and characterless face, which accentuates their physical agility in regards to the choreography rather than their erotic quality. By doing this, she desexualizes women and presents them at face value. Furthermore, she allows people to understand womens’ representation issues, whether or not they’re specific to the digital practice. And as a female, this is something that I think is important to present to the world and that is why I admire her project.

Claudia Hart

Rjpark – Project 10 – Generative Landscape

generativelandscape

var jellyfish = [];

function setup() {
    createCanvas(480, 480); 
    
    // create an initial collection of jellyfish
    for (var i = 0; i < 10; i++){
        var rx = random(width);
        var ry = random(height);
        jellyfish[i] = makeJellyfish(rx, ry);
    }

    frameRate(30);
}

function draw() {
    background("lightblue"); 
    
    updateJellyfish();
    removeJellyfish();
    addNewJellyfish(); 
}

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

function removeJellyfish(){
    var jellyfishToKeep = [];
    for (var i = 0; i < jellyfish.length; i++){
        if (jellyfish[i].y + jellyfish[i].size > 0) {
            jellyfishToKeep.push(jellyfish[i]);
        }
    }
    jellyfish = jellyfishToKeep; // surviving jellyfish
}

// HOW TO ADD SMOOTHLY!!!
function addNewJellyfish() {
    var newJellyfishLikelihood = 0.015; 
    if (random(0, 1) < newJellyfishLikelihood) {
        jellyfish.push(makeJellyfish(random(width), height));
    }
}

// update position of jellyfish every frame
function jellyfishMove() {
    this.y += this.speed;
}

// draw jellyfish
function jellyfishDisplay() {
    fill(this.rr, this.rg, this.rb); 
    noStroke();
    arc(this.x, this.y, this.size, this.size, PI, 2 * PI, CHORD);
    push();
    translate(this.x, this.y);
    noFill();
    stroke(255);
    strokeWeight(2);
    bezier(0, 0, -20, 40, 20, 30, 0, 70);
    bezier(-10, 0, -30, 40, 10, 30, -10, 70);
    bezier(-20, 0, -40, 40, 0, 30, -20, 70);
    bezier(10, 0, -10, 40, 30, 30, 10, 70);
    bezier(20, 0, 0, 40, 40, 30, 20, 70);
    pop();
}

function makeJellyfish(startingX, startingY) {
    var jf = {x: startingX,
    			y: startingY,
    			rr: random(0, 200),
    			rg: random(0, 100),
    			rb: random(0, 255),
                size: random(50, 100),
                speed: -1.0,
                move: jellyfishMove,
                display: jellyfishDisplay}
    return jf;
}

When I read about this project, the first “landscape” I thought of was sea animals passing by in a submarine or in an aquarium. As a result, I wanted to create something to imitate the perspective of someone traveling under water, like being in a submarine. I chose to draw jellyfish and to view them from a bird’s eye view (imagine being in a submarine with glass on the floor/bottom). In addition, I chose to randomize the size and colors of the jellyfish. Here are a few sketches of how I decided on perspective/shape.

Connor McGaffin – Project 10

sketch

/*
Connor McGaffin
Section C
cmcgaffi@andrew.cmu.edu
Project-10
*/

var poppies = [];

var terrainSpeed = 0.00001;
var d = 0.0004;
var d2 = 0.0006;

function setup() {
    createCanvas(480, 240); 
    // create an initial collection of poppies
    for (var i = 0; i < 100; i++){
        var rx = random(width);
        poppies[i] = makeFlower(rx);
    }
    frameRate(10);
}

function draw() {
    background(180, 180, 0); 
    noStroke();
    
    sunset();
    //mtn
    displayRocks();

    emeraldCity();
    
    //adjust 
    translate(0, 30);
    displayGrass();

    //poppies behind road
    push();
    translate(0, -40);
    updateAndDisplaypoppies();
    pop();

    //yellow brick road
    ybr();

    //poppies in front of road
    updateAndDisplaypoppies();
    removepoppiesThatHaveSlippedOutOfView();
    addNewpoppiesWithSomeRandomProbability(); 
}

function sunset(){
    //orange 1
    push();
        fill(190, 150, 0);
        rect(0, 50, width, height);
    pop();
    //orange 2
    push();
        fill(200, 130, 0);
        rect(0, 120, width, height);
    pop();
}

function ybr(){
    fill(200,200,0);
    rect(0,180, width, 20);
}

//draw emerald city
function emeraldCity() {
    //halo adjustment
    var scaleFactor = 1.2;
    push();
        //adjustment
        translate(300, -25)
        //halo
        push();
            stroke('rgba(235, 255, 120, 0.4)');
            strokeWeight(3);
            noFill();
            ellipse(125, 100, 110 * scaleFactor);
            strokeWeight(1);
            ellipse(125, 100, 95 * scaleFactor);
            ellipse(125, 100, 50 * scaleFactor);
        pop();
        //city towers
        push();
            //shimmer type 1
            fill(20, random(160,170), 0);
            rect(100, 80, 15, height, 20);
            rect(115, 90, 15, height, 20);
            rect(125, 75, 15, height, 20);
            rect(145, 100, 15, height, 20);
            //shimmer type 2
            fill(20, random(170,180), 0);
            rect(90, 100 , 15, height, 20);
            rect(110, 120 , 15, height, 20);
            rect(130, 90, 15, height, 20);
            rect(150, 130, 15, height, 20);
            //shimmer type 3
            fill(20, random(180,190), 0);
            rect(80, 180, 15, height, 20);
            rect(100, 140, 15, height, 20);
            rect(125, 120 , 15, height, 20);
            rect(145, 150, 15, height, 20);
        pop();
    pop();
}

function updateAndDisplaypoppies(){
    // Update the poppy positions, and display them.
    for (var i = 0; i < poppies.length; i++){
        poppies[i].move();
        poppies[i].display();
    }
}

function removepoppiesThatHaveSlippedOutOfView(){
    // If a poppy has dropped off the left edge,
    // remove it from the array. 
    var poppiesToKeep = [];
    for (var i = 0; i < poppies.length; i++){
        if (poppies[i].x + poppies[i].breadth > 0) {
            poppiesToKeep.push(poppies[i]);
        }
    }
    poppies = poppiesToKeep; // remember surviving poppies
}
function addNewpoppiesWithSomeRandomProbability() {
    // probability of adding a new poppy to the end.
    var newTreeLikelihood = 0.3; 
    if (random(0,1) < newTreeLikelihood) {
        poppies.push(makeFlower(width));
    }
}

// poppy moves every frame
function poppyMove() {
    this.x += this.speed;
}
    
// draw the poppy
function poppyDisplay() {
    var leafDistance = 20;
    var bHeight = this.nGrowth * leafDistance; 
    push();
        translate(this.x, height - this.closeness);
        var distFactor = 4 / this.closeness;
        //stem
        push();
            strokeWeight(25 * distFactor * .6);
            stroke(30, 130, 0);
            line(0, -bHeight * .2, 0, 0);
        pop();
        //flower
        push();
            noStroke();
            fill(200,0,0);
            ellipse(0, -bHeight * .2, 90 * distFactor * .6);
            fill(0);
            ellipse(0, -bHeight * .2, 90 * distFactor * .2);
        pop();
    pop();
}


function makeFlower(birthLocationX) {
    var poppy = {x: birthLocationX,
                breadth: 50,
                speed: -1.0,
                nGrowth: round(random(2,8)),
                closeness: random(20,40),
                move: poppyMove,
                display: poppyDisplay}
    return poppy;
}


function displayGrass() {
//grass
    push();
    fill(0, 90, 0); 
    beginShape(); 
    for (var x = 0; x < width; x++) {
        var t = (x * d) + (millis() * terrainSpeed);
        var y = map(noise(t), 0,1, 145, 190);
        vertex(x, y - 20);
        vertex(0, height);
        vertex(width, height); 
    }
    endShape();
    pop();
}

//rocks behind emerald city
function displayRocks() {
    push();
    fill(90, 90, 60); 
    beginShape(); 
    for (var x = 0; x < width; x++) {
        var t = (x * d2) + (millis() * terrainSpeed);
        var y = map(noise(t * 3), 0, 1, 160, 190);
        vertex(x, y - 20);
        vertex(0, height);
        vertex(width, height); 
    }
    endShape();
    pop();
}





I started my exploration process by brainstorming which landscape I would like to create. I had a running theme of plants going on as the objects in my array. I started with what I was most familiar with, and sketched out an idea where flowers would be generated at the eye level of a squirrel. Expanding on this, I sketched a quick layout of scrolling plants that I am not familiar with, being in the context of a jungle canopy. And finally, I pushed into a setting that doesn’t even exist with the sketch of the poppies leading up to the Emerald City from The Wizard of Oz.

I ended up going with the Wizard of Oz theme, as it excited me most. In the story, surrounding the shimmering Emerald City, the four protagonists encounter a field of poppies, which push Dorothy into a slumber. I designed this code to provide a panning view of the setting where this plot event happened, as if it were cinematically setting the scene.

Justin Yook – Project 10

genland

// Justin Yook
// jyook@andrew.cmu.edu
// Section C
// Project 10

var milk = [];
var milkCol;

function setup() {
    createCanvas(480, 200);
    milkCol = [color(255, 0, 0), color(255, 255, 0), color(0, 0, 255), color(0, 255, 0)];

    for (var i = 0; i < 10; i++) {
        var rx = random(width); // random x location within width
        milk[i] = makeMilk(rx);
    }

    frameRate(60);
}

function draw() {
    background(200, 233, 243);

    displayFloor();

    updateAndDisplayMilk();
    removeMilk();
    addMilkRandom();
}

function displayFloor(){
    stroke(152, 196, 209);
    strokeWeight(3);
    line(0, height - 30, width, height - 30);
}

function makeMilk(spawnX) {
    var mlk = {x: spawnX,
               space: 50,
               speed: -1.0,
               move: milkMove,
               col: random(milkCol),
               display: milkDisplay}
    return mlk;
}

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

function milkDisplay() {
    fill(255);
    stroke(0);
    strokeWeight(1);
    rect(this.x, height - 90, 40, 70);

    fill(this.col);
    rect(this.x, height - 90, 40, 10);

    fill(this.col);
    rect(this.x, height - 30, 40, 10);

    fill(255);
    quad(this.x, height - 90, this.x + 5, height - 100, this.x + 35, height - 100, this.x + 40, height - 90);

    fill(255);
    rect(this.x + 5, height - 105, 30, 5);
}

function addMilkRandom() {
    var newMilkProb = .007;
    if (random(0, 1) < newMilkProb) {
        milk.push(makeMilk(width));
    }
}

function removeMilk() {
    var milkeep = [];
    for (var i = 0; i < milk.length; i++) {
        if (milk[i].x + milk[i].space > 0) {
            milkeep.push(milk[i]);
        }
    }
    milk = milkeep;
}

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

I chose to do a generative landscape of the inside of a refrigerator. The object I defined is the milk quart. Each milk quart has a color that is randomly picked from an array of pre-selected colors. I was inspired when I went to buy some groceries, and I saw that different types of milk had different colors on their packaging. If I were to add to this project, I would include different heights for each milk quart, and other food products (objects) such as eggs, and yogurt. The concept for this project was the hardest to think of by far,  because I could not find inspiration for a long time during the week.

Initial sketches

Justin Yook – Looking Outwards 10

 

Minicade display

Chloe Varelidi’s Minicade project uses a simple approach to teach people how to make mini games. I think that Minicade is not only an education tool but also serves as an inspiration that can convince other people to branch out further from the web-app and create their own video games. Varelidi’s career started out when she pursued a Master in Fine Art at Parson’s Design and Technology Program. After acquiring the degree, she worked for various video game developer studios as creative director, and senior game designer. Later, she set up her own company called Humans Who Play, a business that encourages doing good with play. Minicade was developed when she was a member of LittleBits.

Sources:

http://www.minica.de/

http://varelidi.com/

Sharon Yang Looking Outwards 10

The project developed by a woman practitioner of the computational arts is Kate Hartman’s Botanicall, first started in 2006, and now in display in Museum of Modern Arts in New York through many iterations. It is still an on-going project with a collaboration with three other artists that are Rob Faludi, Kati London, and Rebecca Bray. Its purpose was to embody a connection between the humans and the nature in both literal and figurative sense. Botanicalls is a networked sensing communication system with which the houseplants is able to make use of the channels of human communication such as telephone calls or Twitter. The conditions and the needs of the plants can be communicated. She and the collaborators developed the Botanicall kit; the first kit was a set of Arduino shields, the second included a custom, leaf-shaped PCB design. I admire the artist’s innovative idea of a device that enables the communication between plants and humans, which is something you would only see in sci-fi books or movies. It is also amazing how she was able to implement it with the technology that is available to her. Other works of Kate Hartman include Lilypad XBee, a sewable radio transceiver that allows your clothing to communicate. She is based in Toronto, OCAD University where she is the Associate Professor of Wearable & Mobile Technology and Director of the Social Body Lab. Her work spans the fields of physical computing, wearable electronics, and conceptual art.


Botanicalls Kit


Phone communication through Botanicall


Botanicall being used on a houseplant

Sources: http://www.katehartman.com/about/

Botanicalls