hqq – rsp1 – final_project – sections _ e+b

PSA: THIS IS A TWO-PART ENDEAVOR, SO BE SURE TO SCROLL DOWN FOR PART 2!

Hi guys! This is a game we made called “Carl Cooks a Meal” that exists in two parts. Under the premise, our friend Carl is trying to make a lovely meal for his girlfriend Carla. However, he has absolutely no idea how to start! The first part is a clickventure where people help Carl gather ingredients. People have the option to either check in the refrigerator to see what’s inside OR take a trip to a distant country to get some more exotic ingredients. In travelling, users can learn about the histories behind these ingredients, adding an educational aspect to this part. Users can then return home to begin the second part. In the second part, people help Carl “cook” the meal. This is in the form of a game where users have to catch these ingredients in a pan to reach the final score. However, after each time an ingredient is caught in the pan, they begin to fall faster, making it more difficult as time passes. Once thirty ingredients have been caught, the meal is done, and Carla is very happy! Thanks for helping Carl make the meal!

part 1

/*15-104 final projec
team members: rachel park (rsp1) and hamza qureshi (hqq)
section: b; e


CARL COOKS A MEAL*/

var button1, button2, button3, button4, button5; //these variables create buttons, which are defined
                                                //locally to avoid having to create dozens of em
var home, meetCarl, where2go, worldMap, fridge, //these variables will hold the images that form each slide
    turmeric, miso, acai, foieGras, uSure,
    startup;
var col;                                       //sets color
//---------------------------------------------------
function setup() {
    createCanvas(480,480);
    background(0);
    noLoop();                                //allows the slides to remain static (prevents flickering!)
}
//---------------------------------------------------
function draw() { //will only comment once in detail because it can get redundant
  home = createImg("https://i.imgur.com/aI9WG89.jpg"); //creates slide
  home.position(-760,-760); //position and scales are used to fit the images on the canvas
  home.style("transform", "scale(0.25)");
  button1 = createButton('Play Game!'); //creates a button
  button1.position(300,200);
  col = color(129,178,154);
  button1.style("background-color", col);
  button1.style("color", "white");
  button1.mousePressed(PromptPage); //allows the button to load the next screen
}
//---------------------------------------------------

//functions for each page

function PromptPage() {
  //prompts with info on what to do
    meetCarl = createImg("https://i.imgur.com/HAX6uEa.jpg");
    meetCarl.position(-760, -760);
    meetCarl.style("transform", "scale(0.25)");
    button1 = createButton('Help me out →');
    col = color(129,178,154);
    button1.style("background-color", col);
    button1.style("color", "white");
    button1.position(350,200);
    button1.mousePressed(ScenePage);
}
//---------------------------------------------------
function ScenePage() {
  //loads scene where users have option of gathering ingredients
    where2go = createImg("https://i.imgur.com/7F5M1iF.jpg");
    where2go.position(-760,-760);
    where2go.style("transform", "scale(0.25)");
    button1 = createButton('Open the fridge');
    col = color(129,178,154);
    button1.style("background-color", col);
    button1.style("color", "white");
    button1.position(20,220);
    button1.mousePressed(FridgeFoodPage);
    button2 = createButton('Take a trip');
    col = color(129,178,154);
    button2.style("background-color", col);
    button2.style("color", "white");
    button2.position(140,460);
    button2.mousePressed(WorldFoodPage);
    button3 = createButton('Time to cook!');
    col = color(129,178,154);
    button3.style("background-color", col);
    button3.style("color", "white");
    button3.position(300,180);
    button3.mousePressed(gameLandingPage);
}
//---------------------------------------------------
function WorldFoodPage() {
  //loads international map screen, with buttons for diff locations
    worldMap = createImg("https://i.imgur.com/aNsxfi1.jpg");
    worldMap.position(-760,-760);
    worldMap.style("transform", "scale(0.25)");
    button1 = createButton('Brazil');
    button1.style("background-color", col);
    button1.style("color", "white");
    button1.position(130,230);
    button1.mousePressed(brazil);
    button2 = createButton('France');
    button2.style("background-color", col);
    button2.style("color", "white");
    button2.position(150,80);
    button2.mousePressed(france);
    button3 = createButton('India');
    button3.style("background-color", col);
    button3.style("color", "white");
    button3.position(320,160);
    button3.mousePressed(india);
    button4 = createButton('Japan');
    button4.style("background-color", col);
    button4.style("color", "white");
    button4.position(420,120);
    button4.mousePressed(japan);
    button5 = createButton('Go back home!');
    button5.style("background-color", col);
    button5.style("color", "white");
    button5.position(190,450);
    button5.mousePressed(ScenePage);
}
//---------------------------------------------------
function FridgeFoodPage() {
  //loads fridge screen with items available in the fridge
    fridge = createImg("https://i.imgur.com/jPanqPC.jpg");
    fridge.position(-760,-760);
    fridge.style("transform", "scale(0.25)");
    button1 = createButton('Grab the items!');
    col = color(129,178,154);
    button1.style("background-color", col);
    button1.style("color", "white");
    button1.position(320,220);
    button1.mousePressed(FridgeGrab);
    button2 = createButton('No thanks!');
    col = color(129,178,154);
    button2.style("background-color", col);
    button2.style("color", "white");
    button2.position(320,260);
    button2.mousePressed(ScenePage);
}
//---------------------------------------------------
function FridgeGrab(){
  //simulates "grabbing" items from the fridge
    fridge = createImg("https://i.imgur.com/zlj1DaE.jpg");
    fridge.position(-760,-760);
    fridge.style("transform", "scale(0.25)");
    button1 = createButton('Back to the kitchen!');
    col = color(129,178,154);
    button1.style("background-color", col);
    button1.style("color", "white");
    button1.position(320,220);
    button1.mousePressed(ScenePage);
}
//---------------------------------------------------
function india() {
  //loads turmeric screen
    turmeric = createImg("https://i.imgur.com/tj04pYa.jpg")
    turmeric.position(-760,-760);
    turmeric.style("transform", "scale(0.25)");
    countryButtons();
}
//---------------------------------------------------
function japan(){
  //loads miso screen
    miso = createImg("https://i.imgur.com/A0mow9a.jpg")
    miso.position(-760,-760);
    miso.style("transform", "scale(0.25)");
    countryButtons();
}
//---------------------------------------------------
function france(){
  //loads france screen
    foieGras = createImg("https://i.imgur.com/4OLHPzQ.jpg")
    foieGras.position(-760,-760);
    foieGras.style("transform", "scale(0.25)");
    countryButtons();
}
//---------------------------------------------------
function brazil(){
  //loads brazil screen
    acai = createImg("https://i.imgur.com/H4gDOUD.jpg")
    acai.position(-760,-760);
    acai.style("transform", "scale(0.25)");
    countryButtons();
}
//---------------------------------------------------
function countryButtons(){
  //creates two sets of buttons on country screen to
  //allow for less code to be used in each of the country slides.
    button1 = createButton('Take home!');
    button1.style("transform", "scale(0.8)");
    button1.style("background-color", col);
    button1.style("color", "white");
    button1.position(170,310);
    button1.mousePressed(WorldFoodPage);
    button2 = createButton('All done!');
    button2.style("transform", "scale(0.8)");
    button2.style("background-color", col);
    button2.style("color", "white");
    button2.position(178, 370);
    button2.mousePressed(gameLandingPage);
}
//---------------------------------------------------
function gameLandingPage(){
  //makes sure the user is ready (lol)
    uSure = createImg("https://i.imgur.com/9RFTHko.jpg");
    uSure.position(-760,-760);
    uSure.style("transform", "scale(0.25)");
    button1 = createButton('Yes, I am ready!');
    button1.style("background-color", col);
    button1.style("color", "white");
    button1.position(190,250);
    button1.mousePressed(gameStartScreen);
    button2 = createButton('No, not yet!');
    button2.style("background-color", col);
    button2.style("color", "white");
    button2.position(200, 300);
    button2.mousePressed(ScenePage);
}
//---------------------------------------------------
function gameStartScreen(){
  //loads final screen of this part, instructing users to scroll
    startup = createImg("https://i.imgur.com/duuVdOZ.jpg");
    startup.position(-760,-760);
    startup.style("transform", "scale(0.25)");
}
//---------------------------------------------------

part 2

/*15-104 final project
team members: rachel park (rsp1) and hamza qureshi (hqq)
section: b; e


CARL COOKS A MEAL*/

//setting global variables to use throughout the code

//for score
var score = 0;
//for falling objects
var speed = 10;
var canHit = true;
var x = 0;
var y = 0;
var s = 5;
//for key functions
var keyRIGHT= false;
var keyLEFT= false;
var moveRight = false;
var moveLeft = false;
//for frypan options
var onBasket = false;
//setting modes to use to run the functions
var beforeGame;
var endGame;
var beginning;
var ending;
//for arrays used in code
var fridge = [];
var ixs = [50,-50,350];
var iys = [-500, 0, -1000];
//to load frypan image
var frypan;
//---------------------------------------------------

//preloading images of foods and pushing into new array
function preload() {
    var Foods = [
      "https://i.imgur.com/WrAqBJF.png",
      "https://i.imgur.com/F6VoqQ8.png",
      "https://i.imgur.com/6Piz1HF.png",
      "https://i.imgur.com/Qltr0uK.png"];
    for (var i = 0; i < Foods.length; i++){
      fridge.push(loadImage(Foods[i]));
    }
}
//---------------------------------------------------
//setting up canvas and using modes
function setup () {
  createCanvas(480, 480);
  background(129,178,154);
  beforeGame = true;
  endGame = false;
  frypan = loadImage("https://i.imgur.com/UdaokKr.png");
  ending = loadImage("https://i.imgur.com/0EdDOXJ.jpg");
  beginning = loadImage("https://i.imgur.com/crhULDP.jpg");
}
//---------------------------------------------------
//function to start game when any key is pressed
function keyPressed() {
    beforeGame = false;
}
//---------------------------------------------------
//function to make frypan move as a gathering platform
function keyTyped() {
   if (keyCode === LEFT_ARROW) {
      keyLEFT = true;
   } else if (keyCode === RIGHT_ARROW) {
      keyRIGHT = true;
     }
}
//---------------------------------------------------
//drawing the game by calling the other functions which make the visuals of the objects
function draw() {
    if (beforeGame == true) {
      push();
      scale(0.24);
      imageMode(CORNER);
      image(beginning,0,0);
      pop();
    } else {
      background(129,178,154);
      BasketDraw();//drawing the frypan
      foodDraw();//drawing the falling food objects
      update();//updating the so that frypan moves with keys and food continuously falls onto canvas
      displayScore();//displaying number of foods caught
    }
  if (endGame == true) {//displaying ending page when game is finished
    push();
    scale(0.24);
    imageMode(CORNER);
    image(ending,0,0);
    pop();
  }
}
//---------------------------------------------------
function reachBottom() {//ending the game when food hits limit
    endGame = true;
}
//---------------------------------------------------
function displayScore() {//function to create the score
  fill(0);
  textSize(20);
  text(("Score: " + this.score + " out of 30!"), 80, 23);
}

//--------------------------------------------------

function makeFood(length, xpos, ypos, space) {//class to draw the food objects

  var food = {"l": length, "ix": xpos, "iy": ypos, "s": space}
  food.draw = foodDraw;
  return food;
}

//--------------------------------------------------

function foodDraw() {//drawing the foods

    for (var i = 0; i < ixs.length; i++){
    imageMode(CORNER);
    canHit = true;
    fill(255);
    stroke(4);
      image(fridge[i], this.ixs[i], this.iys[i]);
    }
    for (var i = 0; i < iys.length; i++) {

      this.iys[i] += this.s/2
    }

}

//---------------------------------------------------
function makeBasket(xpos,ypos,moveBasket) {//class to make the frypan (aka basket)
  var Basket = {"x": xpos, "y": ypos}
  Basket.draw = BasketDraw;
  return Basket;
}
//---------------------------------------------------
function BasketDraw() {//drawing the basket
  noStroke();
  fill("#FFD581");
  image(frypan,this.x, this.y + height-50);
}
//---------------------------------------------------
function update() {//function to update the objects and have them restart at top to be continuously moving
  //for basket
  if(keyIsDown(RIGHT_ARROW) & this.x < width-20){
     this.x += speed;
     print(x);
   }
 if (keyIsDown(LEFT_ARROW) & this.x > -20){
     this.x -= speed;
     print(x);
  }
  print(width)
//for food
  for(var i = 0; i < iys.length; i++){
    if (this.iys[i] >= height-80) {
      if(this.ixs[i] >  this.x - 100 & this.ixs[i] < this.x + 100) {
         this.score++;
         this.s ++;
         if( this.score == 30) {
           reachBottom();
         }
      }
      this.iys[i] = random(-1000, -300);
      this.ixs[i] = random(-300 ,width-40);
    }
  }
}
//---------------------------------------------------

As one might expect with almost 400 lines of code, there were a couple of roadblocks on the way. The biggest one was probably the marrying of the two parts to create one code, which we weren’t able to do. This is primarily because the first part uses the DOC library via buttons and commands like createImg, while the second part relies solely on p5. This caused difficulties in combining the two sets of code because they required a change in the HTML template to allow them to be combined. Once we were able to, the code wasn’t running as smoothly as we had intended. However, despite dividing them into these two parts, we were able to successfully create a unified game experience that uses two modes to reach a greater goal. For us, that’s a win! 🙂

hqq – LookingOutwards – 12

For our project, Rachel and I are working off of two inspirations. The first is a choose-your-own-adventure game created by a group of five students at MIT that allowed players to create alternate endings to the storyline of the Hunger Games. This is helpful to our process because it uses sound effects and animations that could be relevant to our process. Additionally, it was created by a student team that points towards a supremely beneficial exploration of various features or tactics.

^The original Tetris from 1984 by Alexey Pajitnov

Our other inspiration is rather well-known. One of the first “falling block” games ever created, Tetris has become one of the most distinguishable video games ever created. In an interview for the Guardian, Pajitnov wrote:

“Next I put together the procedures for manipulating the pieces: pick a tile, flip it, rotate it. But the playfield filled up in 20 seconds flat. Also, once you’d filled a line, it was kind of dead, so why keep it on the screen? So I made each full line disappear, which was key. I was a pretty good programmer and it took me about three weeks to get something controllable on screen. I pretended I was debugging my program, but in truth I just couldn’t stop playing it. When other people tried it, they couldn’t, either. It was so abstract – that was its great quality. It appealed to everybody.”

Our stacking game uses slightly different principles, but Tetris paved the way for determining issues of velocity, instance, and randomness, all of which will be extremely relevant to our final project.

hqq – secE – project12 – proposal

Project Name: Carl Makes a Meal (tentative);

Project Partner: Rachel Park (rsp1);

Project Manifesto: “For our project, we are creating a two-part immersive experience that’s part-“choose your own adventure” and part-Pong game. The premise brings back an earlier character Hamza created in the early days of the class, Carl, whose goal is to make a nice, home-cooked meal for his girlfriend Carla. But, it has to be perfect. In a choose-your-own-adventure game, you’ll have the option to check the fridge for ingredients, or travel to a new country to pick some more rare ingredients. There’ll also be information on these pages about these ingredients. We’ll create these pages on Illustrator and use a series of key presses to activate each ones. (see diagram below).

Players will “cook” the meal through a stacking game where they use a plate to catch the ingredients to make the “perfect” meal (see below). Once the stack reaches a certain height, the game ends with an image of the final meal in its finest presentation.

hqq – LookingOutwards10 – sputniko!

Hi guys! This week, I’m profiling one of my favorite new media artists, Sputniko!. I met Sputniko! [sic] when I visited the MIT Media Lab where she is an instructor

a few years ago and learned a lot about her work as an artist working in a field dominated by men. Much of her work posits questions about these double standards. One of my favorite works of hers is a music video she created called Menstruation Machine.

^The music video project which combines computational story development with reproductive and trans-rights.

The music video tells the story of Takashi, a trans woman who, before undergoing transition, explores the idea of a post-transition lifestyle through understanding menstruation. She creates a “menstruation machine” to experience these. Though controversial, Sputniko! explored this issue while it was still uncomfortable for many to talk about while using people’s comments as an expose on how people react to such issues.

She uses computational effects throughout this video, and it succeeds in making a machinic flow throughout the video while creating a story that successfully does the same thing.

hqq – secE – project 10 – generative landscape

hamza

//hamza qureshi
//hqq@cmu.edu
//section e
//project 10: generative landscapes

var bird = []; //new index to draw image of bird
var frame = 0; //frames
var aspeed = 0.0005; //speeds for various cloud layers
var bspeed = 0.0007;
var cspeed = 0.0009;
var dspeed = 0.00099;
var change = 0.007;
var bchange = 0.009;
var cchange = 0.006;
var dchange = 0.005;

function preload(){
    var birdframes = []; //each frame of bird image
    birdframes[0] = "https://i.imgur.com/bQsrqmu.png"
    birdframes[1] = "https://i.imgur.com/K5dXjwK.png"
    birdframes[2] = "https://i.imgur.com/kK4kW4t.png"
    birdframes[3] = "https://i.imgur.com/K5dXjwK.png"

    for (var i = 0; i < birdframes.length; i++){
        bird.push(loadImage(birdframes[i])); //push bird frames into array
    }
}

function setup(){
    createCanvas(480,480);
    frameRate(10);
}

function draw(){
    background(220,240,225);

    noStroke(); //shades of the sky
    fill(230, 240, 225);
    rect(0,width/5,width,height);
    fill(240,240, 200);
    rect(0, width/4, width, height);
    fill(250,241,185);
    rect(0,width/3,width,height);
    fill(255,208,121); //sun
    ellipse(width/2,height/2,200,200);

    backclouds(); //functions for the cloud layers
    backmiddle();
    frontmiddle();
    frontclouds();

//bird 1
    push();
    scale(0.4);
    image(bird[frameCount%4], 800, 100);
    frame += 1;
    if (frame > bird.length){
        frame = 0;
    }
    pop();

//bird 2
    push();
    scale(0.1);
    image(bird[frameCount%4],1400, 1400);
    frame += 1;
    if (frame > bird.length){
        frame = 0;
    }
    pop();

//bird 3
    push();
    scale(0.2);
    image(bird[frameCount%4], 1000, 1000);
    frame += 1;
    if (frame > bird.length){
        frame = 0;
    }
    pop();

    //airplane wing
    push();
    noStroke();
    fill(255,150,150);
    triangle(360,200,420,240,370,160);
    fill(248);
    triangle(480,480,360,200,480,280);
    fill(254);
    triangle(360,200,480,280,480,210);

    //airplane window
    stroke(245);
    strokeWeight(70);
    noFill();
    rect(0,0,width,height,75,75);
    pop();

}

function backclouds(){ //back row of clouds
    push();
    noStroke();
    beginShape();
    fill(219,241,252);
    for (var x = 0; x < width; x++){
        var k = (x*change) + (millis()*aspeed);
        var y = map(noise(k), 0,1, 190, height/2); //noise remaps change vs speed
        vertex(0, height); //to draw high and low-points in the shape
        vertex(width, height);
        vertex(x,y)
    }
    endShape();
    pop();
}

function backmiddle(){ //repeated for middle
    push();
    noStroke();
    beginShape();
    fill(229,241,252);
    for (var x = 0; x < width; x++){
        var k = (x*bchange) + (millis()*bspeed);
        var y = map(noise(k), 0,1, 260, height/2);
        vertex(0, height);
        vertex(width, height);
        vertex(x,y)
    }
    endShape();
    pop();
}

function frontmiddle(){
    push();
    noStroke();
    beginShape();
    fill(239,241,252);
    for (var x = 0; x < width; x++){
        var k = (x*cchange) + (millis()*cspeed);
        var y = map(noise(k), 0,1, 320, height/2);
        vertex(0, height);
        vertex(width, height);
        vertex(x,y)
    }
    endShape();
    pop();
}

function frontclouds(){ //and repeated for end
    push();
    noStroke();
    beginShape();
    fill(249,246,249);
    for (var x = 0; x < width; x++){
        var k = (x*dchange) + (millis()*dspeed);
        var y = map(noise(k), 0,1, 500, height/3);
        vertex(0, height);
        vertex(width, height);
        vertex(x,y)
    }
    endShape();
    pop();
}

For this project, I wanted to mimic a simulation of looking out of the window on an airplane. Thus, the “landscape” is actually a multi-layered blanket of clouds that move at varying speeds depending on its distance from the airplane. To get a bit more whimsical, I used image animations to show birds somehow flying alongside the plane – maybe they’re robots?

This was a fun method of creating a scene that was just interesting to watch over time, as the varying changes create different intensities of each of the layers.

hqq – secE – LookingOutwards09

Rachel Park sure can look outwards. 

I’m really inspired by a project she found when researching in Week 7 called Digital Calligraffiti:

^Video trailer for the project

Calligraffiti isn’t necessarily new or groundbreaking – in fact, it’s become an important movement in the development of the underground organized abstract vandalism movement. However, in this project, the Public Art Lab did things a little differently. Digital Calligraffiti is a project that bands together refugees with visual and graphic designers to create art and computational visualizations to raise awareness of social justice issues.

The project acts as a canvas for refugees to express issues that they face in a universally noticeable medium. The installation took place throughout public spaces in Berlin in 2016 and served to help normalize the voices of refugees in a country whose influx of Syrian refugees proved to be a contentious point of debate to native Germans.

The project uses a computational derivation of a font scheme to allow refugees to partner with visual designers to create uniquely serifed and expressive works of art.

I’m inspired by pieces like this because it bands together designers with those whose voices are often silenced. These kinds of partnerships use computing for social good to help raise the perspectives of the underprivileged to the forefront of the public eye.

hqq – secE – project 09 – portrait

hamza

//hamza qureshi
//hqq@andrew.cmu.edu
//section e
//project 08 : portrait

var pic; //new variable for base image

function preload(){
    var URL = "https://i.imgur.com/uWj0FJC.jpg"; //url for image
    pic = loadImage(URL); //loads image from url
}

function setup(){
    createCanvas(480,480);
    pic.loadPixels(); //loads pixels of image to be individually interpreted
    frameRate(10); //pls dont be slow
}

//create circles
function draw(){
    var posX = random(width); //position of x and y coordinates of shape
    var posY = random(height);
    var colX = constrain(floor(posX), 0, width-1); //determines pixel color
    var colY = constrain(floor(posY), 0, height-1);
    var picFill = pic.get(colX,colY); //grabs info for each pixel in image
    noStroke();
    fill(picFill); //apply fill
    ellipse(posX, posY, 7, 7); //draw circle at random location
                              //colored based on the pixel of its origin location
}

//create target shapes when mouse is pressed
function mousePressed(){
    var posX = mouseX; //new local variable for x and y
    var posY = mouseY;
    var colX = constrain(floor(posX), 0, width-1);
    var colY = constrain(floor(posY), 0, height-1);
    var picFill = pic.get(colX,colY);
    var sz = random(10, 20); //new variable to randomize shape
    noStroke();
    fill(picFill);
    //scale(sz);
    ellipse(posX, posY, 10, 10); //new, larger central ellipse
    stroke(picFill);
    strokeWeight(0.5);
    noFill();
    ellipse(posX, posY, sz + 2, sz + 2); //outer rings of ellipse
    ellipse(posX, posY, sz + 7, sz + 7); //are random in size to change
    ellipse(posX, posY, sz + 9, sz + 9); //size
}

For my sketch, I used an image from Orientation this past summer:

I appreciated the variety of colors in this picture of myself and some great friends. I chose to create a dynamically drawn portrait that allows for a slightly modified outcome when the mouse is clicked. The sketch operates as it generates each frame, but each click produces a randomly sized target shape. This creates an oil-painting-like stroke when the image nears completion. See below:

 

hqq-LookingOutwards-08

^”Hacking IKEA”, a project by Taeyoon Choi focusing on the multiplicity of noise density in a busy context.

I was pretty captured by the work of Taeyoon Choi, a visual and computer artist based out of New York City and Seoul, South Korea, who combines a passion for digital interfacing with a passion for urban and human interactions to create a school of thought he calls “poetic computation”. Poetic computation allows an artist to intervene in a social space to use digital and computational tools to reorganize and reparametrize that space. In doing so, Choi enables spaces to reflect both their natural, intuitive elements of being juxtaposed against his interventions which, big or small, transform spaces in different ways.

Choi’s work is particularly reflective of a new model of architectural thinking that I’m inspired by, which is personally driving my academic path as we speak. If spaces have the power to be fundamentally altered by what we as individuals can do to them, then architects and designers have the power to optimize these spaces for complete user intervention. What does it mean for a store like IKEA, where customers slowly follow a calculated path in environments meant to reflect their own homes, to suddenly exhibit an experience so foreign to a customer that it forces them to remind themselves that they’re in a store? (See Choi’s project, linked above). How can designers use this thinking to drive the creation of spaces? These questions elevate off of Choi’s work and serve as a major inspiration for what I strive to do.

hqq – LookingOutwards-07

Above: Zoomed and static network visualization of Twitter connections by Santiago Ortiz.

Santiago Ortiz, founder of Moebio Labs, is a visual scientist and designer, whose work uses expressive network theory to demonstrate physical and metaphorical connections between people and their surroundings. Ortiz believes that data visualization is most effective not in the form of static charts and graphs, but as fluid, moving pieces of art. Ortiz’s analysis of connections on Twitter between different followers in different locations exemplifies this belief perfectly. The analysis considers a variety of metrics to highlight important information on who is tweeting, who they connect with, how often they connect, and even why they connect the way they do. The visualization uses a series of nodes and lines to create webs between different users who connect with each other. Subtle nuances such as line thickness and node size highlight other important statistics such as the amount of communication and popularity. Moreover, the analysis is fluid. From the webpage, you can zoom in, click, and slide metrics to reveal more information.

hqq – secE – project 07 – curves

hamza

//hamza qureshi
//hqq@andrew.cmu.edu
//section e
//project 07 - curves

function setup(){
    createCanvas(480,480);
    angleMode(DEGREES);
}

function draw(){
    background(130,120,150);
    stroke(40,40,60);
    strokeWeight(0.25);
    noFill();
    translate(width/2,height/2); //moves shapes to center of canvas
    drawEpitrochoid(); //calls function to draw epitrochoid
    stroke(200,200,240);
    drawHypotrochoid(); //calls function to draw hypotrochoid
}

function drawEpitrochoid(){
    var p = width/2; //variable to call bounds of rotational shift
    var a = map(mouseX,0,width,0,40); //remaps x-value of mouse location to adjust center diameter
    var b = map(mouseY,0,height/2,0,80); //remaps y-value of mouse location to adjust radius of petals
    var h = 75; //number of lines
    beginShape();
    for (var i = 0; i < p; i++){
        var t = map(i,0,mouseX/30,0,360); //remaps i-value to correspond angularly
        var x = (a + b) * cos(t)-h*cos(t*(a+b)/b); //equations for epitrochoid
        var y = (a + b) * sin(t)-h*sin(t*(a+b)/b);
        vertex(x,y);
        endShape();
    }
}

function drawHypotrochoid(){
    var p = width/2;//variable to call bounds of rotational shift
    var a = map(mouseX,0,width,0,10); //remaps x-value of mouse location to adjust center diameter
    var b = map(mouseY,0,height/2,0,20);//remaps y-value of mouse location to adjust radius of petals
    var h = 50;//number of lines
    beginShape();
    for (var i = 0; i < p; i++){
        var t = map(i,0,mouseX/15,0,360); //remaps i-value to correspond angularly
        var x = (a + b) * cos(t) + h*cos(t*(a+b)/b);//equations for hypotrochoid
        var y = (a + b) * sin(t) - h*sin(t*(a+b)/b);
        vertex(x,y);
        endShape();
    }
}

In my exploration of a dynamic image using curve functions, I chose to draw an epitrochoid and a hypotrochoid. I appreciated the fact that both shapes are essentially inverses of each other. I wanted to also work the algorithms so that one would sit within the other, but the smaller one would increase in size less exponentially than the larger one. This creates an interesting sequence of shapes that produces a variety of silhouettes of the outer curve shape while maintaining a consistently shaped interior shape.