Final Project: Ocean Clean-up Simulator

sketch
//Anthony Pan
//Section C
//final project proposal final

//requirements:
    //loops, arrays, conditionals (if), user interaction, transformations, 
    //functions (besides setup and draw), 
    //and use of at least one object definition of your own design.

//net object "line" "pushes" trash objects to the right of the canvas 
    // if trash objects are to the right of the line, update all of the ones to the right 
    //within certain number of pixels, x position of the trash objects will update and increase incrementally
    //lin search particle loop
    //if statement with mouseX
        //capture value of mouseX at that instance to avoid bugs
//create seperate function that changes background color
// use series of if statements

//array and object for garbage 1
var garbage1Showing = [];
var garbage1; 

//array and object for garbage 2
var garbage2; 
var garbage2Showing = [];


//array and object for ocean details
var OceanDetail; 
var oceanDetailShowing = [];

//frame counter
var counter = 0;

var fishes = [];
var fish;  

//angle for rotation og garbage2 object
var angle = 0;

function setup() {
    createCanvas(500, 200);

    //create objects for garbage 1
    for(var i = 0; i < 8; i ++) {
        garbage1 = makeGarbage1(random(50,150), color(random(255)));
        garbage1Showing.push(garbage1);

    }

    //create objects for garbage 2
    for(var i = 0; i < 10; i++) {
        garbage2 = makeGarbage2(random(60, 140));
        garbage2Showing.push(garbage2);
    }

    //create objects for ocean details
    for(var i = 0; i < 7; i++) {
        OceanDetail = makeOceanDetail(random(0,height), color(255));
        oceanDetailShowing.push(OceanDetail);
    }

    
    for (var i = 0; i < 10; i++) {
        fish = makeFish();
        fishes.push(fish);
    }
    

    
}

function draw() {
    //change water color based on # of objects in water
    waterChange();



    //ocean detail functions
    OceanDetailDisplay();
    removeOceanDetail();
    addNewOceanDetail();

    noStroke();
    
    //garbage2 functions
    garbage2DisplayandMove();
    removeGarbage2();

    //garbage1 functions
    garbage1DisplayandMove();
    removeGarbage1();

    //add new garbage to ocean based on probability
    addNewGarbage1();
    addNewGarbage2();

    //display fish if water is blue to dark blue
    if(garbage1Showing.length > 0 & garbage1Showing.length <= 40) {
        displayFish();
    }
    

    //draw net
    fill(255);
    noStroke();
    rect(mouseX, 0, 2, 400);

    //check if garbage is ahead of net, if so use net to push them off screen 
    checkGarbage1Ahead();
    checkGarbage2Ahead();
    

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//fish code

//fish constructor
function makeFish() {
    var fish = {x: random(25, 600), y: random(25, 220),
        speed: random(-0.2,0.2),
        c: color(10,10,random(255)),
        draw: drawFish,
        move: moveFish
    }
    return fish;
}

//draw fish shape
function drawFish() {
    fill(this.c);
    push();
    scale(0.8); //transformation 
    ellipse(this.x, this.y, 20, 10);

    //direction of fish indicates which way tail is facing
    if(this.speed < 0) {
        triangle(this.x+10, this.y, this.x+15, this.y-5, this.x+15, this.y+5);
    } else {
        triangle(this.x-10, this.y, this.x-15, this.y-5, this.x-15, this.y+5);
    }
    pop();

}

//move fish 
function moveFish() {
    this.x += this.speed;

    //hits random point within canvas, fish will turn other direction 
    if(this.x > width - random(50) || this.x < random(50)) {
        this.speed = -this.speed; 
    }
}

//one function to display and move fish on canvas 
function displayFish() {
    for(var i = 0; i < fishes.length; i++) {
        fishes[i].move();
        fishes[i].draw();
    }
}




////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//type garbage1 functions

//garbage1 constructor
function makeGarbage1(gy, c) {
    var garbage1 = {x: -10, y: gy,
        speed: random(0.05,0.75),
        Yspeed: random(0,0.2),
        size: random(1,6),
        fill: c,
        move: garbage1Move,
        draw: garbage1Draw }
    return garbage1;
}

//draw garbage1
function garbage1Draw() {
    fill(this.fill);
    ellipse(this.x, this.y, this.size, this.size);


}

//move garbage1
function garbage1Move() {
    this.x += this.speed;
    this.y += this.Yspeed;
    if(this.y >= 150 || this.y <= 50) {
        this.Yspeed = -this.Yspeed;
    }

    //to slow down at the middle and collect
    if(this.x >= width/2) {
        this.speed = 0.001;

    }

}

//1 function to move and draw garbage
function garbage1DisplayandMove() {
    for(var i = 0; i < garbage1Showing.length; i++) {
        garbage1Showing[i].move();
        garbage1Showing[i].draw();
    }

}

//make new garbage based on probability 
function addNewGarbage1() {
    var newGarbage1likelihood = 0.01;
    if(random(0,1) < newGarbage1likelihood) {
         garbage1Showing.push(makeGarbage1(random(50,150), color(random(255))));
    }
}

//remove garbage off screen 
function removeGarbage1() {
    var garbage1ToKeep = [];
    for (var i = 0; i < garbage1Showing.length; i++){
        if (garbage1Showing[i].x < width) {
            garbage1ToKeep.push(garbage1Showing[i]);
        }
    }
    garbage1Showing = garbage1ToKeep; // remember the showing garbage2
}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//garbage2 functions

//garbage 2 constructor
function makeGarbage2(gy) {
    var garbage2 = {x: -10, y: gy,
        speed: random(0.1,0.3),
        Yspeed: random(0,0.2),
        size: random(2,7),
        r: random(255),
        g: random(255),
        b: random(255),
        move: garbage2Move,
        draw: garbage2Draw }
    return garbage2;

}

//draw garbage 2 
function garbage2Draw() {
    rectMode(CENTER);

    //garbage spins
    push();
    translate(this.x,this.y);
    rotate(radians(angle));
    angle += 0.1;

    fill(this.r, this.g, this.b);
    rect(0, 0, this.size, this.size);

    pop();
}

//move garbage 2
function garbage2Move() {
    this.x += this.speed;
    this.y += this.Yspeed;
    if(this.y >= 140 || this.y <= 60) {
        this.Yspeed = -this.Yspeed;
    }

    //to slow down at the middle and collect
    if(this.x >= width/2) {
        this.speed = 0.001;

    }

}

//1 function to draw and move garbage
function garbage2DisplayandMove() {
    for(var i = 0; i < garbage2Showing.length; i++) {
        garbage2Showing[i].move();
        garbage2Showing[i].draw();
    }

}

//remove garbage 2 if off screen 
function removeGarbage2() {
    var garbage2ToKeep = [];
    for (var i = 0; i < garbage2Showing.length; i++){
        if (garbage2Showing[i].x < width) {
            garbage2ToKeep.push(garbage2Showing[i]);
        }
    }
    garbage2Showing = garbage2ToKeep; // remember the showing garbage2
}

//add new garbage periodically
function addNewGarbage2() {
    var newGarbage2likelihood = 0.01;
    if(random(0,1) < newGarbage2likelihood) {
         garbage2Showing.push(makeGarbage2(random(50,150)));
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//make ocean details

//make ocean detail object
function makeOceanDetail(oy, c) {
    OceanDetail = {x: 0, y: oy,
        speed: random(0.1,0.3),
        fill: c,
        move: oceanDetailMove,
        draw: oceanDetailDraw }
    return OceanDetail;
}

//move ocean detail
function oceanDetailMove() {
    this.x += this.speed;
}

//drawocean details
function oceanDetailDraw() {
    noFill();
    strokeWeight(0.2);
    stroke(this.fill);
    curve(this.x, this.y, this.x + 10, this.y - 10, this.x + 10, this.y - 20, this.x, this.y - 30);

}

//1 function to draw and move ocean details
function OceanDetailDisplay() {
    for(var i = 0; i < oceanDetailShowing.length; i++) {
        oceanDetailShowing[i].move();
        oceanDetailShowing[i].draw();
    }

}

//remove ocean details if off screen
function removeOceanDetail() {
    var oceansToKeep = [];
    for (var i = 0; i < oceanDetailShowing.length; i++){
        if (oceanDetailShowing[i].x < width) {
            oceansToKeep.push(oceanDetailShowing[i]);
        }
    }
    oceanDetailShowing = oceansToKeep; // remember the showing ocean details
}

//add new ocean details periodically
function addNewOceanDetail() {
    counter +=1;
    if (counter % 100 == 0){
        oceanDetailShowing.push(makeOceanDetail(random(40,height-40), color(255)));
    }

}





////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//change background color based on number of garbage objects on the screen 

//make this change more gradual 
function waterChange() {
    if(garbage1Showing.length <= 20) {
        background(20,100,255);
    }

    if(garbage1Showing.length > 20 & garbage1Showing.length <= 40) {
        background(51, 89, 163);
    }

    if(garbage1Showing.length > 40 & garbage1Showing.length <= 60) {
        background(59, 81,125);
    }

    if(garbage1Showing.length > 60 & garbage1Showing.length <= 100) {
        background(59, 117,125);
    }

    if(garbage1Showing.length > 100 & garbage1Showing.length <= 120) {
        background(59, 125, 90);
    }

    if(garbage1Showing.length > 120 & garbage1Showing.length <= 140) {
        background(56, 74, 43);
    }

    if(garbage1Showing.length > 140 & garbage1Showing.length <= 160) {
        background(43, 54, 36);
    }

    if(garbage1Showing.length >= 160) {
        background(69, 57, 42);
    }

}




////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//functions that check if particles are ahead of net

function checkGarbage1Ahead() {
    for(var i = 0; i < garbage1Showing.length; i++) {
        if(garbage1Showing[i].x > mouseX & garbage1Showing[i].x < mouseX + 10) {
            garbage1Showing[i].x = mouseX + 6;
        }
    }   

}

function checkGarbage2Ahead() {
    for(var i = 0; i < garbage2Showing.length; i++) {
        if(garbage2Showing[i].x > mouseX & garbage2Showing[i].x < mouseX + 10) {
            garbage2Showing[i].x = mouseX + 6;
        }
    }   

}



////////////////////////////////////////////////////////////////////////////////////////////////////////////////






For my final project, I have created an ocean clean-up interaction program. Ocean plastics contribute to the rapid increase in the rate of climate change because it acts as a carbon sink. Thus, cleaning up ocean plastics is imperative to slow down the rate of climate change in addition to protecting ocean life.

This program aims to create an abstraction of ocean clean-up and the adverse effects on the environment if pollution is left unattended for too long. The water starts off as a nice, blue color with fish swimming around. Waves are added as extra details to keep the canvas somewhat recognizable as the ocean. As the program continues, trash enters from the left side of the canvas. The trash is represented by randomized rectangles and circles of varying colors and sizes. These objects float towards the center of the canvas on randomized paths. They begin to collect in the middle of the screen, clumping together into a massive garbage patch. As the number of trash objects enters the scene, the water begins to dirty, from a clear blue to a muddy brown—if left out for too long. The fish die-off as the trash on the canvas reaches a certain number.

However, the user is equipped with a net that can be used to clean the garbage. The net is represented by a long, white rectangle. The net works by identifying if a garbage object is within a certain threshold in front of the net. If the trash is within a certain distance in front of the net, it will be sucked in by the net. The user can then use mouseX to push the garbage off the screen to clean the ocean! As trash leaves the screen from the right side of the canvas, the water becomes blue once more. Remember that the net cannot move too fast. If the user is too hasty with their movements of the net, the trash may fall out of the net. Slowly moving the trash off the canvas is the most effective method of cleaning the ocean!

What inspired me to create this program is a video on YouTube by The Ocean Cleanup. They were able to develop a method of cleaning plastics and other pollutants in oceans around the world. They are specifically focusing on cleaning up the Great Pacific Garbage Patch.

If I had more time, I would like to add more detail to the ocean to make the entire program more visually appealing. I would also have liked to use particles and strings to create the net instead of a rectangle. However, I couldn’t figure out how to create a net that you could drag all the particles at once.

In order to run this program, all you have to do is open the index file into the browser of your choice!

Project 11: Generative Landscape

This is the concept sketch of my generative landscape. I wanted to create a road with hills in the background and cars driving across the road. If I had more time with the project, I would’ve added more randomized details to the hills like stripes or grass texture patterns.

My process was pretty simple. I created objects for the different elements that I would be randomizing. For example, I made an array of objects for the hills, the roads, and the cars. I would repeat the process of creating the different functions for the various elements—with minor adjustments to the movement and randomness of each element.

sketch
//Anthony Pan
//Section C

//objects to create:
    //hills
    //cars
    //road

//hold hills
var hillshowing = [];
//object for hills
var hills;

//hold road1
var road1showing = [];
//object for road1
var road1;

var road2;
var road2showing = [];

//car object
var car;
//array holding car object
var carShowing = [];

//car2 object
var car2;

//array holding car2 objects
var car2Showing = [];

//frame counter
var counter = 0;


function setup() {
    createCanvas(480, 300);

    //create hills
    for(var i = 0; i < 20; i++) {
        hills = makeHills(i*30, 245);
        hillshowing.push(hills);
    }

    //create road1
    for(var j = 0; j<10; j++) {
        road1 = makeRoad1(j*10, 280);
        road1showing.push(road1);

    }

    //create road2
    for(var k = 0; k<10; k++) {
        road2 = makeRoad2(k*10, 250);
        road2showing.push(road2);
    }

    //create cars on road1
    for(var h = 0; h < 5; h++) {
        car = makeCar(0, round(random(270, 290)), random(2,4));
        carShowing.push(car);
    }

    //create cars on road2
    for(var c = 0; c < 5; c++) {
        car2 = makeCar2(width, round(random(240, 255)), random(-4,-2));
        car2Showing.push(car2);
    }

}


function draw() {
    //sky 
    background(135, 221, 255);

    //sun
    drawSun();

    //hills
    updateandDrawhills();
    removeHillsOffScreen();
    addNewHill();


    //roads2 / upper roads
    fill(156, 117, 95);
    rect(0, 245, width, 40);
    updateandDrawRoad2();
    removeRoad2offScreen();
    addNewRoad2();

    //roads lower/ road1
    fill(0);
    rect(0, 270, width, 40);
    updateandDrawRoad1();
    removeRoad1offScreen();
    addNewRoad1();

    //draw cars on road2
    updateandDrawCar2();
    removeCars2OffScreen();
    addCar2();

    //draw cars
    updateandDrawCar();
    removeCarsOffScreen();
    addNewCar();

    

 
}


//draw sun
function drawSun() {
    fill("lightyellow");
    noStroke();
    circle(90,80, 40);

}

////////////////////////////////////////////////////////////////////////////////////////////////////
//MAKE Car2 Functions

//car 2 constructor
function makeCar2(cx, cy, zoom) {
    var car2 = {x: cx, y:cy,
        speed:zoom,
        r: random(255),
        g: random(255),
        b: random(255),
        move: car2Move,
        draw: drawCar2 }
    return car2;
}

//draw car2 object
function drawCar2() {
    fill(this.r, this.g, this.b);
    rect(this.x, this.y, 20, 10);

    fill(0);
    ellipse(3+this.x, 10+this.y, 4, 4);
    ellipse(this.x + 17, this.y +10, 4, 4);

}

//update and draw car2
function updateandDrawCar2() {
    for(var i = 0; i < car2Showing.length; i++) {
        car2Showing[i].move();
        car2Showing[i].draw();
    }
}

//move car2
function car2Move() {
    this.x += this.speed;
}

//remove car2s that are off screen 
function removeCars2OffScreen() {
    var cars2ToKeep = [];
    for (var i = 0; i < car2Showing.length; i++){
        if (car2Showing[i].x > 0) {
            cars2ToKeep.push(car2Showing[i]);
        }
    }
    car2Showing = cars2ToKeep; // remember the showing cars

}

//make new car2 based on probability 
function addCar2() {
    var newcarlikelihood = 0.03;
    if(random(0,1) < newcarlikelihood) {
         car2Showing.push(makeCar2(width, round(random(240, 255)), random(-4,-2)));
    }
}



////////////////////////////////////////////////////////////////////////////////////////////////////
//MAKE Car Functions

//car constructor
function makeCar(cx, cy, zoom) {
    var car = {x: cx, y:cy,
        speed:zoom,
        r: random(255),
        g: random(255),
        b: random(255),
        move: carMove,
        draw: drawCar }
    return car;
}

//draw car object
function drawCar() {
    fill(this.r, this.g, this.b);
    rect(this.x, this.y, 20, 10);

    fill(0);
    ellipse(3+this.x, 10+this.y, 4, 4);
    ellipse(this.x + 17, this.y +10, 4, 4);

}

//update car position and draw car
function updateandDrawCar() {
    for(var i = 0; i < carShowing.length; i++) {
        carShowing[i].move();
        carShowing[i].draw();
    }
}

//move car
function carMove() {
    this.x += this.speed;
}

//remove cars that are off screen
function removeCarsOffScreen() {
    var carsToKeep = [];
    for (var i = 0; i < carShowing.length; i++){
        if (carShowing[i].x < width) {
            carsToKeep.push(carShowing[i]);
        }
    }
    carShowing = carsToKeep; // remember the showing cars

}

//make new car every 100 frames
function addNewCar() {
    counter +=1;
    if (counter % 100== 0){
        carShowing.push(makeCar(0, round(random(270, 290)), random(2,4)));
    }

}




////////////////////////////////////////////////////////////////////////////////////////////////////
//MAKE ROAD2 Functions

//constructor for road2
function makeRoad2(rx, ry) {
    var road2 = {x:rx, y:ry,
        speed: -0.7,
        move: road2Move,
        draw: drawRoad2 }

    return road2;
}

//draw road2 
function drawRoad2() {
    fill(120);
    rect(this.x, this.y, width, 40);

    for(var i = 0; i < 50; i++) {
        var dx = i * 10;
        fill("yellow");
        rect(this.x + dx, this.y + 10, 6, 2);
    }
}

//update road2 position and draw
function updateandDrawRoad2() {
    for(var i = 0; i < road2showing.length; i++) {
        road2showing[i].move();
        road2showing[i].draw();
    }
}

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

//remove roads off the screen
function removeRoad2offScreen() {
    var road2ToKeep = [];
    for (var i = 0; i < road2showing.length; i++){
        if (road2showing[i].x + width > 0) {
            road2ToKeep.push(road2showing[i]);
        }
    }
    road2showing = road2ToKeep; // remember the showing roads
}

function addNewRoad2() {
    counter +=1;
    if (counter % 17 == 0){
        road2showing.push(makeRoad2(width,250));
    }

}



////////////////////////////////////////////////////////////////////////////////////////////////////
//MAKE ROAD1 FUNCTIONS

//constructor for road1
function makeRoad1(rx, ry) {
    var road1 = {x:rx, y:ry,
        speed: -0.5,
        move: road1Move,
        draw: drawRoad1 }

    return road1;
}


//draw road
function drawRoad1() {
    fill(120);
    rect(this.x, this.y, width, 40);

    for(var i = 0; i < 50; i++) {
        var dx = i * 10;
        fill("yellow");
        rect(this.x + dx, this.y + 10, 6, 2);
    }
}

//update road1 position and draw
function updateandDrawRoad1() {
    for(var i = 0; i < road1showing.length; i++) {
        road1showing[i].move();
        road1showing[i].draw();
    }
}

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

//remove roads off the screen
function removeRoad1offScreen() {
    var road1ToKeep = [];
    for (var i = 0; i < road1showing.length; i++){
        if (road1showing[i].x + width > 0) {
            road1ToKeep.push(road1showing[i]);
        }
    }
    road1showing = road1ToKeep; // remember the showing roads
}

function addNewRoad1() {
    counter +=1;
    if (counter % 25 == 0){
        road1showing.push(makeRoad1(width,280));
    }

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//MAKE HILLS FUNCTIONS

//update hill position and draw hill
function updateandDrawhills() {
    for(var i =0; i < hillshowing.length; i++){
        hillshowing[i].move();
        hillshowing[i].draw();
    }

}


//remove hills that have left the screen 
function removeHillsOffScreen(){
    var hillsToKeep = [];
    for (var i = 0; i < hillshowing.length; i++){
        if (hillshowing[i].x +20 > 0) {
            hillsToKeep.push(hillshowing[i]);
        }
    }
    hillshowing = hillsToKeep; // remember the showing hills
}


//make new hill from right side of canvas
function addNewHill() {
    counter +=1;
    if (counter % 25 == 0){
        hillshowing.push(makeHills(width+20,245));
    }
}

//hill constructor
function makeHills(hx, hy) {
    var hills = {x:hx, y:hy, 
        width:random(40, 70), 
        height:random(100, 300), 
        r:0, g:random(115,200), b: random(15, 35),
        speed: -1.0,
        move: hillsMove,
        draw: drawHills }
    return hills;

}

//draw hills
function drawHills() {
    fill(this.r, this.g, this.b);
    ellipse(this.x, this.y, this.width, this.height);
}


//move hill to left
function hillsMove() {
    this.x += this.speed;
}



Looking Outwards – 11: Societal Impacts of Digital Art

This week I took a look at the topic of NFTs and the issues of copyright and privacy that come with this new digital phenomenon. NFTs have been around since 2017 but have recently made a huge surge to the mainstream media. Originally, there wasn’t much of an issue to consider because buyers were aware of there wasn’t much utility or usage from these digital creations. However, now that artists are making upwards of millions from these digital images, copyright infringement and abuse of the NFT system have skyrocketed. According to many, the blockchain is actually the perfect tool for resolving copyright ownership and proof of creation; however, blockchain has never been intended for this purpose. The bottom line of NFTs is a way for artists to create some sort of scarcity and uniqueness that physical products intrinsically have. It’s very interesting to see how the space develops and how the system adapts the ever-present issue of copyright and piracy. As of now, the system is not built to sustain this market and it will not be changing anytime soon.

https://www.plagiarismtoday.com/2021/03/16/nfts-and-copyright/

Project 10: Sonic Story

My project is a simple animation of a bee flying through some daisies and a sunflower to collect nectar. For my process, I created several objects that I animated first. Afterward, I inserted sounds that at different places within the story where the action was happening.

Canvas is 900 pixels wide so you can see the right side on here 🙁

sketch
//Anthony Pan
//Section C

var index = 0;
var duration = 0;
var sunflower;
var daisy;
var daisy2;
var bee;
var cloud;

//sounds
var beeSound;
var windSound;
var popSound;
var yumSound;



//bee positions
var beex = [900, 880, 860, 840, 820, 800, 780, 760, 740, 720, 700, 
680, 660, 640, 620, 600, 580, 560, 540, 540, 540, 540, 540, 540, 540, 540, 500, 450, 400, 200, -100];

//noise for beey heights
var noiseParam = 0;
var noiseStep = 0.05;
var beey = [];

//cloud positions
var cloudX = [];

function preload() {
    beeSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/beeBuzz.wav");
    windSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/wind.wav");
    popSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/pop.wav");
    yumSound = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/yum.wav");

}


function soundSetup() {
    windSound.amp(0.4);
    beeSound.amp(0.8);
    popSound.amp(1.0);
    yumSound.amp(0.8);
}



function setup() {
    createCanvas(900, 400);
    frameRate(1);
    useSound();

    //random y positions of beey
    for(var i=0; i < 30; i++) {
        var n = noise(noiseParam);
        var value = map(n, 0, 1, 0, height);
        beey.push(value);
        noiseParam += noiseStep;
    }

    //positions for cloudX
    for(var j = 0; j < 30; j++) {
        var cloudvalue = 900 - (j * 20);
        cloudX.push(cloudvalue);

    }


    //make objects
    daisy = makeDaisy(width/2, 2* height/3, 100);
    sunflower = makeSunflower(width/4, height/2, 80);
    daisy2 = makeDaisy(2 * width/3, height/3, 100);
    bee = makeBee(beex[index], beey[index]);
    cloud = makeCloud();

    
}

function draw() {
    //draw sky
    background(149, 217, 255);
    cloud.draw(cloudX[index], 100);

    //play windSound at end
    if(frameCount >= 28 & frameCount <= 31) {
        windSound.play();

    } 
    
    sunflower.draw();
    daisy.draw();
    daisy2.draw();

    //daisy petal fall 
    if(index >= 20) {
        fill(255);
        ellipse(600, index * 15, 60, 160);
    }

    //daisy petal pop
    if(frameCount >= 23 & frameCount <= 24) {
        popSound.play();
    }

    //play yum sound when bee is above flower
    if(index >= 20 & index < 21) {
        yumSound.play();
    }

    //sunflower petal pop
    if(frameCount >= 24 & frameCount <= 25) {
        popSound.play();
    }

    //sunflower petal fall
    if(index >= 24) {
        fill("yellow");
        ellipse(width/4, 50+index*15, 20, 180);
        ellipse(1.25 * width/4, 50+index*15, 20, 180);

    }

    bee.draw(beex[index], beey[index]);

    //play bee sound at beginning
    if(frameCount >= 0 & frameCount <= 3) {
        beeSound.play();

    }

    
    index += 1;

    //stop sounds at 30 seconds
    if(index >= 32) {
        popSound.stop();
        windSound.stop();
        beeSound.stop();
        yumSound.stop();
        background(0);
        noLoop();
    }





}

//cloud constructor
function makeCloud(cx, cy) {
    var cloud = {x: cx, y: cy, draw: drawCloud}
    return cloud;

}

//draw cloud
function drawCloud() {
    fill(230);
    ellipse(cloudX[index], 100, 300, 100);
    ellipse(cloudX[index]-90, 110, 100, 80);
    ellipse(cloudX[index]-30, 120, 100, 80);
    ellipse(cloudX[index]+30, 120, 100, 80);
    ellipse(cloudX[index]+90, 110, 100, 80);

    ellipse(cloudX[index]-90, 90, 100, 80);
    ellipse(cloudX[index]-30, 80, 100, 80);
    ellipse(cloudX[index]+30, 80, 100, 80);
    ellipse(cloudX[index]+90, 90, 100, 80);

}

//constructor for daisy
function makeDaisy(fx, fy, fh) {
    var daisy = {x: fx, y: fy, height: fh, draw: drawDaisy}
    return daisy; //return daisy as object

}

//draw daisy
function drawDaisy() {
    fill(10, 200, 20);
    rect(this.x, this.y, 40, height);
    //petals
    for(var i = 0; i < 10; i++) {
        push();
        translate(this.x, this.y);
        noStroke();
        var rotationAngle = radians(36);
        rotate(i * rotationAngle);
        fill(255);
        ellipse(0, -60, 60, 160);
        pop();

    }

    fill("yellow");
    noStroke();
    circle(this.x, this.y, 80);

}

//constructor for sunflower
function makeSunflower(sx, sy, sh) {
    var sunflower = {x: sx, y: sy, height: sh, draw: drawSunflower}
    return sunflower;

}

function drawSunflower() {
    fill(10, 200, 20);
    rect(this.x, this.y, 40, height/2);
    for(var i = 0; i < 40; i++) {
        push();
        translate(this.x, this.y);
        var rotationAngle2 = radians(9);
        rotate(i * rotationAngle2);
        fill("yellow");
        ellipse(0, -80, 20, 180);
        pop();
    }
    fill(33, 12, 11);
    circle(this.x, this.y, 200);
}


//bee constructor
function makeBee(bx, by) {
    var bee = {x: bx, y: by, draw: drawBee}
    return bee;

}

function drawBee() {
    //wings
    stroke(0);
    fill(255);
    ellipse(beex[index]-5, beey[index]-30, 20, 40);
    ellipse(beex[index]+10, beey[index]-20, 20, 40);

    //body
    fill(0);
    ellipse(beex[index], beey[index], 60, 40);

    //stinger
    triangle(beex[index]+25, beey[index]+5, beex[index]+40, beey[index], beex[index]+25, beey[index]-5);

    //stripes
    noStroke();
    fill("yellow");
    rect(beex[index], beey[index]-20,5, 40);
    rect(beex[index]-10, beey[index]-20, 5, 40);
    rect(beex[index]+10, beey[index]-20, 5, 40);


}


Project 09: Portrait

sketch
//Anthony Pan
//Section C



//empty variable to hold/load portrait
var img;

//load portrait
function preload() {
   img = loadImage("https://i.imgur.com/OZnUWbW.jpg");

}

//set up canvas
function setup() {
    createCanvas(420, 280);

}

//create pixelation effect using mouseX position
function draw() {
    background(220);

    //diplay image
    image(img, 0, 0, width, height);

    //constrain mouseX position to canvas and change diamter of circles according to mouseX position
    var mousePosition = map(constrain(mouseX, 0, 280), 0, width, 0, 20);
    //create circles
    for(var row = 0; row < 32; row++) {
        for(var col = 0; col <= 48; col++){
            var x = col * 10;
            var y = row * 10;
            //sample pixel color
            var sampleColor = img.get(x*15, y*15);
            noStroke();
            fill(sampleColor);
            //draw circle
            circle(x + 10, y + 10, mousePosition); 
        }
    }
}

I wanted to create a portrait that would get pixelated as you moved the mouse from left to right. It was cool to see it become stylized, almost like I was applying a filter to the image.

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

This week I decided to look into Caroline Sinders, a machine-learning-design researcher and artist. Her work in recent years has been focused on examining the intersections of technology’s impact in society, interface design, AI, abuse, and politics in digital/conversational spaces. She also is the founder of Convocation Design + Research where they explore and study the intersections of machine learning, user research, and designing for the public good. I wanted to focus on her project “Higher Resolutions” in 2019, a project mainly centered around the state of power and privacy online. They use interactive art installations as well as talks from professionals in the field to educate their audience members about the topic. Some art installations within the space include facial recognition, website tracking, and harmful content recommendation algorithms. Participants can also vote on a feature to ban and view the floor schematic at a closer level. I found her work interesting because I am also working on a data security and privacy research project in my design research class. I found it refreshing to see someone else’s perspective and approach to the problem space.

Higher Resolutions

Looking Outwards: The Creative Practice of an Individual

Today I took a look at Lucianne Walkowicz’s talk during the 2017 Eyeo Festival. She presented her work on astrobiology at the Adler Planetarium in Chicago. Her work explores the ethics of Mars Exploration, magnetic activity, and how stars influence a planet’s suitability as a host for alien life, and specifically how to use advanced computing to discover unusual events in large astronomical data sets. Walkowicz does talks and blogs with large organizations on the topic of Mars colonization and the ethics surrounding the topic. She explores topics like Decolonizing Mars, how police will solve murders on Mars, and the digital dark age! Walkowicz uses methods like interactive and dynamic graphics as well as gestures to keep the audience’s retention. Her work is displayed in an easy and intuitive way to help me stay on track and anticipate what she’s going to say next.

Lucianne Walkowicz

Project 07: Curves

sketch
//Anthony Pan
//Section C

//Cardioid Curve Interaction
//polar coordinate equation r = a*(1-cos(theta))
//parametric equation
    //x = a * cos(t) * (1 - cos(t))
    //y = a * sin(t) * (1 - cos(t))
//mouseX change colors
//mouseY changes how many are drawn



function setup() {
    createCanvas(480, 480);
    background(220, 100, 150);
}

function draw() {
    //var x1 = 0
    //var y1 = 0

    push();
    //drawRect(x1,y1); //draw another shape
    translate(width/2, height/2);
    drawCardioidCurve();
}


function drawCardioidCurve() {
    var x;
    var y;

    var a = 80;
    var h = mouseX; //mouseX interaction
    var h1 = map(mouseY, 0, 480, 0, 256); //mouseY interaction

    fill((h1 * 0.7)%256, 0, h1);
    beginShape();
    for(var i = 0; i < 101; i++) {
        var theta = map(i, 0, 101, 0, TWO_PI);

        x = (h + a) * cos(theta) * (1 - cos(theta));
        y = (h + a) * sin(theta) * (1 - cos(theta));
        vertex(x, y);
    }
    endShape(CLOSE);
}

For this project, I wanted to create a curve that would be drawn multiple times as the user moved mouseX. I chose to create a heart using the cardioid function and chose purple/pink as my color for the heart. I wanted it to feel like you were drawing hearts repeatedly that would change color and dimensions based on the mouseX and Y positions.

For the process, I did something very similar to the technical assignment this week, utilizing an equation to draw the different points on the curve rather than the noise function.

Looking Outwards 07: Computational Data Visualization

This week I took a look at some artists who specialize in computational data visualization. In particular, I took a look at Chris Harrison’s piece, Visualizing the Bible. This piece drew me in particular because the bible has always been something I have been so fascinated with. The combination of technology and a piece of world history felt refreshing and innovative. Harrison was able to visualize 63,000 cross-references within the bible to create a stunning piece that “honored and revealed the complexity of the data at every level”. A couple of other pieces were also made following the conclusion of the bible arc piece. Harrison wanted to capture the story of the bible and more specifically the people and the places within the bible. He used a spatial clustering algorithm to show the different connections between the 2619 biblical names. These pieces create new and refreshing ways to view classic pieces of human history. They give us a different perspective on how things can be interpreted.

Chris Harrison’s Bible Visualization

Looking Outwards 06: Randomness

This week I took a look at Tyler Hobbs, a generative artist who utilizes randomness in his work. His project “Waves” is a generative piece made for one of four interior murals for a single client. This piece focuses on water and its fragmented nature. Each shape is a different color, but they come together as a very cohesive piece. I suppose that he uses a program to create these different lines that curve and bend on different generated paths. I would assume that at certain coordinates within the canvas, he changes the shades of blue and uses some random function to create spots/highlights of pink. The curves seem to resemble that of a sin or cos wave. The quality of water is very apparent in this piece, and I think that the artist was able to create a very clear abstract representation of water.

Tyler Hobbs Waves