PROJECT-15 (covid-simulator)

For this project, I decided to go in a direction of analyzing covid spread through showing how if you infect one person, how the others will get infected through probability and chance. I will use an array of people and if one or more is clicked, a droplet of covid is “given” to the person to “infect” them. Over time, the nearby people will heal and recover or pass away. If all people are infected, the population will never recover.

sketch
// 15-104
// SEAN CHEN
// FINAL PROJECT


var people = [];
var wNum = 14;
var hNum = 12;
var chance = .1; // chance of transmission
var speed = 20; // speed of transmission
var deathRate = 0.02; // death rate
var body;

// image for the body
function preload() {
    body = loadImage('https://i.imgur.com/BBvwTQi.png');
}

// creating the heads array
function setup() {
    createCanvas(600, 400);
    for (var i = 0; i < wNum; i++) {
        var temp = []
        for (var j = 0; j < hNum; j++) {
            temp.push(createPerson(i, j));
        }
        people.push(temp);
    }
    frameRate(speed);
}

// drawing people + infection spreading
function draw() {
    background(235);
    updatePerson();
    infectPerson();
}

// step and drawing of people
function updatePerson() {
    for (var i = 0; i < wNum; i++) {
        for (var j = 0; j < hNum; j++) {
            people[i][j].draw();
            people[i][j].step();
        }
    }
}

// creating person object
function createPerson(x, y) {
    var p = {
        px: x*(width/(wNum-1)),
        py: y*(height/(hNum-1)),
        infected: 0,
        age: 0,
        col: 0,
        draw: thePerson,
        step: stepPerson,
    }
    return p;
}

// individual people
function thePerson() {
    stroke(0);
    push();
    translate(-20, 5);
    image(body, this.px, this.py, 40, 80);
    pop();

    push();
    fill(colPerson(this.col));
    circle(this.px, this.py, 30);
    fill(255);
    ellipse(this.px-8, this.py-2, 7, 10);
    ellipse(this.px+8, this.py-2, 7, 10);
    pop();

    push();
    noStroke();
    fill(0);
    circle(this.px-8, this.py-2, 4, 4);
    circle(this.px+8, this.py-2, 4, 4);
    pop();
}

// red for most infected
// green for temp immunity
// black for death
function colPerson(colNum) {
    if (colNum == 0) {
        return color(255);
    } else if (colNum == 1) {
        return color(255, 0, 0);
    } else if (colNum == 2) {
        return color(255, 65, 65);
    } else if (colNum == 3) {
        return color(255, 130, 130);
    } else if (colNum == 4) {
        return color(255, 195, 195);
    } else if (colNum == 5) {
        return color(0, 255, 0);
    } else if (colNum == 6) {
        return color(0);
    }
}

// if infected, what stage infection
function stepPerson() {
    if (this.infected == 2) {
        this.col = 6;
        this.age = 0;
    }
    if (this.infected == 1) {
        this.age++;
        if (this.age <= 10) {
            this.col = 1;
        } else if (this.age > 10 & this.age <= 20) {
            this.col = 2;
        } else if (this.age > 20 & this.age <= 30) {
            this.col = 3;
        } else if (this.age > 30 & this.age < 40) {
            this.col = 4;
        } else if (this.age < 60) {
            if (random(0, 10) < deathRate) {
                this.infected = 2;
            } else {
                this.col = 5;
            }
        } else if (this.age == 60) {
            this.col = 0;
            this.age = 0;
            this.infected = 0;
        }
    }
}

function mouseClicked() {
    clickPerson();
}

// clicking persons to give covid
function clickPerson() {
    for (var i = 0; i < wNum; i++) {
        for (var j = 0; j < hNum; j++) {
            if (dist(mouseX, mouseY, people[i][j].px, people[i][j].py) < 20)  {
                people[i][j].infected = 1;
                people[i][j].col = 1;
                people[i][j].age = 0;
            }
        }
    }
}

// infecting right
function r(i, j) {
    if (random(0, 10) < chance & people[i+1][j].infected != 2) {
        people[i+1][j].infected = 1;
    }
}
// infecting left
function l(i, j) {
    if (random(0, 10) < chance & people[i-1][j].infected != 2) {
        people[i-1][j].infected = 1;
    }
}
// infecting up
function u(i, j) {
    if (random(0, 10) < chance & people[i][j-1].infected != 2) {
        people[i][j-1].infected = 1;
    }
}
// infecting down
function d(i, j) {
    if (random(0, 10) < chance & people[i][j+1].infected != 2) {
        people[i][j+1].infected = 1;
    }
}

// probability and chance of spread
function infectPerson() {
    for (var i = 0; i < wNum; i++) {
        for (var j = 0; j < hNum; j++) {
            if (people[i][j].age >= 20) {
                if (i > 0 & j > 0 && i < wNum-1 && j < hNum-1) {
                    r(i, j);
                    l(i, j);
                    u(i, j);
                    d(i, j);
                } else if (i == 0 & j == hNum-1) {
                    r(i, j);
                    u(i, j);
                } else if (i == wNum-1 & j == 0) {
                    l(i, j);
                    d(i, j);
                } else if (i == 0 & j == 0) {
                    r(i, j);
                    d(i, j);
                } else if (i == 0) {
                    r(i, j);
                    u(i, j);
                    d(i, j);
                } else if (j == 0) {
                    r(i, j);
                    l(i, j);
                    d(i, j);
                } else if (i == wNum-1 & j == hNum-1) {
                    l(i, j);
                    u(i, j);
                } else if (i == wNum-1) {
                    l(i, j);
                    u(i, j);
                    d(i, j);
                } else if (j == hNum-1) {
                    r(i, j);
                    l(i, j);
                    u(i, j);
                }
            }
        }
    }
}

LO-11 (focus on women practitioners)

Karolina Sobecka is an artist, and researcher that operates in the intersection of art, science, technology, and activism. Her most recent work is a series called ‘Matter of Air’ in which she explores environmental activism through art and technology, including a project in which she creates, with a group of folks, a pseudo weather controlling machine. However, for this LO I’ll be discussing  one of her older interactive installations. This project is called stability. The project entails having a user interact with a cube and a screen that supposedly shows a small room with a person inside the cube. Every time you shake up the room, the person rearranges the room and records the “disaster” in its disaster journal. The interesting thing is that every single arrangement created by this person is unique. This perhaps can be interpreted as pseudo Automated Intelligence, as the person is actively “creating” a new layout every time. But, this could perhaps just an illusion coded by the creator.

http://cargocollective.com/karolinasobecka/Stability

PROJECT-10 (generative landscape)

sketch
// 15-104
// SEAN CHEN

var bgbuildings = [];
var forebuildings = [];
var sidewalk = [];
var dash = [];
var light, bgCloud, foreCloud;
var frames = [];
var run = [];

function preload() {
    light = loadImage('https://i.imgur.com/147kNrs.png');
    bgCloud = loadImage('https://i.imgur.com/Fn6e7H6.png');
    foreCloud = loadImage('https://i.imgur.com/PNyKohG.png');
    frames[0] = loadImage('https://i.imgur.com/xxj2N5D.png');
    frames[1] = loadImage('https://i.imgur.com/ju233XV.png');
    frames[2] = loadImage('https://i.imgur.com/En4Sjg2.png');
    frames[3] = loadImage('https://i.imgur.com/KXPlTB9.png');
    frames[4] = loadImage('https://i.imgur.com/Ya0obgN.png');
    frames[5] = loadImage('https://i.imgur.com/wFN72zO.png');
    frames[6] = loadImage('https://i.imgur.com/DtMtZEq.png');
    frames[7] = loadImage('https://i.imgur.com/oEUisa6.png');
}

// update scene objects
function sceneUpdate(){
    for (var i = 0; i < bgbuildings.length; i++){
        bgbuildings[i].move();
        bgbuildings[i].display();
    }
    for (var i = 0; i < forebuildings.length; i++) {
        forebuildings[i].move();
        forebuildings[i].display();
    }
    for (var i = 0; i < dash.length; i++) {
        dash[i].move();
        dash[i].display();
    }
    for (var i = 0; i < run.length; i++) {
        run[i].move();
        run[i].display();
    }
    for (var i = 0; i < sidewalk.length; i++) {
        sidewalk[i].move();
        sidewalk[i].display();
    }
}

// adding and deleting excess objects
function shiftScene() {
    var buildingsToKeep = [];
    for (var i = 0; i < bgbuildings.length; i++) {
        if (bgbuildings[i].x + bgbuildings[i].breadth > 0) {
            buildingsToKeep.push(bgbuildings[i]);
        }
    }
    bgbuildings = buildingsToKeep;
    for (var i = 0; i < forebuildings.length; i++) {
        if (forebuildings[0].x + forebuildings[0].width < 0) {
            forebuildings.push(makeBuildingFore((forebuildings.length-1)*95));
            forebuildings.shift();
        }
    }
    for (var i = 0; i < sidewalk.length; i++) {
        if (sidewalk[0].x + 50 < 0) {
            sidewalk.push(makeSidewalk(width + width/7));
            sidewalk.shift();
        }
    }
    for (var i = 0; i < dash.length; i++) {
        if (dash[0].x + width/7 < 0) {
            dash.push(makeDash(width));
            dash.shift();
        }
    }
}

// randomly adding background buildings
function bldgProb() {
    var newBuildingLikelihood = 2.5; 
    if (random(0,100) < newBuildingLikelihood) {
        bgbuildings.push(makeBuilding(width));
    }
}

// method to update position of objects every frame
function buildingMove() {
    this.x += this.speed;
}

// draw background building and windows
function buildingDisplay() {
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight; 
    fill(53); 
    stroke(0); 
    push();
    translate(this.x, height - 60);
    rect(0, -bHeight, this.breadth, bHeight);
    for (var i = 0; i < this.nFloors; i++) {
        for (var j = 0; j < this.breadth/20; j++) {
            fill(155, 133, 38);
            circle(j*15+10, -10-(i * floorHeight), 10);
        }
    }
    pop();
}

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

// drawing foreground buildings with long windows
function buildingDisplayFore() {
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight;
    fill(120);
    stroke(0);
    push();
    translate(this.x, height - 60);
    rect(0, -bHeight, this.width, bHeight+10);
    for (var i = 0; i < this.nFloors; i++) {
        fill(155, 133, 38);
        rect(5, -10-(i*floorHeight), this.width-10, floorHeight-10, 5);
    }
    pop();
}

function makeBuildingFore(birthLocationX) {
    var bldg = {x: birthLocationX,
                width: 90,
                speed: -2,
                nFloors: round(random(3, 6)),
                move: buildingMove,
                display: buildingDisplayFore
                }
    return bldg;
}

// adding street lights
function sidewalkDisplay() {
    image(light, this.x, height-85, 57, 50);
}

function makeSidewalk(birthLocationX) {
    var swalk = {x: birthLocationX,
                 speed: -2.5,
                 width: width/4,
                 move: buildingMove,
                 display: sidewalkDisplay
                }
    return swalk;
}

// adding street dashes
function dashDisplay() {
    stroke(144, 133, 0);
    line(this.x, height-20, this.x + width/14, height-20);
}

function makeDash(birthLocationX) {
    var d = {x: birthLocationX,
             speed: -2.5,
             width: width/7,
             move: buildingMove,
             display: dashDisplay
            }
    return d;
}

// adding running dude
function charDisplay() {
    image(frames[this.frame], this.x, 243, 30, 27);
}

function frameMove() {
    if (this.frame == 7 & this.step%3 == 0) {
        this.frame = 0;
    } else if (this.step%3 == 0) {
        this.frame++;
    }
    this.step++;
}

function makeChar(birthLocationX) {
    var c = {x: birthLocationX,
             frame: 0,
             step: 0,
             move: frameMove,
             display: charDisplay
            }
    return c;
}

function setup() {
    createCanvas(450, 300);
    background(5, 5, 45);
    // create an initial collection of buildings
    for (var i = 0; i < 7; i++){
        var rx = random(width);
        bgbuildings[i] = makeBuilding(rx);
        forebuildings[i] = makeBuildingFore(i * 95);
        dash[i] = makeDash(i * width/6);
    }
    for (var i = 0; i < 5; i++) {
        sidewalk[i] = makeSidewalk(i * width/4);
    }
    for (var i = 0; i < frames.length; i++) {
        run[i] = makeChar(10);
    }
    frameRate(30);
}

function draw() {
    background(5, 5, 45);
    //backgournd cloud
    image(bgCloud, 0, 0, 600, 100);
    // road and sidewalk
    fill(0);
    rect(0, height-50, width, 60);
    fill(66);
    rect(0, height-60, width, 20);
    // updatinga and displaying scene objects
    sceneUpdate();
    shiftScene();
    bldgProb(); 
    push();
    // layering transparent clounds
    tint(255, 127);
    image(foreCloud, 0, 0, 600, 100);
    pop();
}

LO-10 (computer music)

For this LO I’ll be looking at a service that provides computer generated music for creative users.This service/machine/Ai is called AIVA. The service allows you to set various parameters including instruments, tempo, etc. or completely randomized if left blank. The resulting music created actually sounds quite professional and due to its random nature, it will not likely create the same track twice. To ensure that, AIVA uses stochastic algorithms to randomize each of its elements to allow for ‘original’ creations every single time. Looking through each sample created for each genre, I wouldn’t be able to tell the difference between aiva and a professional track.

https://www.aiva.ai

PROJECT-10 (sonic story)

sketch
// 15-104
// SEAN CHEN
// A person running in the rain rushes toward a gathering indoors
// and suddenly the person busts through the window causing panic.

var rain, running, panting, group, intrain, scream, glass;
var note = 0;
var walkImage = [];
var filenames = [];


// various sounds
function preload() {
    rain = loadSound ('http://127.0.0.1:5500/handin10/seanc1-10-project/sounds/-combo.wav');
    group = loadSound ('http://127.0.0.1:5500/handin10/seanc1-10-project/sounds/-combo-group.wav');
    scream = loadSound ('http://127.0.0.1:5500/handin10/seanc1-10-project/sounds/-group-scream.wav');
    glass = loadSound ('http://127.0.0.1:5500/handin10/seanc1-10-project/sounds/-glass-smash.wav');
}

function setup() {
    createCanvas(600, 300);
    frameRate(15);
}

function soundSetup() {}

// apartment building
function house() {
    push();
    fill(150);
    rect(525, 50, 100, 250);
    fill(244,202,41);
    rect(550, 75, 50, 50);
    rect(550, 150, 50, 50);
    rect(550, 225, 50, 50);
    pop();
}

// rain
function rainfall() {
    stroke(255);
    strokeWeight(0.5);
    for (var x = 0; x < width; x += 5) {
        for (var y = 0; y < height; y += 10) {
            line(x, y, x, y+5);
        }
    }
}

// shadowy figure
function figure(x, y) {
    push();
    fill(0);
    rect(x, y+275, 10, 50);
    ellipse(x+5, 265, 10, 10);
    pop();
}

function draw() {
    background(50);
    // drawing shadowy figure running through rain, into the 1F window
    house();
    if (frameCount < 170) {
        var xpos = map(frameCount, 0, 170, 0, 550);
        figure(xpos, 0);
    }
    push();
    if (frameCount % 3 == 0) {
        translate(random(0, 3), 5);
    }
    rainfall();
    pop();


    var seq = [rain, group, rain, group, rain, group] // event sequence
    var dur = [5, 48, 45, 30, 15, 15]; // event duration

    if (frameCount % dur[note] == 0) { // play time based on frames
        if (note > 0) {
            seq[note-1].stop();
            seq[note].play();  
        }
        seq[note].play();
        note++;
    }
    if (note == seq.length) { // final glass smash
        glass.play(1);
        scream.play(1.3);
        seq[note-1].stop(1.5);
        var totalFrames = frameCount;
        note++;
    }

    if (frameCount == totalFrames+30) {
        noLoop();
    }
    print(frameCount);
}

LO-09 (on looking outwards)

For this LO, I am looking at Bennett’s entry for the sound art LO-04. I agree with him in the sense that one of the more interesting parts of this project is the sound that is created, a smooth earthy tone that changes mildly or drastically depending on the external environments. However, I don’t quite agree with the amount of creator input that Bennett implies in this LO. The creator passes through the micro-voltage fluctuations into a oscillator that reads the frequency of the waves thus creating the sounds generated, so I personally think that the sounds generated reflect the “true tones” of the plant. Perhaps the creator intended this to be a single item project, I wonder what the tones created from various types of plants could differ from one another.

Bennett’s post: https://courses.ideate.cmu.edu/15-104/f2020/2020/09/28/looking-outwards-04-4/

“Plant sounds”: https://www.youtube.com/watch?v=VvWPT4VhKTk&ab_channel=TomuTomu

PROJECT-09(portrait)

sketch
// SEAN CHEN
// 15-104 A

var img;
var widthSml = 4; // width parameters
var widthBig = 10;
var lengthSml = 2; // length parameters
var lengthBig = 10;
var mode = 1; // modes keeper

function preload() { // preload image
  img = loadImage('https://i.imgur.com/HNOE05S.png?1');
}

function setup() {
  frameRate(300);
  createCanvas(480, 788);
  imageMode(CENTER);
  background(255);
  img.loadPixels();
  mode = int(random(1, 4)); 
}

function rotAng(x, y) { // calculating rotation angle
    var distX, distY, ang;
    distX = mouseX - x;
    distY = mouseY - y;
    ang = atan(distX/distY);
    if (mode == 1) { // changing line mapping rotation
        return PI - ang; 
    } else if (mode == 2) {
        return PI / 2 - ang;
    } else if (mode == 3) {
        return ang;
    }
}

function border() { // instructions text
    push();
    stroke(0);
    fill(255);
    rectMode(CENTER);
    textAlign(CENTER);
    rect(width/2, 20, 200, 35, 10);
    noStroke();
    fill(0);
    text('double click to change modes!\n*hold for text rendering*', width/2, 17.5);
    rect()
    pop();
}

function draw() {
    let thickness = map(mouseX, 0, width, widthSml, widthBig);
    let len = map(mouseY, 0, height, lengthSml, lengthBig);
    let x = floor(random(img.width));
    let y = floor(random(img.height));
    let pix = img.get(x, y);
    push(); 
    var rot = rotAng(x, y);
    translate(x, y);
    rotate(rot);
    if (mouseIsPressed) { // render in rotated text
        fill(pix, 128);
        textSize(thickness); // size based on mouse
        textAlign(CENTER);
        text('face', 0, 0)    
    } else { // rotate in rotated lines
        rotate(radians(90));
        stroke(pix, 128);
        strokeWeight(thickness); // thickness based on mouse
        line(0, -len, 0, len); // length of line based on mouse
    }
    pop();
    border();
}

function doubleClicked() { // changing mode
    if (mode == 3) {
        mode = 1;
    } else {
        mode++;
    }
}

LO-08 (the creative practice of an individual)

Taeyoon Choi is an artist, educator, and activist who works in New York and Seoul. He studied in the Art Institute of Chicago and Korea Advanced Institute of Science and technology and holds a BFA and MS respectively. He presents his work as an intersection between art and technology, physical technology as a platform for understanding life and the experience of it. He presents his technological work as a design and artistic process where he pursues creative moments when they’re provided to him. For instance, the project he started with was the creation of a computer from scratch. He educated himself in the language of computers and through practice and innovation eventually created his own version of what a computer could/should be. And further extending from that was experimentation of time and computing in which he created a machine that would capture the users own sense of time. After watching him present his work and process, I’ve gained a deeper appreciation for the contemporary integration of technology and artistic expression.

LO-07 (information visualization)

For this LO, I looked at Chris Harrisons data visulazation on amazon books. In the project he let his computer run an automated algorithm based on title, topic, and relevance to each other. This allows for similar books to “cluster” and create a more solid color. What I thought was interesting is how he mentions through each iteration, the books that are more and more similar will then begin to attract to one another, thus the more time provided equals a more coherent data graph. But due to the sheer sample size of the project, 700,000 books, Chris stated that it would have taken too much memory for the computer to run. Thus emphasizing the sheer physical space it takes to process data with a large sample group. What I thought was the most intriguing aspect of the project is the resulting color field as it creates such a unique gradient that almost seems like some form of abstract pixel art.

PROJECT-07 (curves)

sketch
// SEAN CHEN
// 15-104 A

var nPoints = 100;
var tx = []; // keeping track of the x y of each hypotrochoid
var ty = [];
var rot = 0; // rot init
var size = []; // each size
var col = []; // each color

function setup() {
    createCanvas(480, 480);
    background(255);
}

function distance() { // distance from center to mouse
    var d = dist(width/2, height/2, mouseX, mouseY);
    return d;
}

function hypotrochoid(a, col) {
    push();
    fill(col);
    var x, y, a, b, t;
    b = a / int(map(distance(), 0, width/2, 1, a));
    stroke(0);
    rotate(radians(rot));
    beginShape();
    for (var i = 0; i < nPoints; i++) {
        t = map(i, 0, nPoints, 0, TWO_PI);
        x = (a - b) * cos(t) - b * cos((a-b) / b * t);
        y = (a - b) * sin(t) + b * sin((a-b) / b * t);
        vertex(random(3)+x, random(3)+y);
    }
    endShape(CLOSE);
    pop();
}

function draw() {
    background(255);
    rect(0, 0, 480, 480);
    push();
    translate(width/2, height/2); // initial hypotrochoid
    hypotrochoid(120, color(245,211,114));
    pop();
    for (var i = 0; i < tx.length; i++) { // added hypotrochoid
        push();
        translate(tx[i], ty[i]);
        hypotrochoid(size[i], col[i]);
        pop();
    }
    rot += 1;
    text("click to add!", 10, 20);
}

function mouseClicked() { // add new hypotrochoid
    tx.push(mouseX); // input new at mouseXY
    ty.push(mouseY);
    size.push(random(50, 200));
    col.push(color(random(255),211,114));
    if (tx.length > 12) { // delete after 12
        tx.shift();
        ty.shift();
        size.shift();
        col.shift();
    }
}