Project 11: Generative Landscape

wpf-landscape.js
//Patrick Fisher, Section B, wpf@andrew.cmu.edu Assignment -11-project
var trackLines = []; //array for converyer belt
var robots = []; //array for the robots

function setup() {
    createCanvas(480,300);
    background(219.219,211);
    for(var i = 0; i <= 9; i++){
        trackLines[i] = i*48; //fills the track array
    }

    for(var i = 0; i <= 5; i++){
        robots[i] = makeRobot(i); //fills the robot array
        robots[i].centerX = -50 + (i*-200);
    }
}

function draw(){
    push();
    stroke(0);
    strokeWeight(4);
    fill(54,54,66);
    rect(0,50,width,200);
    fill(28,150,195);
    rect(0,25,width,25);
    rect(0,250,width,25);
    stroke(0);
    strokeWeight(3); //draws the lines and moves them forward
    for(var i = 0; i <= 9; i++){
        line(trackLines[i],50,trackLines[i],250);
        trackLines[i] += 1;

        if(trackLines[i] >= width){ //sends a line back to the start when it gets to big
            trackLines[i] = 0;
        }
    }
    pop();

    for(var i = 0; i <= 5; i++){
        robots[i].draw(); //draws the robots
        

        robots[i].centerX ++; //sends the robots forward
        
        if(robots[i].centerX >= 800){ //deletes a robot from the array when it gets too far off screen and makes a new one
            robots.shift();
            robots.push(makeRobot(0));
            robots[5].centerX = -400
        }
    }
}

function makeRobot(i) {
    var rob = {centerX: 0, //funciton for making the robot
               head: floor(random(0,3)),
               eyes: floor(random(0,4)),
               glowColor: clrSelect(floor(random(0,6))), //sends a random number to the color select function to set the color variable
               mouth: floor(random(0,3)), //5
               chest: floor(random(0,2)),
               chestPiece: floor(random(0,3)), //8
               arms: floor(random(0,3)), //4
               legs: floor(random(0,3)), //3
               draw: drawRobot,
               drawHead: drawRobotHead,
               drawBody: drawRobotBody,
               drawEye: robotEyes,
               drawMouth: robotMouth,
               drawPiece: robotChestPiece,
               drawArms: robotArms,
               drawLegs: robotLegs,
           }
    return rob;

}

function drawRobot(){// draws the robot in fragments
    this.drawHead();
    this.drawBody();

}

function drawRobotHead(){
    fill(101,108,127);
    if(this.head == 0){
        circle(this.centerX,90,60);
    }
    if(this.head == 1){
        push();
        rectMode(CENTER);
        rect(this.centerX,90,60,60);
        pop();
    }
    if(this.head == 2){
        triangle(this.centerX,120,this.centerX-50,70,this.centerX+50,70);
    }

    this.drawEye();

    this.drawMouth();
    

}

function drawRobotBody(){
    fill(101,108,127);
    if(this.chest == 0){
        rect(this.centerX-25,120,50,75);
    }
    if(this.chest == 1){
        ellipse(this.centerX, 157.5,50,75);
    }
    
    this.drawPiece();

    this.drawArms();

    this.drawLegs();


}

function robotEyes() {
    push();
    fill(this.glowColor);
    if(this.eyes == 0){
        circle(this.centerX + 15,85,20);
        circle(this.centerX - 15,85,20);
    }

    if(this.eyes == 1){
        push();
        rectMode(CENTER);
        rect(this.centerX + 15, 85, 15, 15);
        rect(this.centerX - 15, 85, 15, 15);
        pop();

    }
    if(this.eyes == 2){
        push();
        stroke(this.glowColor);
        strokeWeight(3);
        line(this.centerX + 20, 80 , this.centerX + 5, 80);
        line(this.centerX - 20, 80 , this.centerX - 5, 80);
        pop()
    }

    if(this.eyes == 3){
        push();
        stroke(this.glowColor);
        strokeWeight(3);
        line(this.centerX + 15, 90 , this.centerX + 15, 75);
        line(this.centerX - 15, 90 , this.centerX - 15, 75);
        pop()
    }
    pop();
}

function robotMouth() {
    if(this.mouth == 0){
        push();
        stroke(this.glowColor);
        strokeWeight(4);
        noFill();
        arc(this.centerX, 100, 20, 20, 0, PI);
        pop();
    }

    if(this.mouth == 1){
        push();
        stroke(this.glowColor);
        strokeWeight(4);
        line(this.centerX + 10, 105, this.centerX -10, 105);
        pop();
    }
    if(this.mouth == 2){
        push();
        fill(this.glowColor);
        rect(this.centerX - 10, 101, 20, 8);
        line(this.centerX -10, 105, this.centerX + 10, 105);
        pop();

    }

}

function robotChestPiece() {
    if(this.chestPiece == 0){
        push();
        fill(this.glowColor);
        circle(this.centerX, 147,20);
        pop();
    }
    if(this.chestPiece == 1){
        push();
        fill(this.glowColor);
        rectMode(CENTER);
        rect(this.centerX, 147,20,20);
        pop();
    }
    if(this.chestPiece == 2){
        push();
        fill(this.glowColor);
        translate(this.centerX,147);
        rotate(radians(45));
        rectMode(CENTER);
        rect(0,0,20,20);
        pop();
    }

}

function robotArms(){
    if(this.arms == 0){
        push();
        stroke(0);
        strokeWeight(2);
        line(this.centerX + 25, 147, this.centerX + 50, 147);
        line(this.centerX - 25, 147, this.centerX - 50, 147);
        pop();
        circle(this.centerX - 55, 147, 10);
        circle(this.centerX + 55, 147, 10);

    }
    if(this.arms == 1){
        ellipse(this.centerX+37.5,147,25,10);
        ellipse(this.centerX-37.5,147,25,10);
    }
    if(this.arms == 2){
        push();
        rectMode(CENTER);
        square(this.centerX+35,147,20);
        square(this.centerX-35,147,20);
        pop();

    }
}

function robotLegs(){
    if(this.legs == 0){
        push()
        stroke(0);
        strokeWeight(2);
        line(this.centerX + 20, 195, this.centerX + 20, 225);
        line(this.centerX - 20, 195, this.centerX - 20, 225);
        pop();
        circle(this.centerX + 20, 230, 10);
        circle(this.centerX - 20, 230, 10);

    }
    if(this.legs == 1){
        ellipse(this.centerX - 15, 215, 10,40);
        ellipse(this.centerX + 15, 215, 10,40);
    }
    if(this.legs == 2){
        triangle(this.centerX-15, 197.5, this.centerX - 10, 235, this.centerX - 20, 235);
        triangle(this.centerX+15, 197.5, this.centerX +10, 235, this.centerX + 20, 235);
    }
}

function clrSelect(i){
    if(i == 0){
        var c = color(128,196,99); //green
    }
    if(i == 1){
        var c = color(182,20,29); //red
    }
    if(i == 2){
        var c = color(10,201,239); //blue
    }
    if(i == 3){
        var c = color(217,16,207); //purple
    }
    if(i == 4){
        var c = color(248,241,25); //yellow
    }
    if(i == 5){
        var c = color(244,239,221); //off white
    }

    return c;

}

For my project, I did a robot factory line, with all the different parts of the robots changing. I started with getting the conveyor belt to look correct. Then I worked on making one look for the robot and getting it to loop continuously. Afterward, I started to separate the body parts into distinct functions and then implements the if statements to draw different types of body parts. I am very happy with how it worked out, I think the robots look kind of cute and I am happy with how seamless the loop is. I also think I have a good amount of variety so the robots do not get immediately boing.

Looking Outwards-11

The article I read discusses the digital divide. The digital divide is the phenomenon of poorer people and areas having less access to functional computers, smart phones, or internet, all devices that are becoming more and more needed in the modern education and work worlds. This has been especially relevant during the Covid-19 pandemic, considering how many people were working or attending school from home, those without internet or an internet capable device were severely impacted. This article discusses an exhibition at a museum in Barcelona. The exhibition focuses not only on the digital divide, but also how it can disproportionately affect women and ethnic minorities. As the world continues to become more reliant on digital access, the worse the affects of the digital divide will become.

https://www.reuters.com/article/us-health-coronavirus-tech/spanish-art-show-spotlights-hidden-digital-divide-in-pandemic-idUSKBN28S0IC

Project 11: Generative Landscape

As winter approaches, I wanted create a landscape that resembles the cold weather and loneliness of the season. That’s why I decided to keep a greyscale color scheme.

sketch
// Christy Zo
// andrew id: czo
// Section C

var hill = [];
var hill2 = [];
var noiseParam = 0;
var noiseStep = 0.05;
var noiseParam2 = 0;
var noiseStep2 = 0.05

var snowflakePerLayer = 200;
var maxSize = 3;
var gravity = 0.75;
var layerCount = 5;
var snowflakes = [];

var walkImage = [];
var newCharacter = [];
var airplane;
var newPlane = [];

var buildings = [];



function preload() {
    var filenames = [];
    filenames[0] = "https://i.imgur.com/Uz3ltZC.png";
    filenames[1] = "https://i.imgur.com/ofNc4Wv.png";
    filenames[2] = "https://i.imgur.com/7hMA7W6.png";
    filenames[3] = "https://i.imgur.com/3RBTODb.png";
    filenames[4] = "https://i.imgur.com/FliwTsj.png";

    for (var i = 0; i < filenames.length; i++) {
        walkImage[i] = loadImage(filenames[i]);
    }
    airplane = loadImage("https://i.imgur.com/dbPwlhp.png");
}

//airplane 
function makePlane(px, pdx, py, pdy) {
    var p = {x: px, dx: pdx, y:py, dy: pdy,
            stepFunction: stepPlane,
            drawFunction: drawPlane
        }
    return p;
}

function stepPlane() {
    this.x += this.dx;
    this.y += this.dy;

    if (this.x > 480) {
        this.x = 0;
        this.y = 100;
    }
}

function drawPlane() {
    image(airplane, this.x, this.y, 20, 20);
}

//person
function makeCharacter(cx, cdx) {
    var c = {x: cx, dx: cdx,
             // walkingRight: true, 
             imageNum: 0,
             stepFunction: stepCharacter,
             drawFunction: drawCharacter
         }
    return c;
}

function stepCharacter() {
    this.x += this.dx;
    this.imageNum += 1;
    
    if (this.imageNum == 4 ) {
        this.imageNum = 0;
    }

    if (this.x >= 680) { 
        this.x = 200;
    } 
}

function drawCharacter() {
    image(walkImage[this.imageNum], this.x, 430);
    
}

//snowflake update
function updateSnowflake(snowflake) {
    var diameter = (snowflake.l * maxSize) / layerCount;
    if (snowflake.y > height + diameter) {
        snowflake.y = -diameter;
    } else {
        snowflake.y += gravity * snowflake.l * snowflake.mass;
    }
}

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

function removeBuildingsThatHaveSlippedOutOfView(){
    var buildingsToKeep = [];
    for (var i = 0; i < buildings.length; i++){
        if (buildings[i].x + buildings[i].breadth > 0) {
            buildingsToKeep.push(buildings[i]);
        }
    }
    buildings = buildingsToKeep; // remember the surviving buildings
}

function addNewBuildingsWithSomeRandomProbability() {
    // With a very tiny probability, add a new building to the end.
    var newBuildingLikelihood = 0.007; 
    if (random(0,1) < newBuildingLikelihood) {
        buildings.push(makeBuilding(width));
    }
}

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

// draw the building and some windows
function buildingDisplay() {
    var floorHeight = 20;
    var bHeight = this.nFloors * floorHeight; 
    fill(255); 
    noStroke; 
    push();
    translate(this.x, height - 40);
    rect(0, -bHeight, this.breadth, bHeight);
    stroke(200); 
    fill(200);
    for (var i = 0; i < this.nFloors; i++) {
        rect(5, -15 - (i * floorHeight), this.breadth - 10, 10);
    }
    pop();
}

function makeBuilding(birthLocationX) {
    var bldg = {x: birthLocationX,
                breadth: 50,
                speed: -1.0,
                nFloors: round(random(2,8)),
                move: buildingMove,
                display: buildingDisplay}
    return bldg;
}


function setup() {
    createCanvas(480, 480);
    noStroke();
    frameRate(20);
    for (i=0; i<width/5+1; i++) {
        var n = noise(noiseParam);
        var value = map(n, 0, 1, 100, height);
        
        hill.push(value);
        noiseParam += noiseStep;

    }


// snowflakes
    for (let l = 0; l < layerCount; l++) {
        snowflakes.push([]);
        for (let i = 0; i < snowflakePerLayer; i++) {
            snowflakes[l].push({
            x: random(width),
            y: random(height),
            mass: random(0.75, 1.25),
            l: l + 1
            });
        }
    }
    for (var i = 0; i < 10; i++){
        var rx = random(width);
        buildings[i] = makeBuilding(rx);
    }

    imageMode(CENTER);

    var d = makeCharacter(50, 1);
    newCharacter.push(d);

    var p = makePlane(10, 5, 100, -1);
    newPlane.push(p);
    
}

function draw() {
    background(0);

    for (let l = 0; l < snowflakes.length; l++) {
        var layer = snowflakes[l];

        for (let i = 0; i < layer.length; i++) {
            var snowflake = layer[i];
            fill(255);
            circle(snowflake.x, snowflake.y, (snowflake.l * maxSize) / layerCount);
            updateSnowflake(snowflake);
        }
    }

    beginShape();
        vertex(0, height);
        for (i=0; i<width/5+1; i++) {
            noStroke();
            fill(200);
            vertex(i*5, hill[i]);
 

        }
        vertex(width, height);
        endShape();

        var n = noise(noiseParam);
        var value = map(n, 0, 1, 100, height);
        hill.shift();
        // append(hill, value);
        hill.push(value);
        noiseParam += noiseStep;
    fill(150);
    rect(0, 430, width, height);


    updateAndDisplayBuildings();
    removeBuildingsThatHaveSlippedOutOfView();
    addNewBuildingsWithSomeRandomProbability(); 


    newCharacter[0].stepFunction();
    newCharacter[0].drawFunction();

    newPlane[0].stepFunction();
    newPlane[0].drawFunction();
    // image(walkImage[1], 100,100);

}

*Due to the way I saved my png drawing of the person, you have to wait a little long for the person to appear!*

After I created this work, I realized that the mountain behind moves significantly faster than everything else, making it look like this space is not on earth. Maybe this could be what winter looks like in a different planet.

2. Looking Outwards 11: Societal Impacts of Digital Art

As technology develops, the definition of art and its value keeps evolving. The idea of craftsmanship and delicate human effort is now replaced by manufacturers and computer technology that can create similar feature within seconds with lines of codes. When I read Sebastian Smee’s criticism on Beeple’s artwork, I could understand why he was so critical of the digital artwork being valued more than Michelangelo’s. But I think that there should be different standards for work that is digitally produced and physically produced. I think they carry different values—for example, digital work can be a sign for newly developed technology and testing out their uses in creative ways, even if they don’t have the delicacy and the conetextual depth of traditional art.

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

Women in AI: LO-11

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

I started off this week reading about women in media arts. The first video included on Gender Shades, I did not, sadly, get surprised by the context. What did surprise me however, was how the computer system was so wrong on identifying females of darker color; one as a person at all, and secondly, not even being able to identify their genders correctly. The digital world needs to grow to be neutral and inclusive, and if in testing there is a gap between recognizing people of gender and race, there is a problem. The computation itself is biased, but not by the machine by the programmers. I feel that sometimes testing can be overlooked when it seems to be working fine on individuals, but this is a flaw we see commonly not just in AI but in Women’s healthcare.

For the Women reclaiming AI videos I found the idea of the voice speaking system, that was similar to Alexa to be particularly interesting. I wonder where that could go if those types of questions could be asked by younger girls. Questions about womanhood that could be answered when they need help or clarification, I think, could be pretty revolutionary. I have never tried to ask my Alexa any of those types of questions, but I wonder how current AI on the market would answer. I never really considered how AI might be biased with speaking technology, but I could imagine that if anything, it probably holds the most bias.

 In the European Platform video I also thought it was interesting to consider how AI is imagined with blue, which is a very masculine color and how women can find themselves in that space. Something that I ran across recently when concerning women in coding was hearing about Margaret Hamilton and getting men on the moon. I feel that there is a lot of gender bias in her story and people refused to listen to her and asked her why she was even at NASA, when her programming helped get the astronauts home. She was very overlooked for her astounding work and I don’t think many people ever come across her name.

Generative Landscape

sketchDownload
var cld = [];
var shl = [];

function setup() {
    createCanvas(480, 320);
    background(200);
    noStroke();
}

function draw() {
    //static background
    fill(57, 16, 115);
    rect(0, 0, 480, 40);
    fill(129, 21, 150);
    rect(0, 40, 480, 40);
    fill(189, 28, 119);
    rect(0, 80, 480, 40);
    fill(224, 47, 31);
    rect(0, 120, 480, 40);
    fill(230, 107, 50);
    rect(0, 160, 480, 40);
    fill(255, 185, 64);
    circle(240, 200, 60);
    fill(179, 161, 91);
    rect(0, 200, 480, 120);

    //cloud code
    if(random() > 0.95) cld.push(makeCloud((random()*120), color(random()*30+220, 220, random()*30+220))); //chance to draw new cloud
    for(let i = 0; i < cld.length; i++) { //draws and updates clouds
      cld[i].drawCloud();
      cld[i].moveCloud();
    }
    if(cld[0].x > 480) cld.shift(); //removes clouds that move too far

    //shell code
    if(random() > 0.85) shl.push(makeShell(random()*200+120, color(random()*255, random()*255, random()*255), random()*3)); //chacne to draw new drawShell
    for(let i = 0; i < shl.length; i++) { //draws and updates shells
      shl[i].drawShell();
      shl[i].moveShell();
    }
    if(shl[0].x > 480) shl.shift(); //removes shells that move too far
}

function makeCloud(ty, tc) {
    var cloud = {x: 0, y: ty, c: tc};
    return cloud;
}

function drawCloud() {
    fill(this.c);
    ellipse(this.x, this.y, 40, 20);
}

function moveCloud() {
    this.x += 10;
}

function makeShell(ty, tc, ts) {
    var shell = {x: 0, y: ty, c: tc, s: ts}
    return shell;
}

function drawShell() {
    fill(this.c);
    if(this.s < 1) circle(this.x, this.y, 20);
    else if(this.s < 2) square(this.x, this.y, 20);
    else triangle(this.x, this.y, this.x+10, this.y+20, this.x+20, this.y);
}

function moveShell() {
    this.x += 10;
}

This isn’t running correctly right now and I can’t figure out why ?-?

I made a sunset landscape because I thought I could incorporate some really cool colors into the background. First I coded the hard landscape. Since the sun is so far away, it will look like it isn’t moving. Next I created very simple clouds. To create randomness and variety in my landscape the clouds have a randomized color and height. I created a method that updated their x position so that they’d look like they were “moving” across the screen. After that I made shells. I followed a similar procedure, but I also added shape as a random variable. Having different shaped/colored shells in different locations helps make the landscape more exciting. I wish the code was displayed properly so you could see the final product 🙁

LO: NFTs

I read the Plagiarism Today article which discussed how copyright relates to NFTs. I really like the example used in the article that equates NFTs to limited edition posters. Having an NFT doesn’t mean no one else will have that art, and it doesn’t give the owner permission to use it for everything. An issue right now is that some people are selling art that they don’t have a copyright for. Should this be allowed? NFTs can be a cool source of revenue for artists, but if other people are selling their work that’s theft. Sites are attempting to regulate this kind of problem, but everything is so new and they haven’t had time to catch up. Similarly, courts haven’t implemented any laws around NFTs. Until that happens a huge amount of fraud could occur within NFT trading. Right now people are making a lot of money from NFTs, so it will be interesting to see how this trend continues to evolve.

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

LO-11

The technological field has been and still is filled with a lot of stereotypes and biases surrounding people’s gender, race, or sexuality. It is a concrete fact that only 20% of professional computer scientists are women and only 5.8% of professional computer scientists are African American. Even though the 21st century US appears to be a progressive utopia, there’s still a lot of stigma around the technology and its developers. 

For this week’s Looking Outwards I chose an article by Meilan Solly called “Art Project Shows Racial Biases in Artificial Intelligence System”. This article addresses an issue of racial bias in the artificial intelligence tool ImageNet Roulette that was developed by artist Trevor Paglen and A.I. researcher Kate Crawford. What this tool was programmed to do is identify some characteristics of a person based on the photograph such as a photo of John F. Kennedy would be labeled “Politician” and a photo of Shakira would be labeled “Singer”. This tool seems to be impressive, right? But not everything is so simple, so perfect, so equal. When an African American young man, Tabong Kima, uploaded a photograph of himself and his friend to the tool, the ImageNet Roulette labeled him as “Wrongdoer, Offender”.  “I  might have a bad sense of humor, but I don’t think this is particularly funny”, said Kima on his Twitter page. The developers of the tool programmed descriptions such as dog, Boy Scout, or hairdresser, while others were rapist, adultress, loser, etc. The program seemed to identify white individuals largely in terms of occupation or other functional descriptors, but it classified those with darker skin solely by race and skin color: when an African American man uploaded a picture of himself the tool was only to describe him as “Black” and when an East Asian woman uploaded a photo of herself the tool described her as “Gook, Slant-eye”. The bias and racism here are seen crystal clear. 

This tool was taken off the Internet on September 27th, 2020, due to the existence of so many offensive and upsetting terms that were used to describe human beings. “We want to show how layers of bias and racism and misogyny move from one system to the next,” Paglen tells the New York Times’ Cade Metz. “The point is to let people see the work that is being done behind the scenes, to see how we are being processed and categorized all the time.” The creators of the tool told the press that the point of this project was to show the bias towards the race but my question would be just: Why? What for? Not everyone knew the point of this tool so it upset and offended a lot of people on the Internet when racist slurs popped up as their descriptions. This article pointed out how ImageNet Roulette was wrong and how it only increased the stigma around race and technology rather than got rid of it. The bias obviously exists and we shouldn’t prove it by creating more racist technology – we should fix it!

How artificial intelligence classified Julia Carrie Wong’s headshot. Photograph: ImageNet Roulette

https://www.smithsonianmag.com/smart-news/art-project-exposed-racial-biases-artificial-intelligence-system-180973207/

Solly, M. (2019, September 24). Art Project Shows Racial Biases in Artificial Intelligence System. Smithsonian.com. Retrieved November 13, 2021, from https://www.smithsonianmag.com/smart-news/art-project-exposed-racial-biases-artificial-intelligence-system-180973207/. 

Landscape: Tulip Fields

I worked too hard on this project. I ended up drawing all of the images in my code on procreate, so I do not have many sketches except for some resizing issues.

Math on Bottom side
Trying to figure out tulip configuration

The code was easier to figure out than I thought, but because I decided to use so many elements it got repetitive fast, there are a few things I could have tried i think in ways of getting my stuff to show up more randomly, but because of the way I wrote my code I found that setting that up farther would have not been worth the time for the effect.

Drawing took a few days, but I really like my images.

a cat
very many tulips(color added with code)

Some of the math I had to do really made me think and I can’t quite decide if using images made this take longer or shorter to code.

sketchfile

var szex = 550; // x size for some images
var szey = 365; //y size for some images
var szex2 = 367.2; //x size for smaller img
var szey2 = 240; //y size for smaller img
var tulip = [];
var offset = 0;
var skys = [];
var mountains = [];
var airballoons = [];
var trees = [];
var windmillBottoms = [];
var birds = [];
var electric = [];
var bunnys = [];
var fullWind = [];
var treeLines = [];
var cats = [];



function preload() {
    flowerImg = loadImage("https://i.imgur.com/VSMWH0A.png");
    tree1Img = loadImage("https://i.imgur.com/s66n2RJ.png");
    mountainsImg = loadImage("https://i.imgur.com/FCSY9xA.png");
    birdImg = loadImage("https://i.imgur.com/2zN4jIk.png");
    windmillBottomImg = loadImage("https://i.imgur.com/xGOhbMn.png");
    electricWindmillImg = loadImage("https://i.imgur.com/0R2RKsz.png");
    airballoonImg = loadImage("https://i.imgur.com/HPmyDXQ.png");
    bunnyImg = loadImage("https://i.imgur.com/tOtLTev.png");
    fullWindmillImg = loadImage("https://i.imgur.com/EUCzk9P.png");
    treeLineImg = loadImage("https://i.imgur.com/ipeIQSL.png");
    catImg = loadImage("https://i.imgur.com/d9pAL7i.png");
    skyImg = loadImage("https://i.imgur.com/AykCYLx.png");
}



function tulips(tx) {
    var p = {x: tx, 
        right: tulipsRight,
        display: tulipsDisplay};
    return p;
}

function tulipsRight() {
    return this.x + 900;
}

function tulipsDisplay(tx) {
    flower2Img.resize(flower2Img.width - 100, flower2Img.height);
   image(flower2Img, this.x, 190, 900, 105);//left
}


function bird(bx) {
    var b = {x: bx, 
        right: birdRight,
        display: birdDisplay};
    return b;
}

function birdRight() {
    return this.x + szex2 + width * 9;
}

function birdDisplay(tx) {
   image(birdImg, this.x + 200, 0, 165.4, 100); //move faster across the screen
}



function airballoon(ax) {
    var a = {x: ax, 
        right: airballoonRight,
        display: airballoonDisplay};
    return a;
}

function airballoonRight() {
    return this.x + szex2 + width * 1.5;
}

function airballoonDisplay(tx) {
   image(airballoonImg, this.x, 110, szex2, szey2);
}



function sky(sx) {
    var s = {x: sx, 
        right: skyRight,
        display: skyDisplay};
    return s;
}

function skyRight() {
    return this.x + 500;
}

function skyDisplay(tx) {
   image(skyImg, this.x, 0, 500, 300);
}


function mountain(mx) {
    var  m = {x: mx, 
        right: mountainRight,
        display: mountainDisplay};
    return m;
}

function mountainRight() {
    return this.x + 827 + width * 5;
}

function mountainDisplay(tx) {
   image(mountainsImg, this.x - 20, -85, 827, 500);
}


function tree(tx) {
    var  t = {x: tx, 
        right: treeRight,
        display: treeDisplay};
    return t;
}

function treeRight() {
    return this.x + szex + width * 1.5;
}

function treeDisplay(tx) {
   image(tree1Img, this.x, 20, szex, szey);
}


function treeLine(tx) {
    var  t = {x: tx, 
        right: treeLineRight,
        display: treeLineDisplay};
    return t;
}

function treeLineRight() {
    return this.x + szex + width * 1.7;
}

function treeLineDisplay(tx) {
   image(treeLineImg, thisx, 25, szex, szey); //with mountains or without
}
   

function windmillBottom(wx) {
    var  w = {x: wx, 
        right: windmillBottomRight,
        display: windmillBottomDisplay};
    return w;
}

function windmillBottomRight() {
    return this.x + szex2 + width * 2.2;
}

function windmillBottomDisplay(tx) {
   image(windmillBottomImg, this.x + 150, 87, szex2, szey2);//dont show with mountain
}


function windmill(wx) {
    var  w = {x: wx, 
        right: windmillRight,
        display: windmillDisplay};
    return w;
}

function windmillRight() {
    return this.x + 248 + width * 3.2;
}

function windmillDisplay(tx) {
   image(fullwindmillImg, this.x + 20, 100, 248, 150);
}
 

function electricwindmill(wx) {
    var  w = {x: wx, 
        right: electricwindmillRight,
        display: electricwindmillDisplay};
    return w;
}

function electricwindmillRight() {
    return this.x + szex + width * 10.2;
}

function electricwindmillDisplay(tx) {
   image(electricWindmillImg, this.x , 5, szex, szey); //dont show with other windmills
}
    

function bunny(bx) {
    var  b = {x: bx, 
        right: bunnyRight,
        display: bunnyDisplay};
    return b;
}

function bunnyRight() {
    return this.x + szex2 + width * 7.3;
}

function bunnyDisplay(tx) {
   image(bunnyImg, this.x, 130, szex2, szey2);
}


function cat(cx) {
    var  c = {x: cx, 
        right: catRight,
        display: catDisplay};
    return c;
}

function catRight() {
    return this.x + width * 5.5;
}

function catDisplay(tx) {
   image(catImg, this.x + 200, 160, 206.75, 125);
}





function setup() {
    createCanvas(480, 280);
    var sk = sky(1);
    skys.push(sk);
    var tul = tulips(1);
    tulip.push(tul);
    var ar = airballoon(1);
    airballoons.push(ar);
    var mount = mountain(1);
    mountains.push(mount);
    var bunn = bunny(1);
    bunnys.push(bunn);
    var kitten = cat(1);
    cats.push(kitten);
    var bid = bird(1);
    birds.push(bid);
    var tr = tree(1);
    trees.push(tr);
    var tre = treeLine(1);
    treeLines.push(tre);
    var wmb = windmillBottom(1);
    windmillBottoms.push(wmb);
    var fw = windmill(1);
    fullWind.push(fw);
    var ew = electricwindmill(1);
    electric.push(ew);
}




function draw() {
    noStroke();
    //SKY
    for (var i = 0; i < skys.length; i++) {
        var s = skys[i];
        image(skyImg, s.x - offset, 0, 500, 400);//left
    }
    // clean up statement
    if (skys.length > 0 & skys[0].right() < offset) {
        skys.shift();
    }
    // make a new sky
    var lastSky = skys[skys.length-1];
    if (lastSky.right() - offset < width) {
        var s = sky(lastSky.right()); 
        skys.push(s);
}


//MOUNTAIN
     for (var i = 0; i < mountains.length; i++) {
        var m = mountains[i];
        image(mountainsImg, m.x - offset, -78, 827, 500);
    }
    // make a new mountain
    var lastMountain = mountains[mountains.length-1];
    if (lastMountain.right() - offset < width) {
        var m = mountain(lastMountain.right()); 
        mountains.push(m);
}


//TREE
for (var i = 0; i < trees.length; i++) {
        var tr = trees[i];
        image(tree1Img, tr.x - offset, 23, szex, szey);
    }
    // clean up statement
    if (trees.length > 0 & trees[0].right() < offset) {
        trees.shift();
    }
    // make a new tree 
    var lastTree = trees[trees.length-1];
    if (lastTree.right() - offset < width) {
        var tr = tree(lastTree.right()); 
        trees.push(tr);
}
   
   //TREELINE
for (var i = 0; i < treeLines.length; i++) {
        var tre = treeLines[i];
        image(treeLineImg, tre.x - offset, 25, szex, szey); //with mountains or without
    }
    // clean up statement
    if (treeLines.length > 0 & treeLines[0].right() < offset) {
        treeLines.shift();
    }
    // make a new treeline
    var lastTreeLine = treeLines[treeLines.length-1];
    if (lastTreeLine.right() - offset < width) {
        var tre = treeLine(lastTreeLine.right()); 
        treeLines.push(tre);
} 



//WINDMILLBOTTOM
    for (var i = 0; i < windmillBottoms.length; i++) {
        var wnd = windmillBottoms[i];
        image(windmillBottomImg, wnd.x - offset, 87, szex2, szey2);
    }
    // clean up statement
    if (windmillBottoms.length > 0 & windmillBottoms[0].right() < offset) {
        windmillBottoms.shift();
    }
    // make a new windmill
    var lastwindmillBottom = windmillBottoms[windmillBottoms.length-1];
    if (lastwindmillBottom.right() - offset < width) {
        var wnd = windmillBottom(lastwindmillBottom.right()); 
        windmillBottoms.push(wnd);
}
    


//ELECTRIC WINDMILL
for (var i = 0; i < electric.length; i++) {
        var ew = electric[i];
        image(electricWindmillImg, ew.x - offset, 5, szex, szey); //dont show with other windmills
    }
    // clean up statement
    if (electric.length > 0 & electric[0].right() < offset) {
        electric.shift();
    }
    // make a new windmill
    var lastElectricWindmill = electric[electric.length-1];
    if (lastElectricWindmill.right() - offset < width) {
        var ew = electricwindmill(lastElectricWindmill.right()); 
        electric.push(ew);
}
    

//WINDMILL
for (var i = 0; i < fullWind.length; i++) {
        var full = fullWind[i];
         image(fullWindmillImg, full.x - offset, 100, 248, 150); //can be anytime show up
    }
    // clean up statement
    if (fullWind.length > 0 & fullWind[0].right() < offset) {
        fullWind.shift();
    }
    // make a new windmill
    var lastWindmill = fullWind[fullWind.length-1];
    if (lastWindmill.right() - offset < width) {
        var full = windmill(lastWindmill.right()); 
        fullWind.push(full);
}



//AIRBALLOONS
    for (var i = 0; i < airballoons.length; i++) {
        var air = airballoons[i];
        image(airballoonImg, air.x - offset, 110 - offset/10, szex2, szey2);
    }
    // clean up statement
    if (airballoons.length > 0 & airballoons[0].right() < offset) {
        airballoons.shift();
    }
    // make a new balloom
    var lastAirballoon = airballoons[airballoons.length-1];
    if (lastAirballoon.right() - offset < width) {
        var air = airballoon(lastAirballoon.right()); 
        airballoons.push(air);
}

//background for tulips
for(var i = 0 ; i < width; i ++){
    fill(253, 218 - offset / 75, 42);
    rect(0, 195, 480, 100);
}
//slight change every time offset increases so slight won't notice till big change




//TULIPS
    for (var i = 0; i < tulip.length; i++) {
        var t = tulip[i];
        image(flowerImg, t.x - offset, 190, 900, 105);//left
    }

    // clean up statement
    if (tulip.length > 0 & tulip[0].right() < offset) {
        tulip.shift();
    }

    // make a new tulip
    var lastTulip = tulip[tulip.length-1];
    if (lastTulip.right() - offset < width) {
        var t = tulips(lastTulip.right()); 
        tulip.push(t);
}





//BIRD ??NEEDS FIX
 for (var i = 0; i < birds.length; i++) {
        var bids = birds[i];//need to change spawn pnt
        image(birdImg, bids.x - (offset + offset), 0, 165.4, 100); //move faster across the screen
    }
    // clean up statement
    if (birds.length > 0 & birds[0].right() < offset) {
        birds.shift();
    }
    // make a new bird //make less often
    var lastBird = birds[birds.length-1];
    if (lastBird.right() - (offset + offset) < width) {
        var bids = bird(lastBird.right()); 
        birds.push(bids);
}





    //BUNNY
 for (var i = 0; i < bunnys.length; i++) {
        var buns = bunnys[i];
        image(bunnyImg, buns.x - offset, 130, szex2, szey2);
    }
    // clean up statement
    if (bunnys.length > 0 & bunnys[0].right() < offset) {
        bunnys.shift();
    }
    // make a new rabbit //make less often
    var lastBunny = bunnys[bunnys.length-1];
    if (lastBunny.right() - offset < width) {
        var buns = bunny(lastBunny.right()); 
        bunnys.push(buns);
}




    //CAT
 for (var i = 0; i < cats.length; i++) {
        var kittens = cats[i];
        image(catImg, kittens.x - offset , 160, 206.75, 125);
    }
    // clean up statement
    if (cats.length > 0 & cats[0].right() < offset) {
        cats.shift();
    }
    // make a new cat //make less often
    var lastCat = cats[cats.length-1];
    if (lastCat.right() - offset < width) {
        var kittens = cat(lastCat.right()); 
        cats.push(kittens);
}



    offset ++;
}

Project 10: Sonic Story

For this project, I made 2 fish who are lovers that swim randomly around an aquarium looking for each other. When they meet, they fall in love again and the supportive crab in the corner claps for them and a love song plays.

sketchDownload

//Catherine Liu
//jianingl@andrew.cmu.edu
//Section D
//project 10

//two fishes swimming around tank (bump sound when they hit the sides)
//when they bump into each other they fall in love (song plays)
//crab clapping for them (clapping sound)
//house bubbles turn into hearts (bubbling sound)

// use http://localhost:8000/ to run html

//variables for pink fish
var x1 = 50;
var y1 = 50;
var dx1 = 50;
var dy1 = 20;

//variables for green fish
var x2 = 300;
var y2 = 300;
var dx2 = 40;
var dy2 = 30;

var meet = false; //checks to see if fish meet
var crabClaw = 1; //keeps track of frame for crab claw clapping
var songCount = 0; //counter for song played
var bubbleArrayX = []; //x value for each bubble
var bubbleArrayY = []; //y value for each bubble
var heartArrayX = []; //x value for each heart
var heartArrayY = []; //y value for each heart

//sound variables 
var bump;
var bubbles;
var heart;
var clap;

function preload() {
    bump = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/bump.mp3");
    bubbles = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/bubble-4.wav");
    heart = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/lovesong.mp3");
    clap = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/clap.wav");
}

function setup() {
    noStroke();
    createCanvas(600, 400);
    useSound();
    frameRate(10);

    //sets up bubble and heart arrays
    for (i = 170; i > 50 ; i-=15) {
        bubbleArrayX.push(400 + random(-10,10));
        bubbleArrayY.push(i);
        heartArrayX.push(400 + random(-10,10));
        heartArrayY.push(i);
    }

}

function soundSetup() { 
    bump.setVolume(0.2);
    bubbles.setVolume(0.2);
    clap.setVolume(0.1);
    heart.setVolume(0.3)

}

function draw() {
    background(65,105,225);
    fill(255,250,205);
    rect(0,height-50,width,height);


    drawCrab();
    drawHouse();

    //if fish meet, play song and stop bump sounds
    if (meet == true) {
        bump.stop();
        playSong();
    }

    //if fish have not met, keep moving them
    if (meet == false) {
        x1 += dx1;
        y1 += dy1;
    }
    fill(255,182,193) //pink fish
    drawFish(x1,y1,dx1);
    dx1 += random(-5,5);
    dy1 += random(-5,5);
    if (x1 < 40) {
        bump.play();
        dx1 = -dx1;
    }
    if (x1 > width - 40) {
        bump.play();
        dx1 = -dx1;
    }
    if (y1 < 40) {
        bump.play();
        dy1 = -dy1;
    }
    if (y1 > height - 75) {
        bump.play();
        dy1 = -dy1;
    }

   if (meet == false) {
        x2 += dx2;
        y2 += dy2;
    }
    fill(173,255,47) //green fish
    drawFish(x2,y2,dx2);
    dx2 += random(-5,5);
    dy2 += random(-5,5);
    if (x2 < 40) {
        bump.play();
        dx2 = -dx2;
    }
    if (x2 > width - 40) {
        bump.play();
        dx2 = -dx2;
    }
    if (y2 < 40) {
        bump.play();
        dy2 = -dy2;
    }
    if (y2 > height - 75) {
        bump.play();
        dy2 = -dy2;
    }

    meetUp(25); //checks if fish have met
}

function drawFish(x, y, dx) {
    ellipse(x, y, 60, 40); //fish body

    //checks which direction fish is facing to draw tail
    if (dx > 0) {
        if (meet == true) { //if fish met, draw smile
            push();
            fill(0);
            circle(x+20,y,10);
            pop();

            push();
            noFill();
            stroke(2);
            arc(x+10, y+7, 10, 10, 0, PI);
            pop();
        } else { //no smile
            push();
            fill(0);
            circle(x+20,y,10);
            pop();
        }
        triangle(x-30, y, x-50, y-10, x-50, y+10); //fish tail

    } if (dx < 0) {
        if (meet == true) { //if fish met, draw smile
            push();
            fill(0);
            circle(x-20,y,10);
            pop();

            push();
            noFill();
            stroke(2);
            arc(x-10, y+7, 10, 10, 0, -PI);
            pop();
        } else { //no smile
            push();
            fill(0);
            circle(x-20,y,10);
            pop();
        }
        triangle(x+30, y, x+50, y-10, x+50, y+10); //fish tail
    }

}

//checks if fish have "met" by checking distance between them <= 0 and draws heart
function meetUp(size) {
    if (dist(x1, y1, x2, y2) <= 40) {
        //draws heart
        fill("red")
        var xPos = x1;
        if ((y1-70) < 10) {
            var yPos = y1 + 70;
        } else {
            var yPos = y1 - 70;
        }
        beginShape();
        vertex(xPos, yPos);
        bezierVertex(xPos - size / 2, yPos - size / 2, xPos - size, yPos + size / 3, xPos, yPos + size);
        bezierVertex(xPos + size, yPos + size / 3, xPos + size / 2, yPos - size / 2, xPos, yPos);
        endShape();

        meet = true; //change variable to true to show fish have met
    }
}

function drawCrab() {
    fill("orange");
    ellipse(100, height-80,80,50);
    circle(60,height-100,20);
    circle(140,height-100,20);
    arc(60,height-130, 50, 50, -(radians(30)), -HALF_PI);
    arc(150,height-130, 50, 50, -(radians(30)), -HALF_PI);
    push();
    noFill();
    strokeWeight(10);
    stroke("orange");
    arc(120, height-35, 80, 80, PI + QUARTER_PI, TWO_PI);
    arc(80, height-35, 80, 80, PI, PI + HALF_PI);
    pop();
    fill(0);
    circle(120,height-90, 8);
    circle(100,height-90, 8);

    //if fish have met, crab claps by drawing circles on top of arcs
    if (meet == true) {
        arc(100, height-80, 20, 20, 0, -PI);

        //alternating variable so crab claws open and close with every frame
        if (crabClaw == 1) {
            clap.play();
            fill("orange");
            circle(60, height-130,50,50);
            circle(150,height-130,50,50);
            crabClaw += 1;
        } else if (crabClaw == 2) {
            crabClaw = 1;
        }

    }

}

function drawHouse() {
    fill(160,82,45); //brown
    rect(width-200, height-170, 120,120);
    triangle(width-220,height-170,width-140,height-250,width-60,height-170);
    rect(width-200,height-230,20,80);
    fill(173,216,230); //light blue
    rect(width-160, height-110,40,60);
    fill(0); //black
    circle(width-155,height-70,5);
    fill(173,216,230); //light blue
    rect(width-180,height-150,20,20);
    rect(width-120,height-150,20,20);

    fill(224,255,255); //light cyan
    bubbles.play();

    //moving bubbles up the canvas by adding random dx and dy
    for (i = 0; i < bubbleArrayX.length; i++) {
        var randomDx = (random(-5,5));
        var randomDy = (random(-10,0));

        if (meet == false) { //if fish have not met, house bubbles
            bubbleArrayX[i] += randomDx;
            bubbleArrayY[i] += randomDy;
            //reset x and y position if bubble leaves canvas
            if (bubbleArrayY[i] <= 0) {
                bubbleArrayX[i] = 400 + random(-10,10);
                bubbleArrayY[i] = 150;
            }
            circle(bubbleArrayX[i], bubbleArrayY[i], 5)

        } else if (meet == true) { //if fish have met, house bubbles hearts
            heartArrayX[i] += randomDx;
            heartArrayY[i] += randomDy;
            var size = 10;
            fill("pink")
            beginShape();
            vertex(heartArrayX[i], heartArrayY[i]);
            bezierVertex(heartArrayX[i] - size / 2, heartArrayY[i] - size / 2, heartArrayX[i] - size, heartArrayY[i] + size / 3, heartArrayX[i], heartArrayY[i] + size);
            bezierVertex(heartArrayX[i] + size, heartArrayY[i] + size / 3, heartArrayX[i] + size / 2, heartArrayY[i] - size / 2, heartArrayX[i], heartArrayY[i]);
            endShape();
            //reset x and y position if heart leaves canvas
            if (heartArrayY[i] <= 0) {
                heartArrayX[i] = 400 + random(-10,10);
                heartArrayY[i] = 150;
            }
        }
    } 

}

//plays love song after fish meet
function playSong() {
    //only want song to play once so use counter
    if (songCount == 0) {
        heart.play();
        songCount += 1;
    } else {
        //do nothing
    }
}