Final Project

This game is about “Trowing out flammable objects” like cigarettes, sparklers, fireworks, lanterns, heaters, and etc. With this game, I would be able to inform people to throw away caution objects, instead of leaving them in the forest.

*Systems & Keys

For this game, I have two scoring systems. One system is adding points(+)when the user successfully throws out an item while another system is deducting points(-) when the user throws out an item that is not dangerous.

Right arrow, Left arrow, ENTER (detailed instructions in the program)

*Goal

Score at least 5 points by throwing out flammable objects

*Attention

If you score lower than -5, Fail page will pop up. If you fail, you can’t start again because you CAN NOT undo wildfire 🙁 But you can start again if you success by pressing ENTER key 🙂

sketch copy
//Final Project

var introPage; //Click page
var introScreen; //click screen 
var item_counter = 0;
var item_interval = 13; // items amount decreases as the user earns more point
var item_startPage; // How page
var item_finishPage; // Congrats page
var item_finishFailPage;  //fail page
var item_startScreen; // How page illustration 
var item_finishScreen; //Congrats page illustration
var item_finishFailScreen; //Fail page illustration
var weapons = [];  //dangerous items array
var nonWeaps = []; //non-weapons array
var dropping_weapons = [] 
var dropping_nonWeaps = []
var trashcan; // trash can image
var backg;
var rate = 2; // speed of items falling
var item_score = 0; // score of throwing out items
var x = 0;
var height = 540;
var y = height - 100;

//trash can keys
var moveRight = false;
var moveLeft = false;

function preload() { // preloads images of dangerous weapons
    var Weapons = [
      "https://i.imgur.com/nu43pvX.png", //lantern
      "https://i.imgur.com/iftAnZO.png", //cigarette
      "https://i.imgur.com/JWyEvWW.png", //firework
      "https://i.imgur.com/RDVdcYb.png"]; //sparklers
    for (var i = 0; i < Weapons.length; i++){
      weapons.push(loadImage(Weapons[i]));
    }
    var NonWeaps = [
      "https://i.imgur.com/y3uSh1k.png", //leaf
      "https://i.imgur.com/RVbYaC6.png", //branch
      "https://i.imgur.com/2UQizyS.png"]; //acorn
    for (var i = 0; i < NonWeaps.length; i++){
      nonWeaps.push(loadImage(NonWeaps[i]));
    }
}

function item_setup () {
  createCanvas(450, 440);
  item_score = 0;
  item_startPage = false; 
  item_finishPage = false;
  trashcan = loadImage("https://i.imgur.com/JpPvsJn.png"); //trash can image
  item_startScreen = loadImage("https://i.imgur.com/in44Atu.png"); // How page of the game
  backg = loadImage("https://i.imgur.com/m6iJCVQ.png"); // forest background
  item_finishScreen = loadImage("https://i.imgur.com/UJUGvtS.png"); // congrats page of the game
  item_finishFailScreen = loadImage("https://i.imgur.com/JZkuboH.png");  //Fail page of the game
  item_counter = 0; // counts the number of trash caught in the trash can
  item_interval = 50;
}

function item_keyPressed() { 
  item_startPage =false;
  if (key === RIGHT){
    moveRight = true;
  } else if(key === LEFT){
    moveLeft = true;
  }
  if (item_startPage) {  // starts the game after pressing any key
      item_startPage = false;
  } else if (keyCode == ENTER) { // returns back to home screen 
      setup();
  }
}

function item_draw() { // draws other functions that is needed for game page
    if (item_startPage == true) {
      push();
      scale(1/4);
      image(item_startScreen, 0, 0);
      pop();
    } else {
      scale(0.35);
      image(backg, 0, 0);
      scale(1/0.4);
      drawTrashCan(); // draw trash can
      drawItems(); // draw dangerous items
      drawNonWeaps();    
      item_drawScore(); // number of items thrown out
      item_update(); // drops items continuously
    }
    if (item_finishPage == true) { // appears the finish page as the game ends
      push();
      scale(0.28);
      image(item_finishScreen,0,0);
      pop();
    }
    if (item_finishFailPage == true){
      push();
      scale(0.28);
      image(item_finishFailScreen,0,0);
      pop();
    }
}

function ScoreMax() { // if score of 5(maximum) is reached, shows congratulation page
    max = 5;          
    if(item_score >= max){
      item_finishPage = true;
    }
}

function ScoreMin(){  // if score of -5(minimum) is reached, shows Fail page
    min = -5;
    if(item_score <= min){
      item_finishFailPage = true;
    }
}

function item_drawScore() { // score on top left of the screen
  textSize(15);
  fill(25,30,37);
  text(("Your score: " + this.item_score), 10, 30);
}

function makeNonWeap(xposs, yposs, imagee) {
  var non = {
    "x": xposs,
    "y": yposs,
    "img": imagee,
    }
  return non;
}

function makeItem(xx, yy, image) {
  var item = {
    "x": xx,
    "y": yy,
    "img": image,
    }
  return item;
}

function drawNonWeaps() { 
    for (var i = 0; i < dropping_nonWeaps.length; i++){
      var non = dropping_nonWeaps[i];
      image(non.img, non.x, non.y,50,50);
    }
}

function drawItems() { 
    for (var i = 0; i < dropping_weapons.length; i++){
      var item = dropping_weapons[i];
      image(item.img, item.x, item.y,50,50);
    }
}

function drawTrashCan() { // renders the trash can
  image(trashcan, this.x, this.y-90,120,180);
}

function updateNonWeapY() { // updates the varying dropping of the non weapons
  for (var i = 0; i < dropping_nonWeaps.length; i++){
    var non = dropping_nonWeaps[i];
    non.y += rate;
    if (non.y > height) { 
      dropping_nonWeaps.splice(i, 1);
    }
  }
}

function updateItemY() { 
  for (var i = 0; i < dropping_weapons.length; i++){
    var item = dropping_weapons[i];
    item.y += rate;
    if (item.y > height) { 
      dropping_weapons.splice(i, 1);
    }
  }
}

function itemHitsTrashCan(item) { // moment when dangerous items hit the trash can
  var hit = this.x < item.x + 10 & item.x < this.x + 80 - 20 & item.y > this.y - 110; 
  return hit;
}

function nonWeapHitsTrashCan(non) { // moment when non-weapon items hit the trash can
  var hitt = this.x < non.x + 10 & non.x < this.x + 80 - 20 & non.y > this.y - 110;
  return hitt;
}

function updateNonWeapHit() { // the non-weapons disappear when it hits the trash can
  for (var i = 0; i < dropping_nonWeaps.length; i++){
    var non = dropping_nonWeaps[i];
    if(nonWeapHitsTrashCan(non)) {
      dropping_nonWeaps.splice(i, 1);
      item_score -= 1; //score decreases 
    }
  }
}

function updateItemHit() { // dangerous items disappear when it hits the trash can
  for (var i = 0; i < dropping_weapons.length; i++){
    var item = dropping_weapons[i];
    if(itemHitsTrashCan(item)) {
      dropping_weapons.splice(i, 1);
      item_score++; //score increases
      item_interval += 1; 
    }
  }  
}

function item_update() { // update random items from the top
  if(item_counter % item_interval == 0){
    var new_item = makeItem(random(10, 440), -80, random(weapons)); 
    dropping_weapons.push(new_item);
    var new_non = makeNonWeap(random(9,430),-80, random(nonWeaps));
    dropping_nonWeaps.push(new_non);
    item_counter = item_counter % item_interval; 
  }
  if(keyIsDown(RIGHT_ARROW) & this.x < width - 10){  // right arrow moving the trash can
     this.x += rate;
   }
  if (keyIsDown(LEFT_ARROW) & this.x > -10){ // left arrow moving the trash can
     this.x -= rate;
  }
  item_counter++;
  updateItemY();
  updateNonWeapY();
  updateItemHit();
  updateNonWeapHit();
  ScoreMax();
  ScoreMin();
}

function setup() {
  createCanvas(450, 450);
  introPage = true; // intro page is "true" here because it should start with this
  score = 0; //initial score
  introScreen = loadImage("https://i.imgur.com/EWQ38kD.png"); // home screen
  item_setup(); // calls the item setup function to combine
}

function keyPressed(){
  if (item_startPage | item_finishPage){
    item_keyPressed();
  } else if(item_finishPage & key == ENTER){  //going back to start page
    setup();
  }
}

function draw() {
  if (introPage == true) { // draws the intro page
    push();
    scale(1/4);
    image(introScreen, 0, 0);
    pop();
  } else {
    item_draw(); // game page
  }
}

function mouseClicked() {
  var xx = mouseX;
  var yy = mouseY;
  if (introPage) {
    if (0 < xx & xx < width & 0 < yy & yy < height) { //click any part of the screen
      item_startPage = true; // start page shows up
      introPage = false; 
    }
  }
}

LookingOutwards-11

For this Looking Outwards, I’ve decided to look into Lauren. I first got interested in her because I saw this description saying, creator/lead-developer of p5.js. One of her works that caught my eye was the LAUREN, in which she attempted to become a human version of Amazon Alexa. It is an installation of a series of custom-designed networked smart devices like camera, door locks, electronic functions, switches, and etc. She claimed that her performance was better than an AI because she can understand the user as a person and anticipate their needs. It was interesting for me because recently there’s a lot of tryout going on to create AI devices to make people’s life easier. LAUREN was an improved version of current AIs except for empathy, that only humans can do.

Project 11: Generative Landscape

sketch
var clouds = [];
var bikeImage = [];
var bike = [];
var terrainCurve = 0.01;
var terrainSpeed = 0.001;


function preload(){
    var filenames =[];
    filenames[0] = "https://i.imgur.com/DSPjyoM.png";
    filenames[1] = "https://i.imgur.com/kGGBLDh.png";
    filenames[2] = "https://i.imgur.com/v9RMtPT.png";
    filenames[3] = "https://i.imgur.com/ZUC5xZ2.png";
    for(var i = 0; i < filenames.length; i++){
      bikeImage.push(loadImage(filenames[i]));
    }
}

function setup() {
    createCanvas(480,480); 
    //clouds 
    for (var i = 0; i < 9; i++){
        var ccloud = random(width);
        clouds[i] = drawCloud(ccloud);
    }
    frameRate(11);
    imageMode(CENTER);
    //bike
    var b = makeCharacter(240, 350);
    bike.push(b);
}

function draw() {
    sky(0, 0, width, height);
    DisplayClouds();
    removeClouds();
    newClouds();
    ground();
    for (var i = 0; i < bike.length; i++) { 
        var bb = bike[i];
        bb.stepFunction();
        bb.drawFunction();
    }
}

function sky(x, y, w, h) { 
    //sky
    var Blue;
    var Pink;    
    Blue = color(114, 193,215);
    Pink = color(253, 209, 164);
    for (var i = y; i <= y + h; i++) {
        var ssky = map(i, y, y + h, 0, 1.1);
        var cco = lerpColor(Blue, Pink, ssky);
        stroke(cco);
        line(x, i, x + w, i);
    }
    //mountains
    beginShape();
    stroke(1, 33,92);
    strokeWeight(200);
    for (var x = 0; x < width; x++){
        var tt = (x * terrainCurve) + (millis() * terrainSpeed);
        var mm = map(noise(tt), 0,1, 110, 255);
        vertex(x, mm + 180); 
    }
    endShape();
}

this.display = function() {
    strokeWeight(this.border);
    stroke(240);
    fill(240);
    ellipse(this.x, this.y,  this.display,  this.display);
}

function ground(){
    beginShape(); 
    noStroke();
    fill(18,12,46);
    rect(0,400,width,80);
    endShape();
}

function cloudDisplay(){
    noStroke(); 
    var floorH = 21;
    var cloudH = this.nFloors * floorH; 
    fill(250,50); 
    push();
    translate(this.x, height - 95);
    ellipse(95, -cloudH, this.breadth, cloudH / 2);
    pop();
    push();
    fill(250,80)
    translate(this.x, height - 220);
    ellipse(95, - cloudH, this.breadth/1.5, cloudH);
    pop();
}

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

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

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

function newClouds(){ 
//random probability
    var newP = 0.01; 
    if (random(0,0.4) < newP) {
        clouds.push(drawCloud(width));
    }
}
    


function drawCloud(xx) {
    var cha = {x: xx,
                breadth: random(95, height),
                speed: -random(1,4),
                nFloors: round(random(4,8)),
                move: cloudMove,
                display: cloudDisplay}
    return cha;
}

function makeCharacter(cx, cy) {
    ccha = {x: cx, y: cy,
         imageNumber: 0,
         stepFunction: characterStep,
         drawFunction: characterDraw
        }
    return ccha;
}
function characterStep() {
    this.imageNumber++;
    if (this.imageNumber == 4) {
        this.imageNumber = 0;
    }
}
function characterDraw() {
    image(bikeImage[this.imageNumber], this.x, this.y,120,120);
}

For this Deliverable 11 project, I tried to collaborate on what I’ve learned from deliverable 9, using preloads for calling image animations and generating landscapes from deliverable 11. I also tried to show the difference in the speed by giving a certain frameRate for the rider and background mountains. Clouds are displayed with low opacity and different speed so that it shows how it has a different relationship with elements on the ground(mountains and humans). It was hard for me to figure out having two functions of makeCharacter because I had two figures to move: character, and the elements in the sky.

Project-10-Sonic-Story

sketch
// Jasmin Kim
//Section D
      
var mouseSound;       
var mouseeX=250;
var mouseeY=100;
var x;
var y;


function preload() { //preloading sounds
//loading sounds
mouseSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/11/rat.wav");
}

function setup() {
    createCanvas(500, 550);
    frameRate(1);
    useSound();
}


function soundSetup() { //setup for audio generation
    mouseSound.setVolume(0.3);
}

function draw(){
    console.log(frameRate);
    background(230);
    drawCheese();
    mouseSound.play();
    //plateSlide.play();
    if(frameCount >=2 & frameCount <=4){
        translate(0,-80);
        drawMouse(x,y);
    }
    if(frameCount > 4 & frameCount <=6){
        translate(0,0);
        drawMouse(x,y);
        translate(100,-50);
        drawMouse(x,y);
    }
    if(frameCount > 6 & frameCount <=8){
        translate(0,60);
        drawMouse(x,y);
        translate(100,-30);
        drawMouse(x,y);
        translate(-200,-60);
        drawMouse(x,y);
    }
    if(frameCount > 8 & frameCount <=10){
        translate(0,120);
        drawMouse(x,y);
        translate(100,0);
        drawMouse(x,y);
        translate(-200,-50);
        drawMouse(x,y);
    }
    if(frameCount > 10 & frameCount <=12){
        push();
        circle(302,342,62);
        pop();
        translate(0,130);
        drawMouse(x,y);
        rotate(PI/10);
        translate(100,60);
        drawMouse(x,y);
        rotate(-PI/10);
        translate(-200,-30);
        drawMouse(x,y);
    }
    if(frameCount >12 & frameCount <=14){
        push();
        circle(276,357,110);
        pop();
        translate(0,180);
        drawMouse(x,y);
        rotate(PI/10);
        translate(100,120);
        drawMouse(x,y);
        rotate(-PI/10);
        translate(-200,0);
        drawMouse(x,y);
    }
    if(frameCount >14 & frameCount <=16){
        push();
        circle(276,357,110);
        circle(193,367,79);
        pop();
        translate(0,190);
        rotate(PI/10);
        drawMouse(x,y);
        translate(100,130);
        drawMouse(x,y);
        rotate(-PI/10);
        translate(-200,60);
        drawMouse(x,y);
    }
    if(frameCount >16 & frameCount <=18){
        push();
        circle(276,357,110);
        circle(193,367,79);
        pop();
        translate(0,250);
        rotate(PI/10);
        drawMouse(x,y);
        translate(0,180);
        drawMouse(x,y);
        rotate(-PI/10);
        translate(-200,80);
        drawMouse(x,y);
    }
    if (frameCount>18 & frameCount <20){
        fill(255);
        circle(249,379,181);
    } else if(frameCount >= 20){
        fill(255);
        circle(249,379,181);
        mouseSound.disconnect();
        textSize(30);
        fill(0);
        text("Your cheese is gone.", width/2-100,200);
        noLoop();
    }

}

function drawCheese(x,y){
    fill(255);
    noStroke();
    circle(249,387,234);    //white plate
    push();
    noFill();
    strokeWeight(1);
    stroke(49,51,73);
    circle(249,387,220);        //navy plate
    pop();
    fill(253,222,85);
    noStroke();
    triangle(323,334,241,471,167,363);      //cheese
    fill(255);
    circle(200,357,20);
    circle(270,346,11);
    circle(236,391,11);
    circle(189,395,12);
    circle(222,436,20);
    circle(247,459,11);
    circle(277,413,20);
    circle(315,349,11);
}


function drawMouse(){
    fill(127,84,41);        //brown
    stroke(0);
    strokeWeight(1);
    ellipse(mouseeX,mouseeY,98,103);            //body
    arc(mouseeX, mouseeY+45, 52, 52, 0, PI);       //face
    push();
    //eyes
    fill(0);                                    
    ellipse(mouseeX-10,mouseeY+52,7,8); //left
    ellipse(mouseeX+10,mouseeY+52,7,8); //right
    ellipse(mouseeX,mouseeY+66,5,5);
    fill(255);
    ellipse(mouseeX-10,mouseeY+51,3.7,4.7);
    ellipse(mouseeX+10,mouseeY+51,3.7,4.7);
    noFill();
    stroke(0);
    line(mouseeX-30,mouseeY+61,mouseeX-7,mouseeY+65);  //left
    line(mouseeX-30,mouseeY+69,mouseeX-7,mouseeY+67);
    line(mouseeX-23,mouseeY+78,mouseeX-5,mouseeY+69);
    line(mouseeX+30,mouseeY+61,mouseeX+8,mouseeY+65);  //right
    line(mouseeX+7,mouseeY+67,mouseeX+30,mouseeY+69);
    line(mouseeX+6,mouseeY+69,mouseeX+24,mouseeY+78);
    pop();
    stroke(127,84,41);
    strokeWeight(4);
    line(mouseeX,mouseeY-50,mouseeX-23,mouseeY-69);     //tail
    noStroke();

    push();
    fill(0);
    arc(mouseeX+24, mouseeY+30, 37, 39, -PI,TWO_PI);  //right ear black
    arc(mouseeX-24, mouseeY+30, 37, 39,PI, TWO_PI);  //left ear black
    pop();
    ellipse(mouseeX+25, mouseeY+31, 37, 39);  //right ear brown
    ellipse(mouseeX-25, mouseeY+31, 37, 39);  //left ear brown
   
    push();
    fill(247,168,170);      //pink
    ellipse(mouseeX+25,mouseeY+30,31,31);
    ellipse(mouseeX-25,mouseeY+30,31,31);
    pop();
    ellipse(mouseeX+22,mouseeY+34,31,28);       //left ear cover
    ellipse(mouseeX-22,mouseeY+34,32,28);       //right ear cover
}

For this project, I tried to show a short animation of mice eating all of my cheese. As frameCount increases, mouse appears and the mouse sound increases. I also tried to show how the cheese gradually disappears throughout the frame.

LookingOutwards-10

There isn’t specific computational music for this launchpad but I choose this is one because it is a new method(at least for me) to create music using technology. People can compose/edit a music using launchpad that had each own’s volume and pitch. Depending on how the user sets up the mode, it can be used as a bass or the main pitch. Even though this video is not creating original music, people can edit/make a chorus corresponding to the music. I think it is also fascinating how music can be linked to those notes and be edited/created right away by the composer.

LookingOutwards-09

For today’s looking outwards, I’ve selected tian’s LO 4, Sound Art. It was a new approach for me to see how technology can collaborate and create musical interactions with people. As it allows people to interact with musical notes with their bodies, it was interesting, as a person who’s interested in music, to watch a video of creating a musical composition on the spot. Just like tian said, I also think it is such a great project(LINES) that people with no musical experiences can also participate and “bring novelty and inspiration” to the new world of music(using a very engaging method). By exploring this project, I also realized that people can find/learn new forms of musical interactions and expand the exploration of new artistic expressions.

Project-09

sketch
//Jasmin Kim
//Section D

var img;
var emo= ["•ᴥ•", "☉_☉", "◕‿‿◕", "。◕‿◕。", "✿◠‿◠"];

function preload() {
    var myURL = "https://i.imgur.com/gS9jRCI.jpg";
    img = loadImage(myURL);

}
function setup() {
    createCanvas(480, 480);
    background(0);
    img.loadPixels();
    img.resize(480,480);
    frameRate(200);
}

function draw() {
    // pixels appear
    var px = random(width);
    var py = random(height);
    var xx = constrain(floor(px), 0, width);
    var yy = constrain(floor(py), 0, height);
    var base = img.get(xx, yy);
    //emoji drawn
    fill(base);
    var ee = int(random(0,9));
    var rrandom = emo[ee]; 
    textSize(5)
    text(rrandom, px,py);
    //shape drawn
    noStroke();
    ellipse(px, py, random(0, 8), random(0, 8));
    rect(px, py, random(0, 10), random(0, 10));

}

For this project, I wanted to make something where emojis and shapes can be created at the same time. Rectangles and circles are random sized and emojis are selected from the emo arrays.

Looking Outwards 08

Hyphen-Labs is an international team of women of color working at the intersection of technology, art, science, and the future. Through their global vision and unique perspectives, they are driven to create meaningful and engaging ways to explore emotional, human-centered, and speculative design. In the process they challenge conventions and stimulate conversations, placing collective needs and experiences at the center of evolving narratives. It was interesting for me to learn that Hyphen-Labs experiments in immersive, computationally-driven, large scale installations that combine conceptual art, design, and science. Because I was able to discuss about virtual reality from my other design course too, this team’s work caught my attention. I admire that they listen to their co-collaborators and use emerging technology in their recent projects, highlighting themes of privacy and surveillance through the lens of speculative design, objects, neuroscience, architecture, and virtual reality.

I especially liked their NSAF project because it wasn’t just about 3D but included everything like product design, virtual reality (VR), and social-psychological/cognitive impact/biometric/fMRI research. This was a project that showed me how different parts of the design can collaborate together. When creating this, they were inspired by the lack of multidimensional representations of black women in technology.

Project-07-Curves

sketch

var angle=360;

function setup(){
  createCanvas(460,460);
  frameRate(5);
}

function draw(){
  background(43,40,41);
  for (var x = 50; x <= 430; x += 90) {       //curves repetition
    for (var y = 50; y <= 430; y += 90) {
      push();
      translate(x,y);
      stroke(mouseX,100,mouseY);
      curve1();
      stroke(mouseX,200,mouseY);
      curve2();
      pop();
    }
  }
}

function curve1(){     //outer curve
  var x;
  var y;
  var a = map(mouseX, 0, width, 0, 50); 
  var h = map(mouseY, 0, height, 0, 50); 
  var b = a / 10;
  beginShape();
  for (var i = 0; i < angle; i ++) {
    strokeWeight(2);
    noFill();
    var t = map(i, 0, 180, 0, TWO_PI)
    x = (a-b) * cos(t) + h * cos(((a-b)/b) * t);
    y = (a-b) * sin(t) - h * sin(((a-b)/b) * t);
    vertex (x, y)
  }
  endShape(CLOSE);
}

function curve2(){      //inner curve
  var x;
  var y;
  var a = map(mouseX, 0, width, 0, 30); 
  var h = map(mouseY, 0, height, 0, 30); 
  var b = a / 10;
  beginShape();
  for (var i = 0; i < angle; i++) {
    noFill();
    strokeWeight(1);
    var g = map(i, 0, 180, 0, TWO_PI);
    x = (a+b) * cos(g) - h * cos(g * (a+b)/b);
    y = (a+b) * sin(g) + h * sin(g * (a+b)/b);
    vertex(x, y);
  }
  endShape(CLOSE);
}

For this project, I wanted show how it would be possible to show diverse configurations only using two shapes. I tried to play around with the curves to create wallpaper-like patterns. For the interaction, when the mouseX/Y leads to top-right/bottom-left areas, it presents the simplest form while the curves show the most complicated form or nothing when the mouse is on the opposite areas. (color Blue and Orange also resembles the opposite tone of the ocean and the sun)

LookingOutwards-07

Martin Wattenberg is a co-leader of the People + AI Research initiative at Google. My career has encompassed machine learning, visualization, journalism, and art. Asking a question to himself, “what does music look like?” made him create this art piece. According to him, The Shape of Song is an attempt to answer his paradoxical question. I admire how he related music with this “visualization method called an arc diagram that highlighted repeated sections of music–or of any sequence–with translucent arcs.” It is very interesting to see how arc diagrams shape different thicknesses, sizes, saturation, etc to express diverse kinds of music. Just like every music has its own sequence, all of these art pieces create their own unique components.