Jenni Lee — Final Project

sketch

/* Jenni Lee
Section E
jennife5@andrew.cmu.edu
Final Project
*/

var tapirImage = [];
var cloudImage = [];
var clouds = [];
var plantImage = [];
var plants = [];

var numMovingFrame = 2;

function preload() {

  var filenames = [];
  // image location for tapir
  filenames[0] = "https://i.imgur.com/DW5kRkh.png";
  filenames[1] = "https://i.imgur.com/4KccJ7e.png";

  // image location for plants
  filenames[2] = "https://i.imgur.com/CICxu5P.png";
  filenames[3] = "https://i.imgur.com/KObxJ71.png";
  filenames[4] = "https://i.imgur.com/IYuCsVt.png";

  // image location for clouds
  filenames[5] = "https://i.imgur.com/w9ND0YA.png";
  filenames[6] = "https://i.imgur.com/6Ovkd5e.png";
  filenames[7] = "https://i.imgur.com/JH0DqMf.png";


  // PUT CODE HERE TO LOAD THE IMAGES INTO THE frames ARRAY,
  // USING THE FILENAMES STORED IN THE filenames ARRAY.

  for (var i = 0; i < numMovingFrame; i++) {
    tapirImage[i] = loadImage(filenames[i]);
  }

  for (i = 0; i < 3; i++) {
    plantImage[i] = loadImage(filenames[i + 2]);
  }

  for (i = 0; i < 3; i++) {
    cloudImage[i] = loadImage(filenames[i + 5]);
  } 
}

var ibuffer = 120; // buffer space (minimum distance) between two plants for jumping
function setup() {
  createCanvas(1000, 300);
  initiate();
  frameRate(30);
  textFont('Helvetica');
}

var currentTapirImageIndex = 0; // rotating tapir images to simulate tapir movement
var tapirLocationX = 80;
var tapirLocationY = 80;
var upperYJump = 200,
  lowerYJump = 80;
var speed = 3; // jump speed per frame
var jumpSpeed = 3;
var tapirMinHeight = 120;
var jumpStatus = false; // use this to tell if tapir is jumping or not
var tapirInPlantRangeCurr = []; // to record if tapir is in the plant range or not, the current state
var tapirInPlantRangePrev = []; // to record if tapir is in the plant range or not, the previous state
var numPlantsJumped = 0; // count total # of plants tapir jumps over
var isGameOver = false;

function initiate() {

  // create an initial collection of clouds
  for (var i = 0; i < 10; i++) {
    var rx = random(width); // randomly generate clouds at random locations to start with
    clouds[i] = makeCloud(rx);
  }
  // create an initial collection of plants
  for (i = 0; i < 6; i++) { // fixed location for plants, for jumping practice
    plants[i] = makePlant(230 + i * 180);
  }

  tapirLocationY = lowerYJump; // back to original position
  jumpSpeed = 3; // for tapir's jump speed
  jumpStatus = false; // to keep track if tapir is in jumping state or not
  isGameOver = false;
  numPlantsJumped = 0;
  currentTapirImageIndex = 0;
  for (i = 0; i < 10; i++) {
    tapirInPlantRangePrev[i] = false;
    tapirInPlantRangeCurr[i] = false;
  }
}

function draw() {
  background(229, 233, 137);

  noStroke();
  fill(70, 83, 130);
  rect(0, 0, width - 1, height - 51);

  // handling cloud display, the bottom layer of objects
  updateAndDisplayClouds();
  removeCloudsThatHaveSlippedOutOfView();
  addNewCloudsWithSomeRandomProbability();

  // draw terrain, next layer of object
  drawTerrain();

  // handling plants display, next layer of objects
  updateAndDisplayPlants();
  removePlantsThatHaveSlippedOutOfView();
  addNewPlantsWithSomeRandomProbability();

  // check the jumping status and display tapir
  updateTapirStatus();
  checkTapirOverPlant();
  
  // display the status such as # of total plants jumped, score
  displayStatusString();
}

function checkTapirOverPlant() {
  // check if tapir is inside any plant range
  for (var i = 0; i < plants.length; i++) {
    if (plants[i].x <= tapirLocationX + tapirImage[0].width) {
      if (plants[i].x + plantImage[plants[i].nPlantType].width >= tapirLocationX + tapirImage[currentTapirImageIndex].width) {
        tapirInPlantRangePrev[i] = tapirInPlantRangeCurr[i];
        tapirInPlantRangeCurr[i] = true;
        if (tapirLocationY < tapirMinHeight) {
          noStroke();
          fill(0, 0, 0);
          textSize(20);
          text("Game Over. Touch screen, click mouse, or press 'r' to restart.", width / 2 - 230, height / 2);
          isGameOver = true;
          noLoop();
        }
      } else {
        tapirInPlantRangePrev[i] = tapirInPlantRangeCurr[i];
        tapirInPlantRangeCurr[i] = false;
      }
    }
    if (tapirInPlantRangePrev[i] == true & tapirInPlantRangeCurr[i] == false) {
      numPlantsJumped++;
    }
  }
}

function updateTapirStatus() {
  if (jumpStatus == true) {
    tapirLocationY += jumpSpeed;
    if (tapirLocationY >= upperYJump) { // tapir hit top jupming point, change direction
      tapirLocationY = upperYJump;
      jumpSpeed = -1 * speed;
    } else if (tapirLocationY < lowerYJump) {
      tapirLocationY = lowerYJump;
      jumpSpeed = speed;
      jumpStatus = false;
    }
  }
  image(tapirImage[currentTapirImageIndex], tapirLocationX, height - tapirLocationY);

  if (jumpStatus == false) {
    currentTapirImageIndex++;
  }
  currentTapirImageIndex = currentTapirImageIndex % numMovingFrame; // rotating tapir images

}

function keyTyped() {
  if (key == "a") {
    jumpStatus = true;
  } else {
    jumpStatus = false;
  }
  if (key == "r") {
    if (isGameOver == true) {
      initiate();
      loop();
    }
  }
}

function touchStarted() {
  if (isGameOver == true) {
    initiate();
    loop();
  }
  else {
    jumpStatus = true;
  }
}

// define object for plant
function makePlant(birthLocationX) {
  var plant = {
    x: birthLocationX,
    y: height - 40,
    speed: -2.1,
    nPlantType: round(random(0, 2)),
    move: plantMove,
    display: plantDisplay
  }
  return plant;
}

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

function plantDisplay() {
  imageMode(CORNERS);
  image(plantImage[this.nPlantType], this.x, this.y,
    this.x + plantImage[this.nPlantType].width, this.y - plantImage[this.nPlantType].height);
  imageMode(CORNER);

}

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

function removePlantsThatHaveSlippedOutOfView() {
  var plantsToKeep = [];
  for (var i = 0; i < plants.length; i++) {
    if (plants[i].x + plantImage[plants[i].nPlantType].width > 0) {
      plantsToKeep.push(plants[i]);
    }
  }
  plants = plantsToKeep; // remember the surviving plants
}

function addNewPlantsWithSomeRandomProbability() {
  var newPlantLikelihood = 0.05;
  var toAddPlant = true;
  if (random(0, 1) < newPlantLikelihood) {
    var i = plants.length - 1;
    // make sure there is at least ibuffer distance from previous plant before adding a new one from right
    if (plants[i].x + plantImage[plants[i].nPlantType].width + ibuffer < width) {
      plants.push(makePlant(width));
    }
  }
}

// define object for cloud
function makeCloud(birthLocationX) {
  var cld = {
    x: birthLocationX,
    y: round(random(25, 50)),
    speed: -0.6,
    nCloudType: round(random(0, 2)),
    move: cloudMove,
    display: cloudDisplay
  }
  return cld;
}

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

function cloudDisplay() {
  image(cloudImage[this.nCloudType], this.x, this.y);
}

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


function removeCloudsThatHaveSlippedOutOfView() {
  var cloudsToKeep = [];
  for (var i = 0; i < clouds.length; i++) {
    if (clouds[i].x + cloudImage[clouds[i].nCloudType].width > 0) {
      cloudsToKeep.push(clouds[i]);
    }
  }
  clouds = cloudsToKeep; // remember the surviving clouds
}

function addNewCloudsWithSomeRandomProbability() {
  var newCloudLikelihood = 0.004;
  if (random(0, 1) < newCloudLikelihood) {
    clouds.push(makeCloud(width)); // push the new cloud to the clouds array (to the end)
  }
}


function displayStatusString() {
  noStroke();
  fill(0, 200, 0);
  textSize(14);
  text("Touch screen, click mouse, or press 'a' to jump", 5, 20);
  textSize(40);
//  var statusString = "# Plants jumped over = " + numPlantsJumped;
  var statusString = numPlantsJumped;
  text(statusString, width/2, height/2 - 25);
}

function drawTerrain() {
  noFill();
  beginShape();
  var terrainSpeed = 0.00012;
  var terrainDetail = 0.005;

  for (var x = 0; x < width; x++) {
    var t = (x * terrainDetail) + (millis() * terrainSpeed);
    var y = map(noise(t), 0, 1, 0, height - 40);
    stroke(216, 158, 172);
    line(x, y, x, height - 50);
  }
  endShape();
}

For this project, I wanted to create a game of a tapir that jumps over flowers. Tapirs are my favorite animal, so I wanted to use that. I drew all pictures, clouds, tapir, and plants, on Adobe Illustrator to load them at preLoad time for various effects, and use image() function to display them all at specified locations when they are inside canvas range. I drew 3 types of clouds, and design/define a cloud object to record and keep track of the cloud type/shape (randomly selected), location (x and y), and movement speed. Mountain/terrain: I used noise() function to draw vertical line from a variable y location to the ground to simulate mountain. I drew two frames of tapir to simulate its running. When loading different frames at consecutive frames, it would seem tapir is running. Overall, this project was really fun.

Jenni Lee – Project 12 – Final Project Proposal

For my final project, I plan on using a moving landscape as a base for an animal jumping game. The the ground will be moving, and on the ground there will be posts. Everytime the page refreshes, an animal will appear on the left, and it will begin to run. When the space bar is pressed, the animal will jump, dodging the posts which will result in the animal dying upon touch. I plan to implement elements of sound, such as a sound when the space bar is pressed and a sound when the animal dies. The number of posts that the animal successfully jumps over will be displayed on the top corner. I plan to display the words “you have lost” once the animal dies. The objective of the game is to gather as many points as possible.

Jenni Lee—Looking Outwards 12

“All Aboard the Sonic Train”

The first project that I will draw inspiration from is “All Aboard the Sonic Train” by Phil Giarrusso. Phil Giarrusso is a designer, illustrator, and animator specializing in pixel art and game development. Inspired by a beloved childhood video game, Sonic the Hedgehog, Phil Giarruso recreates a scene from the game through motion graphics using a pixeled aesthetic. Because my project will involve a character running and jumping across a moving landscape, I was inspired by the aesthetic of this project. In addition, I enjoyed the colorful, bright colors in this gif, and I plan on drawing inspiration form this color palette and using it in my project.

Click here to view more of Giarrusso’s work

“Flat Design Dragon for Games”

The second project that I will draw inspiration from is “Flat Design Dragon for Games” by a design company called “Gigantic” which specializes in flat design illustration and 2D animation. Similar to the project above, I was inspired by not only the color palette and gameplay aesthetic, but I liked the usage of various layers within the piece. I plan on incorporating various layers and colors in order to create depth in my project.

Click here to view more of Gigantic’s work

Jenni Lee—Project 11—Composition

sketch

/* Jenni Lee
Section E
jennife5@andrew.cmu.edu
Project-11
*/

var iLine1
var le, to, ri, bo;
var w, h;

function setup() {
  createCanvas(640, 480);
  background(250);

  iLine1 = makeTurtle(0, 0); // starting position of figure 2.  leave 3 pixel for the first stroke (weight is 6)
  iLine1.setWeight(1);

  frameRate(15);

  le = 0;
  to = 0;
  ri = width;
  bo = height;
  w = width;
  h = height;
}

var i1 = 0,
  i2 = 0,
  i3 = 0,
  i4 = 0;
var inc = 10;


function draw() {
  var r = random(0, 255);
  var g = random(0, 255);
  var b = random(0, 255);
  iLine1.setColor(color(r, g, b));

  // first to draw the top part of the lines sequentially.  Use incremented line count for checking
  if (i1 <= w) {
    // equally divide the height into grids
    var y = lerp(to, bo, i1 / w);
    iLine1.goto(ri, y); // draw line
    i1 += inc;

    // go back to the top position
    iLine1.penUp();
    iLine1.goto(i1, to);
    iLine1.penDown();
  } else {
    // when top part finish, sequentially draw the right part, same way, with diffetenr coordinates
    if (i2 <= w) {
      var y = lerp(le, ri, i2 / h);
      iLine1.goto(ri - y, bo);
      i2 += inc;
      iLine1.penUp();
      iLine1.goto(ri, i2);
      iLine1.penDown();
    } else {
				// when top and right parts finish, sequentially draw the bottom part, same way, with diffetenr coordinates
        if (i3 <= w) {
        var y = lerp(to, bo, i3 / w);
        iLine1.goto(le, bo - y);
        i3 += inc;
        iLine1.penUp();
        iLine1.goto(ri - i3, bo);
        iLine1.penDown();
      } else {
				// when top, right, and bottom parts finish, sequentially draw the left part, same way, with diffetenr coordinates
        if (i4 <= w) {
          var y = lerp(le, ri, i4 / h);
          iLine1.goto(y, to);
          i4 += inc;
          iLine1.penUp();
          iLine1.goto(le, bo - i4);
          iLine1.penDown();
        } else {
          // when all parts are done, reset by resetting background, and counters
          background(255);
          i1 = 0;
          i2 = 0;
          i3 = 0;
          i4 = 0;
        }
      }
    }
  }
}

function turtleLeft(d) {
  this.angle -= d;
}


function turtleRight(d) {
  this.angle += d;
}


function turtleForward(p) {
  var rad = radians(this.angle);
  var newx = this.x + cos(rad) * p;
  var newy = this.y + sin(rad) * p;
  this.goto(newx, newy);
}


function turtleBack(p) {
  this.forward(-p);
}


function turtlePenDown() {
  this.penIsDown = true;
}


function turtlePenUp() {
  this.penIsDown = false;
}


function turtleGoTo(x, y) {
  if (this.penIsDown) {
    stroke(this.color);
    strokeWeight(this.weight);
    line(this.x, this.y, x, y);
  }
  this.x = x;
  this.y = y;
}


function turtleDistTo(x, y) {
  return sqrt(sq(this.x - x) + sq(this.y - y));
}


function turtleAngleTo(x, y) {
  var absAngle = degrees(atan2(y - this.y, x - this.x));
  var angle = ((absAngle - this.angle) + 360) % 360.0;
  return angle;
}


function turtleTurnToward(x, y, d) {
  var angle = this.angleTo(x, y);
  if (angle < 180) {
    this.angle += d;
  } else {
    this.angle -= d;
  }
}


function turtleSetColor(c) {
  this.color = c;
}


function turtleSetWeight(w) {
  this.weight = w;
}


function turtleFace(angle) {
  this.angle = angle;
}


function makeTurtle(tx, ty) {
  var turtle = {
    x: tx,
    y: ty,
    angle: 0.0,
    penIsDown: true,
    color: color(128),
    weight: 1,
    left: turtleLeft,
    right: turtleRight,
    forward: turtleForward,
    back: turtleBack,
    penDown: turtlePenDown,
    penUp: turtlePenUp,
    goto: turtleGoTo,
    angleto: turtleAngleTo,
    turnToward: turtleTurnToward,
    distanceTo: turtleDistTo,
    angleTo: turtleAngleTo,
    setColor: turtleSetColor,
    setWeight: turtleSetWeight,
    face: turtleFace
  };
  return turtle;
}

For this project, I wanted to experiment with using the turtle function in order to use simple lines to create illusions. I found that using rainbow colors gave the piece a glitchy, fun, and playful feel.

Jenni Lee—Looking Outwards—11

For this week’s looking outwards, I chose to discuss Imogen Heap’s Mi.Mu gloves, a tool that gives musicians maximum freedom to improvise and allows simple movements to sculpt music. Mi.Mu Gloves are wireless, sensor-enabled gloves for creating and performing music through movement and gesture. The gloves are a fusion of textiles and electronic sensors. Combined with dedicated gesture detection and mapping software, the gloves offer a new and flexible approach to the control of music and visuals with intuitive human movement. When a hand makes a particular gesture/motion or when you activate a particular button on the glove, the Mi.Mu gloves alter the voice. I found this new tool to be innovative and creatively stimulating, as it pushes the boundaries of music and intertwines technology with music. I believe that these Mi.Mu gloves are a great example of advancing technology for creative/artistic purposes.

click here to read more about mi.mu gloves

Jenni Lee—Looking Outwards—10

For this week’s looking outwards, I chose the artist Roz Dimon. Roz Dimon is a digital artist based in New York city. She studied in Italy and moved to New York in the early 80’s to begin working and training in digital media. She has been invited to teach various pioneering courses in digital art at various art universities. She enjoys mixing fine art with corporate design and communications. The work I chose of hers is a digital art series titled “Guns” in which she creates abstract, digital illustrations of guns consisted of mark-making and calligraphy. She states that the symbol of guns have been reoccuring throghout her pieces, and that this motif examines gun violence in America. I was particularly drawn to this not only because of the elegant and engaging visuals of the digital art, but I also felt that this subject matter was very relevant to current events, especially in light of recent events in Pittsburgh.

View the rest of the “guns” series here here

Jenni Lee—Project 10—Landscape

sketch

/* Jenni Lee
Section E
jennife5@andrew.cmu.edu
jennife5-project-10
*/

var houses = [];

function setup() {
  createCanvas(640, 240);

  // create an initial collection of buildings
  for (var i = 0; i < 10; i++) {
    var rx = random(width);
    houses[i] = makeHouse(rx);
  }
  frameRate(10);
}


function draw() {
  background(237, 190, 150);
  
  noStroke ();
  fill (255, 217, 161);
  rect (0, 0, width - 1, height - 51);

  drawTerrain();

  displayStatusString();
  displayHorizon();

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


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


function removeHousesThatHaveSlippedOutOfView() {
  // If a house 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 houses
  // 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 housesToKeep = [];
  for (var i = 0; i < houses.length; i++) {
    if (houses[i].x + houses[i].breadth > 0) {
      housesToKeep.push(houses[i]);
    }
  }
  houses = housesToKeep; // remember the surviving houses
}


function addNewHousesWithSomeRandomProbability() {
  // With a very tiny probability, add a new house to the end.
  var newHouseLikelihood = 0.003;
  if (random(0, 1) < newHouseLikelihood) {
    houses.push(makeHouse(width));
  }
}


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


// draw the building and some windows
function houseDisplay() {
  var floorHeight = 30;
  var bHeight;
  if (this.nFloors == 1) {
    bHeight = 30;
  } else {
    bHeight = 50;
  }
  fill(255);
  noStroke();
  push();
  translate(this.x, height - 40);
  if (this.nHouseColor == 1) {
  	fill(128, 0, 0);
  }
  else {
  	noStroke();
    fill (252, 235, 180);
  }
  rect(0, -bHeight, this.breadth, bHeight);
  
  // door
  noStroke();
  
  if (this.nDoorColor == 1) {
  	fill(0, 128, 0);
  }
  else {
  	fill(204, 204, 0);
  }
  rect(5, -20, this.breadth - 35, 20);
  // door knob
  stroke(0);
  strokeWeight(3);
  point(10, -10);

  // window

  stroke(0);
  strokeWeight(1);
  fill(200);
  rect(this.breadth - 20, -25, 15, 10);
  line(this.breadth - 20, -20, this.breadth - 5, -20);
  line(this.breadth - 12.5, -15, this.breadth - 12.5, -25);
  if (this.nFloors == 2) {
    line(0, -30, this.breadth, -30);
    rect(this.breadth - 30, -45, 15, 10);

    line(this.breadth - 30, -40, this.breadth - 15, -40);
    line(this.breadth - 22.5, -45, this.breadth - 22.5, -35);
  }
  fill(35);
  triangle(-10, -bHeight, this.breadth + 10, -bHeight, this.breadth / 2, -bHeight - 20);
  pop();
}


function makeHouse(birthLocationX) {
  var hse = {
    x: birthLocationX,
    breadth: 50,
    speed: -1.0,
    nFloors: round(random(1, 2)),
    nHouseColor: round(random(1, 2)), 
    nDoorColor: round(random(1, 2)),
    move: houseMove,
    display: houseDisplay
  }
  return hse;
}


function displayHorizon() {
  stroke(0);
  line(0, height - 50, width, height - 50);
}


function displayStatusString() {
  noStroke();
  fill(0);
  var statusString = "# Houses = " + houses.length;
  text(statusString, 5, 20);
}

// Simple demonstration of the noise() function. 
// Change these for different effects:
var terrainSpeed = 0.00005;
var terrainDetail = 0.005;

function drawTerrain() {
  noFill(); 
  beginShape();
  for (var x = 0; x < width; x++) {
    var t = (x * terrainDetail) + (millis() * terrainSpeed);
    var y = map(noise(t), 0, 1, 0, height - 40);
    stroke (196, 176, 146);
    line (x, y, x, height - 50);
//    vertex(x, y);
  }
  endShape();

  noStroke ();
  rect(0, 0, width - 1, height - 1);
}

For this project, I was inspired by the movie Inception. There was a scene in the movie in which the characters are in a dream and they walk around a eerie environment with various houses. I used a warm color scheme to give it a dilapidated, desert-like feeling.

Here is one of my preliminary digital concept sketches drawn on my ipad in which I tested out forms and colors.

Jenni Lee — Looking Outwards — 09

For this week’s looking outwards, I chose to analyze my classmate Elena Deng’s post about the disney movie, Frozen. She chose to analyze a video which described the process of creating life-like snow in the movie. The animators explain that they used a method where they created very small particles of snow and assign them a random volume and size. After factoring velocities as well as collision variables for each of those particles, the grain of snow is then able to move. I found this to be particularly interesting, as I am a designer who has interest in motion graphics and animation, and seeing the behind-the-scenes making of this animation was very inspiring and creatively stimulating. The methods used in this project very applicable to a blend of interests in both physical products and also animation.

Jenni Lee — Project 09 — Portrait

sketch

/* Jenni Lee
Section E
jennife5@andrew.cmu.edu
Project - 09
*/

var underlyingImage;

function preload() {
  var myImageURL = "https://i.imgur.com/VBTpoj5.jpg"; // i uploaded my own photo to http://i.imgur.com and get this link
  underlyingImage = loadImage(myImageURL);
}

function setup() {
  createCanvas(720, 480);
  background(0);
  underlyingImage.loadPixels();
  frameRate(2000); // make frame rate high to updare the image faster
}

// this function/routine is to get the pixel value of (x, y)
function getPixel(image, x, y) {
  var pix = 4 * (y * image.width + x);
  return color(image.pixels[pix], image.pixels[pix + 1], image.pixels[pix + 2]);
}

var iClickCurrent = 0,
  iCurrentEffect = 0,
  iPrevEffect = 0;

function draw() {
  if (iClickCurrent == 0) {
    drawGraduallyUsingEffects();
  } else { // display the final result at once instead of waiting for gradual update
    drawAtOnceUsingEffects();
  }
}

function drawGraduallyUsingEffects() {
  var px = random(width); // get a random x position
  var py = random(height); // get a random y position
  var ix = constrain(floor(px), 0, width - 1); // constrain it within canvas
  var iy = constrain(floor(py), 0, height - 1); // constrain it within canvas
  var theColorAtLocationXY = getPixel(underlyingImage, ix, iy);

  if (iCurrentEffect == 0) {
    fill(theColorAtLocationXY);
    text("i am jenni", ix, iy); // using text to update the image
  } else if (iCurrentEffect == 1) {
    noStroke();
    fill(theColorAtLocationXY);
    ellipse(ix, iy, 10, 10); // using circle
  } else if (iCurrentEffect == 2) {
    noStroke();
    fill(theColorAtLocationXY); 
    rect(ix, iy, 10, 10); // using rect
  }
}

function drawAtOnceUsingEffects() {
  var i = 0;
  // noprotect
  for (var iy = 0; iy < underlyingImage.height; iy += 5) {
    for (var ix = 0; ix < underlyingImage.width; ix += 5) {
      var theColorAtLocationXY = getPixel(underlyingImage, ix, iy); // get the color of the current pixel and drive an effect
      if (iCurrentEffect == 0) {
        fill(theColorAtLocationXY);
        text("i am jenni", ix, iy);
      } else if (iCurrentEffect == 1) {
        noStroke();
        fill(theColorAtLocationXY);
        ellipse(ix, iy, 10, 10);
      } else if (iCurrentEffect == 2) {
        noStroke();
        fill(theColorAtLocationXY);
        rect(ix, iy, 10, 10);
      }
    }
  }
}

function mousePressed() {
  iClickCurrent = (iClickCurrent + 1) % 2;
  if (iClickCurrent == 0) {
    while (iCurrentEffect == iPrevEffect) { // make sure the effect doesn't repeat
      iCurrentEffect = floor(random(0, 3)); // get random selection of effect
    }
    iPrevEffect = iCurrentEffect;
    loop ();
  }
  else {
    noLoop ();
  }
  background(0);
}

For this portrait project, I applied 3 effects onto a photo of myself from when I was in elementary school. The 3 effects I used were squares, ellipses, and the phrase “I am Jenni.” It was fun to choose a photo and customize the effects.

Jenni Lee — Looking Outwards — 08

Eyeo 2018 – Giorgia Lupi from Eyeo Festival on Vimeo.

The artist I chose for this week’s looking outwards is Giorgia Lupi. She is an information designer who designs engaging visual narratives in a humanistic way that re-connects numbers with stories, people, and ideas. She creates work that emphasizes the notion that data can not only describe the objective world, but can also illustrate aspects of human life, which are not commonly associated with numbers. I was particularly drawn to her work, as she uses design methodologies, particularly user empathy and designing for emotion, in order to transform quantitative analysis into beautiful, playful moments of emotion, humanity, poetry, and art. She does so by creating work through very hand-drawn, analog, and raw forms, which strongly appeal to me. As someone who is interested in user experience, information design, and design methodologies, this lecture allowed me to view information design and data from a different perspective– one that is empathetic and humanistic rather than purely quantitative. From this lecture, my main takeaway was that we can inspire empathy through data, data is the eye of the beholder, data is never the point but always a medium we have to abstract, data can unite us, and ultimately, that data has the potential to transform the uncountable into something that can be reconnected to our lives and to our behaviors.

Lupi’s project titled “Bruises — the Data We Don’t See” initially drew me in through its aesthetics and color palette. At first, the image’s pastel colors and floral texture make it appear as a cherry blossom illustration. However, as I began to read the artist statement, I realized that they were not flower petals, but platelet counts, showing the amount of petechiae. This project highlighted how clinical records alone can hardly capture the impact the illness of a child has on a family. This project was moving to me, as it demonstrates how data visualization can evoke empathy and activate us on not only a cognitive level, but also an emotional level.

Giorgia lupi’s website