Final Project: Air Pollution Simulator

sketch
var plastic = ["https://i.imgur.com/n3n2yAx.png", 
                "https://i.imgur.com/GO1fho6.png",
                "https://i.imgur.com/HTF7LVN.png",
                "https://i.imgur.com/lPCz5Kl.png",
                "https://i.imgur.com/uOAHfcT.png",
                "https://i.imgur.com/714d3E7.png",
                "https://i.imgur.com/mxW1JT4.png",
                "https://i.imgur.com/2diHO2t.png",
                "https://i.imgur.com/YfCSzcQ.png",
                "https://i.imgur.com/TZovsxa.png",
                "https://i.imgur.com/lK07FmR.png"];
var waste1;
var waste2;
var waste3;
var waste4;
var waste5;
var waste6;
var waste7;
var waste8;
var waste9;
var waste10;
var waste11;

var humanfiles = [];
var human = [];
var vehiclefiles = [];
var vehicles = [];
var wheel;
var instruction;

var newBackground = [];
var newCharacter = [];

var c1,c2;
var mode = false;
var instructionMode = true;

function preload() {
    //waste images
    waste1 = loadImage(plastic[0]);
    waste2 = loadImage(plastic[1]);
    waste3 = loadImage(plastic[2]);
    waste4 = loadImage(plastic[3]);
    waste5 = loadImage(plastic[4]);
    waste6 = loadImage(plastic[5]);
    waste7 = loadImage(plastic[6]);
    waste8 = loadImage(plastic[7]);
    waste9 = loadImage(plastic[8]);
    waste10 = loadImage(plastic[9]);
    waste11 = loadImage(plastic[10]);

    //characters
    humanfiles[0] = "https://i.imgur.com/gGl600Z.png";
    humanfiles[1] = "https://i.imgur.com/6yqtw3q.png";

    for (var i = 0; i < humanfiles.length; i++) {
        human[i] = loadImage(humanfiles[i]);
    }

    //vehicle
    vehiclefiles[0] = "https://i.imgur.com/gnO3lJm.png";
    vehiclefiles[1] = "https://i.imgur.com/S1GOMdC.png";

    for (var i = 0; i < vehiclefiles.length; i++) {
        vehicles[i] = loadImage(vehiclefiles[i]);
    }
    wheel= loadImage("https://i.imgur.com/Wkpp7B1.png");
    instruction = loadImage("https://i.imgur.com/QcOMxYC.png");
}
//Factory made of waste
function generateBackground(bx, bdx) {
    var b = {
        x: bx, 
        y:height-75,
        dx: bdx,
        items: random([waste1, waste2, waste3, waste4, waste5, waste6, waste7, waste8, waste9, waste10, waste11]),
        moveFunction: moveBackground,
        drawFunction: drawBackground
    }
    return b;

}

function moveBackground() { //generative landscape
    if (keyIsDown(RIGHT_ARROW)) {
        this.x -= this.dx; 
               
    } else if (keyIsDown(LEFT_ARROW)) {
        this.x += this.dx;
    }
    
}


function drawBackground() {
    var smallSize = 20;
    var bigSize = 30
    push();
    if (this.items == waste1) {
        image(waste1, this.x, 325-waste1.height);
    } else if (this.items == waste2) {
        image(waste2, this.x, 325-waste2.height);
    } else if (this.items == waste3) {
        image(waste3, this.x, 325-waste3.height);
    } else if (this.items == waste4) {
        image(waste4, this.x, 325-waste4.height);
    } else if (this.items == waste5) {
        image(waste5, this.x, 325-waste5.height);
    } else if (this.items == waste6) {
        image(waste6, this.x, 325-waste6.height);
    } else if (this.items == waste7) {
        image(waste7, this.x, 325-waste7.height);
    } else if (this.items == waste8) {
        image(waste8, this.x, 325-waste8.height);
    } else if (this.items == waste9) {
        image(waste9, this.x, 325-waste9.height);
    } else if (this.items == waste10) {
        image(waste10, this.x, 325-waste10.height);
    } else if (this.items == waste11) {
        image(waste11, this.x, 325-waste11.height);
    }

    pop();
    

}

function itemShow() {
    for(var i = 0; i < 100; i++) {
        newBackground[i].moveFunction();
        newBackground[i].drawFunction();
    }
}

//Character skating
function makeSkateCharacter (cx, cdx) {
    var c = {
        x: cx,
        dx: cdx,
        y: height-150,
        movingRight: true,
        stepSkateFunction: stepSkateCharacter,
        drawSkateFunction: drawSkateCharacter
    }
    return c;
}

function stepSkateCharacter () {
    if (keyIsDown(RIGHT_ARROW)) {
        this.movingRight = true;
        if (this.x < width/2) {
            this.x += this.dx;
        } 
    }
}

function drawSkateCharacter () {
    image(vehicles[0], this.x-25, height-80, 70, 25);
    image(human[0], this.x, this.y);

    
}

//Character riding bike
function makeBikeCharacter (mx, wmx, mdx) {
    var m = {
        x: mx,
        wx: wmx,
        dx: mdx,
        y: height-150,
        movingRight: true,
        stepBikeFunction: stepBikeCharacter,
        drawBikeFunction: drawBikeCharacter,
    }
    return m;

}


function stepBikeCharacter () {
    if (keyIsDown(RIGHT_ARROW)) {
        this.movingRight = true;
        push(); //bike wheel rotating
        imageMode(CENTER);
        translate(this.wx+18, this.y+73);
        r+=0.5;
        rotate(r);
        image(wheel, 0, 0, 35, 35);
        pop();
        push();
        imageMode(CENTER);
        translate(this.wx+103, this.y+73);
        r+=1;
        rotate(r);
        image(wheel, 0, 0, 35, 35);
        pop();

        if (this.x < width/2) {
            this.x += this.dx;
        } 

    }

}
var r = 0;

function drawBikeCharacter () {
    if (this.movingRight == true) {
        image(vehicles[1], this.x-40, height-120, 120, 60);
        image(human[1], this.x, this.y);
        
        
    } else {
        push();
        translate(600, 0);
        scale(-1, 1);
        image(vehicles[1], this.x-25, height-80, 200, 100);
        image(human[1], this.x, this.y);
        pop();

    }

}




function setup() {
    createCanvas(600, 400);
    frameRate(15);
    var n = 0;
    for (var i = 0; i < 100; i++) {
        var x = generateBackground(n, 5);
        newBackground.push(x);
        if (newBackground[i].items == waste1) { //placement of each waste factory
            n += waste1.width-2;
        } else if (newBackground[i].items == waste2) {
            n += waste2.width-2;
        } else if (newBackground[i].items == waste3) {
            n += waste3.width-2;
        } else if (newBackground[i].items == waste4) {
            n += waste4.width-2;
        } else if (newBackground[i].items == waste5) {
            n += waste5.width-2;
        } else if (newBackground[i].items == waste6) {
            n += waste6.width-2;
        } else if (newBackground[i].items == waste7) {
            n += waste7.width-2;
        } else if (newBackground[i].items == waste8) {
            n += waste8.width-2;
        } else if (newBackground[i].items == waste9) {
            n += waste9.width-2;
        } else if (newBackground[i].items == waste10) {
            n += waste10.width-2;
        } else if (newBackground[i].items == waste11) {
            n += waste11.width-2;
        }
    }

    var d = makeSkateCharacter(width/2, 3);
    var e = makeBikeCharacter(width/2, width/2-40, 5);

    newCharacter.push(d);
    newCharacter.push(e);
   

}

function draw() {
    var cAmount = 100;
    
    c1 = color(80);
    //gradient color change & fleeting effect on the factory in sustainable future
    c1.setAlpha(10 + 10 * sin(millis() / 1000)); 
    c2 = color(230);
    c4 = color(225,247,255);
    c3 = color(0, 171, 245);
    c3.setAlpha(10 + 10 * sin(millis() / 1000));

    var year = 2050;
    var title = "WHICH FUTURE DO YOU CHOOSE TO LIVE IN?";
  
        
    
    noStroke();
    if (mode) {        
         for(let y=0; y<height; y++){ //gradient background
            n = map(y,0,height,0,1);
            let newc = lerpColor(c3,c4,n);
            stroke(newc);
            line(0,y,width, y);
        }
        fill(255);
        textSize(270);
        text(year, width/2, height-82);
        textSize(25);
        textAlign(CENTER);
        text(title, width/2, height-300);
        itemShow();
        fill(100);
        noStroke();
        rect(0, height-76, width, 76);
        newCharacter[0].stepSkateFunction();
        newCharacter[0].drawSkateFunction();
    } else {
        background(0);
        for(let y=0; y<height; y++){
            n = map(y,0,height,0,1);
            let newc = lerpColor(c1,c2,n);
            stroke(newc);
            line(0,y,width, y);
        }
        fill(255);
        textSize(270);
        text(year, width/2, height-82);
        textSize(25);
        textAlign(CENTER);
        text(title, width/2, height-300);
        itemShow();
        fill(100);
        noStroke();
        rect(0, height-76, width, 76);
        newCharacter[1].drawBikeFunction();
        newCharacter[1].stepBikeFunction();

    }

    if (instructionMode) {
        push();
        imageMode(CENTER);
        image(instruction, width/2, height/2);
        pop();    }

    if (keyIsDown(81)) { //show instruction page
        push();
        imageMode(CENTER);
        image(instruction, width/2, height/2);
        pop();
     } 
    
    
}

//toggle between bike and skate
function keyPressed() {
    if (key == ' ') {
        if (mode == false) {
            mode = true;
        } else if (mode == true) {
            mode = false;
        }
    } 

}

function mousePressed() {
    if (instructionMode == true){
        instructionMode = false;
    }

}














When I heard that the topic for this project is climate change, I was instantly reminded of previous poster work on air pollution, in which I used everyday waste material to draw factories as a metaphor.

This program is a future simulator that shows two alternative versions of 2050’s air quality based how sustainable our lifestyle is. I wanted to continue this use of symbols, so I decided to create a character that interacts with this environment by creating a character that rides a vehicle that is also a metaphor for wasteful lifestyle and a sustainable one. The user of this program can toggle between a character that rides a skateboard made out of a reusable water bottle and a character that rides a motorcycle made of waste like aluminum can wheels. As the user presses down the right arrow key, they can see that the character is moving in the generative landscape. As they toggle the space bar, they can change the vehicle, and see how the air quality changes depending on how much single use products we use. In the sustainable future factories made out of trash starts to wither away, in contrast to how static they are in the polluted version. The main goal of this program is to alert people of the drastic difference our everyday behavior can make to our environment and future and provoke action.in goal of this program is to alert people of the drastic difference our everyday behavior can make to our environment and future and provoke action.

Project 11: Generative Landscape

As winter approaches, I wanted create a landscape that resembles the cold weather and loneliness of the season. That’s why I decided to keep a greyscale color scheme.

sketch
// Christy Zo
// andrew id: czo
// Section C

var hill = [];
var hill2 = [];
var noiseParam = 0;
var noiseStep = 0.05;
var noiseParam2 = 0;
var noiseStep2 = 0.05

var snowflakePerLayer = 200;
var maxSize = 3;
var gravity = 0.75;
var layerCount = 5;
var snowflakes = [];

var walkImage = [];
var newCharacter = [];
var airplane;
var newPlane = [];

var buildings = [];



function preload() {
    var filenames = [];
    filenames[0] = "https://i.imgur.com/Uz3ltZC.png";
    filenames[1] = "https://i.imgur.com/ofNc4Wv.png";
    filenames[2] = "https://i.imgur.com/7hMA7W6.png";
    filenames[3] = "https://i.imgur.com/3RBTODb.png";
    filenames[4] = "https://i.imgur.com/FliwTsj.png";

    for (var i = 0; i < filenames.length; i++) {
        walkImage[i] = loadImage(filenames[i]);
    }
    airplane = loadImage("https://i.imgur.com/dbPwlhp.png");
}

//airplane 
function makePlane(px, pdx, py, pdy) {
    var p = {x: px, dx: pdx, y:py, dy: pdy,
            stepFunction: stepPlane,
            drawFunction: drawPlane
        }
    return p;
}

function stepPlane() {
    this.x += this.dx;
    this.y += this.dy;

    if (this.x > 480) {
        this.x = 0;
        this.y = 100;
    }
}

function drawPlane() {
    image(airplane, this.x, this.y, 20, 20);
}

//person
function makeCharacter(cx, cdx) {
    var c = {x: cx, dx: cdx,
             // walkingRight: true, 
             imageNum: 0,
             stepFunction: stepCharacter,
             drawFunction: drawCharacter
         }
    return c;
}

function stepCharacter() {
    this.x += this.dx;
    this.imageNum += 1;
    
    if (this.imageNum == 4 ) {
        this.imageNum = 0;
    }

    if (this.x >= 680) { 
        this.x = 200;
    } 
}

function drawCharacter() {
    image(walkImage[this.imageNum], this.x, 430);
    
}

//snowflake update
function updateSnowflake(snowflake) {
    var diameter = (snowflake.l * maxSize) / layerCount;
    if (snowflake.y > height + diameter) {
        snowflake.y = -diameter;
    } else {
        snowflake.y += gravity * snowflake.l * snowflake.mass;
    }
}

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

function removeBuildingsThatHaveSlippedOutOfView(){
    var buildingsToKeep = [];
    for (var i = 0; i < buildings.length; i++){
        if (buildings[i].x + buildings[i].breadth > 0) {
            buildingsToKeep.push(buildings[i]);
        }
    }
    buildings = buildingsToKeep; // remember the surviving buildings
}

function addNewBuildingsWithSomeRandomProbability() {
    // With a very tiny probability, add a new building to the end.
    var newBuildingLikelihood = 0.007; 
    if (random(0,1) < newBuildingLikelihood) {
        buildings.push(makeBuilding(width));
    }
}

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

// draw the building and some windows
function buildingDisplay() {
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight; 
    fill(255); 
    noStroke; 
    push();
    translate(this.x, height - 40);
    rect(0, -bHeight, this.breadth, bHeight);
    stroke(200); 
    fill(200);
    for (var i = 0; i < this.nFloors; i++) {
        rect(5, -15 - (i * floorHeight), this.breadth - 10, 10);
    }
    pop();
}

function makeBuilding(birthLocationX) {
    var bldg = {x: birthLocationX,
                breadth: 50,
                speed: -1.0,
                nFloors: round(random(2,8)),
                move: buildingMove,
                display: buildingDisplay}
    return bldg;
}


function setup() {
    createCanvas(480, 480);
    noStroke();
    frameRate(20);
    for (i=0; i<width/5+1; i++) {
        var n = noise(noiseParam);
        var value = map(n, 0, 1, 100, height);
        
        hill.push(value);
        noiseParam += noiseStep;

    }


// snowflakes
    for (let l = 0; l < layerCount; l++) {
        snowflakes.push([]);
        for (let i = 0; i < snowflakePerLayer; i++) {
            snowflakes[l].push({
            x: random(width),
            y: random(height),
            mass: random(0.75, 1.25),
            l: l + 1
            });
        }
    }
    for (var i = 0; i < 10; i++){
        var rx = random(width);
        buildings[i] = makeBuilding(rx);
    }

    imageMode(CENTER);

    var d = makeCharacter(50, 1);
    newCharacter.push(d);

    var p = makePlane(10, 5, 100, -1);
    newPlane.push(p);
    
}

function draw() {
    background(0);

    for (let l = 0; l < snowflakes.length; l++) {
        var layer = snowflakes[l];

        for (let i = 0; i < layer.length; i++) {
            var snowflake = layer[i];
            fill(255);
            circle(snowflake.x, snowflake.y, (snowflake.l * maxSize) / layerCount);
            updateSnowflake(snowflake);
        }
    }

    beginShape();
        vertex(0, height);
        for (i=0; i<width/5+1; i++) {
            noStroke();
            fill(200);
            vertex(i*5, hill[i]);
 

        }
        vertex(width, height);
        endShape();

        var n = noise(noiseParam);
        var value = map(n, 0, 1, 100, height);
        hill.shift();
        // append(hill, value);
        hill.push(value);
        noiseParam += noiseStep;
    fill(150);
    rect(0, 430, width, height);


    updateAndDisplayBuildings();
    removeBuildingsThatHaveSlippedOutOfView();
    addNewBuildingsWithSomeRandomProbability(); 


    newCharacter[0].stepFunction();
    newCharacter[0].drawFunction();

    newPlane[0].stepFunction();
    newPlane[0].drawFunction();
    // image(walkImage[1], 100,100);

}

*Due to the way I saved my png drawing of the person, you have to wait a little long for the person to appear!*

After I created this work, I realized that the mountain behind moves significantly faster than everything else, making it look like this space is not on earth. Maybe this could be what winter looks like in a different planet.

2. Looking Outwards 11: Societal Impacts of Digital Art

As technology develops, the definition of art and its value keeps evolving. The idea of craftsmanship and delicate human effort is now replaced by manufacturers and computer technology that can create similar feature within seconds with lines of codes. When I read Sebastian Smee’s criticism on Beeple’s artwork, I could understand why he was so critical of the digital artwork being valued more than Michelangelo’s. But I think that there should be different standards for work that is digitally produced and physically produced. I think they carry different values—for example, digital work can be a sign for newly developed technology and testing out their uses in creative ways, even if they don’t have the delicacy and the conetextual depth of traditional art.

https://www.washingtonpost.com/entertainment/museums/beeple-digital-artwork-sale-perspective/2021/03/15/6afc1540-8369-11eb-81db-b02f0398f49a_story.htm

Project 10: Sonic Story

sketch
//Christy Zo
//Section C

var cricketSound;
var roosterSound;
var cowSound;
var pigSound;
var sunHue;

function preload() {
    cricketSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/cricketSound.wav");
    roosterSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/roosterSound.wav");
    cowSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/cowSound.wav");
    pigSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/pigSound.wav")
 }

function soundSetup() {
    osc = new p5.TriOsc();
}
function setup() {
    createCanvas(600, 300);
    useSound();
    frameRate(30);
}



function barn(x) {
    stroke(255);
    strokeWeight(2);
    fill(50);
    rect(x, 100, 200, 150);
    fill(255);
    rect(x+10, 110, 180, 80);
    fill(50);
    rect(x+10, 200, 180, 40);
    line(x+10, 200, x+190, 240);
    line(x+10, 240, x+190, 200);
    triangle(x, 100, x+200, 100, x+100, 30);
    triangle(x+15, 100, x+185, 100, x+100, 40);
}

function rooster(x) {
    stroke(0);
    fill(255);
    line(x, 150, x-30, 190); 
    line(x, 150, x+30, 190);
    circle(x, 150, 50); 
    fill(220);
    circle(x, 180, 20);
    triangle(x, 140, x-10, 110, x+10, 110); 
    fill(150);
    triangle(x, 150, x-10, 160, x+10, 160);
    triangle(x, 170, x-10, 160, x+10, 160);
    fill(255);
    circle(x-10, 145, 5);
    circle(x+10, 145, 5);

}

function cow(x) {
    fill(255);
    stroke(0);
    rect(x, 125, 50, 50);
    fill(200);
    ellipse(x+25, 170, 52, 30); //nose
    fill(255);
    circle(x+12, 170, 10);
    circle(x+37, 170, 10);
    circle(x+15, 145, 5);
    circle(x+35, 145, 5);
    ellipse(x-10, 125, 25, 10); //ears
    ellipse(x+55, 125, 25, 10);
    line(x, 150, x-30, 190);
    line(x+50, 150, x+80, 190);

}

function pig(x) {
    line(x, 150, x-30, 190);
    line(x, 150, x+30, 190);
    circle(x, 150, 60);
    circle(x-10, 145, 5);
    circle(x+10, 145, 5);
    fill(150);
    ellipse(x, 160, 30, 15);
    fill(255);
    circle(x-5, 160, 5);
    circle(x+5, 160, 5);
    fill(100);
    triangle(x-20, 120, x-25, 130, x-15, 125);
    triangle(x+20, 120, x+25, 130, x+15, 125);

    

}

var light = 0;
var position = 255;
function draw() {
    
    background(light);
    fill(light);
    rect(0, 0, 600, 300);

    sunHue = map(position, 0, height, 255, 0);
    fill(sunHue, 150, 0);
    ellipse(200, position, 50, 50);
    if (position < -50) {
        position = 300;
        light = 0;
        frameCount = 0;

    }
    fill(220);
    noStroke();
    rect(0, 200, 600, 300);
    barn(0);
    barn(200);
    barn(400);



    rooster(100);
    cow(275);
    pig(500);

    light = light + 1;
    position = position - 1;
    if (frameCount == 30) {
        cricketSound.play();
    }
    if (frameCount == 80) {
        roosterSound.play();

    } else if (frameCount == 140) {
        cowSound.play();
    } else if (frameCount == 200) {
        pigSound.play();
    }

    if (roosterSound.isPlaying()) {
        fill(255,0,0);
        circle(100, 180, 20);
        triangle(100, 140, 90, 110, 110, 110);
        fill(255,255,0);
        triangle(100, 150, 100-10, 160, 100+10, 160);
        triangle(100, 170, 100-10, 160, 100+10, 160);
    } else if (cowSound.isPlaying()) {
        fill(165,42,42);
        ellipse(275+25, 170, 52, 30);
        fill(255);
        circle(275+12, 170, 10);
        circle(275+37, 170, 10);
    } else if (pigSound.isPlaying()) {
        fill(255, 192, 203);
        triangle(500-20, 120, 500-25, 130, 500-15, 125);
        triangle(500+20, 120, 500+25, 130, 500+15, 125);
        ellipse(500, 160, 30, 15);
        fill(255);
        circle(500-5, 160, 5);
        circle(500+5, 160, 5);

    }

}


I was reminded of the story Animal Farm, and wanted to create a simple yet cute! I wanted to make everything greyscale, but emphasize the colors when each of the animals sound play!

Looking Outwards 09: A Focus on Women and Non-binary Practitioners in Computational Art

Filipa Valente is an exhibit designer and architect who specializes I the development of designs for experiences, exhibits, and architecture. She has a background in architecture and a practice as a media artist. I think that her work on mobility is particularly intriguing. Mobility is a field that has a lot of potential with innovative design. I’m really interested in how mobility plays a role into redefining spatial design.

FI_02_(fabric images).jpg
Volvo Pure Tensions Pavilion

I was fascinated by Filipa Valente’s “The Pure Tension Pavilion” for Volvo Italia. This project is a design of a portable charger for the new Volvo V6 plug-in hybrid electric car which not only charges the car but also flat-packs to fit in the trunk of the car and assembles in less than one hour. It is also very aesthetically pleasing with its organic design, also serving as a structure that roofs the vehicle.

Project 09: Computational Portrait

First reading the instructions for this project, I was reminded of mosaic effect on images.

I proceeded to work with square pixels, but I realized that using a rounded shape like an ellipse could create a more organic jittery effect on my animated portrait.

sketch
var p = 1000;
var particles = [];

function preload() {
    img = loadImage("https://i.imgur.com/30d3jx2.jpeg"); 
}

function setup() {
  createCanvas(480, 480);
  pixelDensity(5);
 
  for (var i = 0; i < p; i++) {
    particles[i] = new squareParticle(240, 240); //appending new square paricles to the array that will draw the shapes
  }
}

function draw() {
 
  for (var i = 0; i < particles.length; i++) {
    particles[i].update();
    particles[i].show();
  }
}


function squareParticle(x, y) { 
  this.x = x;
  this.y = y;
  this.r = random(1, 5); //range of particle size

  this.update = function() { 
    this.x += random(-3, 3);
    this.y += random(-3, 3);

    this.x = constrain(this.x, 0, width);
    this.y = constrain(this.y, 0, height);
  };

  this.show = function() {
    stroke(250);
    strokeWeight(0.1);
    var c = img.get(this.x, this.y);
    fill(c); 
    ellipse(this.x, this.y, this.r, this.r+3);
  

  }
}

Project 07: Composition with Curves

sketch
//Christy Zo
//Section C

var nPoints = 400;
function setup() {
    createCanvas(480, 480);
}

function draw() {
    background(220);
    push();
    translate(width / 2, height / 2);
    drawEpitrochoidCurve();
    pop();
    push();
    translate(width / 2, height / 2);
    drawEpicycloidCurve();
    pop();
    push();
    translate(width / 2, height / 2);
    rotate(radians(90)); //rotating Epicycloid to create a radial pattern
    drawEpicycloidCurve();
    pop();
    push();
    translate(width / 2, height / 2);
    rotate(radians(45));
    drawEpicycloidCurve();
    pop();
    push();
    translate(width / 2, height / 2);
    rotate(radians(135));
    drawEpicycloidCurve();
    pop();


}

function drawEpicycloidCurve() {
    // Epicycloid:
    // http://mathworld.wolfram.com/Epicycloid.html
    
    var x;
    var y;
    
    var a = constrain(mouseY,0, height);
    var b = constrain(mouseX, 0, width);
    //var h = constrain(mouseY / 8.0, 0, b);
    //var ph = mouseX / 50.0;
    noFill();
    stroke(0);
    beginShape();
    for (var i = 0; i < nPoints; i++) {
        var t = map(i, 0, nPoints, 0, TWO_PI);
        
        x = 4 * b * cos (t)* cos (t)* cos (t);
        y = a * sin (t) *sin (t)* sin (t);
        
      vertex(x, y);
    }
    endShape(CLOSE);

}

function drawEpitrochoidCurve() {
    // Epicycloid:
    // http://mathworld.wolfram.com/Epitrochoid.html
    
    var x;
    var y;
    
    var a = mouseX;
    var b = a / 2.0;
    var h = constrain(mouseY / 8.0, 0, b);
    var ph = mouseX / 120.0;
    
    fill(mouseX, mouseY, mouseX);
    beginShape();
    for (var i = 0; i < nPoints; i++) {
        var t = map(i, 0, nPoints, 0, TWO_PI);
        
        x = (a + b) * cos(t) - h * cos(ph + t * (a + b) / b);
        y = (a + b) * sin(t) - h * sin(ph + t * (a + b) / b);
        vertex(x, y);
    }
    endShape(CLOSE);
    
}

In this project, I wanted to create something that not only shows horizontal and vertical change, but something that goes diagonally too. I was inspired by how stars twinkle and their strokes/beams of light reduce and increase as it sparkles.

Free Drawings Of Stars Download Free Clip Art Free - Christmas Star  Coloring Page - Png Download - Full Size Clipart (#267769) - PinClipart
sample image of star

snippets of code:

As the cranioid in the center increases in size, the color changes from black-green-pink-white in a gradual scale.

Looking Outwards 07: Information Visualization

Maps and globes always intrigue me because there are so many different versions of them, visualizing and emphasizing different categories of information. This version of a digital globe by UnstableGround that shows the temperature rise due to climate change came to me as a very strong example that appropriately uses color and dimensions to convey information to the viewer.

UnstableGround (2021)

Before taking this course, I had no particular thoughts about how these projects would be created, but now I wonder what kind of code would be used to create this. The algorithm for color would surely be associated with the data of climate change (the higher the temperature, the darker the shade of red), but I wonder how the 3D aspect of the project would be coded, and if it would be possible with p5.js.

Project 06 – Abstract Clock

I remember learning about the Korean water clock that was invented in the Chosun dynasty in elementary school, which inspired me to create a simplified version of it through p5.js.

엄마표 과학] 만공한국사, 자격루 만들기 - 물시계의 원리 : 네이버 블로그
reference image
sketch
var angle = 180;
function setup() {
    createCanvas(420, 400);
    // rectMode(CENTER);
}

function draw() {
    background(0);
    fill(255);
    textAlign(CENTER);
    textSize(30);
    text('The water clock', width/2, 50);
    textSize(10);
    textAlign(LEFT);

    let hr = hour();
    let mn = minute();
    let sc = second();

   
    fill(255);
    text(hr + ':' + mn + ':' + sc, 10, 150);
    text('24:00:00', width-65, 150);
    rect(100, 140, 30, 5);
    rect(200, 140, 30, 10);
    
    //hour
    push();
    fill(255);
    translate(350, 380);
    rotate(radians(180)); //rotation to make the rectangle grow upwards
    rect(0, 0, 120, 240);
    fill(0, 0, 255);
    translate(5, 0);
    rect(0, 0, 110, hr*10);
    pop();

    //minute
    push();
    fill(255); //red rectangle
    translate(205, 260);
    rotate(radians(180)); //rotation to make the rectangle grow upwards
    rect(0, 0, 80, 120);
    fill(0, 75, 255);
    translate(5, 0);
    rect(0, 0, 70, mn*2);
    if (mn==59) { //when each the mn container is full, water is transferred to the hr contatiner
        translate(-30, 115);
        stroke(0, 100, 255);
        strokeWeight(5);
        line(-8, 0, 30, 0);
        stroke(0, 0, 255);
        line(-8, 0, -8, -115);
    }
    pop();

    //second
    noStroke();
    push();
    fill(255); 
    translate(100, 200);
    rotate(radians(angle)); //rotation to make the rectangle grow upwards
    rect(0, 0, 40, 60);
    fill(0, 150, 255);
    translate(5, 0);
    rect(0, 0, 30, sc);
    if (sc==59) { //when each the sc container is full, water is transferred to the mn contatiner
        translate(-30, 57.5);
        stroke(0, 150, 255);
        strokeWeight(3);
        line(-8, 0, 30, 0);
        stroke(0, 100, 255);
        line(-8, 0, -8, -115);
    }
    pop();
}
 
   
    

    

   

Looking Outwards 06: Randomness

When I think about randomness and computation, the first thing that comes into my mind is random number/word generator. While it is a very simple program, I think it inspires people to utilize that randomness to create something. For example, there is a singer who uses random word generator and uses 3-5 random words to start creating an entire song at the spot, and although this is not directly related computational projects, I think this interaction between humans and computers to create art is truly fascinating!