Julie Choi – Final Project

My final project requires the use of a camera (webcam), so it does not properly run on WordPress. Here is the link to the zip file:

Julie_Choi_Final_Project.zip

Instructions: Start with a white background for this project. Preferably wear a dark shade shirt and place your portrait on the center on the screen. An easier way to interact with this short game is to wait for all the balls to drop from the top of the screen, but this does not matter hugely. Start clicking the red balls to make them disappear. Once the screen has no red balls, an orange screen will pop up and tell you “good job!”

Since the program does not run on this page, here are some screenshots of the step by step process of the game.

This is how it looks when all the bubbles have stacked on top of each other.
This is how it looks when you click on the red bubbles to get rid of them on the screen.
This screen will appear once all the red bubbles disappear from the screen.

final project

/*Julie Choi
15-104 Section E
jjchoi@andrew.cmu.edu
Final Project
*/

var px = 20;
var py =  100;
var myCaptureDevice;
var brightnessThreshold = 50;
var darknessThreshold = 45
var circleCenter = [];
var x = 5;
var radius = 20;
var randomBalls = 2;
var initGeneration = true;
var initRandom = true;
let timer = 30;


function setup() {
    createCanvas(640, 480);
    myCaptureDevice = createCapture(VIDEO);
    myCaptureDevice.size(640, 480); // attempt to size the camera. 
    myCaptureDevice.hide(); // this hides an unnecessary extra view.
    frameRate(60);
    // generateCircleCenter function is called in setup
    generateCircleCenter();   	
}

function generateCircleCenter(){
	// sets the circles on the top of the circle by pushing makeCircleFall into the circle center
    while(x <= width - radius){
        circleCenter.push(makeCircleFall(x, 20, radius, true, false));
        x += radius;
    }
    x = 5;
    generateRandom(randomBalls);
}

function generateRandom(n){
	// generates more lines of circles to fall after the previous line
    if (n == 0){
        return;
    }
    var j = int(random(0, circleCenter.length));
    if (circleCenter[j].random != true){
        circleCenter[j].random = true;
        generateRandom(n-1);
    } else {
        generateRandom(n);
    }
}

function draw() {
    background(220);
    myCaptureDevice.loadPixels(); 
    // draw the camera at 1:1 resolution
    image(myCaptureDevice, 0, 0);  
    fill(255);
    // call all the objects in draw function
    for(var c = 0; c < circleCenter.length; c++){
        if (circleCenter[c].exist){
            circleCenter[c].render();
            circleCenter[c].update();
            if(circleCenter[c].py >= height){
                circleCenter[c].reset();
            }
        }
    }
    // if the frameCount is divisible by 60, then a second has passed. it will stop at 0
    if (frameCount % 60 == 0 & timer > 0) { 
        timer --;
    }
    if (timer % 2 == 1 & initGeneration){
        initGeneration = false;
        generateCircleCenter();
    }
    if (timer % 2 == 0 & initGeneration != true){
        initGeneration = true;
    }

    // instruction text on the bottom
    fill(0);
    noStroke();
    fill(255);
    textFont('futura');
    textSize(10);
    text("use a white background", width / 2, height - 25);
    text("tip: wait for all the balls to fall and have fun playing with the balls :)", width / 2, height - 10);
    textAlign(CENTER, CENTER);
    textSize(30);
    text( "Pop the red bubbles!", width / 2, height - 50);

    // detect only the py of the yellow point exsisting on the screen
    var result = circleCenter.filter(obj => {
    return obj.py > 0 & obj.random;
    });
    // if the result of the value above is 0 then the timer stops
    if (result.length == 0){
        timer == 0;
        fill(249, 173, 129);
        rect(0, 0, width, height);
        noFill();
        stroke(255);
        strokeWeight(1);
        text("GOOD JOB!", width/2, height /2);
    }
}

function makeCircleFall(inputX, inputY, radius, exist, random) {
    return {px: inputX, py: inputY, radius: radius, exist: exist, random: random,
            update: Update,
            reset: Reset,
            render: Render
           };
}

function isColor(c) {
    return (c instanceof Array);
}

function Update() {
    // fetch the color of the pixel at the (px,py) location of the circleCenter
    var theColorAtPxPy = myCaptureDevice.get(this.px, this.py);
    // compute its brightness
    if(isColor(theColorAtPxPy)){
        var theBrightnessOfTheColorAtPxPy = brightness(theColorAtPxPy);
    }
    // if the circleCenter is in a bright area, move downwards.
    // else, if it's in a dark area, move up until we're in a light area
    if(theBrightnessOfTheColorAtPxPy > brightnessThreshold){
        this.py += 1;
    } else if(theBrightnessOfTheColorAtPxPy < darknessThreshold & this.py > 0){
        this.py -=1;
        theColorAtPxPy = myCaptureDevice.get(px, py);
    }
    // take the objects in the circleCenter array and filter them into the name obj
    // obj.px to keep track of each px in the circleCenter array
    // this makes each circle stack on top of each other regarding the distance of the diameter of each circle
    var result = circleCenter.filter(obj => {
        return obj.px == this.px & obj.py > this.py
    });
    for (var i = 0; i < result.length; i++) {
        if ((result[i].py - radius) < this.py){
            this.py --;
        }
    }
}

function Reset() {
	// reset py to stop at the bottom of the screen
    this.py = height;
}

function Render() {
	// choose 3 circles randomly from each line to fill with red
    if(this.random){
        fill("red");
        stroke(255);
        strokeWeight(2);
        if (initRandom){
            initRandom = false;
        }
    }
    // draw circle at points of px and py in a line across the top of the screen
    if (this.exist) {
        ellipse(this.px, this.py, this.radius, this.radius);
        fill(random(0, 255), random(0, 255), random(0, 150), 80);
        stroke(255);
        strokeWeight(2);
        initRandom = true;
    }
}

function mousePressed() {
	// circles stay on the screen if exist is true
	// when mouse is pressed, exist and random becomes false to pop and make the circle that was clicked disappear
    for (var i = 0; i < circleCenter.length; i++) {
        var c = circleCenter[i];
        if (c.exist & dist(c.px, c.py, mouseX, mouseY) < c.radius / 2) {
            c.exist = false;
            c.random = false;
            return;
        }
    }
}

Reflection: This project utilizes the concept of raining letter assignment that we did a few weeks back. Using what we have learned plus some outside research more about p5.js, I was able to execute a satisfying result. I would say though that that using the different existing functions of p5.js and applying my mathematical calculation for the timer and the balls stacked on top of each other was the most challenging part. Overall, I learned a lot of new operators in the program and enjoyed the process of controlling both the display and the function.

Julie Choi – Final Project Proposal – 12

For my final project for this class, I would like to make an interactive game that involved both the mouse, camera, and a patterned background of some sort.  The patterns will lie across the white space of the screen on the background. The patterns will be composed of different shapes with different shapes and different colors. The task is to “pop” or click on the right colors or the shapes in order to win. when the person on the camera moves, the patterns will move according to the silhouette of the person in the camera. When the user finishes the game, the screen will transition into a different screen and will inform the user whether they have won or lost the game.

This is how the game will start when the user first interacts with the screen.

Julie Choi – Looking Outwards – 12

Sand Dollar with sand stroke painting technique.

This is a project called Sand Dollar by a programming company called Complexification. This project was created through a constructed radical pattern through a technique called sand stroke painting. The radical form is controlled under a delicate craft of tree-like structure that is slowly turned clockwise around the origin. Hundred of radical patterns are created through programming creating a form with its own unique shape.

1984X1984 by RAFAEL LOZANO-HEMMER.

This installation is called 1984X1984 by an electronic artist, Rafael Lozano-Hemmer. When a person stands in front of the screen, it mimics the silhouette of the object by shifting the patterns on the screen. This is one art piece from his series, Shadow Box in which it is built upon a computerized tracking system. The background pattern is pulled out from random addresses photographed by Google Street View. The piece is moved by any object interacting in front of the screen.

These two projects have a very similar characteristic. They are both generated through programming with a basis of patterns that fill up the visual composition. These projects can potentially inspire my final project because there are many ways to play around with patterns. I plan to create my final project with a pattern of some sort that has the ability to interact with another factor. I personally enjoy interactive art because the second element that reacts to the base of the art becomes part of the artwork.

Julie Choi – Project 11 – Composition

Julie Choi Composition

/*Julie Choi
15-104 Section E
jjchoi@andrew.cmu.edu
Project-11
*/

var shapeSize = 50;

function setup() {
    createCanvas(400, 400);
    background(0);

}

function mousePressed(){

    //randomize angle to create different compositions
    var angle = random(30, 90);
    //create turtle variable
    var turtle = makeTurtle(mouseX, mouseY);
    // set like color to light turquoise
    turtle.setColor(color(162, 215, 207));

    //draw geometric composition
    for(var x = 0; x < 20; x++){
        turtle.penDown();
        turtle.forward(shapeSize);
        turtle.right(angle);
        turtle.forward(shapeSize);
        turtle.right(angle);
        turtle.forward(shapeSize);
        turtle.right(angle);
        turtle.forward(shapeSize);
        turtle.right(angle);
        //alter angle when ever new shape is drawn
        shapeSize -= 1;
        turtle.right(25);
    }
}




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 week’s composition project, I enjoyed the freedom that we had with the turtle graphics. My project was created after I had fun creating randomized circular geometric shapes. I used some techniques that I learned from the video lectures and the recitation.

 

After many clicks, my composition creates an abstract spider web.

Julie Choi – Looking Outwards – 11

This video shows how a person can interact with a musical machine Apparatum – Inspired by the Polish Radio Experimental Studio.

Created by a solo exhibition, panGenerator, Apparatum is made with a digital interface that produces purely electroacoustic sounds strictly through creating analog sounds. The visual language within this machine produces audio cues to create a collection of a symphony. I admire this project because it is an innovative way to create work of audio through customizable visual cues. Although there are many music producing machines, this work, in particular, is designed with two magnetic tapes to create tape samplers to collect the noise and base tone of the music. I also respect the physical design of this machine because it makes the user feel like they are in full control as it opens up an interactive space with the screen attached to the standing level of human height.

Julie Choi – Project 10 – Landscape

Julie Choi Landscape

/*Julie Choi
15-104 Section E
jjchoi@andrew.cmu.edu
Project-10
*/
var skyscrapers = [];
var terrainSpeed = 0.0005;
var terrainDetail = 0.005;

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


function draw() {
    background(200); 
    buildMountains();
    buildRoad();
    addSkyscrapers();
    removeSkyscrapers();
    randomSkyscrapers(); 
    
}

// build mountains on the background to show nature
function buildMountains(){
	push();
    beginShape();
    fill(67, 67, 22);
    vertex(0,height);
    for (var x = 0; x < width; x++) {
        var t = (x * terrainDetail) + (millis() * terrainSpeed);
        var y = map(noise(t), 0, 1, 0, height);
        vertex(x, y);
    }
    vertex(width, height);
    endShape();
    pop();
}

//build rod on the bottom to create depth in composition
function buildRoad(){
	fill(25, 51, 76);
	rect(0, 4 * height/5 + 15, width, 80);
}

//as skyscrapers disappear on the left, create new skyscrapers from the right
function addSkyscrapers(){
    for (var i = 0; i < skyscrapers.length; i++){
        skyscrapers[i].move();
        skyscrapers[i].display();
    }
}

//When skyscrapers hit the edge of canvas, make them disappear
function removeSkyscrapers(){
    var buildingsToKeep = [];
    for (var i = 0; i < skyscrapers.length; i++){
        if (skyscrapers[i].x + skyscrapers[i].breadth > 0) {
            buildingsToKeep.push(skyscrapers[i]);
        }
    }
    skyscrapers = buildingsToKeep;
}

// add probability to update the numbers of skyscrapers to the end
function randomSkyscrapers() {
    var newBuildingLikelihood = 0.3; 
    if (random(0,1) < newBuildingLikelihood) {
        skyscrapers.push(makeSkyscrapers(width));
    }
}


// print skyscrapers for every changing frame
function moveSkyscrapers() {
    this.x += this.speed * 2;
}
    

// draw skyscrapers with bright colored windows
function displaySkyscrapers() {
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight;  
    stroke(0); 
    push();
    translate(this.x, height - 40);
    fill(random(0,255), random(0,255), random(0,255));
    stroke(200); 
    for (var i = 0; i < this.nFloors; i++) {
        rect(5, -15 - (i * floorHeight), this.breadth - 10, 10);
    }
    pop();
}


function makeSkyscrapers(birthLocationX) {
    var windows = {x: birthLocationX,
                breadth: 50,
                speed: -3.5,
                nFloors: round(random(5,10)),
                move: moveSkyscrapers,
                display: displaySkyscrapers}
    return windows;
}

I felt like this project was a little bit more challenging than the previous projects because using many objects can get pretty tricky. I concluded this project by making a landscape that portrays my views Seoul, Korea. Seoul is a big city with very colorful lights and building signs because so many business branches are located in the area. Bright lights and colorful signs along the buildings basically dominate any views of the mountains that are located outside of the city. I tried to portray this image in this project by representing the colorful rectangles as tall skyscrapers. Overall, I feel like I ended up with a satisfying result because my meanings show through the visuals.

Julie Choi – Looking Outwards – 10

color mapping algorithm presented by Kate Hollenbach based on the information on Wikipedia.

This project is called Color Mapping Algorithm conducted by an artist/programmer, Kate Hollenbach. Hollenbach created this piece based on the information on Wikipedia using a program called, Chromogram. The program basically sequences big text data into visually appealing patterns and color blocks. Categorizing the number of edits made on the page and the number of article headlines, Hollenbach produces a set of color patterns to show the ratio of each relative activities. I admire this project because this is a very useful tool for visual people who are analyzing a large amount of data. Although Hollenbach focused on specific sections of information on Wikipedia, this concept can be applied to many different platforms.
Kate Hollenbach works to create and examine interactive systems and inventive technological forms of space commonly in the fields of digital devices. She has built herself as an interface designer and a product developer to be in the place that she is now. She was previously the Director of Design and Computation at Oblong Industries and collected her skills of leading designers and programmers to develop systems and interfaces that are mainly user oriented.

Julie Choi – Project 09 – Portrait

julie and alice

/*Julie Choi
15-104 Section E
jjchoi@andrew.cmu.edu
Project-09
*/
var underlyingImage;

function preload() {
    var myImageURL = "https://i.imgur.com/re8jPYz.jpg";
    underlyingImage = loadImage(myImageURL);
}

function setup() {
    createCanvas(700, 700);
    background(0);
    underlyingImage.loadPixels();
    frameRate(1000);
}

function draw() {
    var px = random(width);
    var py = random(height);
    var ix = constrain(floor(px), 0, width-1);
    var iy = constrain(floor(py), 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);
    var ballSize = map(mouseX, 0, width, 4, 20);

    stroke(theColorAtLocationXY);
    strokeWeight(2);
    line(px + random(10), py + random(10), px + random(30), py + random(30));

    push();
    rotate(random(0, PI));
    noStroke();
    fill(theColorAtLocationXY);
    quad(px + random(30), py + random(30), px-random(30), py-random(30), px+random(30), py+random(30), px - random(30), py - random(30));
    pop();
}

I had a lot of fun doing this project because I had the chance to use my personal photo as a visual element of the project. I chose a photo of me and my friend that we took during the sunset of an afternoon.

Original Image
Result after few minutes

Julie Choi – Looking Outwards – 09

This project was shed light on Sophia Kim’s Looking Outwards for Week 3.

Hyper-Toroidal Deep Surface, Sean Ahlquist, Prof. Achim Menges, Boyan Mihaylov, Viktoriya Nicolova, from seminar Deep Surface Morphologies.

This is one of the many pieces of artworks by Sean Ahlquist who is an expert architecture professor within the fields of interactive systems and computational media at the University of Michigan. This initially caught my eyes because of the intricate details of form within the art piece. I learned that this piece was created through a Java-based framework to represent multiple membrane systems that represent the delicacy in our human body. I also enjoyed Sophia’s personal view on this project how it reminded her of knowledge of DNA molecules that she learned in high school. I would have also really enjoyed her take on analyzing the specific process of this sculpture and what the artist’s intentions were when developing the project.

Julie Choi – Looking Outwards – 08

Maria Scileppi is an artist and a designer whose career has been dedicated to developing mission-driven programs. She gave a lecture in Eyeo talking about some of her works and experiments that had the most takeaways. She confidently believes in collaboration has it creates a beautiful mix of people’s strengths and alertness into an execution. She solely believes that collaboration complements occupation’s creativity and that it extends the reach as a creator. One of my favorite projects done by Scileppi is her social experiment in which she makes a friend every day for a year. This required her to be vulnerable to strangers by telling her story and opening up first. However, the takeaways from this social experiment were that you cannot neglect other people’s stories and perspectives because since art and thinking expands with collaboration. Under the collaboration, people tend to bring their best attitudes and abilities because of the psychological trust that they build upon each other while working and build on ideas.
The way Scileppi enunciated her words while speaking really helped me understand the point she was trying to deliver. Although she was standing behind the podium during her lecture, she made sure that she had clear eye contact and made gestures that kept the attention of the audience on her. Another notable thing was that she used visual cues in her slides so that the audience caught specific transitions during her presentation.

Link to the Vimeo: https://vimeo.com/channels/eyeo2015/135073611
Link to Maria Scileppi’s website: http://www.mariascileppi.com/