Collect water!

This is my final project about collecting raindrops. Your health starts to lose from dehydration and the one way to survive is through collecting raindrops!. Watch out for those black ones, as they deplete your health if you touch them!

Get water final

//Yunfeng Jiang
//Section E

//setting up variables
var myCanvas;
var waterN = 10;
var water = [];
var p;
var plat;
var waterSlopeProj = []

var acc = 0.5;
var size = 40;
var score = 0;
var health = 100;

function setup() {
    myCanvas = createCanvas(500, 300);
    //push water object to water array
    for(var i = 0; i < waterN; i++){
        var w = createWater(random(20, width-20), random(-200, -10), 2);
        water.push(w);
    }

    //add platform object
    if(random()<0.5){
        plat = createPlatform(-125, random(25, 50), random(200, 250), 0);
    }
    else{
        plat = createPlatform(width+125, random(25, 50), random(200, 250), 1);
    }
    

    //push waterslopeProj to array
    for(var i = 0; i < waterN; i++){
        var k = plat.h / plat.w; //slope
        if(plat.sdir > 0.5){
        var wsp = 100-tan(k)*(-water[i].x+plat.x+0.5*plat.w)
        }
        else{
        var wsp = 100-tan(k)*(-water[i].x+plat.x-0.5*plat.w)    
        } //expression of the slope
        
        waterSlopeProj.push(wsp);
    } 
    
    //add player object
    p = player();  
}

function draw() {
    //draw scene
    background(176, 192, 200);
    myCanvas.parent('canvasPlaceholder');
    scene();
    strokeWeight(1)
    
    
    

    //add rain
    updateWater();
    addWater();
    

    //update player
    p.display(size); 
    p.moveY();
    playerMove();

    //add platform
    updatePlatform();
    addPlatform();

    //gameplay properties
    updateHealth();
    updateProj();
    checkHitRain();
    checkHitPlat();
        
}
    

//draw scene
function scene(){
    rectMode(CORNER)
    strokeWeight(0);
    fill(128, 96, 67);
    rect(0, 250, width, 50)
    text('score = '+ score, 10, 20);
    text('health = '+ health, 10, 50)
}

//jump
function keyPressed(){
    if (keyCode === 32 & p.y == 230){
                p.dy = -10
                }
            } 

//move player left and right
function playerMove(){
    if (keyIsPressed === true){
        
            if (keyIsDown(65) || keyIsDown(LEFT_ARROW)){
                if(p.x > size/2){
                    p.moveX(-5);
                }
                
            }
            if (keyIsDown(68) || keyIsDown(RIGHT_ARROW)){
                if(p.x < width-size/2){
                    p.moveX(5);
                }
            }    
        }
}

//update health
function updateHealth(){
    
    //deplete health
    if (frameCount%30 == 0){
        health = health - 1
    }
    
    //game over
    if (health < 0){
        textAlign(CENTER, CENTER)
        fill(255, 0, 0);
        textSize(50);
        text("GAME OVER", width/2, height/2)
        noLoop()
    }
}

//check player location to raindrops
function checkHitRain(){
    //check distance from player to rain
    for(var i = 0 ; i < waterN; i++){
        if(dist(p.x, p.y, water[i].x, water[i].y) < size*0.75){
            score += 1;
            //water that hits platform are considered bad water that depletes health
            if(water[i].bad == false){
                health += 1;
            }
            else{
                health -= 1;
            }
            var w = createWater(random(20, width-20), random(-200, -10), 2);
            water[i] = w;

        }
    }
}
 
function updateProj(){
    for(var i = 0; i < waterN; i++){
        var k = plat.h / plat.w; //slope
            if(plat.sdir == 1){
                waterSlopeProj[i] = 100-tan(k)*(-water[i].x+plat.x+0.5*plat.w) //expression of the slope
            }
            else{
                waterSlopeProj[i] = 100+tan(k)*(-water[i].x+plat.x-0.5*plat.w)  //expression of the slope
            }
        } 


}
function checkHitPlat(){
     for(var i = 0 ; i < waterN; i++){
        var k = plat.h / plat.w
        if(water[i].x > plat.x-plat.w*0.5 & water[i].x < plat.x + plat.w*0.5 && water[i].y > waterSlopeProj[i] && water[i].y < 100){
                water[i].bad = true;
                if(plat.sdir == 1){
                    water[i].x += 0.25*water[i].v/k
                    water[i].y += 0.25*water[i].v
                }
                else{
                    water[i].x -= 0.25*water[i].v/k
                    water[i].y += 0.25*water[i].v
                }
            }
        else{
            water[i].y += water[i].v
        }
            

}
}


A day in the future city

I took inspiration from a scene in cyberpunk edgerunner and made a city landscape based on that. I am surprised by the flexibility of object, the properties can be manipulated in different ways to create completely different stuff. For example, the pillars, foreground, and background buildings are created with one single object.

Inspired scene

sketch

//Jason Jiang
//Section E

//setting up arrays of objects
var bldg = [];
var bldgBack = []
var pillar = []
var vhc = []

//number of objects in each array
var bldgN = 6;
var bldgBackN = 11;
var vhcN = 2;

//color palatte for buildings
var palatte = ['#7670b2', '#5ab6b0', '#5ab6b0', '#3f5c60', '#1c4167', '#3f5c60', '#7e9868'];

//image links of assets
var facadeLink = [
            "https://i.imgur.com/oPA4x4y.png",
            "https://i.imgur.com/xeOW3sz.png", 
            "https://i.imgur.com/gbr6ySL.png",
            "https://i.imgur.com/WqUehK3.png"];
var facadeImg = [];
var vehicleLink = [
            "https://i.imgur.com/gFtwhqV.png",
            "https://i.imgur.com/KX1dLCi.png",
            "https://i.imgur.com/Fo43Kep.png"];
var vehicleImg = [];

//load assets
function preload(){
    train = loadImage("https://i.imgur.com/BFxe31d.png");
    for (var i = 0; i < facadeLink.length; i++){
        facadeImg[i] = loadImage(facadeLink[i]);
    }
    for (var i = 0; i < vehicleLink.length; i++){
        vehicleImg[i] = loadImage(vehicleLink[i]);
    }

}

function setup() {

    createCanvas(400, 200);
    imageMode(CENTER);
    colorMode(HSB);
    
    
    //create front building arrays
    for(var i = 0; i < bldgN; i++){
        //randomly pick color from array
        var palatteIndex = floor(random(palatte.length));
        //randomly pick an image from array
        var facadeIndex = floor(random(facadeImg.length));
        var b = building(80*i, random(-height/3, height/3), random(80, 100), color(palatte[palatteIndex]), facadeImg[facadeIndex]);
        bldg.push(b);
    }

    //create back building arrays
    for(var i = 0; i < bldgBackN; i++){
        var b = building(40*i, random(150), 40, color(20, 10, 30, 0.5), -1);
        bldgBack.push(b);
    }

    //create pillars
    for (var i = 0; i < 2; i++) {
        var p = building(200*i, 70, 20, color(80), -1);
        pillar.push(p);
    }

    //creating vehicles
    for (var i = 0; i < 2; i++) {
        //randomly pick an image from array
        var vehicleIndex = floor(random(vehicleImg.length));
        //randomize vehicle moving direction
        if (random(1) <= 0.5){
            //vehicles from left to right
            var v = vehicle(random(-width/2, 0), random(50, 150), random(5, 10), vehicleImg[vehicleIndex]);
        }
        else{
            //vehicles from right to left
            var v = vehicle(random(width, 1.5*width), random(50, 150), random(-5, -10), vehicleImg[vehicleIndex]);
        }
        vhc.push(v);
    }

 }


function draw() {
    background(200, 20, 100);
    //update information in each frame
    updateObjs();
    updateArray();
    //add train image
    image(train, 200, 90); 
    }


function updateObjs(){
    
    //updating building background
    for(var i = 0; i < bldgBack.length; i++){
        bldgBack[i].move(2);
        bldgBack[i].display();
    }

    //updating building foreground
    for(var i = 0; i < bldg.length; i++){
        bldg[i].move(5);
        bldg[i].display();
    }
    //updating pillars
    for(var i = 0; i < pillar.length; i++){
        pillar[i].move(5);
        pillar[i].display();
    }

    //updating vehicles
    for (var i = 0; i < vhc.length; i++) {
        vhc[i].move();
        vhc[i].display();
    }
    
}


//displaying buildings
function buildingDisplay(){
    
    //draw rectangles
    noStroke();
    fill(this.color);
    rect(this.x, this.y, this.w, height-this.y);
    var centerX = this.x + 0.5*this.w ;
    var centerY = this.y + 0.5*(height - this.y);
   
    //see if the detail property of object is an image, since not pillars and background buildings dont need facade details on them
    if (this.detail != -1){
    //add details on building facade
    push();
    translate(centerX, centerY);
    image(this.detail, 0, 0, 0.8*this.w, 0.95*(height-this.y));
    pop();
    }
   
}

//update building position
function buildingMove(s){
    this.x -= s;
}

//displaying vehicles
function vehicleDisplay(){
    push();
    //flip the image if going from right to left
    if(this.s < 0){
        scale(-1, 1);
        image(this.detail, -this.x, this.y);
    }
    else{
        image(this.detail, this.x, this.y);
    } 
    pop();
}

//update vehicles position and age
function vehicleMove(){
    this.x += this.s;
    this.age += 1;
}




function updateArray(){
    //replacing foreground buildings outside canvas
     for(var i = 0; i < bldg.length; i++){
        if (bldg[i].x <= -bldg[i].w){
            var palatteIndex = floor(random(palatte.length));
            var facadeIndex = floor(random(facadeImg.length));
            var b = building(400, random(-height/3, height/3), random(80, 100), color(palatte[palatteIndex]), facadeImg[facadeIndex]);
            bldg[i] = b;
             
        }
    }

    //replacing background buildings outside canvas
    for(var i = 0; i < bldgBack.length; i++){
        if (bldgBack[i].x <= -bldgBack[i].w){
            var b = building(400, random(150), 40, color(20, 10, 30, 0.5), -1);
            bldgBack[i] = b;
        }
     }

    //replacing pillars outside canvas
    for(var i = 0; i < pillar.length; i++){
        if (pillar[i].x <= -pillar[i].w){
            var p = building(400, 70, 20, color(80), -1);
            pillar[i] = p;
        }
     }

     //replacing vehicles after a certain time
     for(var i = 0; i < vhc.length; i++){
        
        if (vhc[i].age > 200){
            var vehicleIndex = floor(random(vehicleImg.length));
            if (random(1) <= 0.5){
                var v = vehicle(random(-width/2, 0), random(50, 150), random(5, 10), vehicleImg[vehicleIndex]);
            }
            else{
                var v = vehicle(random(width, 1.5*width), random(50, 150), random(-5, -10), vehicleImg[vehicleIndex]);
            }
            vhc[i] = v;
        }
    }

}


//create building objects
function building(buildingX, buildingY, buildingWidth, buildingColor, buildingDetail) {
    var b = {   x: buildingX,
                y: buildingY,
                w: buildingWidth,
                color: buildingColor,
                detail: buildingDetail,
                display: buildingDisplay,
                move: buildingMove
    }
    return b;
}

//create vehicle objects
function vehicle(vehicleX, vehicleY, vehicleSpeed, vehicleDetail) {
    var v = {   x: vehicleX,
                y: vehicleY,
                s: vehicleSpeed,
                age: 0,
                detail: vehicleDetail,
                display: vehicleDisplay,
                move: vehicleMove
    }
    return v;

}




Social impacts of NFT

The reading discusses NFT (Non-fungible tokens) and how it impacts digital artists and collectors. NFT adds authenticity to digital artwork like images, music, or videos, and it helps protect the artwork’s ownership to prevent people from stealing the artwork online through screenshots. The author embraces this new trend in the digital art market because it “economically legitimizes an emerging artform.”

Andrew Benson, Active Gestures 10. Sold for: $3,049

The reading mentions an artist called Andre Benson, who had been experimenting with digital video works for years but had not received any financial rewards. He had to work in a software company to support his career as an artist. However, after selling his work through NFT, he could sustain himself solely through art, which liberated him from doing tedious but necessary jobs.

Despite its benefit to artists and collectors, NFT has its setbacks. Like bitcoins, NFT relies on blockchain technology to add uniqueness to each artwork, which relies on a tremendous amount of computing power that is not environmentally friendly. Moreover, it does not legally prevent people from stealing artwork; it merely protects the metadata of the artwork rather than the work itself. Therefore, NFT is not the prime solution to add ownership to artwork.

Space battle

The spaceship engages in fights with enemies by using energy machine guns and lasers. The most challenging part actually comes in making all the visuals work correctly.

Four characters/sounds:

  • Firing spaceship
  • Explosion
  • Charge laser
  • Shoot laser

Space battle

//Jason Jiang
//Section E

///Storyline: The spaceship engages fights with enemies through using energy machine gun and laser.

//setting up variables for stars
var star = [];
var N = 10; //number of starts
var dx = 10; //speed of star
var w = 600; //x location of enemy
var dShip = 10; //speed of enemy
var a = 0;//scale of laser beam
var imgX = 120;//x location of ship
var imgY = 100;//y location of ship
var angle = 0;//angle of ship
var laserCharged = false; //whether laser is charged
var laserFired = false; //whether laser is fired
var enemyDestroyed = false; //whether enemy is destroyed


//defining assets
var machineGun;
var explosion1;
var explosion2;
var explosion3;
var laserEnergy;
var laserBeam;
var flyEngine;
var machineGun;
var explosion;
var charge;
var laser;

//add assets
function preload(){
    spaceShip = loadImage("https://i.imgur.com/D1QDG4A.png");
    spaceShipFire = loadImage("https://i.imgur.com/h8bQMXa.png");
    enemy1 = loadImage("https://i.imgur.com/OE8l2tK.png");
    explosion1 = loadImage("https://i.imgur.com/c9tLLTo.png");
    explosion2 = loadImage("https://i.imgur.com/kLTBXIa.png");
    explosion3 = loadImage("https://i.imgur.com/0zhmrzn.png");
    laserEnergy = loadImage("https://i.imgur.com/bmn9wZX.png");
    laserBeam = loadImage("https://i.imgur.com/ABposfH.png");
    machineGun = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/machineGun.mp3");
    explosion = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/explosion.wav");
    charge = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/charge.wav")
    laser = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/laser.wav")
}

// setup for audio generation
function soundSetup() { 
    machineGun.setVolume(0.1);
    explosion.setVolume(0.1);
    charge.setVolume(0.2);
    laser.setVolume(0.1);
}

//Create galaxy background
function updateStar(){
    this.x -= dx;
}

function createStar(){
    strokeWeight(3);
    stroke(255);
    point(this.x, this.y);
}

function generateStar(sx, sy){
   for (var i=0; i<N; i++){
        var s = {
            x: sx, y: sy,
            stepFunction: updateStar,
            drawFunction: createStar
        }

    }
    return s;
} 

function setup() {
    createCanvas(400, 200);
    frameRate(10);
    imageMode(CENTER);
    for (var i=0; i<N; i++){
        var s = generateStar(random(width), random(height))
        star.push(s);
 }
     useSound();
}


function draw() {
    background(0);
    //setting up sequence for charging laser and firing laser
    if (a >= 1){
            if(laserCharged == false){
                laserCharged = true
                a = 0
                charge.stop()
                laser.play();
            }
            else if(laserCharged == true & laserFired == false){
                laserFired = true
                a = 0
                laser.pause();
            }
        }
    //resetting enemy position if destroyed  
    if (enemyDestroyed == true){
            w = 600;
        }

   //Update star
    for (var i=0; i<N; i++){
        var s = star[i]
        s.stepFunction();
        s.drawFunction();
        //Remove star that is out of bounds
        if (s.x < 0) {
            var s = generateStar(random(width+5, width+500), random(height))
            star.splice(i, 1, s);
        }
   
    }
    
    //flying spaceship
    if (frameCount >= 0 & frameCount < 30) { 
        flyinSpace(imgX, imgY, 0); 
    }
    
    //killing enemy
    if (frameCount >= 30 & frameCount < 60) { 
        
        //play ship firing sound
        if (w == 600){
            machineGun.loop();  
        }
        
            //ship firing
            shipFiring(w);
            //enemy Ship approaching
            enemyShip(w, height/2);
            w -= dShip; 
       
    
        }
    
    if (frameCount >= 60 & frameCount < 70) { 
        //stop firing
        flyinSpace(imgX, imgY, 0);
        //play explosion sound when the enemy is close
        if(frameCount == 60){
            machineGun.stop();
            explosion.play()
        }
            explode(w, height/2, 60);
        }
    
    if (frameCount >= 70 & frameCount < 110) { 
        //setting up next enemy
        enemyDestroyed = false;
        if(frameCount == 70){
            charge.loop();
        }

        //dodge laser 
        if(dist(imgX, imgY, 120, 160)>0 & laserCharged == true){
        flyinSpace(imgX, imgY, 0);
        imgY += dShip;  
        }
        else{
            flyinSpace(imgX, imgY, 0);
        }

        //enemy Ship
            enemyShip(w, height/2);
            w -= 0.5*dShip;
        
        //charge laser
        if (laserCharged == false){
            laserCharge(w, height/2, a);
            a+=0.05;
        }
        //fire laser
        else if(laserCharged == true & laserFired == false){
            
            laserCharge(w, height/2, 1);
            laserFire(w, height/2, -a);
            a+=0.05;
        }
    
   
}
        
        if (frameCount >= 110 & frameCount < 140) {
            //preparing for next shot
            if (frameCount == 110){
              laserCharged = false;
              laserFired = false; 
              charge.loop();
            }

            //enemy Ship
            enemyShip(w, height/2);
            w -= 0.5*dShip;
            
            //ship fire laser
            //rotate ship
            if (angle>=-18){
                flyinSpace(imgX, imgY, angle);
                angle-=3;
            }
            //fire laser after rotation
            else{
                //charge laser
                flyinSpace(imgX, imgY, angle)
                if (laserCharged == false){
                    laserCharge(imgX, imgY, a);
                    a+=0.1;
                }
                //fire laser
                else if(laserCharged == true & laserFired == false){
                    
                    laserCharge(imgX, imgY, 1);
                    laserFire(imgX, imgY, a, angle);
                a+=0.1;
            }
             
        }
    }
        
        if (frameCount >= 140 & frameCount < 150) { 
        flyinSpace(imgX, imgY, angle);
        //play explosion sound when the enemy is close
            if(frameCount == 140){
                explosion.play();
            }
            explode(w, height/2, 140);
        }

        if (frameCount >= 150){
            background(0);
            noLoop();
        }
}

//adding spaceship
function flyinSpace(x, y, a){
        push()
        translate(x, y);
        rotate(radians(a));
        image(spaceShip, 0, 0);
        pop()
        
}

function shipFiring(w){
        //ship firing
        if(w%20 == 0){
            image(spaceShipFire, 120, height/2);
        }
        else{
            image(spaceShip, 120, height/2);
        }
    }

function enemyShip(w, h){ 
        //enemy ship flying
            image(enemy1, w, h);
        }

function explode(w, h, f){
        //create explosion when the enemy is close
                image(explosion1, w, h);
                if(frameCount-f >= 3){
                    image(explosion2, w, h);
                }
                if(frameCount-f >= 6){
                    image(explosion3, w, h);
                    enemyDestroyed = true;
                }
        
        }

//adding laser charge
function laserCharge(x, y, a){
        push()
        translate(x, y);
        scale(a);
        image(laserEnergy, 0, 0);
        pop()

}

//adding laser beam
function laserFire(x, y, a, angle){
        push()
        translate(x, y);
        rotate(radians(angle));
        scale(-a, 1);
        image(laserBeam, -211, -0.5);
        pop()

}


Computational self-portrait

This is my self-portrait. I try to use parabola lines instead of points to draw my image. The shape of lines is varied by adding an acceleration variable to change dx and dy. The portrait is looped and redrawn every 500 lines.

//Jason Jiang
//Section E
//Setting up variables
var np = 0;
var particleSetup = [];
var myProtrait
function preload(){
    myProtrait = loadImage("https://i.imgur.com/huB83xd.jpg");
}

//Updating properties of particles each step
function particleStep(){
    //Getting pixel color of the location of each particle on the image
    this.c = myProtrait.get(this.x, this.y);
    
    //Adding acceleration to create parabola curve
    this.dx += this.ax;
    this.dy += this.ay;
    
    //Updating x,y locations of particles
    this.x += this.dx;
    this.y += this.dy;
    
    //Updating x,y locations of particles in next step
    this.x1 = this.x + this.dx;
    this.y1 = this.y + this.dy;
    
}

//Drawing lines between two particles
function particleDraw(){
    stroke(this.c);
    strokeWeight(this.s);
    line(this.x, this.y, this.x1, this.y1);
    
}

//Creating particles
function particle(px, py, pdx, pdy, pax, pay, pc, px1, py1, ps){
    var p = {
        x: px, 
        y: py, 
        dx: pdx, 
        dy: pdy, 
        ax: pax, 
        ay: pay, 
        c: pc, 
        x1: px1, 
        y1: py1, 
        s: ps,
        stepfunction: particleStep, 
        drawfunction: particleDraw
        }
    return p; 
}

function setup(){
    createCanvas(400, 400);
    }    


function draw(){
    //Constraining number of particles
    if (np < 500){
        //Creating objects and adding them into array
        c = color(random(255), random(255), random(255))
        var p = particle(random(width), random(height), random(5), random(10), random(0.5, -0.5), random(0.5, -0.5), c, 0, 0, random(1,8));
        particleSetup.push(p);
        np+=1
    }

    //Resetting canvas if num of particles exceeds 500
    if (np == 500){
        background(255);
        np = 0;
        particleSetup = [];
    }

    //Running particles
    for(i = 0; i < np; i++){
        var p = particleSetup[i];
        p.stepfunction();
        p.drawfunction();
    }
   
    }

Computational representation of history

As a pioneer in 3D animation and VR/AR simulation, Claudia focuses on adapting virtual simulations to historical subjects. She studied art and architectural history at NYU and Columbia University and now works in New York. Being a feminist artist, her work has huge historical references where she subverts canonical male rulers into something more fantastical with digital technology.

Claudia’s multi-media exhibition, The Dolls House

As a student majoring in architecture, I am interested in the representation of buildings and how it changes their expressions. Her project, THE DOLLS HOUSE, showcases historical empire buildings like The Arch of Labna and the Roman Forum of Caesar being thrown away like toys inside a giant warehouse. She also adds a rotating light source that casts shadows on those buildings, simulating the idea of sunrise and sunset, which showcases the passage of time and the decay of nations. What draws me most is her play with algorithmic flickering patterns on walls filled with symbols of decayed nations and also logos of multinational companies, hinting that nothing could last forever. The result looks surreal and hypnotic, but at the same time refreshing and enlightening, which encourages the audience to contemplate on time.

Food as data

Stefaner’s lecture

Moritz Stefaner is a data visualizer focusing on UI design. He aims to create unique data representations to raise people’s awareness of problems and encourage them to develop solutions. In the lecture, he mentioned the concept of a hyperobject, an entity that challenges people’s traditional way of thinking. A dataset could similarly be viewed differently from not just pie charts or bar charts. For example, a heat map is not the only option to show a range of temperatures. This revolutionary mindset makes me interested in his work that reflects hyperobject.

Using different chocolate fills to show different death cases

To achieve this, he tried to make the data more tangible and experiential. One of his projects involved using food as a tool to represent data. The information was revealed through the recipe, the layout, and the flavor, which was a more effective way to understand the data. One of the dishes was a series of coffins made of chocolate with different fills inside. Each fill represented a cause of death. It humorously referred to the line, “Life is a bottle of chocolate; you never know what you get.”. I never realized that taste could reflect data. In my work, I will try to break the conventions of traditional representation and link the data to something unexpected but exciting.

Rhythm of food

The project I choose is about visualizing several food searches on the Internet. The designer Moritz Stefaner investigates how people change preferences for particular food over months and years and how it creates a rhythm to showcase the seasonality of food queries. I love how they investigate this topic from many aspects, such as among different countries, different food, or different time.

Stefaner also puts a lot of effort into visualizing how food queries change monthly and yearly. He designed a circle with bars surrounding it clockwise to show different months. Each bar represents the number of times a keyword is searched. After that, he overlayed bars on one another with different colors across different years. Furthermore, he creates an animation to visualize the process more clearly. The rigidity in the structure of the data and clarity in its presentation makes me admire his effort.

Visualizing change in food searches

Finally, Stefaner also provides clues to help the audience understand patterns in data. For example, in months with holidays like Halloween and Christmas. He puts a marker on that day in the graph to show how the frequency of food searches might change around that day.

Curve

This is my curve project. I am using mouseX to control the rotation, scale, and color of curves while using mouseY to control the number of iterations. Also, when you click, the curve changes. I really like how Hypocychoid and Epitrochoid are constructed and how different iterations of them overlap one another.

Different iterations for Hypocychoid

Hypocycloid

//Jason Jiang
//Section E

//Setting up variables
var nPts = 200;
var a = 80;
var N;
var b
var x;
var y;
var crvMode = 1;


function setup() {
    createCanvas(400, 400);
    frameRate(10)
    colorMode(HSB);
    }
    


function draw() { 
    //Mapping mouseY value to number of iterations
    N = map(mouseY, 0, height, 0, 25);
    b = a/N;
    background(0);

    //Draw Hypocychoid
    if (crvMode%2 == 0) {
    for(var i = 3; i <= N; i++) {
        //Decreasing strokeWeight each iteration
        strokeWeight(2-i*0.05)

        //Changing color according to mouseX
        stroke(255-mouseX*0.1, 100-i, 200-i*5)
        crv1(i);
        stroke(255-mouseX*0.1, 100-i, 100-i*5)
        crv1(PI+i);
    }
}   
    //Draw Epitrochoid
    else {
        for(var i = 3; i <= N; i++){ 
            //Decreasing strokeWeight each iteration
            strokeWeight(2-i*0.05)
        
            //Changing color according to mouseX
            stroke(mouseX*0.1, 100-i, 200-i*5)
            crv2(i);
            stroke(mouseX*0.1, 100-i, 100-i*5)
            crv2(PI+i);
        }
    }
}

//Hypocychoid
function crv1(m) {
    //Changing scale and rotation according to mouseX
    h = map(mouseX, 0, width, 1, 2, true)*m*0.05;
    angle = map(mouseX, 0, width, 0, PI);
   
    push()
    translate(width/2, height/2);
    
    //Rotate curve according to mouseX
    rotate(angle + m);

    //Drawing curves
    noFill();
    beginShape()
    
        for(var i = 0; i < nPts; i++){
            var t1 = map(i, 0, nPts, 0, TWO_PI)
            var t2 = t1*(a-b)/b
            x = h*((a-b)*cos(t1)+b*cos(t2))
            y = h*((a-b)*sin(t1)-b*sin(t2))

            //Adding random movement to the curve
            vertex(random(x+4, x-4), random(y+4, y-4));
        }
    endShape(CLOSE);
    pop();
}

//Epitrochoid
function crv2(m) {
    //Changing scale and rotation according to mouseX
    h = map(mouseX, 0, width, 1, 2, true)*m*0.05;
    angle = map(mouseX, 0, width, 0, TWO_PI);
    
    push()
    translate(width/2, height/2);

    //Rotate curve according to mouseX
    rotate(angle + m);

    //Drawing curves
    noFill();
    beginShape()

        for(var i = 0; i < nPts; i++){
            var t1 = map(i, 0, nPts, 0, TWO_PI)
            var t2 = t1*(a-b)/b
            x = h*((a-b)*cos(t1)+b*sin(t2))
            y = h*((a-b)*sin(t1)-b*cos(t2))
            vertex(x, y);
        }
    endShape(CLOSE)
    pop();
}

//Change curves when press mouse
function mousePressed(){
   crvMode++
   print(crvMode);
}
    

Generated 3D Scene

I am interested in David Mignot’s work in using python codes to generate a series of objects in Blender. The randomness is expressed through the random function to vary the type, height, and material of objects. Each time the function creates a different rendered scene that would take days to model by hand. David expressed his artistic sensibilities in attempting to control the randomness of variables so that the final result looks harmonic. It showcases how randomness needs to be controlled in computational art so that the generated work still looks “designed” rather than messy and purely random.

Generated scenes by David using inbuilt python codes in Blender

The work intrigues me in terms of creating generative art in 3d forms. Typically, Blender is used for 3d modeling individual objects for the CG industry. However, David opened up a new possibility in utilizing randomness to generate 3d scenes by coding, which might be a helpful method to create large repetitive scenes quickly.