Final Project

sketch

// Name: Aysha Zackria
// AndrewID: azackria
// Section D

var firelocationx = [];
var firelocationy = [];
var smoke = {
    locationx:[], 
    locationy:[], 
    size: 75
}
var counter = 1;
var xoff = 0;
var firesize = 12;
var treelocationx = [];
var treelocationy = [];
var r = 133;
var g = 214;
var b = 139;
var waterr = 131;
var waterg = 228;
var waterb = 234;
var smokecolor = 240;

function setup() {
    createCanvas(500, 500);
    for (var i = 0; i < 25; i++) {
        firelocationx.push(random(20, 480));
        firelocationy.push(random(45, 330));
        treelocationx.push(random(20, 480));
        treelocationy.push(random(35, 330));
    }
}

function draw() {
    background(r, g, b);
    r = map(firelocationx.length, 25, 100, 133, 43);
    g = map(firelocationx.length, 25, 100, 214, 24);
    b = map(firelocationx.length, 25, 100, 139, 8);
    noStroke();
    fill(0);
    if (firelocationx.length < 30) {
        text("Slowly drag the fire into the water to put it out.", 10, 15);
    } else if (firelocationx.length >= 30 & firelocationx.length <= 35) {
        text("Drag the fire into the water to put it out.", 10, 15);
    } else if (firelocationx.length > 35 & firelocationx.length < 40) {
        text("Drag the fire into the water.", 10, 15);
    } else if (firelocationx.length >= 40) {
        text("Put the fire out.", 10, 15);
    }
    noStroke();
    fill(waterr, waterg, waterb);
    waterr = map(firelocationx.length, 25, 100, 131, 25);
    waterg = map(firelocationx.length, 25, 100, 228, 54);
    waterb = map(firelocationx.length, 25, 100, 234, 92);
    rect(0, 350, 500, 150); // water
    let nx = noise(xoff) * 600;
    let ny = noise(xoff+10) * 500;
    if ((counter % 20) == 0) {
        smoke.locationx.push(nx);
        smoke.locationy.push(ny);
    }
    for (var i = 0; i < treelocationx.length; i++) {
        drawtree(i);
    }
    for (var i = 0; i < firelocationx.length; i++) {
        drawfire(i);
        if (mouseIsPressed & dist(firelocationx[i], firelocationy[i], 
            mouseX, mouseY) < 12) {
            firelocationx[i] = mouseX;
            firelocationy[i] = mouseY;
        }
        if (firelocationy[i] > 350) {
            firelocationy.splice(i, 1);
            firelocationx.splice(i, 1);
        }
    }
    fill(smokecolor, 100);
    smokecolor = map(firelocationx.length, 25, 100, 240, 100);
    for (var i = 0; i < smoke.locationx.length; i++) {
        circle(smoke.locationx[i], smoke.locationy[i], smoke.size);
    }
    counter += 1;
    xoff += 0.1;
    if ((counter % 100) == 0) {
        firelocationx.push(random(20, 480));
        firelocationy.push(random(35, 330));
    }
}

function drawtree(i) {
        strokeWeight(4);
        stroke(165, 115, 75);
        line(treelocationx[i], treelocationy[i] - 2, 
            treelocationx[i], treelocationy[i] - 10);
        stroke(50, 100, 50);
        fill(50, 100, 50);
        triangle(treelocationx[i], treelocationy[i] - 15, treelocationx[i] - 3, 
            treelocationy[i] - 10, treelocationx[i] + 3, treelocationy[i] - 10);
        triangle(treelocationx[i], treelocationy[i] - 10, treelocationx[i] - 3, 
            treelocationy[i] - 5, treelocationx[i] + 3, treelocationy[i] - 5);
}

function drawfire(i) {
    fill(255, 100, 0); 
    noStroke();
    push();
    translate(firelocationx[i], firelocationy[i]);
    scale(firelocationx.length / 15);
    circle(0, 0, firesize);
    triangle(-(firesize / 2), -1, (firesize / 2), -1, 0, -20);
    pop();
}

My program is a game that includes fire and smoke appearing at regular intervals on a background of grass and trees. The fire can be extinguished by dragging it into the water area. The game is designed to not be winnable to reflect my growing feeling of hopelessness in regards to the climate crisis. The smoke ultimately obscures a good portion of the screen while the colors of the background and water grow darker to mimic soot buildup. The text direction in the top left corner also changes to convey a sense of urgency as the user gets more frustrated. I didn’t end up implementing any separate sound or image files, so the program can be run normally. If I had more time, I would probably add simple sounds to accompany the fires appearing and disappearing.

LO 10: Sonic Story

sketch

// sketch.js template for sound and DOM
//
// This is the 15104 Version 1 template for sound and Dom.
// This template prompts the user to click on the web page
// when it is first loaded.
// The function useSound() must be called in setup() if you
// use sound functions.
// The function soundSetup() is called when it is safe
// to call sound functions, so put sound initialization there.
// (But loadSound() should still be called in preload().)
var img;
var bx = 20;
var by = 400;
var cx = 20;
var cy = 300;
var tx = 20;
var ty = 200;
var mx = 20;
var my = 100;
var bikeTone;
var bikeDynamics;
var carTone;
var carDynamics;
var trainTone;
var trainDynamics;
var motorcycleTone;
var motorcycleDynamics;

function preload() {
    // call loadImage() and loadSound() for all media files here
}


function setup() {
    // you can change the next 2 lines:
    createCanvas(480, 480);
    createDiv("p5.dom.js library is loaded.");
    //======== call the following to use sound =========
    useSound();
}


function soundSetup() { // setup for audio generation
    // you can replace any of this with your own audio code:
    bikeTone = new p5.Oscillator();
    bikeTone.setType('sine');
    bikeTone.freq(440.0);
    bikeTone.amp(0.1);
    bikeTone.start();
    bikeDynamics = new p5.Oscillator();
    bikeDynamics.setType('sine');
    bikeDynamics.disconnect();
    bikeDynamics.start();
    carTone = new p5.Oscillator();
    carTone.setType('sine');
    carTone.freq(261.63);
    carTone.amp(0.1);
    carTone.start();
    carDynamics = new p5.Oscillator();
    carDynamics.setType('sine');
    carDynamics.disconnect();
    carDynamics.start();
    trainTone = new p5.Oscillator();
    trainTone.setType('sine');
    trainTone.freq(164.81);
    trainTone.amp(0.1);
    trainTone.start();
    trainDynamics = new p5.Oscillator();
    trainDynamics.setType('sine');
    trainDynamics.disconnect();
    trainDynamics.start();
    motorcycleTone = new p5.Oscillator();
    motorcycleTone.setType('sine');
    motorcycleTone.freq(110);
    motorcycleTone.amp(0.1);
    motorcycleTone.start();
    motorcycleDynamics = new p5.Oscillator();
    motorcycleDynamics.setType('sine');
    motorcycleDynamics.disconnect();
    motorcycleDynamics.start();
}


function draw() {
    // you can replace any of this with your own code:
    background(255);
    stroke(0);
    makeBike(bx, by);
    bx += .5;
    makeCar(cx, cy);
    cx += 1;
    makeTrain(tx, ty);
    tx += 1.5;
    makeMotorcycle(mx, my);
    mx += 2;
    bikeDynamics.amp(0.5);
    bikeDynamics.freq(.034);
    bikeTone.amp(bikeDynamics);
    carDynamics.amp(1);
    carDynamics.freq(.06);
    carTone.amp(carDynamics);
    trainDynamics.amp(2);
    trainDynamics.freq(.085);
    trainTone.amp(trainDynamics);
    motorcycleDynamics.amp(2);
    motorcycleDynamics.freq(.12);
    motorcycleTone.amp(motorcycleDynamics);
    if (millis() > 4200 + soundStart) {
       motorcycleTone.stop();
       motorcycleDynamics.stop();
    }
    if (millis() > 6000 + soundStart) {
        trainTone.stop();
        trainDynamics.stop();
    }
    if (millis() > 8400 + soundStart) {
        carTone.stop();
        carDynamics.stop();
    }
    if (millis() > 15800 + soundStart) {
        bikeTone.stop();
        bikeDynamics.stop();
    }
}

function makeBike(x, y) {
    circle(x, y, 20);
    circle(x + 40, y, 20);
    line(x, y - 10, x + 40, y - 10);
    line(x, y - 10, x, y - 20);
    line(x + 40, y - 10, x + 40, y - 30);
    line(x + 30, y - 25, x + 50, y - 35);
    line(x - 10, y - 20, x + 10, y - 20);
}

function makeCar (x, y) {
    rect(x - 20, y - 20, 40, 20);
    rect(x - 40, y, 80, 20);
    circle(x - 30, y + 30, 20);
    circle(x + 30, y + 30, 20);
}

 function makeTrain(x, y) {
    rect(x, y, 20, 20);
    rect(x, y + 20, 40, 20);
    line(x, y + 30, x - 10, y + 30);
    rect(x - 40, y + 20, 30, 20);
    line(x - 40, y + 30, x - 50, y + 30);
    rect(x - 80, y + 20, 30, 20);
    circle(x + 5, y + 45, 10);
    circle(x + 35, y + 45, 10);
    circle(x - 15, y + 45, 10);
    circle(x - 35, y + 45, 10);
    circle(x - 55, y + 45, 10);
    circle(x - 75, y + 45, 10);
} 

function makeMotorcycle(x, y) {
    rect(x, y, 40, 20);
    triangle(x, y, x + 40, y, x + 40, y - 15);
    triangle(x - 20, y, x, y + 15, x, y);
    triangle(x + 40, y, x + 60, y, x + 40, y + 15);
    circle(x - 10, y + 20, 20);
    circle(x + 50, y + 20, 20);
}

Project 9: Computational Portrait

sketch

var img;
var diameter;

function preload() {
    img = loadImage("https://i.imgur.com/VzFWKC5.jpg");
}

function setup() {
    createCanvas(320, 480);
    image(img, 0, 0, 320, 480);
    background(110);
}

function draw() {
    noStroke();
    x = random(2000);
    y = random(2992);
    c = img.get(x, y);
    fill(c);
    if (x < 1500 & x > 300 && y < 2000 && y > 550) {
        diameter = 10;
    } else {
        diameter = 20;
    }
    circle((x * 0.16), (y * .16), diameter);
}

LO 9: A Focus on Women and Non-binary Practitioners in Computational Art

Wendy Carlos is a pioneer of electronic music, particularly with her work from the late 1960s into the early 1980s. She studied physics and music at Brown University as well as Columbia University. Her work in developing new instruments led to the creation of the Moog synthesizer, which changed the way music was played and recorded dramatically. Her work is most prominently displayed in her album Switched on Bach as well as the scores for several movies: A Clockwork Orange, The Shining, and Tron. All of these pieces explored the emotional effects that the new timbre of computer music opened up. She also is a particularly important figure to study with the place of gender in technological fields. Although she privately began transitioning in 1966, she wasn’t able to publicly appear as a woman until 1972, after the commercial success of Switched on Bach.

LO 8: The Creative Practice of an Individual

Sasha Costanza-Chock’s work focuses on amplifying social movements and transformative justice through design. They are currently based in Boston. After studying at Harvard University, the University of Pennsylvania, and University of Southern California, they taught Civic Media at the Massachusetts Institute of Technology, and continued on to the Berkman-Klein Center for Internet & Society at Harvard University. They describe themselves as “a researcher and designer who works to support community-led processes that build shared power, dismantle the matrix of domination, and advance ecological survival.” I admire their interrogation of white supremacy and colonialism specifically in the context of visualization. I also think it’s important to note that they put their work in conversation with the communities it serves as well as people who have undertaken similar projects. They focus their attention toward on-the-ground organizers who can genuinely create the change rather than some academics who prefer to keep their distance. Their transmedia organizing design is meant to be “cross-platform, participatory, and linked to action.”

Project 7: Composition with Curves

sketch

var x1;
var y1;
var x;
var y;
var a;
var t;
var r;
var g;
var b;
var bcolor;

function setup() {
    createCanvas(480, 480);
    let j = 700
    while (j > 0) {
        strokeWeight(0);
        j = j - 10
        bcolor = map(j, 700, 0, 0, 255);
        fill(bcolor);
        circle(240, 240, j);
    }
}

function draw() {
    stroke(r, g, b);
    strokeWeight(3);
    beginShape();
    for (var i = 0; i < 100; i++) {
        a = map(mouseX, 0, 480, 0, 100);
        t = map(mouseY, 0, 480, 0, 100);
        x1 = a * sin(t);
        y1 = a * sin(t) * cos(t);
        x = 240 + x1 * -1
        y = 240 + y1 * -1
        vertex(x, y);
        print(y);
    }
    endShape(CLOSE);
}

function mousePressed() {
    r = random(0, 255);
    g = random(0, 255);
    b = random(0, 255);
}

As I started working on this project, I wanted the viewer to be able to “draw” the curves themselves. As MouseX changes, the size of the curve changes. As MouseY changes, different points are added on the curve. When the canvas is clicked, the color of the points change. If you manipulate the mouse in a certain way, you can make concentric figure 8s of varying colors. When I finished coding the curves and their mouse interaction, it still felt a little bland, so I added a circular gradient to the background to focus the eye gaze on the center of the canvas.

LO 7: Information Visualization

Juan Francisco Saldarriaga’s CitiBike Rebalancing Study is a investigation and subsequent data visualization to assist CitiBike with maintaining the equilibrium of their bike stations throughout different locations and times of day. The matrix is organized on those two axes, location and time of day, to establish patterns of usage. The imbalance of bikes is demonstrated by color, blue and orange, while the overall usage is characterized by the brightness of the color. This visualization makes it immediately apparent which stations are consistently depleted or overloaded daily. The analysis of this data will allow CitiBike to partially automate their system of organization, significantly cutting labor and expenses from the inefficient old system, which was based almost randomly on urgent need.

Project 6: Abstract Clock

sketch

var x = [0];
var y = [0];
var w = 25;
var rc;
var gc;
var bc;
var r = [];
var g = [];
var b = [];
var theta = [0];
var dtheta = [];
var rad = [50];
var mo;
var d;
var h;
var mi;
var s;


function setup() {
    createCanvas(480, 480);
    translate(240, 240);
    rotate(radians(270)); // midnight pointing upwards
    strokeWeight();
    var mo = month(); // establishing times as variables
    var h = hour();
    var mi = minute();
    var s = second();
    if (mo == 1) { // converting days to be out of 365
        d = day();
    } else if (mo == 2) {
        d = 31 + day();
    } else if (mo == 3) {
        d = 59 + day();
    } else if (mo == 4) {
        d = 90 + day();
    } else if (mo == 5) {
        d = 120 + day();
    } else if (mo == 6) {
        d = 151 + day();
    } else if (mo == 7) {
        d = 181 + day();
    } else if (mo == 8) {
        d = 212 + day();
    } else if (mo == 9) {
        d = 243 + day();
    } else if (mo == 10) {
        d = 273 + day();
    } else if (mo == 11) {
        d = 304 + day();
    } else if (mo == 12) {
        d = 334 + day();
    }
    if (h < 12) { // tying hour to red fill
        rc = map(h, 0, 11, 0, 255);
    } else {
        rc = map(h, 23, 12, 0, 255);
    }
    if (mi < 29) { // tying minutes to green fill
        gc = map(mi, 0, 29, 0, 255); 
    } else {
        gc = map(mi, 59, 30, 0, 255);
    } if (s < 29) { // tying seconds to blue fill
        bc = map(s, 0, 29, 0, 255);
    } else {
        bc = map(s, 59, 30, 0, 255);
    }
    fill(rc, gc, bc);
    circle(0, 0, 480); // clock face
    for(j = 0; j < 4; j += 1) { 
        if (j == 0) { // setting colors of markers inverse
            r[j] = 90;
            g[j] = 75;
            b[j] = map(bc, 255, 0, 0, 255);
        } else if (j == 1) {
            r[j] = 50;
            g[j] = map(gc, 255, 0, 0, 255);
            b[j] = 0;
        } else if (j == 2) {
            r[j] = map(rc, 255, 0, 0, 255);
            g[j] = 50;
            b[j] = 50;
        } else if (j == 3) {
            if (d < 182) {
                r[j] = map(d, 0, 364, 0, 255);
                g[j] = map(d, 0, 364, 0, 255);
                b[j] = map(d, 0, 364, 0, 255);
            } else {
                r[j] = map(d, 364, 0, 0, 255);
                g[j] = map(d, 364, 0, 0, 255);
                b[j] = map(d, 364, 0, 0, 255);
            }
        }
        r.push(r[j]);
        g.push(g[j]);
        b.push(b[j]);
        fill(r[j], g[j], b[j]);
        specialcircle(rad[j], y[j], w);
        rad.push(rad[j] + 50);
        x.push(0);
        y.push(0);
        theta.push(0);
    }
}

function draw() {
    strokeWeight(0);
    translate(240, 240);
    rotate(radians(270)); // midnight pointing upwards
    var mo = month(); // establishing times as variables
    var h = hour();
    var mi = minute();
    var s = second();
    if (h < 12) { // tying hour to red fill
        rc = map(h, 0, 11, 0, 255);
    } else {
        rc = map(h, 23, 12, 0, 255);
    }
    if (mi < 29) { // tying minutes to green fill
        gc = map(mi, 0, 29, 0, 255); 
    } else {
        gc = map(mi, 59, 30, 0, 255);
    } if (s < 29) { // tying seconds to blue fill
        bc = map(s, 0, 29, 0, 255);
    } else {
        bc = map(s, 59, 30, 0, 255);
    }
    r[0] = 90; // marker fill inverse of clock face
    g[0] = 75;
    b[0] = map(bc, 255, 0, 0, 255);
    r[1] = 50;
    g[1] = map(gc, 255, 0, 0, 255);
    b[1] = 0;
    r[2] = map(rc, 255, 0, 0, 255);
    g[2] = 50;
    b[2] = 50;
    if (d < 182) {
        r[3] = map(d, 0, 364, 0, 255);
        g[3] = map(d, 0, 364, 0, 255);
        b[3] = map(d, 0, 364, 0, 255);
    } else {
        r[3] = map(d, 364, 0, 0, 255);
        g[3] = map(d, 364, 0, 0, 255);
        b[3] = map(d, 364, 0, 0, 255);
    }
    fill(rc, gc, bc);
    circle(0, 0, 480); // clock face
    for(j = 0; j < 4; j += 1) { // movement with time
        theta[0] = map(s, 0, 59, 0, 355);
        theta[1] = map(mi, 0, 59, 0, 355);
        theta[2] = map(h, 0, 23, 0, 355);
        theta[3] = map(d, 0, 364, 0, 355);
        x[j] = rad[j] * cos(radians(theta[j]));
        y[j] = rad[j] * sin(radians(theta[j]));
        fill(r[j], g[j], b[j]);
        specialcircle(x[j], y[j], w);
    }
}

function specialcircle(x, y, w) {
    ellipse(x, y, w, w);
}

I wanted to create a clock that was both readable and abstract. The seconds marker corresponds to blue, the minutes to green, the hours to red, and the days of the year to grayscale. The clock face fill is a combination of all of these colors, but the inverse of the marker colors.

LO 6: Randomness

The Computer Composer game, which is featured on the website of The Mathenæum, allows you to choose to generate a short musical composition with the assistance of a computer. For every input of notes and rhythms, you can either manually input values or choose to have the computer randomly assign them for you. It is interesting to see the limitations of randomness within music; for example, this program specifically only writes in C major or A natural minor, which eliminates 5 of the possible notes in each octave. It is also limited to one and a half octaves, as opposed to the 7 usually present on a piano. Compositionally, the creation of rhythms is always much more variable, as is the case even more clearly in this program.

Project 5: Wallpaper

sketch-wall

var x = 5
var y = 5
var w = 5
var h = 20
var dx = 8

function setup() {
    createCanvas(500, 500);
    background(220);
}

function draw() {
    for (hirow = 0; hirow < 5; hirow += 1) { // higher rows
        x = 5 + hirow*130
        for (hicol = 0; hicol < 5; hicol += 1) { // higher columns
            squiggle();
            y = 5 + hicol*154
        }
    }
    for (lorow = 0; lorow < 5; lorow += 1) { // lower rows
        x = 53 + lorow*130
        for (locol = 0; locol < 5; locol += 1) { // lower columns
            squiggle();
            y = 100 + locol*154
        }
    }
}

function squiggle() { // diamond of arcs w/ ellipses 
    noFill();
    strokeWeight(1);
    stroke(107, 70, 27);
    for (arccount = 0; arccount < 7; arccount += 1) {
        y += 3
        arc(x + arccount*dx, y, w, h, 3*PI/2, PI/2);
        arc(x + arccount*dx, y+h, w, h, -3*PI/2, -PI/2);
        arc(x + arccount*dx, y+2*h, w, h, 3*PI/2, PI/2);
        arc(x + arccount*dx, y+3*h, w, h, -3*PI/2, -PI/2);
    }
    ellipse(x + 7*dx, y+h, 11, 15);
    ellipse(x + 7*dx, y+3*h, 11, 15)
}

For my wallpaper, I drew inspiration from this design circa 1805. I thought the handmade recurring pattern, most likely created through block printing, would be fun to convert to a digital format. While I took the diamond shape from the original design, I opted for a more minimalist approach that didn’t need to align exactly to be visually interesting.