Srauch – Final Project

Here is my final project! It’s an interactive animation of a waterpark. Click anywhere to send someone down a random slide — or, if you prefer, click the top of a slide to send someone down that specific one!

sketch

//sam rauch, srauch, section B
//final project
//this code creates an animation of a waterpark. It's populated with people objects that have a
//skin tone and swimsuit color randomly picked from an array, so they are different every time
//you reload the page. In the foreground, people go by in a lazy river in tubes. In the background,
//people wait in line for waterslide towers.
//click anywhere to send someone down a random slide, or, click at the top of a slide to send
//a person down that specific slide!

//clouds x, y, and scale
var cloudsx = [];
var cloudsy = [];
var cloudsSc = [];

//skin tones and swimsuit colors
var skincolors;
var swimcolors;

//will hold people waiting for waterslide 1
var topSlide = [];
var slideToppers =[];
var groundWaiters1 = [];
var stairWaiters1 = [];

//will hold people waiting for waterslide 2
var groundWaiters2 = [];
var stairWaiters2 = [];
var topguy;

//bushes and trees
var bushSizes = [];
var bushColors = [];
var treeSizes = [];
var treeColors = [];

//people in lazy river
var tubers = [];

//color of wood in waterslide towers
var woodcolor;

//variables for people going down slides
var slider;
var slidetoggler;
var randomizer1;

//store mouseX and mouseY when clicked
var xWhenClick;
var yWhenClick;

function setup() {
    createCanvas(600, 400);
    background(220);

    woodcolor = color(105, 89, 56);

    //fill cloud array with clouds at random scales and positions
    for (var i=0; i<8; i++){
        cloudsx[i]= random(-10, width-10);
        cloudsy[i] = random(-10, 200);
        cloudsSc[i] = random(1,3);
    }

    //skin tones and swimsuit color values
    skincolors = [color(235, 207, 176), color(204, 168, 126), color(107, 77, 43),
                color(148, 98, 41), color(117, 84, 47), color(217, 195, 154),
                color(235, 213, 192), color(69, 48, 29), color(247, 220, 195)];
    swimcolors = [color(194, 78, 130), color(224, 49, 22), color(224, 144, 22),
                color(102, 23, 11), color(102, 23, 11), color(102, 93, 11),
                color(207, 195, 87), color(159, 207, 87), color(49, 145, 42),
                color(42, 145, 89), color(92, 191, 186), color(92, 140, 191),
                color(24, 73, 125), color(105, 89, 156), color(154, 89, 156),
                color(55, 84, 179)]

    //filling the array that handles the people in the lazy river
    var tubespacer = 50;
    for (var i=0; i<10; i++){
        tubers[i] = makeTuber(tubespacer, random(340, 350));
        tubespacer += random(30, 100);
    }

    //creating the size and color of the bushes and trees
    for (var i=0; i<width+30; i++){
        bushColors[i] = color(100, random(150, 170), 100);
        bushSizes[i] = random(30, 60);
        treeColors[i] = color(100, random(150, 170), 100);
        treeSizes[i] = random(100, 150);
    }

    //filling the array of people waiting on top of waterslide1
    var slideLocation = 410;
    for (var i=0; i<3; i++){
        topSlide[i] = makeDude(365+(i*15), 125, false);
        slideToppers[i] = makeDude(slideLocation, 125, false);
        slideLocation +=40;
    }

    //filling the array of people waiting for waterslide1 on the ground
    var groundWaiters1Loc = 280;
    for (var i=0; i<9; i++){
        groundWaiters1[i] = makeDude(groundWaiters1Loc, 280, false);
        groundWaiters1Loc += 20;
    }

    //filling the array of people waiting on the waterslide1 stairs
    var stairWaiters1Loc = 460;
    var stairHeight1 = 280;
    for (var i=1; i<13; i++){
        stairWaiters1[i] = makeDude(stairWaiters1Loc, stairHeight1, false);
        stairWaiters1Loc += 17;
        if (i<4 || i>=3) {stairHeight1-= 20;}
        if (i%4 == 0) {stairWaiters1Loc = 460;}
        if (i>4 & i<=8) {stairHeight1 = 205;}
    }

    //filling array of people waiting on ground for waterslide 2
    var groundWaiters2Loc = 240;
    for (var i=0; i<6; i++){
        groundWaiters2[i] = makeDude(groundWaiters2Loc, 270, false);
        groundWaiters2Loc -= 20;
    }

    //filling array of people waiting on stairs for waterslide 2
    var stairWaiters2Loc = 120;
    var stairHeight2 = 265;
    var sidestep = 14;
    var counter2 = 0;
    for (var i=0; i<20; i++){
        stairWaiters2[i] = makeDude(stairWaiters2Loc, stairHeight2, false);
        counter2 += 1;
        if (counter2%4==0){
            sidestep = sidestep*-1;
        }else{
            stairWaiters2Loc -= sidestep;
        }
        stairHeight2 -= 11;
    }
    topguy = makeDude(85, 50, false);

    //when this is true (set to true when mouse is clicked), an if statement in draw
    //runs that sends someone down a slide
    slidetoggler = false;

}

function draw() {
    background(162, 219, 222);
    backgroundstuff(); //draw clouds, trees, waterslides
    slidego(); //send someone down slide when the mouse is clicked
    foregroundstuff(); //draw lazy river and bushes
}

//trigger someone to go down slide in draw function
function mousePressed(){
    xWhenClick = mouseX;
    yWhenClick = mouseY;
    slidetoggler = true;
    slider = makeDude(0, 0, true);
    randomizer1 = random(0,4);
}

//translate and rotate to the top of a specific slide
function slidemover(xpos,ypos,rot){
    push();
    translate(xpos,ypos);
    rotate(radians(rot));
    slider.y += 4;
    slider.draw();
    pop();
}

//send someone down specific slide if clicked, random otherwise
function slidego(){
if (slidetoggler==true){
        //if click at the top of a specific slide, send someone down that slide
        if (xWhenClick >= 70 & xWhenClick <= 130 && yWhenClick >= 40 && yWhenClick <= 100){
            slidemover(88,50,-25);
        } else if (xWhenClick >= 400 & xWhenClick <= 435 && yWhenClick >= 110 && yWhenClick <= 170){
            slidemover(432,140,30);
        } else if (xWhenClick >= 440 & xWhenClick <= 475 && yWhenClick >= 110 && yWhenClick <= 170){
            slidemover(472,140,30);
        } else if (xWhenClick >= 480 & xWhenClick <= 515 && yWhenClick >= 110 && yWhenClick <= 170){
            slidemover(512,140,30);
        } else { //otherwise, send down a random slide
            push();
            if(randomizer1<=3){ //for three slides on right tower
                if (randomizer1 < 1){
                    translate(432,140);
                } else if (randomizer1 >= 1 & randomizer1 < 2){
                    translate(472,140);
                } else {
                    translate(512, 140);
                }
                rotate(radians(30));            
            } else { //for tall slide on left tower
                translate(88,50);
                rotate(radians(-25));
            }
            slider.y+= 4;
            slider.draw();
            pop();
        }
    }
}

//creates a person object
function makeDude(xpos, ypos, armpos){
    var dude = {x:xpos, y:ypos, armsup:armpos,
        swimsuit:swimcolors[floor(random(0,15))],
        swimtype:random(0,2),
        skin:skincolors[floor(random(0,9))],
        draw:drawDude};
    return dude;
}

function drawDude(){
    noStroke();
    fill(this.skin);
    ellipse(this.x, this.y, 10, 10); //head
    rect(this.x-5, this.y+7, 10, 16); //torso
    stroke(this.skin);
    strokeWeight(4.5);
    line(this.x, this.y, this.x, this.y+10); //neck

    strokeWeight(3.5); //toggles if arms are up or down based on this.armsup var declared in constructor
    if (this.armsup == true){
        line(this.x-4, this.y+7, this.x-11, this.y-2); //right arm
        line(this.x+4, this.y+7, this.x+11, this.y-2); //left arm
    } else {
        line(this.x-4, this.y+7, this.x-10, this.y+16); //right arm
        line(this.x+4, this.y+7, this.x+10, this.y+16); //left arm
    }

    strokeWeight(4);
    line(this.x-3, this.y+22, this.x-3, this.y+35); //right leg
    line(this.x+3, this.y+22, this.x+3, this.y+35); //left leg

    noStroke();
    if (this.swimtype<1){ //swim trunks
        fill(this.swimsuit);
        rect(this.x-6, this.y+18, 12, 5);
        rect(this.x-6, this.y+23, 5, 5);
        rect(this.x+1, this.y+23, 5, 5);
    } else { //bikini
        fill(this.swimsuit);
        rect(this.x-5, this.y+10, 10, 13);
        ellipse(this.x-2, this.y+10.5, 5, 5);
        ellipse(this.x+2, this.y+10.5, 5, 5);
        stroke(this.swimsuit);
        noStroke();
        fill(this.skin);
        triangle(this.x-1, this.y+24, this.x-5, this.y+24, this.x-5, this.y+18);
        triangle(this.x+1, this.y+24, this.x+5, this.y+24, this.x+5, this.y+18);
        rect(this.x-5, this.y+13, 10, 4);
    }
}

//creates a person in a tube object
function makeTuber(xpos, ypos){
    var tuber = {x:xpos, y:ypos,
        swimsuit:swimcolors[floor(random(0,15))],
        swimtype:random(0,2),
        skin:skincolors[floor(random(0,9))],
        draw:drawTuber};
    return tuber;
}

function drawTuber(){
    push();

    //inner tube
    stroke(this.skin);
    strokeWeight(4);
    line(this.x-1, this.y+12, this.x-11, this.y+22);
    noStroke();
    fill(62, 158, 62);
    rect(this.x-14, this.y+18, 28, 16);
    ellipse(this.x-14, this.y+26, 16);
    ellipse(this.x+14, this.y+26, 16);
    stroke(30, 94, 30);
    strokeWeight(4);
    line(this.x-10, this.y+23, this.x+10, this.y+23);

    //head, neck, torso, and back arm
    push();
    translate(this.x+6, this.y+4);
    rotate(radians(10));
    noStroke();
    fill(this.skin);
    ellipse(0, 0, 10, 10); //head
    rect(-5, 7, 10, 16); //torso
    stroke(this.skin);
    strokeWeight(4.5);
    line(0, 0, 0, 10); //neck

    noStroke();
    if (this.swimtype<1){ //swim trunks
        fill(this.swimsuit);
        rect(-6, 18, 12, 5);
        rect(-6, 23, 5, 5);
        rect(1, 23, 5, 5);
    } else { //bikini
        fill(this.swimsuit);
        rect(-5, 10, 10, 13);
        ellipse(-2, 10.5, 5, 5);
        ellipse(+2, +10.5, 5, 5);
        stroke(this.swimsuit);
        noStroke();
        fill(this.skin);
        triangle(-1, 24, -5, 24, -5, 18);
        triangle(1, 24, 5, 24, 5, 18);
        rect(-5, 13, 10, 4);
    }
    pop();
    strokeWeight(4.5);
    stroke(this.skin);
    line(this.x+4, this.y+25, this.x+4, this.y+25);
    line(this.x, this.y+25, this.x-6, this.y+21);

    //a few more details
    noStroke();
    fill(62, 158, 62);
    rect(this.x-10, this.y+25, 20, 9);
    strokeWeight(4.5);
    stroke(this.skin);
    line(this.x+10, this.y+14, this.x+16, this.y+25); //front arm
    line(this.x-6, this.y+21, this.x-10, this.y+31); //right leg
    line(this.x+2, this.y+25, this.x, this.y+34); //left leg

    //water texture
    noStroke();
    fill(81, 181, 201, 100);
    rect(this.x-22, this.y+30, 44, 6);

    pop();

}

//draws the waterslide on the left
function waterslide1(x,y){
    //stairs
    fill(woodcolor);
    beginShape();
    vertex(x+100, y+80);
    vertex(x+100, y+90);
    vertex(x+170, y+20);
    vertex(x+170, y+10);
    endShape();
    rect(x+100, y+80, 70, 8);
    beginShape();
    vertex(x+100, y+160);
    vertex(x+113, y+160);
    vertex(x+170, y+95);
    vertex(x+170, y+80);
    endShape();

    //pillars
    fill(95, 79, 46);
    rect(x+5, y+5, 5, 155);
    rect(x+100, y+5, 5, 155);
    rect(x+170, y+5, 5, 155);

    //shade poles
    rect(x+3, y-50, 3, 50);
    rect(x+180-6, y-50, 3, 50);
    rect(x+50, y-55, 3, 55);
    rect(x+130-6, y-55, 3, 55);

    //shades
    fill(35, 82, 168);
    rect(x+3, y-55, 47, 6);
    triangle(x+3, y-55, x+50, y-55, x+27, y-70);
    rect(x+50, y-60, 77, 5);
    triangle(x+50, y-60, x+127, y-60, x+88.5, y-85);
    rect(x+127, y-55, 50, 5);
    triangle(x+127, y-55, x+176, y-55, x+152, y-70);

    //railings
    fill(95, 79, 46);
    var xpos = x;
    for (var i = 0; i < 12; i++){
        rect(xpos, y-15, 2, 15);
        xpos += 5;
    }
    for (var j = 0; j<2; j++){
        xpos += 22
        for (var i = 0; i < 4; i++){
            rect(xpos, y-15, 2, 15);
            xpos += 5;
        }
    }
    xpos += 19
    for (var i = 0; i < 4; i++){
        rect(xpos, y-15, 2, 15);
        xpos += 5;
    }

    //deck
    fill(woodcolor);
    rect(x, y, 180, 10);
    rect(x, y-15, 180, 3);

    //draw slides
    var color1 = color(166, 61, 124);
    slide1(x+60, y, color1);
    var color2 = color(186, 176, 67);
    slide1(x+100, y, color2);
    var color3 = color(57, 94, 163);
    slide1(x+140, y, color3);

}

//draws slides for waterslide1 function
function slide1(x,y,color){ 
    var slidewide = 22;
    fill(color);
    beginShape();
    vertex(x, y);
    vertex(x+slidewide, y);
    vertex(x-80, y+180);
    vertex(x-80-slidewide, y+180);
    endShape();

    var margin = 4;
    fill(150, 255, 255, 50);
    beginShape();
    vertex(x+margin, y);
    vertex(x+slidewide-margin, y);
    vertex(x-80-margin, y+180);
    vertex(x-80-slidewide+margin, y+180);
    endShape();
}

//draws waterslide on left
function waterslide2(x,y){

    //pillars and stairs
    var loc = 310; //increment 46
    for (var i = 0; i< 5; i++){
        fill(woodcolor);
        if (i%2==0 || i==0) {
            beginShape();
            vertex(x-30, loc-51);
            vertex(x-30, loc-41);
            vertex(x+30, loc);
            vertex(x+30, loc-10);
            endShape();
        } else {
            beginShape();
            vertex(x-30, loc);
            vertex(x-30, loc-10);
            vertex(x+30, loc-51);
            vertex(x+30, loc-41);
            endShape();
        }   
        loc -= 44;
    }
    fill(95, 79, 46);
    rect(x-30, y, 6, 230); //bottom y = 310
    rect(x+24, y, 6, 230);

    rect(x-30, y-40, 3, 40);
    rect(x+27, y-40, 3, 40);
    fill(189, 65, 43);
    rect(x-30, y-45, 60, 6);
    triangle(x-30, y-45, x+30, y-45, x, y-60);

    fill(woodcolor);
    rect(x-30, y, 60, 10);
    rect(x-30, y-15, 15, 2.5);
    rect(x+15, y-15, 15, 2.5);
    var location = x-30;
    for (var i = 0; i<8; i++){
        rect(location, y-15, 2, 15);
        if (i != 3){location += 5;}
        else {location += 28;}
    }

    fill(252, 165, 3);
    beginShape();
    vertex(x-15, y);
    vertex(x+15, y);
    vertex(x+140, y+260);
    vertex(x+110, y+260);
    endShape();

    fill(150, 255, 255, 50);
    beginShape();
    vertex(x-10, y);
    vertex(x+10, y);
    vertex(x+130, y+250);
    vertex(x+115, y+260);
    endShape();
}

//draws cloud
function cloud(x,y, amt){
    noStroke();
    fill(218, 237, 236);
    push();
    translate(x,y);
    scale(amt);
    ellipse(0,0,40);
    ellipse(-20, 5, 30);
    ellipse(20, 5, 30);
    pop();
}

//draws background
function backgroundstuff(){
    //clouds
    for (var i=0; i<8; i++){
        cloud(cloudsx[i], cloudsy[i], cloudsSc[i]);
    }

    //trees
    noStroke();
    for (var i=0; i<width+30; i+= 80){
        fill(treeColors[i]);
        ellipse(i, 270, treeSizes[i]);
    }

    //fence
    strokeWeight(2);
    stroke(120);
    line(0, 280, width, 280);
    strokeWeight(.75);
    for (var i=-12; i<width+12; i+=4){
        line(i, 300, i+16, 280);
        line(i, 300, i-16, 280);
    }

    //concrete
    noStroke();
    fill(199, 196, 163); //concrete color
    rect(0, 300, width, 100);
    fill(168, 162, 28);

    //pool at base of slides
    fill(81, 181, 201);
    rect(80, 325, 420, 100);
    ellipse(80, 350, 50);
    ellipse(500, 350, 50);

    //people in waterslide1 line
    for (var i=0; i<topSlide.length; i++){
        topSlide[i].draw();
        slideToppers[i].draw();
    }
    for (var i=0; i<groundWaiters1.length; i++){
        groundWaiters1[i].draw();
    }
    for (var i=1; i<stairWaiters1.length; i++){
        stairWaiters1[i].draw();
    }

    //people in waterslide2 line
    for (var i=0; i<stairWaiters2.length; i++){
        stairWaiters2[i].draw();
    }
    for (var i=0; i<groundWaiters2.length; i++){
        groundWaiters2[i].draw();
    }
    topguy.draw();

    //draw waterslides
    waterslide1(350, 160);
    waterslide2(100, 80);
}

//draws bushes, draws and updates lazy river
function foregroundstuff(){
        //bushes
    for (var i=0; i<width+30; i+= 30){
        fill(bushColors[i]);
        ellipse(i, 350, bushSizes[i]);   
    }

    //lazy river
    fill(179, 176, 143);
    rect(0, 350, width, 50);
    fill(81, 181, 201);
    rect(0, 355, width, 40);

    //lazy river inhabitants
    for (var i = 0; i < tubers.length; i++){
        if (tubers[i].x <= -30){
            var mover = tubers.shift();
            mover.x = width + 28;
            tubers.push(mover);
        }
        tubers[i].draw();
        tubers[i].x -= 0.5;
    }
}

Srauch – Project 11 – Scrolling Landscape

My code shows a scrolling New Mexico landscape, with sagebrush in the foreground, sage-covered land stretching to the mountains in the middleground, and a mountain range in the background.

sketch
//Sam Rauch, section B, srauch@andrew.cmu.edu, project
//this code creates a randomly generated scrolling new mexico landscape with sagebrush
//in the foreground, distant bushes in the middleground, and mountains in the background.
//A late afternoon moon hangs low in the sky.

//arrays for objects
var sageArray = [];
var mountainArray = [];
var backbushes = [];

function setup() {
    createCanvas(400, 200);
    background(220);
    text("p5.js vers 0.9.0 test.", 10, 15);
    frameRate(30);

    //fill sage array with random sagebrush
    var initsageY = random(30, 40);
    for (var i = 0; i<20; i++){
        sageArray.push(newSage(initsageY, random(160, 190)));
        initsageY += random(20, 40);
    }

    //fill mountain array with random starter mountains
    var initmountX = random(0,40);
    for (var i = 0; i < 20; i ++){
        var mont = makeMountain(initmountX, random(70, 90), random(40, 60));
        mountainArray.push(mont);
        initmountX += random(30, 40);
    }

    //fill backbushes array with random starter bushes
    var initBushX = random(0,10);
    for (var i = 0; i<100; i++){
        backbushes.push(newBush(initBushX, random(100, 150)));
        initBushX += random(0, 10);
    }
}

function draw() {
    background(129, 173, 223);
    noStroke();

    //draw moon
    var moonfill = color(235, 243, 247, 200);
    fill(moonfill);
    ellipse(300, 50, 20, 20);

    //draw middleground
    fill(111, 158, 148);
    rect(0, 100, 400, 100);

    //draw mountains, push in new mountains on right as they go off screen to left
    for (var i = 0; i < mountainArray.length; i++){
        mountainArray[i].peakX -= 0.25;
        mountainArray[i].draw();

        if (mountainArray[i].peakX <= -70){
            mountainArray.shift();
            mountainArray.push(makeMountain(random(440, 460), random(60, 90), random(40, 60)));
        }
    }

    //draw backbushes, push in new ones as go off screen
    for (var i = 0; i < backbushes.length; i++){
        backbushes[i].x -= 0.5;
        backbushes[i].draw();

        if (backbushes[i].x <= -10){
            backbushes.shift();
            backbushes.push(newBush(random(402, 420), random(100, 150)));
        }
    }

    //draw foreground
    fill(156, 127, 70);
    rect(0, 150, 400, 50);

    //draw sagebrush in front

    for (var i = 0; i < sageArray.length; i++){
    //draw each sagebrush shadow; in seperate loop so it will always draw before
    //(thus underneath) the sagebrush
        fill(117, 98, 56);
        ellipse(sageArray[i].x, sageArray[i].y, 20, 8);
    }

    for (var i = 0; i < sageArray.length; i++){
        sageArray[i].x -= 2; //move each sagebrush along to left
        sageArray[i].draw(); //draw each sagebush
    }

    if (sageArray[0].x < -10){ //if sagebrush is off the canvas, shift and push in a new one
        sageArray.shift();
        sageArray.push(newSage(random(410, 430), random(160, 190)));
    }

}

//objects for sagebrush, mountain, and backbush

function newSage(xpos,ypos){
    var sage = {x: xpos, y:ypos, draw:drawSagebrush};
    return sage;
}

function drawSagebrush(){
    stroke(66, 46, 23);
    var bushstart = this.x-10;
    for (var i = 0; i<8; i++){
        line(this.x,this.y,bushstart,this.y-15);
        bushstart += 3;
    }
    stroke(66, 110, 90);
    fill(93, 135, 111);
    ellipse(this.x-8, this.y-15, 7, 7);
    ellipse(this.x+8, this.y-15, 7, 7);
    ellipse(this.x-5, this.y-17, 8, 8);
    ellipse(this.x+5, this.y-17, 8, 8);
    ellipse(this.x,this.y-18, 10, 10);
    noStroke();
}

function makeMountain(x, y, wide){
    var mountain = {peakX: x, peakY: y, base:wide, draw: drawMountain};
    return mountain;
}

function drawMountain(){
    fill(96, 129, 181);
    beginShape();
    vertex(this.peakX, this.peakY);
    vertex(this.peakX-this.base, 100);
    vertex(this.peakX+this.base, 100);
    endShape();
}

function newBush(xpos,ypos){
    var bush = {x: xpos, y:ypos, draw: drawBush};
    return bush;
}

function drawBush(){
    strokeWeight(5);
    stroke(106, 135, 124);
    point(this.x, this.y);
    strokeWeight(1);
    noStroke();
}

srauch – Blog 11 – Societal Impacts of Digital Art

I found a very interesting episode of Sidedoor, a podcast created by the Smithsonian, that interviewed artist Stephanie Dinkins about her work on how Black stories interact with AI.

Many AIs that are programmed to generate language pull information from the internet. This makes sense – if you’re looking to train an AI to talk, why not use the biggest and most easily accessible database of language in the world? Well, because, as Dinkins articulates, the internet is racist. It’s full of language that, even if it’s not overtly racist, is filled with the inherent racist biases and assumptions that have become ingrained within the English language. Those biases, by extension, become embedded in the AI. To counter this phenomena, Dinkins created Not the Only One: an AI that creates a memoir of a Black American family. It draws its language ability not from the internet, but from the familial stories from Dinkins, her mother, and her grandmother. Her work raises valuable questions about where our information is coming from. While we think of computers as completely logical, we can’t forget that they’re a product of human creation, and thus always susceptible to our biases and human errors.

Project 09 – srauch – portrait

Here is my “glass door” portrait. You can change the fidelity of it by moving the mouse up and down. By moving your mouse all the way to the bottom of it, the full portrait is revealed.

sketch
//Sam Rauch, section B, srauch@andrew.cmu.edu, project 09 
//this code makes a "glass door" picture of me with colored ellipses, like you're looking
//at me through one of those textured glass doors. It samples the image
//color at each pixel location (though it skips every other y row to help it run a bit faster)
//and draws a circle there. The circle size is tied to mouseY, so when the mouse is higher up, 
//the circles are larger and the image is lower-fidelity, but it gets higher fidelity as the
//user moves the mouse down the image. 

var samImg;
var uploadImg;

var dotArray = [];

var first = 0;

function preload(){
    uploadImage = "https://i.imgur.com/nTNXyHg.jpg";
}

function setup() {
    createCanvas(400, 533);
    background(220);
    samImg = loadImage(uploadImage);
    frameRate(1);
}

function draw() {
    
    background(50);
    image(samImg, 0, 0);
    
    if (first == 0){ // define all the dot objects; run once at start of draw

        for (var y = 0; y < 533; y+=2){ //fill array with dots all over canvas
            for (var x = 0; x < 400; x++){
                var clr = samImg.get(x, y);
                dotArray.push(makeDot(x, y, 20, clr))
            }
        }
        first ++;
    }

    var sizeTicker = map(mouseY, 0, height, 45, 3); //set dot size to move with mouseY

    shuffle(dotArray, true);
    for(var i = 0; i < dotArray.length; i++){ //draw dots in array
        dotArray[i].size = sizeTicker;
        dotArray[i].drawDot();
    }
}

//dot object and draw function
function makeDot(xpos,ypos,siz,clr){
    var dot = {x: xpos, y:ypos, size:siz,
            color:clr,
            drawDot: drawDotFunction}
    return dot;
}

function drawDotFunction(){
    stroke(this.color);
    //print(this.color)
    strokeWeight(this.size);
    point(this.x, this.y);
}

Blog 09 – Women and Non-Binary Practitioners in Computational Art – srauch

For my piece, I picked ENIGMA, a computer-generated film created by Lillian Schwartz in 1972. 

ENIGMA (1972)

Schwartz worked out of Bell Labs’ Acoustical and Behavioral Research Center from 1968 to 2002, and during her time there, she created a series of videos that were visual output of computer algorithms, ENIGMA being one of them.

What I find so remarkable about her videos is that they were algorithmically generated, but because of the technology at the time, they were physically produced. Each frame the computer output had to be burned into 35mm film one at a time, and then the film itself had to be developed before Schwartz could see the image. Schwartz fluently used the kind of creative thinking afforded by computer-generated art decades before such computational art was accessible or even necessarily made sense to make, allowing her to produce art that is completely unlike anything else being made at the time. As she said in an interview, “I’ve always been interested in what different media could provide me in terms of creating something that had never been seen before or provoke me to create in ways I had not created before.” 

Her work prompts me to think about how art can inspire technology. Art is perhaps an excellent place for an algorithm or computer program to begin its life, because there isn’t initially an expectation that it’s perfect or exactly efficient. Freed from the initial constraints of functionality, new creative ideas can flow and grow, and by the time the program is being translated into the practical realm, it’s become something completely new.

Blog 08 – The Creative Practice of an Individual – srauch

I watched Deb Chachra’s talk on architectural biology and biological architecture. Chachra considers herself an engineer rather than an artist; she’s a professor of engineering at Olin College in Massachusetts. While her primary focus is on making engineering more accessible and inclusive, particularly in the realm of where engineering and gender intersect, she also has an interest in where material science and biology intersect. This talk was about the overlaps between biological structures and architectural engineering. As she explains, with architectural calculation and fabrication techniques evolving as they are, we’re approaching being able to create structures that imitate bone that provide the highest possible strength to weight ratio and can “heal” themselves. 

Bone-like building structures would be a spectacular example of biomimicry, a branch of design I find fascinating. Biomimicry is the practice of imitating nature to create the most efficient design possible – after all, there’s no better designer than 3.7 billion years of evolution. Because biology and engineering don’t traditionally intersect, it takes someone who is interested in both to ideate such solutions, which is why I admire Chachra’s ingenuity to be crossing fields and embracing the emergent potential. Beyond her work itself, I admired her presentation. She gave a very comprehensive but brief history of architecture, and gave an easy-to-understand but not infantilizing explanation of some of the basic biological processes of bones.

Project 07 – srauch – curves

Here is my program that runs on curves. I call it “laser ballerinas”. Move your mouse left to right to increase the size of the curves and the overall rotation, and move your mouse up and down to change the number of “lobes” on each curve. Click to change the colors of each lobe!

sketch

//Sam Rauch, section B, srauch@andrew.cmu.edu, project 07
//This code produces a "laser ballerinas" using epicycloid curves. Ten epicycloid curves of decreasing
//size and random colors are drawn on top of each other to produce "nested curves", and six nested curves
//are drawn in a hexagon pattern around the center of the canvas, which spins. MouseX controls the size of
//the curves and the rotation of the hexagon pattern, while mouseY controls the number of "lobes" produced
//in each epicycloid curve. Click to change the colors of the ballerinas!

var coloroptions;

function setup() {
    createCanvas(400, 400);
    background(220);
    text("p5.js vers 0.9.0 test.", 10, 15);

    coloroptions = [];
    for (var i = 0; i < 9; i++) {
        coloroptions[i] = color(random(255), random(255), random(255));
    }

}

function draw() {
    background(0);
    translate(width/2, height/2);
    
    //create spin the hexagon of curves around the center of the canvas according to mouseX
    push();
    var spinamt = map(mouseX, 0, width, 0, 2*PI)
    rotate(spinamt);


    //draws six nested curves in a hexagon pattern
    for (var i = 0; i < 6; i++){
        push();
        translate(100, 0);
        nestedCurve();
        pop();
        rotate(radians(60));
    }

    pop();

}

//generates epicycloid curve (https://mathworld.wolfram.com/Epicycloid.html) with center at 0,0
function drawCurve(color){ 
    
    noFill();
    stroke(color);
    strokeCap(ROUND);
    strokeJoin(ROUND);
    strokeWeight(3);

    var points = 80;
    var xValues = [];
    var yValues = [];
    var a = mouseX/4; //radius of larger inner circle 
    var b = constrain(mouseY/10, 0, a) ; //40; //radius of smaller outer circle
    var theta = 0;

    //generating x and y values based on epicycloid curve forumla, and increasing the center angle
    //by a small amount
    for (var i = 0; i < points; i++) {
        theta += radians(5);
        xValues[i] = (a+b)*cos(theta) - b*cos(((a+b)/b)*theta);
        yValues[i] = (a+b)*sin(theta) - b*sin(((a+b)/b)*theta);
    }
    
    //plotting x and y values
    beginShape();
    for (var i = 0; i <points; i++) {
        vertex(xValues[i], yValues[i]);
    }
    endShape();
}

//draws ten epicycloid curves of random colors nested inside each other
function nestedCurve() {
    push();

    var size = 1;
    var sizeIncrement = 0.1;

    //draws ten epicycloid curves, but for each one, decreases scale and change color
    for (var i = 0; i < 9; i++) {
        scale(size);

        var col = coloroptions[i];
        drawCurve(col);
        size -= sizeIncrement;
    }

    pop();
}

function mousePressed(){
    for (var i = 0; i < 9; i++) {
        coloroptions[i] = color(random(255), random(255), random(255));
    }
}

Blog 07 – Data Visualization – srauch

I enjoy these data visualizations of the 2021 summer olympics, conceived by designer Eden Weingart and created by the New York Times graphic department. This one is specifically for swimming, the 400-meter freestyle.

To make these animations, the graphic team created a program that can apply the raw data of the race onto animations, allowing twitter users to see a sped-up version of the race’s events (not just the results!). This raw data included each swimmer’s time for every meter of the race, the time they hit the end of the pool and turned around, and the time they finished. The program then mapped this data onto an animated avatar for each athlete.

I find this approach to sports reporting really cool, since it provides a different way for us to interact with the data of the sport. It can be quite tempting to throw all of the data out the window once we know who won, but an approach such as this allows casual readers to see those intricacies – who led at first, any surprising turnovers, etc. – in a consumable and exciting way.

Project 06 – Abstract Clock – srauch

Here is my abstract clock. It’s a beach with tides: high tide is at noon and low tide is at midnight. The grass rustles in the breeze, and the beach is strewn with starfish and shells. It’s dark from 8 pm to 5am. Sunrise is from 6am to 7am, and sunset is from 7pm to 8pm.

sketch

//Sam Rauch, section B, srauch@andrew.cmu.edu, project 06: abstract clock
//this code creates a beach with a tide. High tide is at noon, and low tide is at midnight.
//the grass rustles in the sea breeze. it gets darker from 7pm 8 pm and lighter from 6 to 7am. 

var grasslength = []; //length of blades of grass
var sandspotX = []; //x position of specks in sand
var sandspotY = []; //y position of specks in sand
var waveY; //height of the tide
var waveShift; //amount the water's edge fluctuates by 
var daytime; //the time of day in minutes
var darkness; //amount of darkness it is

function setup() {
    createCanvas(400, 400);
    background(220);
    text("p5.js vers 0.9.0 test.", 10, 15);

    //initializing x position of specks in sand
    for (var i = 0; i < 50; i++){
        sandspotX[i] = random(0, width);
    }

    //initializing y position of specks in sand
    for (var i = 0; i < 50; i++){
        sandspotY[i] = random(200, 400);
    }

    frameRate(5);

    //creating y position of tide. High tide is at noon, low tide is at midnight
    daytime = hour()*60 + minute(); //time of day, in minutes
    if (daytime < 690) { //if before noon
        waveY = map(daytime, 0, 690, 400, 200); //before noon, wave gets higher with time
    } else { //if after noon
        waveY = map(daytime, 690, 1380, 200, 400); //after noon, wave gets lower with time
    }

    //making it get lighter and darker at sunrise and sunset
    if (daytime >= 300 & daytime < 360) { //if from 5 to 6 am, it gets lighter
        darkness = map(daytime, 300, 360, 120, 0);
    } else if (daytime >= 1140 & daytime < 1200) { //from 7 to 8 pm, it gets darker
        darkness = map(daytime, 1140, 1200, 0, 120);
    } else if (daytime >= 360 & daytime < 1140) { //in the middle of the day, it's not dark
        darkness = 0;
    } else { //in the middle of the night, it's dark
        darkness = 120;
    }
}

function draw() {
    noStroke();
    background(155, 207, 207);

    //row of grass bunches
    for (var i = 0; i <2; i++){
        for(var j = 0; j<=width; j += 20) {
        grass(j, 220);
        }
    }
    
    //sand
    fill(196, 178, 122);
    rect(0, 200, width, 200);

    //little specks in sand
    strokeWeight(3);
    stroke(146, 128, 72)
    for (var i = 0; i<50; i++){
        point(sandspotX[i], sandspotY[i]);
    }
    noStroke();

    //assorted shells and starfish
    starfish(250, 250, color(120, 130, 120), 10);
    starfish(50, 340, color(50, 74, 64), 50);
    starfish(180, 370, color(120, 79, 97), 5);
    shell(140, 260, color(60, 50, 70), color(100, 80, 107), 60);
    shell(300, 300, color(80, 50, 50), color(120, 80, 97), -5);

    //waves
    waveShift = randomGaussian(1, 2);
    fill(30, 100, 155, 240);
    rect(0, waveY+waveShift, width, 300);
    fill(30, 100, 155, 100);
    rect(0, waveY-(random(1,3))+waveShift, width, 300);

    //rectangle that makes darkness and lightness of environment using alpha channel
    blendMode(MULTIPLY);
    fill(35, 50, 70, darkness);
    rect(0,0,width,height);
    blendMode(BLEND);
}

//makes starfish
function starfish(x,y, color, spin){
    push();
    translate(x,y);
    rotate(radians(spin));
    strokeWeight(4);
    stroke(color);
    for (var i = 0; i<5; i++){ //draw five arms from 0,0, rotating after each one
        line(0,0,0,-10);
        rotate(radians(72));
    }
    noStroke();
    pop();
}

//makes seashells
function shell(x,y, color1, color2, spin) {
    push();
    translate(x,y);
    rotate(radians(spin));
    strokeWeight(1);
    stroke(color1);
    fill(color2);

    var radius = 7; //radius of seashell, ie distance from circles to center
    var size = 12; //size of circles themselves
    var angle = radians(0); //theta of circle location
    for (var i = 0; i<20; i++) { //draw circles that get smaller as they get closer to the center
        ellipse ( cos(angle)*radius, sin(angle)*radius, size);
        angle-=radians(24);
        size -= i/20; //decrease size of circles
        radius -= i/30; //decrease radius of seashell       
    }
    noStroke();
    pop();
}

//makes a bunch of grass
function grass(x,y){
    push();
    translate(x,y);
    stroke(65, 100, 52);
    strokeWeight(2);
    rotate(radians(-40));
    for (var i = 0; i < 20; i++){ //creating each blade of grass in a bunch
        for (var j = 0; j < 20; j++){ //creating random lengths for each blade of grass
            grasslength[j] = random(35, 40);
        }
        line(0,0,0, -1*grasslength[i]);
        rotate(radians(4));
    }

    pop();
}

Blog 06 – Randomness – srauch

I find Paul Dunham’s installation Click::RAND to be fascinating. It’s based on the book A Million Random Digits with 100,000 Normal Deviates, which was published by the RAND corporation in 1955 to allow computer programmers to have an extensive amount of truly random numbers on hand. (The numbers themselves were generated by a program designed to work as a roulette wheel.) The book was available in standard print, but also as computer punchcards, and it’s the latter version that Dunham was inspired by. He created “instruments” by wiring together a grid of old-fashioned electromagnetic relays that make an audible click when they open and close, then feeding them the random numbers provided by the punchcards as instructions on when to move. The result is an audible experience of randomness, with ephemeral patterns seemingly flashing in and out of the composition.

The listening experience seems to say something about how we as humans tend to try to impose order on our surroundings. Because of the way our neural networks work, we aren’t capable of thinking in a truly random way, and we have an inherent tendency to seek patterns. So, it’s an interesting experience to listen to something random and watch your brain spin itself out looking for patterns that actually aren’t there. 

Here is a video of Click::RAND in action. Scroll to about halfway in to see it in all its glory: