ICM Final – My Beautiful Dark Twisted Recursive Trees

For my final, I chose to create a recursive tree that responds to sentiment analysis of personally typed text. For every “positive” word, I wanted the tree to have a flower, and for every “negative” word, I wanted to have a flower disappear.

Before I discuss my process and issues, I would like to state my position on sentiment analysis, which I have included on a file with my cited sources in my final project:

We live in a time where innovation often outpaces critical thought vis a vis the social systems we change, and subsequently, the people we affect. Sentiment analysis is the perfect example of a technology that at first glance is cool, but can and has been utilized to perniciously exacerbate problematic social structures, particularly but not limited to racial discrimination.

I did not create the coding schema that values and devalues certain words based on their perceived positivity. In fact, I take great issue with the rudimentary nature of this schema and find it necessary to communicate that context is what truly determines how one may interpret a given word or phrase. Furthermore, the context of how we choose our words, the history of our phrases, and what they mean in relation to different lived experiences, is imperative to communicating in a manner that serves to diminish the hostility (intentional or not) of our communication.

The greatest struggle of this project was figuring out how to map flowers over the tree. There were a bunch of techniques tried before a true attempt at mapping was executed – the following were two attempts that worked conceptually, though I ended up bringing the latter attempt to “completion” because it was easier to complete in the time that I had to turn in this assignment

Attempt 1

Conceptualized by Cassie Tarakajian and with the assistance of Alden Jones, I attempted to map my recursive tree by “cheating” (in a super complicated way). Essentially, I would:

  1. In a first animation, generate a recursive tree
  2. In a second animation, upload the image of the tree, map the pixel positions of the image using edge detection and black pixel recognition arrays, load 50 random pixel positions from these arrays into a JSON file and export that JSON file.
  3. In a third animation, upload the image of the tree and the JSON file, and use the JSON coordinates to place my flower constructor

I stopped at step 3 due to deadline constraints – I now understand that I need to change step 2 to not make an inverse color image during edge detection.

Attempt 2

With the guidance of Max Da Silva, I developed a recursive tree generated from more complex vector geometry. This made it considerably easier to map the positions and nodes of each branch, to facilitate an easier “random” generation of flowers. I played around with some prototypes before adding the tree to sentiment analysis. These prototypes are linked below.

ICM – Weeks 9 & 10 Assignment

For this week’s assignment, our class was tasked with integrating sound into a p5 animation. This assignment was an interesting challenge, as I aimed to make a drum pad, usable both on a desktop and touch screen device, that played different lyric sections of Daft Punk’s Harder, Better, Faster, Stronger.

I tried three different methods to reach my end result, accessible in the buttons below.

In six words, I would describe this project as:

Tactile, Colorful, Harder, Better, Faster, Stronger

Users may interact with my final sketch on touch screens using the preview link.

If I had more time I would have made a popup introductory epilepsy warning with the song’s chorus quietly playing in the background. The drum pad would be accessible once the user clicked the warning, which would be superimposed over the helmet of one of the members of Daft Punk’s members. I have stored all of these media files in my sketch, and intend to add this feature in the near future.

ICM – Week 8 Assignment

This week’s assignment was to create a sketch using pixelated images and describe it under specific parameters. I created a “Who’s That Pokemon” game with Neta Bomani – our description is as follows:

We based our animation on the “Who’s that Pokemon” television bump sketch.

We were asked to describe the experience in 5-10 words, we chose: A memory game to flex your nostalgiac fandom for Pokemon.

The sketch is split into 8 sections based on each Pokemon, Bulbasaur, Mewtwo, Jigglypuff, Electrobuzz, Infernape, Squirtle and Vilplume.

We were also asked to describe each section in 2-3 words below:

Section 1: This is Bulbasaur.

Section 2: This is Mewtwo.

Section 3: This is Jigglypuff.

Section 4: This is Electrobuzz.

ICM – Week 7 Assignment

This week we were tasked with cleaning up the code from last week’s assignment. Frankly, I found that my code was clean and satisfactory, without redundancies, so I added an outro level to my animation exercise that prevented my users from surpassing 100 cat clicks.

The ease with which I was able to construct this level was surprisingly gratifying. Without assistance, and with minimal troubleshooting, I was able to execute a precise vision of what I wanted to create; I have come a long way. I find it both satisfying and funny that for each week, with each tool I’ve learned, I’ve come closer and closer to the game I wanted to create for my first ICM class. To that end, my increased comfortability with JavaScript has given me hope that I will, eventually, be able to approach and master (with time) higher-level programming concepts like machine learning, and addictive user interface development. To be clear, I am not interested in understanding these tools exclusively because I want to generate with these tools – I see danger in their overuse, but recognize that in order to contend with the dangers these tools present I must first understand them. In a funny way, my addition this week reflects my concern that technology grabs our attention to a toxic degree, and I am excited that I can push back against this trend at a level that reflects my (growing!) capability.

Images for this and last week’s documentation to come

ICM – Week 6 Assignment

This week, our class was expected to create a sketch with constructor-based objects, and explain our sketch. I decided to continue on an original idea I had had, a balloon popping game, utilizing new and old skills from throughout my projects. I used arrays to generate my cats, and the transparent “button” ellipses that allowed my counter to increase, and the position of the cats to reset. I used for loops to populate my arrays, and move my cloud animations (as I had done in the past). I also uploaded a new font to match the 8-bit aesthetic of my animation, and a loading screen that reflected the same aesthetic

The only issue I ran into was when I tried to draw from a randomized “meow” array, which would play when I pressed my ellipse balloon buttons. I assume the issue came from the syntax I used after establishing the variable in the constructor, or the syntax I used when linking it to the event “clicked”.

ICM – Week 5 Assignment

This week, my class was expected to represent our comfort in defining our own functions and creating objects. After some practice, I felt very comfortable using these tools – and utilized some old code that I had used to make balloons float, to make a pattern of multiple bubbles floating. This was satisfying because I had initially struggled with making multiple balloons float, and I was able to overcome this obstacle and apply it in a new animation. I also learned how to add audio and gifs into my animation, I look forward to using these skills in future projects.

I ran into two interesting issues. First, for whatever reason, I could not get Adobe Photoshop to represent the color I had generated for my background in the background of my seaweed images. Second, I wanted to try and generate a realistic water ripple pattern and was not able to find any examples written in JavaScript. In the future, I’d like to see if there is a way I could interface different languages in a similar manner to p5.serialport.js (used to communicate with Arduino).

Below is a video of my final animation:

Below is the code I used:

let x;
let y;
let speedX;
let speedY;
let d ;
let gif_loadImg;
let gif_createImg;

let b1 = {
  x: 0,
  y: 25,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b2 = {
  x: 50,
  y: 40,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b3 = {
  x: 100,
  y: 60,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b4 = {
  x: 125,
  y: 91,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b5 = {
  x: 150,
  y: 84,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b6 = {
  x: 400,
  y: 93,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b7 = {
  x: 450,
  y: 101,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b8 = {
  x: 500,
  y: 30,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b9 = {
  x: 3700,
  y: 74,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b10 = {
  x: 420,
  y: 24,
  speedX: 3,
  speedY: 5,
  d: 5
};
let b11 = {
  x: 400,
  y: 300,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b12 = {
  x: 450,
  y: 250,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b13 = {
  x: 500,
  y: 275,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b14 = {
  x: 370,
  y: 274,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b15 = {
  x: 420,
  y: 244,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b16 = {
  x: 42,
  y: 24,
  speedX: 3,
  speedY: 5,
  d: 5
};
let b17 = {
  x: 24,
  y: 300,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b18 = {
  x: 45,
  y: 250,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b19 = {
  x: 65,
  y: 275,
  speedX: 3,
  speedY: 5,
  d: 5
};

let b20 = {
  x: 37,
  y: 274,
  speedX: 3,
  speedY: 5,
  d: 5
}

let b21 = {
  x: 90,
  y: 244,
  speedX: 3,
  speedY: 5,
  d: 5
};

let bg = {
  r: 62,
  g: 96,
  b: 167
}

function clearCanvas(r, g, b) {
  background(r, g, b);
}

function drawBubble(x, y, d, bubbleColor) {
  fill(bubbleColor);
  circle(x, y, d);
}

function initializeBubble(b1) {
  b1.x = width / 18;
  b1.y = height / 2;
  b1.speedX = b1.speedX + random(-1, 1);
  b1.speedY = -1;
  b1.d = 5;
}

function updateBubble(b1) {
  b1.x = b1.x + random(-1, 1);
  b1.y = b1.y - 1;
  if (b1.y < 0) 
  b1.y = height; 
}
  
// drew gif insertion concept from https://editor.p5js.org/kjhollen/sketches/S1bVzeF8Z
function preload() {
  gif_loadImg = loadImage("fishes.gif");
  gif_createImg = createImg("fishes.gif");
  song = loadSound('dive.mp3');
  img1 = loadImage('seaweed.png');
  img2 = loadImage('seaweed3.png');
}

function setup() {
  createCanvas(550, 390);
    initializeBubble(b1);
}

function mousePressed() {
  if (song.isPlaying()) {
    // .isPlaying() returns a boolean
    song.stop();
  } else {
    song.play();
  }
}
function draw() {
  clearCanvas(bg.r, bg.g, bg.b);
  gif_createImg.position(155, 0);
  image(img1, 0, 200);
  image(img2, 350, 200);

//b1
drawBubble(b1.x, b1.y, b1.d, 255);
  updateBubble(b1);
  
//b2
drawBubble(b2.x, b2.y, b2.d, 255);
  updateBubble(b2);  

//b3
drawBubble(b3.x, b3.y, b3.d, 255);
  updateBubble(b3);    

//b4
drawBubble(b4.x, b4.y, b4.d, 255);
  updateBubble(b4);    
  
//b5
drawBubble(b5.x, b5.y, b5.d, 255);
  updateBubble(b5);    
  
//b6
drawBubble(b6.x, b6.y, b6.d, 255);
  updateBubble(b6);    
  
//b7
drawBubble(b7.x, b7.y, b7.d, 255);
  updateBubble(b7);    
  
//b8
drawBubble(b8.x, b8.y, b8.d, 255);
  updateBubble(b8);    
  
//b9
drawBubble(b9.x, b9.y, b9.d, 255);
  updateBubble(b9);    
  
//b10
drawBubble(b10.x, b10.y, b10.d, 255);
  updateBubble(b10);  

//b11
drawBubble(b11.x, b11.y, b11.d, 255);
  updateBubble(b11);    
  
//b12
drawBubble(b12.x, b12.y, b12.d, 255);
  updateBubble(b12);    
  
//b13
drawBubble(b13.x, b13.y, b13.d, 255);
  updateBubble(b13);    
  
//b14
drawBubble(b14.x, b14.y, b14.d, 255);
  updateBubble(b14);

//b15
drawBubble(b15.x, b15.y, b15.d, 255);
  updateBubble(b15);

//b16
drawBubble(b16.x, b16.y, b16.d, 255);
  updateBubble(b16);    
  
//b17
drawBubble(b17.x, b17.y, b17.d, 255);
  updateBubble(b17);    
  
//b18
drawBubble(b18.x, b18.y, b18.d, 255);
  updateBubble(b18);    
  
//b19
drawBubble(b19.x, b19.y, b19.d, 255);
  updateBubble(b19);

//b20
drawBubble(b20.x, b20.y, b20.d, 255);
  updateBubble(b20);

//b21
drawBubble(b21.x, b21.y, b21.d, 255);
  updateBubble(b21);   
}

ICM – Week 4 Assignment

This week, my assignment was to present my competence using for loops. While thinking of projects I often came up with ideas that relied on more advanced concepts – specifically arrays and objects. Initially, I tried to create a yahtzee-esque game, which I intend to complete once I have a mastery of arrays, and particularly, the shuffle function. However, I ended up creating a grid of multiple faces to represent the range of emotions I could be feeling on a given day. As a cute added feature, I included a mouseIspressed function that printed “Lol don’t worry about me, life’s great rn”.

In the future, I believe I could use an array, and the shuffle function, to display a randomized grid of a greater variety of emotions – and would like to do so. Creating the for loops, and aligning these three images in the grid were relatively time-intensive, though creating this project has definitely given me greater insight into how to troubleshoot positioning issues in for loop generated grids.

This is a picture of my screen, which shows the code and preview that I described above

Below is my code

const GRID_SIZE = 3;
let confused;
// function preload() {
//   img = loadImage('confused.png');}
let frustrated;
// function preload() {
//   img = loadImage('frustrated.png');}
let sleepy;
// function preload() {
//   img = loadImage('sleepy.png');}

function setup() {
  createCanvas(400, 400);
  confused = loadImage('confused.png', img => {
    image(img, 0, 0);
  });
  frustrated = loadImage('frustrated.png', img => {
    image(img, 0, 0);
  });
  sleepy = loadImage('sleepy.png', img => {
    image(img, 2, 2);
  });
}

function draw() {
  background(220);
  textSize(16);
  let rectSide = width / GRID_SIZE;
  for (let x = 0; x < GRID_SIZE; x += 1) {
    for (let y = 0; y < GRID_SIZE; y += 1) {
      let xPos = x * rectSide;
      let yPos = y * rectSide;
      rect(xPos, yPos, rectSide, rectSide);
      let circleSize = width / 3;
      for (let i = 0; i < width; i += GRID_SIZE) {
        image(confused, xPos + 35, height / 2.4, 80, 80);
      }
      for (let i = 0; i < width; i += GRID_SIZE) {
        image(frustrated, xPos + 35, height / 9.7, 80, 80);
      }
      for (let i = 0; i < width; i += GRID_SIZE) {
        image(sleepy, xPos + 38, height / 1.35, 83, 83);
      }
    }
    if (mouseIsPressed){print ("Lol don't worry about me, life's great rn")}
  }
}

ICM – Week 3 Assignment

This week my partner, Ashwita, and I expanded on my initial balloon popping game concept. We wanted to expand the concept by being able to generate multiple balloons, have those balloons change colors in a non-monochromatic range, have the balloons be pressable buttons (instead of relying on a general mouseClick function), and to incorporate a popping sound and pop counter.

We ran into the following problems. First, we could not figure out how to make a circular moving button (the balloon). We tried doing so by using the distance function and not having the balloons pop when clicked, but when the mouse hovered over the balloons instead. We also struggled with making each balloon, as individual objects, separate clickable entities.

Pending feedback we look forward to making different levels, turning this exercise into a game. Below is a video of our animation, with a final and test iteration of code.

let balloonColor;
let balloonPositionX;
let balloonPositionY;
let s = 'POP lol';
let r,g,b;
let imga, imgb;
    
function setup() {
  createCanvas(800, 600);
  balloonColor = random(255);
  balloonPositionX = random(0,200);
  balloonPositionY = 400;
}


function preload() {
  // sound = loadSound('balloon-pop.mp3'); // balloon pop sound
  imga = loadImage('balloon.png');
  imgb = loadImage('balloon.png');
}

function draw() {
  background(220);
  image(imgb, balloonPositionX, balloonPositionY, 200, 200);
  push();
  pop();
  fill(0);

  // pin 
  ellipse(mouseX, mouseY, 5, 5);
  line(mouseX, mouseY, mouseX + 20, mouseY - 10);
  
  //floating balloon waver
  balloonPositionX = balloonPositionX ;
  balloonPositionY = balloonPositionY - 4;
  if (balloonPositionY === 0) {
    balloonPositionY = 600;
    balloonPositionX = random(0,400);
    balloonColor = random(255,0,0);
  }
  if (mouseIsPressed) {
    // text(s, balloonPositionX , balloonPositionY, 80, 80)
    balloonPositionY = 600;
    balloonPositionX = random(0,800);
    balloonColor = random(255);
  }
}

Below is the code for one of our test iterations

let counter1 = 400; // counter for balloon 1 
let counter2 = 600; // counter for balloon 2
let xpos1, xpos2; // the horizontal positions for the balloon 1 and 2
// let speed = 1;
let position;
let ypos;
var sound;
var imga, imgb;
let bx1, by1, bx2, by2;

function setup() {
  createCanvas(400, 400);
  xpos1 = random(0, 400); // setting a random position for balloon 1
  xpos2 = random(0, 400); // setting a random position for balloon 2
  ypos = random(0, 400); // setting up horizontal pos. differences between Balloon 1&2.
  bx1 = random(0, 600);
  bx2 = random(0, 600);
  by1 = random(0, 400);
  by2 = random(0, 400);
}

function preload() {
  // sound = loadSound('balloon-pop.mp3'); // balloon pop sound
  imga = loadImage('balloon.png');
  imgb = loadImage('balloon.png');
}


function draw() {
  background(255);
  strokeWeight(1);
  image(imga, xpos1, counter1, 200, 200);
  // let ball1 = rect(xpos1,counter1,50, 50) // balloon 1 represented by a square

  // to make the balloon float one after the other in a loop
  if (counter1 <= -50 && counter2 <= -50) {
    counter1 = 400;
    counter2 = 600;
    xpos1 = random(0, 400);
    fill(255); // resets the color every loop 

    if (dist(mouseX, mouseY, xpos1, counter1) < 200 / 2 ||
      dist(mouseX, mouseY, xpos2, counter2) < 200 / 2) {
      background(0);
    } else {
      background(255);
    }
    
    // ellipse(bx1, by1, d, d);
    // ellipse(bx2, by2, d, d);
  }
  image(imgb, xpos2, counter2, 200, 200);
  // let ball2 = rect(xpos2,counter2,50, 50); // balloon 2 represented by a square
  counter1 -= 1;
  counter2 -= 1;


  ellipse(mouseX, mouseY, 5, 5);
  line(mouseX, mouseY, mouseX, mouseY - 15);

  // // making the balloon pop sound
  // if (mouseIsPressed) {
  //   // sound.play();
  //  fill(0,0,255);
  // }


}

ICM – Week 2 Assignment

For this week I was tasked with animating a scenario where elements acted automatically and were interactive. I knew I wanted to animate a poppable balloon, however, my initial approach (which I, unfortunately, scrapped before I could document) left me more confused than inspired. After an insightful help session with my professor, I was put on the right track, and was able to animate the following work. Partly my issue stemmed from not knowing the material well enough, though I would say a larger issue I ran into was conceptualizing how best to plan and approach my design in individual steps.

Balloon Popping!

Below is the code I wrote to generate my project.

let balloonColor;
let balloonPositionX;
let balloonPositionY;
let s = 'POP lol';
    
function setup() {
  createCanvas(400, 600);
  balloonColor = random(255)
  balloonPositionX = 200
  balloonPositionY = 400
}

function draw() {
  background(220);

  fill(balloonColor);
  ellipse(balloonPositionX, balloonPositionY, 100, 140);
  push();
  noFill();
  bezier(balloonPositionX, balloonPositionY + 70, balloonPositionX + 20, balloonPositionY + 100, balloonPositionX - 20, balloonPositionY + 150, balloonPositionX, balloonPositionY + 200);
  pop();
  fill(0);
  ellipse(mouseX, mouseY, 5, 5);
  line(mouseX, mouseY, mouseX + 20, mouseY - 10);
  balloonPositionX = balloonPositionX + random (-1,1);
  balloonPositionY = balloonPositionY - 4;
  if (balloonPositionY === 0) {
    balloonPositionY = 600;
    balloonColor = random(255);
  }
  if (mouseIsPressed) {
    text(s, balloonPositionX - 20, balloonPositionY, 80, 80)
    balloonPositionY = 400;
    balloonColor = random(255);
  }
}

Moving forward with this project, I’d like to be able to have the balloons generate in multi-color (non-monochrome). Furthermore, I would like to add a pop counter, and have multiple balloons generate, to turn this small project into a full game.