Week 14: Final Project: Trash Removal

My Final Project Modified for WordPress

//Chuong Truong;
//cbtruong;
//FINAL PROJECT;
//Modified for WordPress;

//array that holds all existing trash objects;
var trashPieces = [];

//this array holds all of the indices of trash objects that have been clicked on - removed;
//then it uses the splice method of arrays to remove that object 
//and erase it from the trashPieces array;
//and the screen as well;
//this effectively removes it;
var trashPiecesRemoval = [];

//gameOver condition that is used for the game overall;
//when true it ends the game and transfers the screen to facts;
var gameOver = false;

//number of current trash objects on screen;
var trashNumCurrent = 0;

//number of trash objects removed;
var trashGone = 0;

//variables that holds the time;
//numSecondsPast is how many seconds have passed;
var numSecondsPast = 0;
//while numSecondsAllowed is how many seconds are left for the player;
//the initial number of seconds allowed for the player is 120 or 2 minutes;
//the reason for two seperate variables is more flexibility for time as a feature;
var numSecondsAllowed = 120;
//the frameCount variable needed for the timer Function that counts time;
var frameCount = 0;

//the variable that determines how many trash objects can be drawn at a time;
var spawnNum = 20;

function setup() {
    //modified canvas size;
    createCanvas(600, 600);
    //creates sea background;
    background(91, 161, 176);
    
    //creates the first initial trash objects;
    for (var l = 0; l < 20; l++){
        makeTrash(random(80, 520), random(80, 520), floor(random(5)), 
            floor(random(0,8)), floor(random(0,8)), random(360), true);
    }


    //sets the frameRate to 30;
    frameRate(30);
    
}

function draw() {
    //calls the display function;
    displays();
    
    //print method used for debugging, it shows how many seconds have passed;
    print(numSecondsPast);
    //increases the frameCount every iteration;
    frameCount++;

    //calls the countTime function that counts the time;
    countTime(frameCount);
    
    //This is the main checker for whether the game is over or not;
    //Namely, it checks for if the time left is 0 or not by way of comparing;
    //the number of seconds allowed - numSecondsAllowed;
    //and the number of seconds that have passed - numSecondsPast;
    //if there is still time, then gameOver is false;
    //And the game runs as usual;
    if (numSecondsAllowed > numSecondsPast){
        gameOver = false;
        //draws all of the existing trash objects;
        for (var m = 0; m < trashNumCurrent; m++){
            var pT = trashPieces[m];
            pT.drawFunction();
        }
    
        //removes any trash objects deemed nonexistant;
        //also uses background to reset the drawing board and removed previous 'drawings' of the object;
        for (var r = 0; r < trashPiecesRemoval.length; r++){
            background(91, 161, 176);
            trashGone++;
            trashPieces.splice(trashPiecesRemoval[r], 1);
        }

        //completely wipes out the trashPiecesRemoval array to allow it to be filled with indices again;
        while (trashPiecesRemoval.length > 0){
           trashPiecesRemoval.shift();
        }
        
        //calls the spawnMoreTrash function;
        spawnMoreTrash();
        }
        //if the time left is 0, then it calls the factScreen function that ends the game;
        else {
            factScreen(facts(floor(random(0, 9))));
    }

    //prints out the current trashPieces array length for debugging;
    trashNumCurrent = trashPieces.length;
    print(trashPieces.length);
    
    //this switch and case checks for the total amount of trash removed;
    //if it passes certain milestones, the spawnNum of trash increases with a one time added bonous of more time;
    switch (trashGone){
        case 40: spawnNum = 25; numSecondsAllowed + 60; break;
        case 80: spawnNum = 30; numSecondsAllowed + 50; break;
        case 120: spawnNum = 35; numSecondsAllowed + 40; break;
        case 1600: spawnNum = 40; numSecondsAllowed + 30; break;
    }

}

//draws the scoreboards, title, time left, and directions;
function displays (){
    stroke(1);
    strokeWeight(0.5);

    //code for top left display of trash removed and trash left;
    fill(255);
    rect(10, 10, 150, 45);

    fill(0);
    var trashNumDisplay = 'Trash Left: ' + trashNumCurrent;
    text(trashNumDisplay, 15, 45);
    var scoreDisplay = 'Trash Removed: ' + trashGone;
    text(scoreDisplay, 15, 25);

    //code for upper middle display of the title of the game;
    fill(240, 133, 11);
    rect(276.5, 15, 100, 35);
    
    fill(0);
    text("Trash-Pick-Up", 285.5, 35);

    //code for upper right display of time left for trash removal;
    fill(255);
    rect(510, 10, 80, 35);

    fill(0);
    var timeLeftDisplay = 'Time: ' + (numSecondsAllowed - numSecondsPast);
    text(timeLeftDisplay, 520, 32.5);

    //code that gives the game directions;
    fill(200, 186, 234);
    rect(60, 555, 480, 40);

    fill(0);
    var directions = 'Click on the red dots to remove the trash before time runs out!  Watch out for misclicks!';  
    var directions2 = 'If you do not see any trash but the trash left is not 0, hit any key to respawn them!';
    text(directions, 65, 570);
    text(directions2, 65, 585);
}


//All of the code below was originally in seperate files to ensure readability and ease of access;
//Due to WordPress, I had to combine all 4 files into 1;

//file that creates the trash objects;

//constructor for the trash object;
//it takes 6 numbers and a boolean value;
//xPost and yPos is the object's main position as it is the first vertex in a given object;
//each object is a randomly constructed shape made with the beginShape() and endShape() function;
//it then takes cPre, a random number that determines its color;
//After that comes the "random points" - which are random numbers added or subtracted to the starting vertex;
//These numbers are stored in an array;
//There are 2 sets of 8 different arrays, one for x and one for y;
//ang is the angling of each object;
//existBol is the boolean value that determines if the object still exists or not;
//it has a drawFunction, drawTrash which handles the drawing;
//it also has a changeFunction. mousePressed, which changes its state as an instance still on the screen;
//and as an existant object within any of the arrays;
function makeTrash (xPos, yPos, cPre, pointsPresetX, pointsPresetY, ang, existBol){
    var t = {x: xPos, y: yPos, col: cPre, 
        pXA: pointsPresetX, pYA: pointsPresetY,
        a: ang, e: existBol, 
        drawFunction: drawTrash, changeFunction: mousePressed};
    trashPieces.push(t);
}

//the drawTrash function is the drawFunction of each trash object;
function drawTrash (){
    //this initial condition decides if it is still on screen (being drawn);
    if (this.e == true){
        stroke(0);

        //switch and case for the color of a given trash object;
        switch (this.col) {
            case 0: fill(228, 200, 98); break;
            case 1: fill(169, 142, 144); break;
            case 2: fill(156, 161, 117); break;
            case 3: fill(135, 206, 250); break;
            case 4: fill(255, 255, 255); break;
        }
  
        //this creates each object, by using beginShape() and endShape(), with numbers that are added to the original vertex;
        //a 7 pointed shape is made;
        //Due to the presence of 8 arrays and a seperate number that determines which array is for x and for y, there are 64 possible combinations;
        //The numbers for each array set is entered and it returns an array to be used for each specific trash object;

        //for the x values added to the original vertex;
        switch(this.pXA){
            case 0: var x = [20, -30, 10, 50, -60, 70]; break;
            case 1: var x = [30, -40, 40, 20, 30, 50]; break;
            case 2: var x = [50, -60, 25, 65, -35, 40]; break;
            case 3: var x = [-30, 70, -30, 40, -25, 65]; break;
            case 4: var x = [20, 30, 10, -50, 60, 30]; break;
            case 5: var x = [60, -20, 35, 20, 45, -20]; break;
            case 6: var x = [-20, 30, 10, -50, 60, 30]; break;
            case 7: var x = [60, -20, 35, 20, 45, -20]; break;
        }
        //for the y values added to the original vertex;
        switch(this.pYA){
           case 0: var y = [40, 30, 10, -25, 30, 20]; break;
           case 1: var y = [35, 25, 10, 50, -70, -40]; break;
           case 2: var y = [20, -0, 10, -10, 40, 20]; break;
           case 3: var y = [-30, 50, 20, 25, 25, -30]; break;
           case 4: var y = [20, 35, -25, -35, 20, 10]; break;
           case 5: var y = [30, -45, 20, -45, 35, 40]; break;
           case 6: var y = [40, 35, 30, -40, 60, -50]; break;
           case 7: var y = [-50, -10, 20, 35, 40, 30]; break;
        }
    
        //with the color and vertex arrays determined, the actual shape is made;
        //it is put within a push and pop for extra variation by way of rotation;
        //the actual tricks for rotation are then applied;
        push();
        translate(this.x, this.y);
        rotate(radians(this.a));
        beginShape();
        vertex(0, 0);
        for (var i = 0; i < 8; i++){
            vertex(0 + x[i], 0+ y[i]);  
        }
        endShape(CLOSE);
        //an additional red circle is added at the original vertex to make it easier to click on;
        fill(255, 0, 0);
        circle(0, 0, 5);
        pop();
    }
}

//this function is the function that changes each object;
//it decides whether each object still exists or not after each click;
function mousePressed() {
    //I made the mouseX and mouseY coordinates into mX and mY respectively for easier typing;
    var mX = mouseX;
    var mY = mouseY;
    
    //the flag variable that becomes true if the player clicks on anything but a trash object's red dot;
    //it is false at the beginning to ensure that a new click is not automatically a misclick;
    var secondOff = false;

    //as the player clicks the mouse, a for loop checks the entire trashPieces array - which;
    //holds all of the existing trashPieces;
    //it checks whether mX and mY are close to the original x and y of any given trash;
    //if the distance is less than 30, then it sets the specific trash object to false;
    //it then pushes the object's index into the trashPiecesRemoval array;
    //this array holds all of the indices of trash objects that have been clicked on - removed;
    //then it uses the splice method of arrays to remove that object and erase it from the trashPieces array;
    //and the screen as well;
    //this effectively removes it;
    for (var i = 0; i < trashPieces.length; i++){
        var rI = i;
        pT = trashPieces[i];
        if (dist(mX, mY, pT.x, pT.y) < 10){
            pT.e = false;
            trashPiecesRemoval.push(rI);
        }
        //if the player clicks and does not remove a piece of trash, it sets the flag variable called secondOff;
        //this in turn makes the following if statement outside of the for loop execute, taking a second off the clock;
        else {
            secondOff = true;
        }
    }
    
    //this function takes a second off of the clock for misclicks;
    if (secondOff == true){
        numSecondsPast++;
    }
}

//this function spawns more trash everytime all of the trash has been removed and the trashPieces array is empty;
function spawnMoreTrash (){
    //it checks to see if the game is over;
    //if true it executes the rest of the code;
    if (gameOver != true){
        //it checks if trashPieces is empty;
        //if true, it creates more trash according to the spawnNum variable;
        if (trashPieces.length == 0){
            for (var l = 0; l < spawnNum; l++){
                makeTrash(random(80, 620), random(80, 520), floor(random(5)), 
                floor(random(0,8)), floor(random(0,8)), random(360), true);
            }
            //this adds more time once a new set of trash has been spawned;
            numSecondsAllowed = numSecondsAllowed + (spawnNum - 10);
            //this gives a change of randomly increasing the spawnNum as well;
            if (floor(random(51)) > 25){
                spawnNum += 2;
            }
        }
    }
}

//a vital function, the keyPress function resets the board;
//Once any key is pressed, the board is redrawn with the same amount of trash pieces left;
//as well as the same amount of time left;
//this is key as there are times where a glitch occurs where all but one or two trash pieces;
//are drawn - meaning they cannot progress as the time winds down;
//Due to not being drawn, the player unfairly loses due to the glitch;
//this keyPress function prevents this by redrawing the board with the same amount of time and trash;
function keyPressed(){
    //this variable is the total amount of trash that has to be redrawn, it is made 0;
    //to ensure that everytime it is called, the number of trash that needs to be redrawn is allowed to change;
    var trashLeftReset = 0;

    //This for loop does the same thing as the loop that removes clicked-on trash;
    //instead of specifically clicked on trash, it removes all of them;
    //It counts how many were removed;
    //Due to this being intended for trash objects that do not appear;
    //It initiates the first step of redrawing them on the board;
    //Therefore, if used for any other purpose, such as cheating, it does nothing but reset the board;
    for (var i = 0; i < trashPieces.length; i++){
        pT = trashPieces[i];
        trashPiecesRemoval.push(pT);
        //this variable offsets the fact that everytime trash is removed, the trash removal counter goes up;
        //this is to prevent cheating as well as the trashGone variable is key for other conditions;
        trashGone--;
        
        //for each piece of trash removed, the counter for trash that needs to be redrawn goes up as well;
        //this is for the following for loop that draws any undrawn trash objects;
        trashLeftReset++;
    }

    //this for loop does the second step of redrawing the board, namely drawing any unremoved and undrawn trash pieces;
    //albiet as a different object altogether;
    for (var l = 0; l < trashLeftReset; l++){
        makeTrash(random(80, 620), random(80, 520), floor(random(5)), 
        floor(random(0,8)), floor(random(0,8)), random(360), true);
    }
}

//separate code file that deals with writing out the facts after the player loses;

//the facts function itself takes a random number and then uses a case and switch for;
//the corresponding fact related to pollution in the ocean;
//I chose to use case and switch due to its simplicity;
function facts (inputNum){
    var factString = "";
    switch(inputNum) {
        case 0: factString = "We dump 8 million tons or 17.6 billion pounds of \nplastic into oceans every year."; return factString; break;
        case 1: factString = "Plastics are responsible for over 80% of the negative \neffects on sea animals."; return factString; break;
        case 2: factString = "By 2050, estimations say that there will be more \nplastic than fish in the ocean when it comes to \nweight alone."; return factString; break;
        case 3: factString = "Over 100,000 marine animals die from eating plastic \nor being trapped by it every year."; return factString; break;
        case 4: factString = "Plastic takes approximately 400 years to degrade\n - when it does in the ocean, more harmful chemicals\n are released."; return factString; break;
        case 5: factString = "Around 70% of ocean garbage are uncleanable \nbecause they sink into the seabed."; return factString; break;
        case 6: factString = "90% of seabirds have plastics in their stomachs."; return factString; break;
        case 7: factString = "300 million tons of plastic is created \nevery year - about 50% is single use."; return factString; break;
        case 8: factString = "Microplastics have been found in Arctic sea ice."; return factString; break;
    }     
}

//related to facts, it takes the fact string and uses it as text;
//this function is the function that causes the game to end;
//it draws the relevant screen and ends the game with a noLoop() call;
function factScreen (factInput){
    background(53, 56, 57);
    fill(255);
    strokeWeight(2);
    stroke(255, 0, 0);
    rect(200, 270, 300, 60);
    stroke(0);
    strokeWeight(0.5);
    fill(0);
    text(factInput, 210, 290);
    stroke(255);
    noLoop();
}


//facts cited from:
//https://www.conservation.org/stories/ocean-pollution-11-facts-you-need-to-know
//https://www.rubicon.com/blog/ocean-pollution-facts/
//https://www.conserve-energy-future.com/various-ocean-pollution-facts.php
//https://www.condorferries.co.uk/marine-ocean-pollution-statistics-facts
//https://www.ehn.org/ocean-plastic-pollution-2654378379/what-can-be-done


//code for the timer that is utilized in the game as a condition for losing;
//the function takes the input of the frameNumber - which is the count of;
//every iteration of the draw loop (the main loop of the game);
//everytime the frameNumber hits 60, numSecondsPast is increased by 1;
//the function also takes the a boolean variable called resetBoolean;
//if the boolean entered is true, it resets the global variable numSecondsPast to 0;
//this is to ensure that everytime a new timer is set, the number of seconds passed 
//is also reset;

function countTime (frameNumber){
    if ((frameNumber % 60) == 0){
        numSecondsPast++;
    }
}


//I got the inspiration for the timer from a program called "countdown timer"
//by user marynotari on the p5js.org site;
//the link for the code: https://editor.p5js.org/marynotari/sketches/S1T2ZTMp-

[Note, I have modified my Project to make it functional for WordPress, the original Canvas size was meant to be 700 by 600, but had to be changed to 600 to 600, therefore, many values regarding specific spots on the canvas has been changed.]

For inspiration, I ran through what I knew about climate change.
Rather than focusing on ways to combat it, I really wanted to tell the effects of it. So, I decided to make an interactive game that showed the depressing facts about ocean pollution. Most of the facts deal with plastics, which are the main objects of the game, the trash objects are supposed to represent.

The game is a simple score as high as possible before time runs out.
The player is given initially 20 trash pieces on a screen and must click on them (the red dots that is their origin as they are shapes made with the beginShape() function). By clicking on them, they are removed and once the number of trash that needs to be removed hits 0, a new set is spawned (if any are undrawn, clicking a key will spawn them in by redrawing the board). Furthermore, there is a timer, so if time runs out (and it always will) the player loses. If any of their clicks are not on the red origin of a trash object, then they have a second deducted from their time. Once losing, they face a black screen with a single text block that tells a fact about ocean pollution.

The fact that the trash is hard to click on is meant to show how hard it is to clean up/fight ocean pollution once it has made its way fully into the ocean. Furthermore, the time limit and countdown are meant to show that we really need to fix ocean pollution now. Finally, the spawning of trash (with the number of a set increasing certain times) is meant to show how the problem is becoming worse and worse. Overall, the program is meant to show that ocean pollution is something that we must fix now because the problem is truly getting worse and harder to solve.

If I had more time, I would have added extra features like making it so that trash can “dissappear” meaning that they are no longer removable/clean-upable, just like in real life as trash in the ocean sink to the seafloor and are impossible to remove. I would’ve also found a way for “true” randomization of the trash, as right now the trash is 7-point polygons that have a set number of versions (64). True randomization is a variable number of points in each polygon and where those points are relation to the original vertex.

I hope you enjoyed my project!

I got the ocean pollution facts from:
https://www.conservation.org/stories/ocean-pollution-11-facts-you-need-to-know
https://www.rubicon.com/blog/ocean-pollution-facts/
https://www.conserve-energy-future.com/various-ocean-pollution-facts.php
https://www.condorferries.co.uk/marine-ocean-pollution-statistics-facts
https://www.ehn.org/ocean-plastic-pollution-2654378379/what-can-be-done

LO-11: Societal Impacts of Digital Art

Cryptopunks – a NFT series made by LarvaLabs

For this Week’s LO, I chose to read into NFTs and the issues that are connected to them. I read the articles from Time and PlagiarismToday. As for the topic, NFTs are also called Non-Fungible Tokens. They are blockchained based digital files. This means that they are not easily messed with (as blockchain makes them public ledgers on the net). This makes ownership very concrete and clear. Furthermore, because they are non-fungible, the price of said tokens/files vary and are decided by producer and consumer.

This has led to a market boom where NFTs (whether they are art, videos, music, etc.) are being sold for big bucks.

However, while it is intended for a way for online copyright for all, problems have arisen. These include bots taking all and any online files and making them NFTs to sell – very bad. Another problem is that NFTs have a considerable starting gap to overcome, thereby keeping many from participating, such as the Times article said, artists of color. A final problem is that the whole market is not that beneficial to the environment, as it requires massive amounts of energy to continue – energy that comes from fossil fuels.


Overall, NFTs are causing big issues, but issues that can be solved relatively fast as it is a growing market that everyone wants to get a slice of.


Articles I read from Time and PlagiarismToday.

Project-10: Sonic Story

My Project

//Chuong Truong;
//cbtruong;
//cbtruong@andrew.cmu.edu;
//Section B;

//The Overall Story of this program is that of fall;
//Leaves are falling off of trees, the sun is getting whiter;
//The air is getting frostier;
//And the birds are seen more actively flying;
//I included no custom sound and instead wanted to portray a scene;
//That was described with a song;


//initial empty array that will hold leaf objects;
var leaves = [];
//variables for the sun's green and blue values which change;
var sunG = 238;
var sunB = 82;
//initial empty array for birds;
var birds = [];

//function of the leaf object that allows it to fall;
function leafFall (){
    //stops each leaf from falling off the canvas;
    //if it has not reached that point, it will continue to fall until it does;
    if (this.f == true){
        if (this.y > height-17){
            this.y = height-5;
        }
        else {
            this.y += random(30, 60);
        }
    }
    //if met, this condition causes the leaf to fall;
    //this randomization occurs to allow for the tree and leaves to be more lifelike;
    //as not all leaves fall off immediately;
    else if (floor(random(200)) == 25){
            this.y += random(30);
            this.x += random(-15, 15);
            this.f = true;

        }
    return this.y;
}

//function that draws the leaves;
function drawLeaf(){
    //this switch and case allows for color variance for the leaves;
    //the colors are those of fall;
    switch(this.col){
      case 0: fill(237, 164, 23); break;
      case 1: fill(167, 159, 15); break;
      case 2: fill(233, 134, 4); break;
      case 3: fill(223, 57, 8); break;
      case 4: fill(201, 30, 10); break;
    }
    rectMode(CENTER);
    push();
    translate(this.x, this.y);
    rotate(radians(45));
    rect(0, 0, 15, 15);
    pop();
}

//function that makes leaves;
function leaf(lx, ly, cPreset){
    //the leaf object constructor;
    l = {x: lx, y: ly, orgY: ly, col: cPreset, f: false, 
        drawFunction: drawLeaf, fallFunction: leafFall};
    return l;
}

function makeLeavesOnTrees (x, y){
    //for loops create the leaves on the trees themselves;
    //the leaves' x and y are dependent on the tree's x and y;
    //the first row is 17 and then decreases by 1 as the row gets closer to the tree's x;
    //as the row gets closer, the leaves' initial x and y increase;

    //this variable allows the leaves to center as each row of them becomes less;
    //it is initalized again to allow for the top row to be centered correctly;
    //like it was before the nested for loops below change it;
    var centeringX = 80;

    //the starting number of leaves for each row
    var leavesRowNum = 17;

    //these nested for loops creates the leaves and gives them their inital x and y;
    //the inner loop creates the leaves for each row, giving them the x, y, and colorPreset;
    //the outer loop controls the leaves' y, as it decreases, a new row will not only be drawn;
    //but that row's total number of leaves decreases, and the centering of them is centered;
    //the loops repeat until only 5 leaves are left and they are closest to the tree's x and y;
    for (var j = 120; j > -10; j-= 10){
        for (var i = 0; i < leavesRowNum; i++){
        var l = leaf(x-centeringX + i*10, y-j, floor(random(5)));
        leaves.push(l);
    }
    //the leaves row number decreases to make each row have less leaves;
    leavesRowNum--;
    //the centering is decreased to make sure the row, as it becomes less in number;
    //is centered correctly to the tree's x;
    centeringX -= 5;
    }
}

//this function creates bird objects;
function bird (bx, by){
    //bird object constructor;
    b = {x: bx, y: by, orgY: by, flyFunction: birdFly, drawFunction: drawBird};
    return b;
}

//function that allows the bird to fly;
function birdFly (){
    this.x -= 10;
    if (this.x < 0){
        this.x = width - 20;
    }
    if (this.y > this.orgY + 20 ){
        this.y -= 5;
    }
    else {
        this.y += 5;
    }
}

//this draws the bird;
function drawBird(){
    fill(36, 143, 190);
    circle(this.x, this.y, 20);
    fill(30);
    circle(this.x, this.y, 5);
    fill(131, 67, 51);
    triangle(this.x-15, this.y, this.x - 10, this.y - 2, this.x - 10, this.y+2);
    stroke(0);
    line(this.x - 15, this.y, this.x - 10, this.y);
    fill(16, 123, 170);
    push();
    rectMode(CORNER);
    translate(this.x, this.y);
    rotate(270);
    rect(0+5, 0 - 12, 15, 10);
    rect(0+5, 0 + 4, 15, 10);
    pop();
}


function setup() {
    createCanvas(700, 500);
    frameRate(10);
    useSound();
    frameRate(3);

    //calls the makeLeavesOnTree function to create the leaves pattern;
    //on each tree dependent on the trees' location;
    makeLeavesOnTrees(125, 390);
    makeLeavesOnTrees(350, 390);
    makeLeavesOnTrees(575, 390);

    //calls the bird function and creates the bird objects;
    for (var i = 0; i < 7; i++){
         var bD = bird(random(100, 600), random(70, 120));
         birds.push(bD);
    }
}
//I kept the same sound setup from the assignment because I liked the sounds;
function soundSetup() { 
    osc = new p5.Oscillator();
    osc.amp(0.25);
    osc.setType('sine');
    osc.start();
}


function draw() {
    //this creates the background of a blue sky and  green grass;
    background(154, 211, 222);
    noStroke();
    rectMode(CORNER);
    fill(24, 136, 39);
    rect(0, 475, 700, 5);
    fill(14, 146, 49);
    rect(0, 480, 700, 20);

    //calls the drawTree function to draw trees;
    drawTree(125, 390);
    drawTree(350, 390);
    drawTree(575, 390);
    
    //this for loop updates and draws each leaf in the leaves array;
    for (var i = 0; i < leaves.length; i++){
        var l = leaves[i];
        l.fallFunction();
        l.drawFunction();
    }
    
    //calls the clouds function to make clouds;
    drawClouds(125, 80);
    drawClouds(325, 130);
    drawClouds(525, 105);

    //draws the sun;
    //this if statement allows for the sun to slowly change colors;
    if (!(sunG == 250 & sunB == 193)){
        sunG += 1.2/5;
        sunB += 11.1/5;
    }
    noStroke();
    fill(255, sunG, sunB);
    circle(600, 75, 100);
    print(leaves.length);

    //draws the birds;
    for (var o = 0; o < birds.length; o++){
        var b = birds[o];
        b.flyFunction();
        b.drawFunction();
    }

    //I turned the code from the assignment into a function;
    musicPlayer(pitches, durations);
}

//function that draws the trees without the leaves;
function drawTree (x, y){
    fill(191, 75, 25);
    rectMode(CENTER);
    rect(x, y, 20, 205);
    push();
    translate(x - 40, y - 40);
    rotate(radians(-30));
    rect(0, 0, 10, 150);
    pop();
    push();
    translate(x + 40, y - 40);
    rotate(radians(30));
    rect(0, 0, 10, 150);
    pop();
    push();
    translate(x - 30, y - 70);
    rotate(radians(-30));
    rect(0, 0, 8, 100);
    pop();
    push();
    translate(x + 30, y - 70);
    rotate(radians(30));
    rect(0, 0, 8, 100);
    pop();
    push();
    translate(x - 20, y - 90);
    rotate(radians(-30));
    rect(0, 0, 5, 80);
    pop();
    push();
    translate(x + 20, y - 90);
    rotate(radians(30));
    rect(0, 0, 5, 80);
    pop();
    push();
    translate(x - 5, y - 100);
    rotate(radians(-30));
    rect(0, 0, 3, 60);
    pop();
    push();
    translate(x + 5, y - 100);
    rotate(radians(30));
    rect(0, 0, 3, 60);
    pop();
    rect(x, y - 105, 2, 40);
}

//this function creates the clouds and draws them;
function drawClouds (x, y){
    fill(243, 242, 231);
    ellipse(x, y, 80, 50);
    ellipse(x + 20, y + 10, 80, 40);
    ellipse(x - 40, y + 10, 80, 30);
    ellipse(x - 10, y + 20, 70, 50);
}

//I used the same code from the assignments to make the music;

//arrays for the pitches and durations;
//also count variables for the index and frameCount;
//finally, the boolean rest is added to account for rests in the music;

//I changed the pitches and went with a simple 1 beat per note;
var pitches = [ 64, 64, 62, 64, 64, 62, 0, 62, 64, 66, 65, 67, 65, 0,
  60, 60, 62, 66, 65, 64, 62, 68, 68, 65, 64, 62, 62 ];
var durations = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
var indexTracker = 0;
var frameCount = 0;
var rest = false;

//I turned the code that creates the music with different notes and beat durations into a function;
//the function takes a note array and a corresponding note duration array;
function musicPlayer (noteArray, noteDurationArray){

    //code for the piano to play;
    //this sets the frequencies of the oscillator to the MIDI pitches;
    osc.freq(midiToFreq(noteArray[indexTracker]));
    
    //checks for when the note's duration is over and acts accordingly;
    if (frameCount > noteDurationArray[indexTracker]){
        //this checks for whether the tune has been completely played;
        //if it has been, then the program and oscillator ends;
        if (indexTracker + 1 == noteArray.length) {
            //print(frameCount);
            //print(indexTracker);
            osc.stop();
            noLoop();
        }
        //if it has not been completely played, then the next note will play;
        //with the frameCount reset to 0;
        else {
        print(frameCount);
        indexTracker++;
        //after the indexTracker is increased;
        //it checks to see if the new note is a rest;
        //if it is, then it deals according;
        //it also turns on the oscillator after a rest;
        if (noteArray[indexTracker] != 0){
            if (rest == true) {
            osc.start();
            rest = false;
                }
            }
        else if (noteArray[indexTracker] == 0){
            rest = true;
            osc.stop();
            }
        }
        frameCount = 0;
    }
    else {
        frameCount++;
    }
    print(noteArray[indexTracker]);
}

Instead of making 4 sounds, I used the same code from the assignments to make a song that I felt fit what I wanted to show, a scene of Fall. That scene has birds flying, leaves falling, and a sun that becomes whiter and whiter to fit the upcoming Winter.

Project-09: Computational Portrait (Custom Pixel)

My Project

//Chuong Truong;
//Section B;

//global variable that holds a picture of my face;
var myFace;

//the preload function loads in my face from imgur;
function preload(){
    myFace = loadImage("https://i.imgur.com/Dd41LFT.jpg");
}

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

function draw() {
    //makes the background from pixels of the upper left part of my picture;
    for (var i = 0; i < 240; i+= 10){
        for (var j = 0; j < 240; j+= 10){
            var sectionPiece = myFace.get(i, j, 20, 20);
            image(sectionPiece, i*2, j*2, 20, 20);
        }
    }

    //lines that connect to make a grid;
    noFill();
    strokeWeight(2);
    ellipse(240, 240, 360, 360);
    stroke(random(256), random(256), random(256));
    line(0, 240, 480, 240);
    line(240, 0, 240, 480);
    for (var m = 60; m < 400; m += 20){
        stroke(random(256), random(256), random(256));
        line(m, 120, m, 360);
    }
    for (var o = 60; o < 480; o += 30){
        stroke(random(256), random(256), random(256));
        line(60, o, 420, o);
    }
    //random outlines of rectangles and circles;
    for (var h = 0; h < 100; h ++){
        stroke(random(256), random(256), random(256));
        rect(random(20, 460), random(20, 460), 20, 20);
        ellipse(random(20, 460), random(20, 460), random(5, 25), random(5, 25));
    }
    //creates the left to right diaganol sections of my picture;
    for (var l = 0; l < 1680; l += 240) {
        push();
            scale(0.25);
            var sectionPiece2 = myFace.get(l, l, 240, 240);
            image(sectionPiece2, l, l, 240, 240);
        pop();
    }
    //creates the right to left diaganol sections of my picture;
    for (var n = 1680; n > 0; n -= 240){
        push();
            scale(0.25);
            var sectionPiece3 = myFace.get(0 + n, 1680 - n, 240, 240);
            image(sectionPiece3, 0 + n, 1680 - n, 240, 240);
        pop();
    }
    noLoop();
}

For this project, I went with something simple (and hopefully acceptable). I am not that creative.

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

Picture of Anne Spalter from her website

For this Week’s LO, I will talk about Anne Morgan Spalter, a mixed-media artist that often works with AI, and her installation “Iteration.”


Spalter is known for founding the digital fine art courses at Brown University, as well as those at the Rhode Island School of Design. She originally studied math at Brown but then got her Master of Fine Art at Rhode Island School of Design. Currently, she is working on NFTs.

This image has an empty alt attribute; its file name is someOfSpalterWork.jpg
Anne’s work, “Iteration”

“Iteration” was created using two image sets, one of Spalter’s own original work and one of random airplane images. She used an algorithm to transform pictures from the first set to that of the second set piece by piece. That is to say that pictures of the first became and more and more like the second each time. She then chose specific “iterations” and painted them with oil.

A closer up view of one of the pieces in the installation.

I admire that it blended both a human and a digital touch to the final product. I also like how it looks overall; each artwork made from the process is interesting. Overall, this piece is now what I think of when I think of algorithmic computer art.


Here is the link to her website, bio, and this specific work.

LO-08: The Creative Practice of an Individual

Christina Phazero Curlee’s Presentation at the 2019 Eyeo Festival

For this Week’s LO, I am talking about Game Designer and Artist, Christina “Phazero” Curlee. She initially was a Fine Artist – doing installation and painting work before getting into Video Games and Video Game Design.
The reasons for her getting into Video Games involved the openness of expression, ability to connect with others, and the lack of need for funding (like that of art installations). She describes herself as a Video Artist as well.

A screenshot from Artifacts II

As for her work, she incorporates psychology, social justice, and self-exploration. This can be seen with her game Artifacts II that deals with the mind, trauma, and memories. I really admire how she incorporates very serious themes and topics into her work. Things that are considered to be very private and personal. But she does it to help others – which is very admirable. I also love her style which is very nonconformist when compared to Video Games in the mainstream.


Finally, I admire how everything she does is self-taught. Something like that is inspirational to me because I want to self-teach myself a lot of things – like coding and video game design. As for presentation, she is open about herself and what she created. She also focuses on how others interact with her work.
I can definitely learn more regarding both from her.

Here are the links to the EYEO Lecture, her website, her game Artifacts 2, and her about me. [Note that her website is not https protected, so be cautious of that]

Project-7: Composition with Curves

My Project

//cbtruong;
//Section B;

//sets up the variables for stroke color;
//col is the stroke color for smooth conical spiral;
//col2 is the stroke color for the rough conical spiral;
var col = 0;
var col2 = 0;
//sets up the variable for angl to allow for rotation;
var angl = 0;
//sets up the variable for the shifting fill color value;
//for the rough conical spiral;
var shiftingVal = 100;
//sets up the variable that allows for reversing the change;
//of shiftingVal;
var shiftingValChange = 1;


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

function draw() {
    background(220);
    stroke(0);
    //diagonal lines that hit the center of the spirals;
    line(0, 0, 120, 120);
    line(0, 480, 120, 360);
    line(480, 0, 360, 120);
    line(480, 480, 360, 360);
    //lines that outline the perimeter of the canvas;
    line(0, 0, 480, 0);
    line(0, 0, 0, 480);
    line(480, 0, 480, 480);
    line(0, 480, 480, 480);
    //lines of the innerbox whose vertices are the spiral centers;
    line(120, 120, 120, 360);
    line(120, 360, 360, 360);
    line(360, 360, 360, 120);
    line(360, 120, 120, 120);

    //draws the middle, rough concial spiral;
    strokeWeight(2);
    fill(shiftingVal);
    stroke(col2);
    push();
    translate(240, 240);
    conicalSpiralTopViewRough();
    pop();
    
    //draws the 4 smooth rotating conical spirals;
    noFill();
    stroke(col);
    for (var i = 120; i <= 360; i += 240){
        for (var j = 120; j <= 360; j += 240){
            push();
            translate(j, i);
            rotate(radians(angl));
            scale(0.5);
            conicalSpiralTopViewSmooth();
            pop();
        }
    }

    //checks if the shiftingVal is too high or low;
    //if too high, the fill becomes darker;
    //if too low, the fill becomes ligher;
    if (shiftingVal >= 255){
        shiftingValChange = shiftingValChange * -1;
    }
    else if (shiftingVal < 100){
        shiftingValChange = shiftingValChange * -1;
    }
    //changes the shiftingVal;
    shiftingVal += 1*shiftingValChange;
    //changes the angle and allows for rotation;
    //of the smooth conical spirals;
    angl += 0.1;
    

}

//function that creates the smooth conical spirals;
function conicalSpiralTopViewSmooth() {
    //variables for h, height; a, angle; r, radius;
    var h = 1;
    var a;
    var r = 30;
    
    //adds interactivity;
    //as one goes right, the size of the spiral increases;
    //as one goes down, the complexity of the spiral increases;
    var indepChangeX = map(mouseX, 0, 480, 500, 1000);
    var indepChangeY = map(mouseY, 0, 480, 800, 1000);
    a = indepChangeY;

    //actually creates the spiral;
    beginShape();
    for (var i = 0; i < indepChangeX; i++){
        var z = map(i, 0, 400, 0, PI);
        x = ((h - z) / h)*r*cos(radians(a*z));
        y = ((h - z) / h)*r*sin(radians(a*z));
        vertex(x, y);
    }
    endShape(CLOSE);

}

//function that creates the rough middle conical spiral;
function conicalSpiralTopViewRough() {
    //variables are the same as the smoothSpiral function;
    var h = 0.5;
    var a = 1000;
    var r;
    
    //adds interactivity;
    //the radius is now dependant on mouseY, going up increases size;
    //going left increases complexity;
    r = map(mouseY, 0, 480, 20, 10);
    var edgeNum = map(mouseX, 0, 480, 60, 30);
    
    //creates the spiral;
    beginShape();
    for (var i = 0; i < edgeNum; i++){
        var z = map(i, 0, 50, 0, TWO_PI);
        x = ((h - z) / h)*r*cos(radians(a*z));
        y = ((h - z) / h)*r*sin(radians(a*z));
        vertex(x, y);
    }
    endShape();
}

//mousePressed function that changes the variables col and col2;
//with random values of r, g, and b;
function mousePressed() {
    var randR = random(150);
    var randG = random(150);
    var randB = random(150);
    col = color(randR, randG, randB);
    col2 = color(randR + random(-50, 50), randG + random(-50, 50), randB + random(-50, 50));
}

I initially had no idea what to make in terms of curves. That was until I happened upon the Conical Spiral. It was supposed to be 3-D, but it ended up as a top down view of a spiral which I liked. Overall, I liked what I did with this Project.

As for how it works, clicking the mouse will change the colors of the middle “rough” Conical Spiral and the 4 “smooth” Conical Spirals. The colors of both types are similar but not the same, as seen with the use of random() in the code.

Along with that, moving the mouse right will increase the size of the “smooth” Spirals and reduce the size and complexity of the “rough” Spiral. Moving left does the opposite. Moving down increases the complexity of the “smooth” Spirals while also reducing the size of them and the “rough” Spiral.

LO 7: Information Visualization

Visualization of Bible Cross References by Chris Harrison

For this week’s LO, I will be talking about a Visualization of the Cross References found in the Bible by Chris Harrison.


Chris Harrison is an Associate Professor of Human-Computer Interaction.
And as the writeup for this week’s LO states, he is here at CMU as well. Some of his work deals with Data Visualization.

This one specifically caught my eye because I am a Christian and with some Bible study under my belt, I am astounded by the references within the Bible. I have also seen this work before, but to now realize that a CMU Professor made this has made me amazed as well. So beyond my own personal beliefs, I just find it beautiful and simplistic in a good way.


As for its creation, a Pastor (Christoph Romhild) and Dr. Harrison began work in 2007. They used the arcs as the connections between chapters (individual bars on the x-axis) that are grouped in alternating light and dark gray sections (they represent books of the Bible). The colors show the length of the connection – with the shortest being dark blue and the longest being what seems to be dark orange. They used the already available 63,000 Cross References and probably separated it by chapter. And using an algorithm(s) of some kind involving the Chapters, created this work.


Overall, I think it is very neat.


Here are links to this specific work, his bio, and other works.

Project-06: Abstract Clock

My Project

//cbtruong;
//Section B;

var secondVal;
var minuteVal;
var hourVal;
var monthVal;

var sixtyCircleX = [];
var sixtyCircleY = [];
var sixtyCircleX2 = [];
var sixtyCircleY2 = [];
var hourAngle = [];


function setup() {
    createCanvas(480, 480);
    background(220);
    text("p5.js vers 0.9.0 test.", 10, 15);
    secondVal = second();
    minuteVal = minute();
    hourVal = hour();
    monthVal = month();
    for (var i = 0; i < 8; i++){
        hourAngle.push(i*45);
    }
    for (var y = 10; y < 120; y += 20){
        for (var x = 10; x < 200; x += 20){
            sixtyCircleX.push(x);
            sixtyCircleY.push(y);
        }
    }
    for (var y2 = 370; y2 < 480; y2 += 20){
        for (var x2 = 290; x2 < 480; x2 += 20){
            sixtyCircleX2.push(x2);
            sixtyCircleY2.push(y2);
        }
    }
}

function draw() {
    background(205, 202, 240);
    timeOfDay(hourVal);
    for (var i = 0; i < 8; i++){
        noStroke();
        fill(230, 100, 120);
        if (i > hourVal % 8){
            fill(27, 30, 35);
        }
        hourSquare(hourAngle[i]);
        hourAngle[i] += 0.1;
    }
    for (var j = 0; j < 60; j++){
        fill(100, 230, 120);
        if (j > secondVal){
            fill(240);
        }
        sixtyCircleTime(sixtyCircleX[j], sixtyCircleY[j]);
    }
    for (var l = 0; l < 60; l++){
        fill(120, 120, 230);
        if (l > minuteVal){
            fill(240);
        }
        sixtyCircleTime(sixtyCircleX2[l], sixtyCircleY2[l]);
    }
    for (var m = 180; m <= 480; m += 25){
        fill(240);
        if (m >= monthVal*22.5){
            fill(45, 67, 89);
        }
        push();
        translate(-60, 20);
        rotate(radians(330));
        monthTri(20, m);
        monthTri(260, m);
        pop();
    }
}

function hourSquare(hourAngle){
    push();
    translate(230, 230);
    square(80*cos(radians(hourAngle)), 80*sin(radians(hourAngle)), 20);
    pop();
}

function timeOfDay(hourValue){
    if (hourVal > 15){
       fill(227, 111, 30);
    }
    else if (hourVal < 15 & hourVal > 7){
       fill(252, 209, 77);
    }
    else {
       fill(27, 30, 35);
    }
    circle(240, 240, 100);
}

function sixtyCircleTime(x, y){
    circle(x, y, 20);
}

function monthTri (x, y){
    triangle(x, y, x + 20, y, x + 10, y + 20);
}

I had grander ideas for an Abstract Clock, but I decided to do one that was practical. This one tells the months (the triangles that fill up according to the month), seconds and minutes (the circles arrays – the upper are seconds and the lower are minutes). And finally, the time of day (which I split into 3, Morning (7-15), Afternoon (15-23), and Night (23-7)) and the hours passed of each time. It is very basic.

LO 6: Randomness

The Tables for Game.

For this Week’s LO, I will talk about Wolfgang Amadeus Mozart’s (attributed but up for debate) Musical Dice Game (1792) – also known as Musikalisches Wurfelspiel.


Seeing how we were to find Randomness, I was initially at a loss. Until I happened onto this piece that was allegedly from Mozart himself.


Its randomness lies in the fact that a die (or two) is supposed to be thrown to get a value from 2 to 12 but minus 1 – so a range of 1-11. With this number, a person will consult a chart that has 8 columns and 11 rows. The “random” number will give the person the measure of music from the row of the column and then they will move onto the next column and repeat the process. They will do this for all 8 columns and the second set of 8 columns and 11 rows each in the second chart. The end product is a 16-Measure Piece of Music.


This is where the computation comes in – it is just like the nested for loops we have been working with. Furthermore, the available measures are like the arrays.

Overall, I like Classical Music and Mozart is one of my favorites. And I find it cool that he supposedly made something like this.


Here is Mozart’s Bio and Musical Dice Games (there is a section for Mozart’s in it).