Project 11: Generative Landscape

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

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

sketch
//Anthony Pan
//Section C

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

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

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

var road2;
var road2showing = [];

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

//car2 object
var car2;

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

//frame counter
var counter = 0;


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

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

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

    }

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

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

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

}


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

    //sun
    drawSun();

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


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

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

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

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

    

 
}


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

}

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

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

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

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

}

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

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

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

}

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



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

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

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

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

}

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

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

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

}

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

}




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

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

    return road2;
}

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

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

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

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

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

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

}



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

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

    return road1;
}


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

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

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

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

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

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

}

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

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

}


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


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

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

}

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


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



Looking Outwards – 11: Societal Impacts of Digital Art

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

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

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 11: Generative Landscape

generative landscape
var wood; // wooden table
var belt = []; // conveyer belt
var sushi = [];
var plate = [];
var sushiTypes = [];
var terrain = [];
var noiseParam = 0;
var noiseStep = 0.01;
var sky;
var clouds = [];

var sushiLinks = [
    "https://i.imgur.com/fm2adto.png",
    "https://i.imgur.com/Q2z9Ki8.png",
    "https://i.imgur.com/tUeehNx.png",
    "https://i.imgur.com/H2lTaNf.png",
    "https://i.imgur.com/t7TbPiI.png",
    "https://i.imgur.com/dNH5jvD.png",
    "https://i.imgur.com/YJ7h1Hl.png",
    "https://i.imgur.com/Hu1TVEI.png",
    "https://i.imgur.com/ZyAzhTq.png",
    "https://i.imgur.com/X8sFOwk.png",
    "https://i.imgur.com/t3pzPkC.png",
    ]

function preload() {
    wood = loadImage("https://i.imgur.com/5cpfZzh.png");
    belt = loadImage("https://i.imgur.com/s1SR1ru.png");
    sky = loadImage("https://i.imgur.com/qvwpqNr.png");
    
    for (var i = 0; i < 11; i ++) {
        var sushiImage;
        sushiImage = loadImage(sushiLinks[i]);
        sushiTypes.push(sushiImage);
    }
}

function setup() {
    createCanvas(450, 400);
    imageMode(CENTER);
    wood.resize(450, 0);
    belt.resize(450, 0);
    sky.resize(450, 0);

    // make collection of sushi
    for (var i = 0; i < 5; i++) {
        var sx = random(width);
        sushi[i] = makeSushi(sx);
    }

    // make background terrain
    for (var i = 0; i <= width; i ++) {
        var n = noise(noiseParam);
        var value = map(n, 0, 1, 0, height);
        terrain.push(value);
        noiseParam += noiseStep;
    }

    // make clouds
    for (var i = 0; i < 5; i ++) {
        var cloudx = random(width);
        var cloudy = random(height);
        clouds[i] = makeClouds(cloudx, cloudy);
    }

}


function draw() {
    image(sky, width/2, height/2);
    drawTerrain();
    image(wood, width/2, 250);
    image(belt, width/2, 250);

    updateAndDisplaySushi();
    removeSushiThatHaveSlippedOutOfView();
    addNewSushiWithSomeRandomProbability(); 

    updateAndDisplayClouds();
    removeCloudsThatHaveSlippedOutOfView();
    addNewCloudsWithSomeRandomProbability(); 
}

// all cloud related functions

function updateAndDisplayClouds() {
    for (var i = 0; i < clouds.length; i ++) {
        clouds[i].move();
        clouds[i].display();
    }
}

function removeCloudsThatHaveSlippedOutOfView() {
    var cloudsToKeep = [];
    for (var i = 0; i < clouds.length; i++){
        if (clouds[i].x + 60 > 0) {
            cloudsToKeep.push(clouds[i]);
        }
    }
    clouds = cloudsToKeep;
}

function addNewCloudsWithSomeRandomProbability() {
    var newCloudLikelihood = 0.01; 
    if (random(0,1) < newCloudLikelihood) {
        var newcloudX = random(width);
        var newcloudY = random(200);
        clouds.push(makeClouds(newcloudX, newcloudY));
    }
}

function makeClouds(CLOUDX, CLOUDY) {
    var c = {x: CLOUDX,
             y: CLOUDY,
             speed: -2,
             move: cloudMove,
             display: cloudDisplay}
    return c;
}

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

function cloudDisplay() {
    fill(255, 254, 246); // cream color
    noStroke();
    ellipse(this.x, this.y - 5, 60, 50);
    ellipse(this.x - 20, this.y + 10, 60, 50);
    ellipse(this.x + 15, this.y - 5, 70, 50);
    ellipse(this.x + 5, this.y + 20, 60, 50);
    ellipse(this.x + 30, this.y + 10, 80, 50);
}

// all terrain functions

function drawTerrain() {
    fill(73, 133, 115); 
    noStroke();
    beginShape();
    vertex(0, height);
    for (i = 0; i <= width/5 + 1; i += 1) {
        vertex(i*5, terrain[i]);
        vertex((i+1)*5, terrain[i+1]);
    }
    vertex(width, height);
    endShape();

    // make terrain continuous
    terrain.shift();
    var n = noise(noiseParam);
    var value = map(n, 0, 1, 0, height);
    terrain.push(value);
    noiseParam += noiseStep;

}

// all sushi related functions

function updateAndDisplaySushi() {
    for (var i = 0; i < sushi.length; i ++) {
        sushi[i].move();
        sushi[i].display();
    }
}

function removeSushiThatHaveSlippedOutOfView() {
    var sushiToKeep = [];
    for (var i = 0; i < sushi.length; i++){
        if (sushi[i].x + sushi[i].breadth > 0) {
            sushiToKeep.push(sushi[i]);
        }
    }
    sushi = sushiToKeep;
}

function addNewSushiWithSomeRandomProbability() {
    var newSushiLikelihood = 0.007; 
    if (random(0,1) < newSushiLikelihood) {
        sushi.push(makeSushi(450));
    }
}


function makeSushi(birthLocationX) {
    var s = {x: birthLocationX,
                breadth: 50,
                speed: -1,
                sushiType: random(sushiTypes),
                move: sushiMove,
                display: sushiDisplay}
    return s;
}


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

function sushiDisplay() {
    image(this.sushiType, this.x, 310, this.breadth+10, this.breadth);
}

For this project, I decided to create a sushi conveyer belt that’s located outdoors. I started off by drawing all the different types of sushi that’ll be randomized in the landscape. I also drew the conveyer belt and the wooden table. Then I implemented the background which is the sky with a randomized terrain/hill and clouds. I struggled a bit with creating an array of objects using images, so I couldn’t quite figure how to make the sushi not overlap each other. I also tried to create plates under the sushi, but I ended up removing them because they weren’t quite matching up with the sushi.

This is all the variations of the sushi:

LO 11: Societal Impacts of Digital Art

In the article, “Beeple’s digital ‘artwork’ sold for more than any painting by Titian or Raphael. But as art, it’s a great big zero.“, Sebastian Smee talks about a “major shake-up” in the art industry with latest revolt towards the NFT (Non-fungible Token), which is a unique digital item stored on a database technology called blockchains, allowing users to secure ownership of their digital works. As time goes by, art, in many forms, constantly evolves over time with several influences like advances in technology and society by instilling values and changing experiences throughout time. Especially today, technology has become a prevalent influence in our art world in the way people create and access art. For instance, many artists now use digital applications like Photoshop on computer and “paint” on their iPad canvas to generate art. Smee further criticizes how the artistic value of NFT has been replaced by generating monetary value from the market by mentioning graphic designer Beeple, who sold his digital product “Everydays: The First 5000 Days” for a crazy amount of $69.3 million. Although I am a fan of digital art collection, I totally understand Smee’s criticism towards Beeple’s work in comparison to the worth of past valuable traditional paintings sold in previous auctions. I think there should be some differentiations in terms of auction standards between traditional and digital work because they not only use different mediums, but also bring creative approaches as well as different value to art.  

Beeple’s digital artwork, “Everydays: The First 5000 Days,” which was sold for an insane amount of $69.3 million.

Reference: https://www.washingtonpost.com/entertainment/museums/beeple-digital-artwork-sale-perspective/2021/03/15/6afc1540-8369-11eb-81db-b02f0398f49a_story.html

Project 11

sketch
function setup() {
    createCanvas(400,400);
    // create an initial collection of buildings
    for (var i = 0; i < 4; i++){
        var cx = random(width);
        var cy = random(320,350)
        cars[i] = makeCar(cx,cy,color(random(255),random(255),random(255)),random(25,45));
    }
    for (var i = 0; i < 3; i++){
        var bx = random(width);
        var by = random(20,150)
        birds[i] = makeBird(bx,by,color(random(255),random(255),random(255)));
    }
    frameRate(10);
}
var cars = [];
var birds = [];
function draw() {
    push()
    fill(170,170,255)
    rect(0,0,400,270)
    fill(0,170,0)
    rect(0,270,400,130)
    drawRoad()
    drawSun()
    for (i=0; i<=50; i++){
        drawTree(i*50+20,260)  
    }
    updateAndDisplayCars();
    removeCarsThatHaveSlippedOutOfView();
    addNewCarsWithSomeRandomProbability();
    updateAndDisplayBirds(); 
    removeBirdsThatHaveSlippedOutOfView();
    addNewBirdsWithSomeRandomProbability();
}
function drawSun(){
    fill(255,200,0)
    ellipse(0,0,100,100)
}
function drawTree(x,y){
    fill(0,255,0)
    triangle(x,y,x-7,y+15,x+7,y+15)
    fill(50,30,0)
    rect(x-2,y+15,4,10)
}
function drawRoad(){
    fill(0)
    rect(0,300,400,60)
    fill(255,255,0)
    for (i = 0; i <= 10; i++){
        rect(50*i+15,325,20,5)
    }
}
function removeCarsThatHaveSlippedOutOfView(){
    var carsToKeep = [];
    for (var i = 0; i < cars.length; i++){
        if (cars[i].x > 0) {
            carsToKeep.push(cars[i]);
        }
        print(cars[i])
    }
    cars = carsToKeep; // remember the surviving cars

}
function updateAndDisplayCars(){
    // Update the cars's positions, and display them.
    for (var i = 0; i < cars.length; i++){
        cars[i].move();
        cars[i].display();
    }
}
function addNewCarsWithSomeRandomProbability() {
    // With a probability, add a new car to the end.
    var newCarLikelihood = 0.05; 
    if (random(0,1) < newCarLikelihood) {
        cars.push(makeCar(0,random(305,345),color(random(255),random(255),random(255)),random(25,45)));
    }
}

// method to update position of cars every frame
function carMove() {
    this.x += this.speed;
}
// draw the cars
function carDisplay() {
    push()
    fill(this.c)
    rect(this.x,this.y,this.l,10)
    rect(this.x+8,this.y-10,14,10)
    ellipse(this.x+11,this.y+8,10,10)
    ellipse(this.x+26,this.y+8,10,10)
    pop()
}
//make new car with different XY location, color, length, and speed
function makeCar(birthLocationX,birthLocationY,color,carLength) {
    var car = {x: birthLocationX,
                y: birthLocationY,
                c: color,
                l: carLength,
                speed: random(2,10),
                move: carMove,
                display: carDisplay}
    return car;
}
function removeBirdsThatHaveSlippedOutOfView(){
    var birdsToKeep = [];
    for (var i = 0; i < birds.length; i++){
        if (birds[i].x > 0) {
            birdsToKeep.push(birds[i]);
        }
        print(birds[i])
    }
    birds = birdsToKeep; // remember the surviving cars
}
function updateAndDisplayBirds(){
    // Update the cars's positions, and display them.
    for (var i = 0; i < birds.length; i++){
        birds[i].move();
        birds[i].display();
    }
}
function addNewBirdsWithSomeRandomProbability() {
    // With a probability, add a new bird to the end.
    var newBirdLikelihood = 0.05; 
    if (random(0,1) < newBirdLikelihood) {
        birds.push(makeBird(width,random(20,160),color(random(255),random(255),random(255))));
    }
}

// method to update position of birds every frame
function birdMove() {
    this.x -= this.speedX;
    this.y += this.speedY
}
// draw the birds
function birdDisplay() {
    push()
    fill(this.c)
    triangle(this.x,this.y,this.x+6,this.y+1.5,this.x+6,this.y-1.5)//beak
    ellipse(this.x+9,this.y,7,7) //head
    ellipse(this.x+17,this.y+4,15,8)//body
    arc(this.x+18, this.y, 10, 10, -0.7, PI-0.7,CHORD)//wings
    ellipse(this.x+8,this.y-1,1,1)//eyes
    pop()
}
//make new bird with different location, color, speedXY
function makeBird(birthLocationX,birthLocationY,color) {
    var bird = {x: birthLocationX,
                y: birthLocationY,
                c: color,
                speedX: random(5,8),
                speedY: random(-1.5,1.5),
                move: birdMove,
                display: birdDisplay}
    return bird;
}

For this project, I created 2 arrays of objects: cars and birds. Cars have random color, length, speedX, and y position on the road; birds have random color, y position in the sky, speedX, and speedY.

LO 11

Link of the article:https://ars.electronica.art/aeblog/en/2020/04/10/women-in-media-arts-ai/

The article I looked into is Women in Media Arts: Does AI think like a (white) man? The article addresses the issue that because an AI is designed by white men and tested by white men, when a woman goes in front of the AI, the AI cannot even recognize her. In response to this kind of issue and to increase the visibility of women working in media art, Women in Media Arts – a comprehensive database devoted specifically to women in media art – emerges. It intends to increase public consciousness and to focus on role models for girls and women.

Project 11: Generative Landscape

sketchDownload
// this program displays a landscape of a stone path along a stream in the woods.

// empty arrays for objects:
var bkgrndtrees = [];
var path = [];
var stream = [];
var trees = [];
var allArrays = [bkgrndtrees, path, stream, trees];

// speed of landscape shift, per frame
// adjusted for background+foreground so 'closer' objects move faster than 'far away' ones
var shift = -1;

function setup() {
    createCanvas(480, 300);
    background(80, 125, 60);
    frameRate(200);

    // create initial collections of objects:
    fillBkgrndtrees();
    fillPath();
    fillStream();
    fillTrees();

    // sort objects in arrays to be drawn properly:
    for (a=0; a<allArrays.length; a++) {
        if (allArrays[a]!=stream){          // stream should not be ordered
            orderObjects(allArrays[a]);
        }
    }
}

// fills backgroundTrees array with initial trees:
function fillBkgrndtrees() {
    for (var i = 0; i < 320; i++) {
        var rx = random(width+75);
        var ry = random(-height/25, 2*height/5);      // top of canvas = background
        bkgrndtrees[i] = makeTree(rx, ry);
    }
}

// fills foreground tree array with initial trees:
function fillTrees() {
    for (var i = 0; i < 5; i++) {
        var rx = random(width+75);
        var ry = random(4*height/5, 3*height/2);    // bottom of canvas = foreground
        trees[i] = makeTree(rx, ry);
    }
}

// fills path array with initial stones:
function fillPath() {
    for (var i = 0; i < 15; i++) {
        var size = random(width/25, width/10);
        var col = color(random(90, 120));
        var x = i*50;
        var ry = random(height/2, 3*height/5);
        path[i] = makeStone(x, ry, size, col);
    }
}

// fills stream array with objects based on stone path:
function fillStream() {
    for (var i = 0; i < path.length; i++) {
        var x = i*50;
        var y = path[i].y + path[i].size;
        stream[i] = makePoint(x, y);
    }
}

// creates a tree object
function makeTree(tx, ty) {
    // background trees:
    if (ty < height/2) {
        var tree = {x:tx,
                    y:ty,
                    age:random(2, 11),
                    trunkc: color(random(70, 90), random(55, 75), random(30, 55)),
                    leavesc: color(random(0, 75), random(65, 175), random(50)),
                    show: showTree,
                    move: moveObject,
                    speed: shift*.85 }
    }
    // foreground trees:
    else {
        var tree = {x:tx,
                    y:ty,
                    age:random(4, 7),
                    trunkc: color(random(50, 80), random(20, 50), random(10, 20)),
                    leavesc: color(random(0, 100), random(100, 200), random(30)),
                    show: showTree,
                    move: moveObject,
                    speed: shift*1.15 }
    }

    return tree;
}

// creates a stone object
function makeStone(sx, sy, ssize, scol) {
    var stone = {x:sx,
                 y:sy,
                 size:ssize,
                 c: scol,
                 show: showStone,
                 move: moveObject,
                 speed: shift}
    return stone;
}

// creates a point object (for stream curve);
function makePoint(px, py) {
    var pnt = {x:px,
               y:py,
               size:width/50,
               c: color(50, 125, 175),
               show: showStone,
               move: moveObject,
               speed: shift}
    return pnt;
}

function draw() {
    background(80, 125, 60);

    // draw all objects in all arrays:
    for (j=0; j<allArrays.length; j++) {
        thisArray = allArrays[j];
        drawObjects(thisArray);
        if (thisArray!=stream) {        // stream is updated with path
            // order and updates arrays:
            orderObjects(thisArray);
            updateArray(thisArray);
        }
    }
}

// draws and moves objects in an array
function drawObjects(array) {
    for (i=0; i<array.length; i++) {
        thisObj = array[i];
        thisObj.show();
        thisObj.move();
    }
    if (array==stream) {
        drawStream();
    }
}

// uses curve shape and array points ot draw stream
function drawStream() {
    push();
    noFill();
    stroke(50, 125, 175);
    strokeWeight(15);
    curveTightness(-.2);
    beginShape();
    curveVertex(stream[0].x, stream[0].y);
    curveVertex(stream[0].x, stream[0].y);
    for (var m=1; m<stream.length-1; m++){
        curveVertex(stream[m].x, stream[m].y);
    }
    curveVertex(stream[stream.length-1].x, stream[stream.length-1].y);
    endShape();
    pop();
}

// sorts objects in an array according to the y feild
// this ordering ensures accurate depth on canvas
function orderObjects(array) {
    for (var j=0; j<array.length-1; j++) {
        var counter = 0;
        for (var i=0; i<array.length-1; i++) {
            if (array[i].y > array[i+1].y) {
                var tmp = array[i];
                array[i] = array[i+1];
                array[i+1] = tmp;
                counter += 1;
            }
        }
        if (counter==0) {
            break;
        }
    }
}

// updates all allArrays
// adds new objects to end and deletes unused objects (off canvas)
function updateArray(array) {
    if (array==trees || array==bkgrndtrees) {
        // add new trees to array off-canvas:
        // background trees:
        var treeLikelihoodB = 320/555;
        if (random(1) < treeLikelihoodB) {
            var ry = random(-height/25, 2*height/5);    // top of canvas = background
            bkgrndtrees.push(makeTree(width+75, ry));
        }
        // foreground trees:
        var treeLikelihoodF = 5/555;
        if (random(1) < treeLikelihoodF) {
            var ry = random(3*height/4, 3*height/2);      // bottom of canvas = foreground
            trees.push(makeTree(width+75, ry));
        }
    }
    else {
        // path and stream use fixed x values:
        if (frameCount%50==0) {
            var size = random(width/25, width/10);
            var col = color(random(90, 120));
            var ry = random(height/2, 3*height/5);
            path.push(makeStone(700, ry, size, col));
            col = color(0, 50, 150);
                var y = ry + size;
            stream.push(makePoint(700, y));
        }
    }

    // remove any object no longer on canvas:
    var keep = [];
    for (var k=0; k<array.length; k++) {
        if (array[k].x > 0) {
            keep.push(array[k]);
        }
    }
    array = keep;
}

// draws tree based on age
function showTree() {
    if (this.y < height/2) {     // top of canvas = background
        var h = this.age*10;
        var w = this.age*2;
    }
    else {                      // bottom of canvas = foreground
        var h = this.age*12;
        var w = this.age*2.5;
    }
    var cx = this.x + w/2;
    var cy = this.y - h*1.5;

    if (this.age > 5) {             // older trees
        stroke(50, 40, 30);
        fill(this.trunkc);
        rect(this.x, this.y-h, w, h);
        fill(this.leavesc);
        for (var i=0; i<3; i++) {
            stroke(0, 75, 0);
            circle(cx - (this.age*4*i) + (this.age*4),
                   cy - (this.age*1.5) + (this.age*3*i),
                   this.age*5);
            circle(cx + (this.age*4*i) - (this.age*4),
                   cy - (this.age*1.5) + (this.age*3*i),
                   this.age*5);
            ellipse(cx - (this.age*6*i) + (this.age*6),
                    cy + this.age,
                    this.age*5,
                    this.age*6);
            ellipse(cx,
                    cy - (this.age*3) + (this.age*4*i),
                    this.age*7,
                    this.age*5);
        }
        noStroke();
        ellipse(cx, cy + this.age, this.age*12, this.age*9);
    }
    else {                          // younger trees
        stroke(50, 40, 30);
        fill(this.trunkc);   // tree trunk lighter brown
        rect(this.x, this.y-h, w/2, h);
        fill(this.leavesc);
        for (var i=0; i<3; i++) {
            stroke(0, 75, 0);
            circle(cx - (this.age*3*i) + (this.age*3),
                   cy - (this.age*1.5) + (this.age*2*i),
                   this.age*4);
            circle(cx + (this.age*3*i) - (this.age*3),
                   cy - (this.age*1.5) + (this.age*2*i),
                   this.age*4);
            ellipse(cx - (this.age*4*i) + (this.age*4),
                    cy + this.age,
                    this.age*4,
                    this.age*5);
            ellipse(cx,
                    cy - (this.age*4) + (this.age*4*i),
                    this.age*6,
                    this.age*4);
        }
        noStroke();
        ellipse(cx, cy + this.age/2, this.age*11, this.age*9);
    }
}

// draws stone for path
function showStone() {
    stroke(75);
    fill(this.c);
    ellipse(this.x, this.y, this.size, this.size/2);
}

// updates x values to move the landscape along
function moveObject() {
    this.x += this.speed;
}

For this project, I was inspired by a trail I used to walk a lot growing up. I struggled a bit to order the objects in a way that looks nice and is recognizable as a landscape, but I think the orderObjects() function that I created helped a lot with that. I also found it difficult to create the stream using a curve shape, but I am again really pleased with how well it came out. I wanted the path and stream to flow along together, and they do. To give more of a landscape effect, I adjusted the shift values for moving the objects so that things in the foreground move faster than things in the background.

My initial sketch of the stream in the woods.

Looking Outwards 11: Societal Impacts of Digital Art

The reading I chose for this blog post is ‘Women in Media Arts: Does AI think like a (white) man?’ The article focuses on female digital artists and feminism within the digital art realm. Through looking at a number of female-created art pieces and projects, the article discusses the ways in which AI and other creative practices shed light on the biases within creators and consumers. One project by Mary Flanagan entitled [“help me know the truth”] explores the way people reinforce their own biases based on others’ physical appearance. Other projects in this article were created with the purpose of combatting the obvious marginalization and discrimination that result from the lack of diversity among those creating digital tools. One example of this is facial recognition software which generally does not accurately recognize people of color. This is just one of the many ways human bias influences artificial intelligence, and there are very real and dangerous consequences that can arise if these types of creative habits are not broken (ex: medical equipment that is only accurate for white male patients).

article link

LO: Societal Impact of Digital Art

For this week’s blog, I read the article “How Artists Can Bridge the Digital Divide and Reimagine Humanity” by Agnes Chavez. The article talks about how art, technology, and science can become tools to increase digital literacy. Chavez categorized the digital divide into “first-level” and “second-level” and stated that solving the problem on both levels is essential. The “first-level” is having affordable access to information and devices; the “second-level” gives people the necessary knowledge to become digital content producers. The PASEO festival is an example that describes how art and technology can support learning and create a positive attitude towards digital media, which bridges the divide on the “second-level.” Later, the author also discussed creating shareable digital resources and implementing the STEMarts model to support access to digital content. The article outlined multiple methods to bridge the digital divide and highlighted the importance of digital technology in connecting people and communities across economic sectors, which I found inspiring.

Chavez, A., “how artists can bridge the digital divide and reimagine humanity”. “How Artists Can Bridge the Digital Divide and Reimagine Humanity”. Available at: https://www.arts.gov/impact/media-arts/arts-technology-scan/essays/how-artists-can-bridge-digital-divide-and-reimagine-humanity [Accessed November 12, 2021].