Final Project: Covid Clicker

Our program is an interactive fight the coronavirus game. Within this game the player must tap on the coronavirus particles attacking the hospital in order to try to create and distribute the vaccine. As the players score increases the
particles spawn at a higher rate making the game harder to win. Once the screen and player are about to be overtaken by the virus the screen will start to flash red indicating the player is close to losing. Once there are 30 or more corona
virus particles on the screen the player has become infected and loses. Losing triggers the game to bring the player to the loser page. In order to win the game the player must click on 100 individual particles filling up the bar on the right side of the game. Once this occurs the player has created and distributed the vaccine bringing them to the winner page. If we had more experience in code we would have liked to have been able to make the virus particles more complex and life like while having the mouse pressed function work on only the virus. With more time and knowledge this might have been accomplished.

sketchDownload
var counter = 0;
var viruses = [];
var newVirusLikelihood = 0.05;
var cars = [];


function setup() {
    createCanvas(480, 480);
    frameRate(10);
}

function draw() {
    push();
    background1();
    pop();
    //gives a flashing warning if there are more than 20 objects
    //Lucas and Anthony
    if(viruses.length > 20){
        if(frameCount % 4 == 0){
            background(255, 0, 0, 100);
        }
        else{
            push();
            background1();
            pop();
        }
    }
    //The following if statements increase the spawn rate at certain scores
    //(Lucas)
    if(counter == 5){
        newVirusLikelihood = .07
    }
    if(counter == 10){
        newVirusLikelihood = .12
    }
    if(counter == 25){
        newVirusLikelihood = .17
    }
    if(counter == 50){
        newVirusLikelihood = .23
    }
    //Creates a progress bar to a vaccine (Lucas)
    fill(0, 255, 0);
    rect(width - 10, 0, 10, counter * height / 100);

    fill(255);
    //displays how many viruses have been "cleansed" (Lucas)
    text("Score = " + counter.toString(), 10, 10, 70, 80);
    updateAndDisplayViruses();
    bounceViruses();
    addNewVirusesWithSomeRandomProbability();
    print(counter.toString());
    //End Screen if the player loses (Lucas)
    if(viruses.length >= 30){
        //erase();
        background(0);
        textAlign(CENTER);
        textSize(26);
        text("You Lose: COVID-19 Has Taken Over", width / 2, height / 2)
        noLoop();
    }
    //End Screen if the player wins (Lucas)
    if(counter == 100){
        background(255);
        push();
        fill(0);
        textAlign(CENTER);
        textSize(26);
        text("You Win: A Vaccine Has Been Distributed", width / 2, height / 2)
        pop();
        noLoop();

    }
}

//The following code was done by Lucas until indicated
function updateAndDisplayViruses(){
    // Update the virus positions, and display them.
    for (var i = 0; i < viruses.length; i++){
        viruses[i].move();
        viruses[i].display();
    }
}
//makes the viruses bounce off the edges of the canvas
function bounceViruses(){
    for(var i = 0; i < viruses.length; i++){
        //determines if a virus is on the left or right and switches direction
        //accordingly
        if(viruses[i].x + viruses[i].breadth / 2 >= width ||
        viruses[i].x - viruses[i].breadth / 2 <= 0){
            viruses[i].speedX = -viruses[i].speedX
        }
        //determines if a virus is on the top or bottom and switches direction
        //accordingly
        if(viruses[i].y + viruses[i].breadth / 2 >= height ||
        viruses[i].y - viruses[i].breadth / 2 <= 0){
            viruses[i].speedY = -viruses[i].speedY
        }
    }
}


function addNewVirusesWithSomeRandomProbability() {
    // Adds a virus based upon a probability
    if (random(0,1) < newVirusLikelihood) {
        viruses.push(makeVirus(random(20, width - 20),
        random(20, height - 20)));
    }
}

// method to update position of virus every frame
function virusMove() {
    this.x += this.speedX;
    this.y += this.speedY;
}

function virusDisplay() {
    //colors the viruses randomly
    push();
    fill(this.clr);
    push();
    translate(this.x, this.y);
    circle(0, 0, this.breadth);
    pop();
    pop();
}

function makeVirus(startLocationX, startLocationY){
    var virus = {x: startLocationX,
               y: startLocationY,
               breadth: random(20, 80), //size of virus
               //random color of each virus
               clr: color(random(255), random(255), random(255)),
               //random speeds of virus
               speedX: random(-5, 5),
               speedY: random(-5, 5),
               move: virusMove,
               display: virusDisplay}
    return virus;
}

function mousePressed(){
    var vBefore = [];
    var vAfter = [];
    var vFinal = [];
    var v = viruses;
    for(var i = 0; i < viruses.length; i++){
        //conditions for mouse to be inside a virus
        if(mouseX > viruses[i].x - viruses[i].breadth / 2 & mouseX <
            viruses[i].x + viruses[i].breadth/2 && mouseY < viruses[i].y +
            viruses[i].breadth / 2 && mouseY > viruses[i].y -
            viruses[i].breadth / 2){
                //viruses up until the clicked object
                vBefore = viruses.slice(0, i);
                //viruses after the clicked object
                vAfter = v.slice(i + 1);
                //combines the two arrays of objects (eliminating the clicked
                //one)
                vFinal = vBefore.concat(vAfter);
                counter += 1
                viruses = vFinal
        }
    }
}
//The following code was done by Anthony
function background1(){   //joining background helper functions into one
  background(135,206,235);
  push()
  hospital();
  pop()
  push()
  updateAndDisplayCars();
  removeCarsThatHaveSlippedOutOfView();
  addNewCarsWithSomeRandomProbability();
  pop()
}

function hospital(){
  translate(0,-50);
  rect(100,250,100,230);    //creating the hospital building
  rect(200,200,200,280);
  rect(240,150,120,50);
  push();
  noStroke();
  fill(255,0,0);    //red cross on the top
  rect(295,160,10,30);
  rect(285,170,30,10)
  pop();
  push();
  fill(0,0,255);
  for(x=115;x<185;x+=30){   //windows
    for(y=255;y<460;y+=30){
      square(x,y,15);
    }
  }
  for(x=215;x<390;x+=30){
    for(y=210;y<400;y+=30){
      square(x,y,15);
    }
  }
  rect(300,450,20,30);    //doors
  rect(280,450,20,30);
  pop();
  push()
  fill(64);
  rect(0,480,480,50);   //street
  pop()
}

function updateAndDisplayCars(){
    // Update the cars' positions, and display them.
    for (var i = 0; i < cars.length; i++){
        cars[i].move();
        cars[i].display();
    }
}

function removeCarsThatHaveSlippedOutOfView(){
    //defines if a car is off the canvas, recreates the array to keep
    //cars still on canvas and remove ones that have moved off
    var carsToKeep = [];
    for (var i = 0; i < cars.length; i++){
        if (cars[i].x + cars[i].breadth > 0) {
            carsToKeep.push(cars[i]);
        }
    }
    cars = carsToKeep;
}


function addNewCarsWithSomeRandomProbability() {
    // Adds a car based upon a probability
    var newCarLikelihood = 0.02;
    if (random(0,1) < newCarLikelihood) {
        cars.push(makeCar(width));
    }
}


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

function carDisplay() {
    //colors the car randomly
    fill(this.clr);
    push();
    translate(this.x, 440);
    //body of the car
    rect(0, 0, this.breadth, 30);
    //windows as roof of the car
    fill(255, 255, 255, 50);
    quad(15, 0, this.breadth*.25, -20, this.breadth*.75,
         -20, this.breadth-5, 0);
    //wheels
    fill(0);
    circle(20, 25, 25);
    circle(80, 25, 25);
    pop();
}

function makeCar(startLocationX){
    var car = {x: startLocationX,
               breadth: 100, // length of car
               //random color of each car
               clr: color(random(255), random(255), random(255)),
               //random speeds of cars
               speed: random(-5, -10),
               move: carMove,
               display: carDisplay}
    return car;
}

Project 11 – Landscape

I wanted to create a landscape from the perspective of a car driving. You can see the cars on the other side of the road travelling in the opposite direction and the scrolling background. I wanted to have cars pass each other so they have random speeds.

sketchDownload
var trees = [];
var cars = [];
var hillHeight = []; //Stores the y values of the hills
var noiseParam = 5;
var noiseStep = 0.02; //Varies the smoothness of the hills
var x = [];

function setup() {
    createCanvas(480, 480);
    background(220);
    //creates a canvas that starts with trees
    for (var i = 0; i < 10; i++){
        var rx = random(width);
        trees[i] = makeTree(rx);
    }

    //for loop creates the values for the mountains in the background
    for(var i = 0; i<=width/5; i++){
        var n = noise(noiseParam);
        //Adjust size to fit the canvas
        var value = map(n, 0, 1, 0, .5*height);
        hillHeight.push(value);
        noiseParam += noiseStep;
    }

    frameRate(10);
}

function draw() {
    //sky
    background(0, 230, 255);
    //continually makes the mountains in the background scroll
    if(hillHeight.length>width/5){
        hillHeight.shift();
        for(var i = 0; i <= width / 5; i++){
            var n = noise(noiseParam);
            var value = map(n, 0, 1, 0, .5*height);
            hillHeight.push(value);
            noiseParam += noiseStep;
        }
    }
    //color of the hills
    fill(130, 130, 130);
    //creates the shape of hills to be able to fill under the line
    beginShape();
    vertex(0, height);
    for(var i = 0; i <= width/5; i++){
        vertex(i*5, hillHeight[i])
    }
    vertex(width, height);
    endShape();
    //foreground grass
    fill(0, 255, 0);
    noStroke();
    rect(0, 360, width, 120);
    //road
    fill(35);
    stroke(0);
    rect(0, 260, width, 100);
    //background grass
    fill(0, 225, 0);
    noStroke();
    rect(0, 200, width, 60);

    //creates the trees on the canvas and conditions for new/old
    updateAndDisplayTrees();
    removeTreesThatHaveSlippedOutOfView();
    addNewTreesWithSomeRandomProbability();
    //creates the cars on the canvas and conditions for new/old
    updateAndDisplayCars();
    removeCarsThatHaveSlippedOutOfView();
    addNewCarsWithSomeRandomProbability();
}


function updateAndDisplayTrees(){
    // Update the trees' positions, and display them.
    for (var i = 0; i < trees.length; i++){
        trees[i].move();
        trees[i].display();
    }
}


function removeTreesThatHaveSlippedOutOfView(){
    //defines trees that have gone off canvas and recreates the array
    //without those trees
    var treesToKeep = [];
    for (var i = 0; i < trees.length; i++){
        if (trees[i].x + trees[i].breadth > 0) {
            treesToKeep.push(trees[i]);
        }
    }
    trees = treesToKeep;
}


function addNewTreesWithSomeRandomProbability() {
    //add a tree at the end based upon a probability
    var newTreeLikelihood = 0.02;
    if (random(0,1) < newTreeLikelihood) {
        trees.push(makeTree(width));
    }
}


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


function treeDisplay() {
    fill(255);
    stroke(0);
    push();
    translate(this.x, 240);
    fill(133, 87, 35);
    //tree trunk
    rect(0, -this.tHeight, this.breadth, this.tHeight);
    noStroke();
    //tree branches
    fill(78, 105, 26);
    circle(this.breadth/6, -this.tHeight, this.breadth*2);
    circle(this.breadth*(5/6), -this.tHeight, this.breadth*2);
    circle(this.breadth/2, -this.tHeight-this.breadth/2, this.breadth*2);
    pop();
}


function makeTree(birthLocationX) {
    var tr = {x: birthLocationX,
                //width of the trees
                breadth: random(10, 40),
                speed: -3.0,
                //tree height
                tHeight: random(50, 130),
                move: treeMove,
                display: treeDisplay}
    return tr;
}

function updateAndDisplayCars(){
    // Update the cars' positions, and display them.
    for (var i = 0; i < cars.length; i++){
        cars[i].move();
        cars[i].display();
    }
}


function removeCarsThatHaveSlippedOutOfView(){
    //defines if a car is off the canvas, recreates the array to keep
    //cars still on canvas and remove ones that have moved off
    var carsToKeep = [];
    for (var i = 0; i < cars.length; i++){
        if (cars[i].x + cars[i].breadth > 0) {
            carsToKeep.push(cars[i]);
        }
    }
    cars = carsToKeep;
}


function addNewCarsWithSomeRandomProbability() {
    // Adds a car based upon a probability
    var newCarLikelihood = 0.02;
    if (random(0,1) < newCarLikelihood) {
        cars.push(makeCar(width));
    }
}


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

function carDisplay() {
    //colors the car randomly
    fill(this.clr);
    push();
    translate(this.x, 290);
    //body of the car
    rect(0, 0, this.breadth, 30);
    //windows as roof of the car
    fill(255, 255, 255, 50);
    quad(15, 0, this.breadth*.25, -20, this.breadth*.75,
         -20, this.breadth-5, 0);
    //wheels
    fill(0);
    circle(20, 25, 25);
    circle(80, 25, 25);
    pop();
}

function makeCar(startLocationX){
    var car = {x: startLocationX,
               breadth: 100, // length of car
               //random color of each car
               clr: color(random(255), random(255), random(255)),
               //random speeds of cars
               speed: random(-5, -10),
               move: carMove,
               display: carDisplay}
    return car;
}

LO 11 – Female Practitioners

Creator: Allison Parrish
Piece: Semantic Similarity Chatbot
Date: 2018

Allison Parrish is a programmer and a linguist. Allison currently works at NYU as a faculty member. She also graduated from NYU with her master’s degree. A lot of her projects involve bots and poetry as these are the topics she is most interested in. All of her projects that I have seen mix language and coding to create unique tools and artwork. The Semantic Similarity Chatbot is a creation of hers which allows people to text with historical figures of their choice. She wrote programs that dissected the way that different characters wrote and then added AI that could replicate similar patterns. One of the coolest aspects of this project in my opinion is that fact that it was created for her students to modify. She started with a few people from history, but as a project, she had her students write more code to add even more unique figures. I really enjoy the concept of this and love that she taught her students through such an interesting project.

https://gist.github.com/aparrish/114dd7018134c5da80bae0a101866581

bot screenshot

Project 10- Sonic Story

I wanted to create a story that was fun and easy to understand. I took a typical camping scary story and turned it into a visual piece of code. I left the story open ended where the viewer can guess what happens next.

sketchDownload
/*There is man at a camp fire telling ghost stories. The flashlight is the
trope of holding a flashlight under one's chin. A ghost then appears but cannot
move past the fire. The wind then blows out the fire and the screen goes dark.
The next part is up to the viewer's imagination.*/

function setup() {
    createCanvas(480, 480);
    createDiv("p5.dom.js library is loaded.");
    frameRate(1);
    useSound();
}

//loads all audio files before running the code
function preload(){
    ghostSound=loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/11/Ghost.wav");
    fireCrackling=loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/11/Fire.wav");
    flashlightClick=loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/11/Flashlight.wav");
    windWoosh=loadSound("https://courses.ideate.cmu.edu/15-104/f2020/wp-content/uploads/2020/11/Wind.wav");
}

//sets the volume for all the sounds
function soundSetup(){
    ghostSound.setVolume(1);
    fireCrackling.setVolume(1);
    flashlightClick.setVolume(1);
    windWoosh.setVolume(1);
}

function draw() {
    background(26, 27, 71);
    fill(0, 255, 0);
    //creates the grass
    rect(0, 200, 480, height-200);


    translate(100, 100);
    push();
    //if frameCount is even it will display one fire, if odd it will display
    //the other
    //the secondary ifs make the fire stop when the wind blows past
    if(frameCount % 2 == 0){
        translate(115, 110);
        scale(.8);
        fill(255, 0, 0);
    //One version of the fire
        if(frameCount < 32){ //stops the fire when the wind blows by
            beginShape();
            curveVertex(84, 70);
            curveVertex(84, 70);
            curveVertex(95, 19);
            curveVertex(87, 5);
            curveVertex(75, 25);
            curveVertex(60, -30);
            curveVertex(40, 25);
            curveVertex(32, -10);
            curveVertex(21, 17);
        curveVertex(32, 70);
        curveVertex(84, 70);
        curveVertex(84, 70);
        endShape();
    //pop();
        }
    }
    else{
        if(frameCount < 32){ //stops fire when the wind blows by
    //Second version of the fire
            push();
            translate(115, 110);
            scale(.8);
            fill(255, 0, 0);
            beginShape();
            curveVertex(84, 70);
            curveVertex(84, 70);
            curveVertex(32, 70);
            curveVertex(21, 17);
            curveVertex(32, 0);
            curveVertex(40, 25);
            curveVertex(50, -25);
            curveVertex(75, 25);
            curveVertex(80, 5);
            curveVertex(90, -5);
            curveVertex(84, 70);
            curveVertex(84, 70);
            endShape();
        }
    }
    pop();

    //downward sloping log under the fire
    fill(165, 42, 42);
    push();
    translate(125, 150);
    rotate(radians(25));
    rect(0, 0, 80, 20);
    pop();
    //upward sloping log under the fire
    push();
    translate(125, 150);
    rotate(radians(-25));
    rect(-20, 30, 80, 20);
    pop();

    //if statement makes the face light up with the flashlight
    if(frameCount>12){
        fill(253, 217, 181);
    }
    else{
        fill(0);
    }
    //head
    circle(0, 5, 50);
    //body
    line(0, 30, 0, 100);
    //legs
    line(0, 100, -15, 150);
    line(0, 100, 15, 150);
    //arms
    line(-15, 60, 15, 60);
    line(15, 60, 0, 70);

    //flashlight
    fill(255);
    rect(-2.5, 60, 5, 20);
    quad(-2.5, 60, 2.5, 60, 7.5, 50, -7.5, 50)


    //flashlight beam that lights up face
    if(frameCount > 12){
        push();
        noStroke();
        fill(255, 255, 0, 60);
        quad(-7.5, 50, 7.5, 50, 25, 0, -25, 0);
        pop();
    }
    //moves the ghost from right to left
    push();
    if(frameCount > 17 & frameCount < 27){
        translate(frameCount*-5, 0);
        ghost();
    }
    pop();

    //wind
    //if moves the wind from right to left
    if(frameCount > 27){
        push();
        translate(200+frameCount*-10, 0);
        stroke(255);
        line(250, 50, 300, 50);
        line(275, 70, 325, 70);
        line(290, 30, 340, 30);
        pop();
    }
    //stops the animation and creates a black screen
    if(frameCount > 32){
        background(0);
        noLoop();
    }
    //when the flashlight turns on, the sound is made
    if(frameCount == 13){
        flashlightClick.play();
    }
    //fire sounds starts at 5 and ends prior to the flashlight
    else if(frameCount == 5){
        fireCrackling.play();
            if(frameCount == 10){
                fireCrackling.stop();
            }
    }
    //ghost sound starts when it is created
    else if(frameCount == 18){
        ghostSound.play();
    }
    //wind sound plays when the wind appears on screen
    else if(frameCount == 28){
        windWoosh.play();
    }
}
//function to create the ghost
function ghost(){
    push();
    beginShape();
    noStroke();
    arc(300, 50, 40, 100, PI, 0);
    triangle(300, 50, 305, 65, 310, 50);
    triangle(310, 50, 315, 65, 320, 50);
    triangle(290, 50, 295, 65, 300, 50);
    triangle(280, 50, 285, 65, 290, 50);
    fill(0);
    ellipse(295, 20, 5, 10);
    ellipse(305, 20, 5, 10);
    pop();
}

LO-10: Computational Music

Author: Christine McLeavey Payne (An assortment of people created the actual product)
Date: April 25, 2019
Project: MuseNet

MuseNet is a neural network that can develop music of its own. It can create short compositions in the style of different artists/composers with instruments of choice. This is a very creative idea because it allows people to compose music in the style of someone like Beethoven, but with guitar instead. I admire the creativity in the project, but also this combination of so many different styles and types of music. Much of what is produced by MuseNet is compositions that would never be possible or done without the computational work done by the team. The algorithms were created by a neural network, essentially a type of code that learns based off of inputs. In doing so, the computer learned patterns from music rather than individual analysis having to be done by people for every type of music/song. The artistic sensibilities are shown by the creative aspect of MuseNet. Clearly, the team cared about music and wanted to create a unique twist so they used their computer science knowledge to do this.

Link to Blog: https://openai.com/blog/musenet/

Link to Example: https://soundcloud.com/openai_audio/pop-nocturne

LO 09: Anthony Prestigiacomo

Author: Anthony Prestigiacomo
Assignment: Looking Outward 03
Artwork: Probability Lattices
Artist: Marius Watz
Year: 2012

I agree with Anthony that the 4 pieces created are all quite unique, but similar in a very interesting way. The sharpness of the edges created by the angles give an interesting appearance to each individual sculpture. I would be interested to see what the parametric functions looked like to create the art pieces. Also, as the piece was created in 2012, the 3D filament is quite apparent. I would be interested to see how complex Watz could make these art pieces with today’s technology. 3D printers are much better at not leaving lines as well as can create more complex structures. I agree with Anthony that the artist relies on abstractionism which gives his artwork the feel that it does. On top of that, the Watz manages to reduce the abstractness with computation. The ties between the two gives the art its appeal which I imagine is quite difficult to create.

http://mariuswatz.com/2012/05/09/probability-lattice/

Marius Watz | Artist archive

Project 09 – Portrait

I wanted to create a replication of the portrait that could be either detailed and accurate or abstract. To do this I made my image get created by squares and circles that are created by a loop. The size gets changed by the x-position of the mouse (left is less abstract and right is more abstract).

sketchDownload
//function that loads image of my face
function preload() {
    lucas = loadImage("https://i.imgur.com/M9dRkNS.png");
}

function setup() {
    //canvas is the size of the resized image
    createCanvas(850/2.29, 480);
    background(0);
    //stores pixels from the image
    lucas.loadPixels();
    //resizes image to keep proportions
    lucas.resize(850/2.29, 480);
    frameRate(100);
}

function draw() {
    //changes position of the circles and squares in the array
    var modifier = 10;
    //constrains the size of the circles and squares
    var restrict = map(mouseX, 0, width, 5, modifier*2);
    for(var i = 0; i < width; i++){
        for(var j = 0; j < height; j++){
            //obtains the pixel color at a given x and y of the picture
            var pixelColor = lucas.get(i*modifier, j*modifier);
            noStroke();
            //fills with the color from the pixel
            fill(pixelColor);
            //creates circles and squares that will replicate the image
            circle(i*modifier, j*modifier, random(restrict));
            square(i*modifier, j*modifier, random(restrict));
        }
    }
}

LO-08: Communication and Emojis

Person of Interest: Jennifer Daniel

Website: http://httpcolonforwardslashforwardslashwwwdotjenniferdanieldotcom.com/

Jennifer Daniel has extensive work experience. She was a graphic designer for many well-known newspapers like the New York Times. Presently, she works as the creative director for Google and Android. She is also a chairperson for Unicode. She lives in San Francisco and has a formal background in graphic design. She described her profession as converting speech and emotions to visual representations. She believes that communication must evolve over time which is where emojis and animations are headed. I was most interested in talking about how different forms of communication relate to others. For example, her discussion of how texting is more similar to speaking than it is to writing. I was also interested in seeing how humans and computers see information differently so for customizable stickers you must have computers use neural networks to generalize aspects of people, then an artist must create a visualization that is most accepting of differences. She used a lot of humor and visualizations in her talk. Humor always makes talks more entertaining, but I would most like to incorporate her visual display techniques into my own presentations.

Jennifer Daniel’s Talk on Emojis
An Unrelated Piece, but Interesting
Jennifer Daniel on Twitter: "THE BOOK is finally available for pre-order in  the US! Coming Oct. 25. YOU SHOULD GET IT. https://t.co/NdhpHee4hv… "

Project-07: Artistic Curves

I really wanted to create a psychedelic piece with curves. To do this, I made a rainbow effect of colors. The main aspect of the art was a hypotrochoid. This is made with a fixed circle and lines created by another circle rolling along the edge. The piece changes different mathematical aspects of the hypotrochoids based upon the position of the mouse. The curve is created with parametric equations based upon the radius of the fixed circle and the radius of the moving circle. These are the elements that are adjusted with the mouse. The loops created many hypotrochoids and in certain positions on the canvas, this can make very interesting designs.

sketchDownload
function setup() {
    createCanvas(480, 480);
    background(220);
    frameRate(20);
}

function draw() {
    background(0);
    //moves the shapes to the center of the canvas
    translate(width/2, height/2);
    for(var i = 0; i<20; i++){
        stroke(random(255), random(255), random(255)); //randomizes colors
        noFill();
        //creates loop of hypotrochoids based upon mouse position
        hypotrochoid(i*mouseX*.5, i*mouseY);
    }
}

//defines the shape hypotrochoid
//https://mathworld.wolfram.com/Hypotrochoid.html
function hypotrochoid(a, mouseY){
    var x; //used for parametric form
    var y; //used for parametric form

    var a; //radius of the fixed circle
    var b = a/10 //radius of the rolling ball
    var h = constrain(mouseY/10, 0, a) //var h depends on mouseY and restricted

    //defines the actual shape
    beginShape();
    for (var i = 0; i < 200; i++){
        var t = map(i, 0, 600, 0, 6*PI);
        x = (a-b)*cos(t)+h*cos(((a-b)/b)*t); //parametric equation for x
        y = (a-b)*sin(t)-h*sin(((a-b)/b)*t); //parametric equation for y
        vertex(x,y);
    }
    endShape(CLOSE);
}

LO-07: Expression of Elements

Artist: Nicholas Felton
Piece: Elements
Date: 2017-Present

Felton with his piece “Elements” created a better experience for learning. In a concept like the periodic table, many elements are hard to visualize. Felton creates impressive 3D renderings to show what each element looks like in its natural state. Felton described the purpose of this piece is to practice techniques needed to show different states of matter. Additionally, with some elements only having slight differences between one another, the level of detail needed is a good way for him to practice micro-details in renderings. Felton’s artistic sensibilities are shown through the attention to detail and the interpretation of elements that are not easily visualized. The best example is hydrogen. Hydrogen is not an element seen by the human eye, but by utilizing computational tools, Felton was able to create an accurate depiction of the element. The piece also shows the position on the periodic table as well as the electron shells. The artwork not only is creative in its interpretations, but scientifically accurate. Creations like this are improving education and understanding of difficult concepts.

http://feltron.com/Elemental.html

Feltron: Elemental
Visual Representation of Hydrogen