ifv Final Project

sketch

//Isabelle Vincent
//ifv@andrew.cmu.edu
//Section E
//Final Project

var bigs;
var littles;
var algaes;
var foods;
var l;
var littleFish;
var bigFish;
var algae;
var lilypad;
var title;
var state = "title";



function preload() {
  title = loadImage('https://i.imgur.com/aebxPZS.png');
  algae = loadImage("https://i.imgur.com/qnqf1gs.png");
  lilypad = loadImage("https://i.imgur.com/3bfrSSw.png");
  littleFish = loadAnimation('https://i.imgur.com/AUq3ML3.png', 'https://i.imgur.com/1z3PLA8.png', 'https://i.imgur.com/Pxw05Sj.png', 'https://i.imgur.com/yA0uKGs.png', 'https://i.imgur.com/dnUjjsr.png', 'https://i.imgur.com/vprw1op.png', 'https://i.imgur.com/u9dgtas.png', 'https://i.imgur.com/tV1RxJZ.png');
  bigFish = loadAnimation('https://i.imgur.com/zqn5YLQ.png', 'https://i.imgur.com/GSV79Mw.png', 'https://i.imgur.com/oh8VzDx.png', 'https://i.imgur.com/RRiwPTC.png', 'https://i.imgur.com/nswooQs.png', 'https://i.imgur.com/w95esvz.png', 'https://i.imgur.com/uPy62tp.png', 'https://i.imgur.com/uHA6DaY.png');
}


function setup() {
  createCanvas(800, 400);
  //looping fish animations
  littleFish.looping = true;
  bigFish.looping = true;
  i = 1;
  //start out on title screen
   if(state == "title"){
    imageMode(CORNER);
    image(title,0,0);
  }

  //create empty groups
  bigs = new Group();
  littles = new Group();
  algaes = new Group();
  foods = new Group();

  //assign new sprites to groups
  for (var i = 0; i < 6; i++) {
    //i put all the creation and initialization instructions in a function I created
    createbig(random(0, width), random(0, height));
  }
}


function draw() {
  if(state == "gameplay"){
  //the more algae there is the darker the bg is
  var q = algaes.length * 20
  var c = color(136-q, 180-q, 136-q);
  background(c);
  textSize(20);
  fill(210, 239, 220);
  text("Click to feed fish, if you dont there will be no more fish",10,30);

  //spawn a algae randomly
  if (frameCount % 40 == 0 & algaes.length < 4 && bigs.length > 3) {
    createAlgae(random(0, width), random(0, height));
  }

  //create a new little fish every 60 frames if there are less than 20 little fish
  if (frameCount % 60 == 0 & littles.length < 20) {

    var side = floor(random(0, 4));

    if (side == 0) //left
      createlittle(0, random(height));
    if (side == 1) //right
      createlittle(width, random(height));
    if (side == 2) //top
      createlittle(random(width), 0);
    if (side == 3) //bottom
      createlittle(random(width), height);

  }

  for (var i = 0; i < algaes.length; i++) {
    var a = algaes[i];
    for (var j = 0; j < bigs.length; j++) {
      var b = bigs[j];
      a.overlap(bigs, algaeTouchesBig);
    }
  }


  //go through the bigs - they wander randomly
  for (var i = 0; i < bigs.length; i++) {

    //way to store fish position
    var b = bigs[i];
    
    b.noisePosition += 0.1;
    b.rotation += (noise(b.noisePosition) - 0.5) * 10;

    //set the velocity based on the new rotation
    b.setSpeed(2, b.rotation);
    
    //check all the bigs,
    for (var j = 0; j < foods.length; j++) {

      var f = foods[j]; //same as above

      var distance = p5.Vector.dist(b.position, f.position);

      //if they are closer make them attract
      if (distance < 500) {
        //find angle between the two
        var angle = degrees(atan2(f.position.y - b.position.y, f.position.x - b.position.x));
        //attraction inverseley proportional to distance
        var attraction = 200 / distance;
        b.addSpeed(attraction, angle);
        b.overlap(foods, BigTouchesFood);
      }
    }
    wrapAroundScreen(b);
  }

  //go through the littles group -
  //they go straight until they get close to bigs
  littles.bounce(bigs);
  bigs.bounce(bigs);
  for (var i = 0; i < littles.length; i++) {
    var l = littles[i]; //save in a temp variable
    l.overlap(algaes, littleTouchesAlgae);
    wrapAroundScreen(l);
  }


  //don't forget to draw all the sprites
  drawSprites();
}
}

//click mouse to feed fish
function mousePressed() {
  for (var i = 0; i < random(3, 5); i++) {
    createFood(mouseX, mouseY);
  }
}

//checks if a sprite is outside of the screen and teleports it on the other side
function wrapAroundScreen(s) {
  //wrap around the screen
  if (s.position.x > width + 20)
    s.position.x = 0;
  if (s.position.x < -20)
    s.position.x = width;
  if (s.position.y > height + 20)
    s.position.y = 0;
  if (s.position.y < -20)
    s.position.y = height;
}
//if little fish touches algae a new little fish is made and algae destroyed
function littleTouchesAlgae(little, algae) {
  algae.remove();
  createlittle(little.position.x, little.position.y);
}
//If algae and Big fish touch big fish disappear
function algaeTouchesBig(algae, big) {
  big.remove();
}
//If Big Fish touches food a new fish is created at a semi-random size
function BigTouchesFood(big, food) {
  food.remove();
  push()
  big.scale = random(0.5, 0.7);
  createbig(big.position.x, big.position.y);
  pop();
}


//function to create Big fish & add to group
function createbig(x, y) {

  var b = createSprite(x, y);

  b.addAnimation("big", bigFish);

  b.velocity.y += random(-2, 2);
  b.velocity.x += random(-2, 2);
  b.scale = 0.5;
  b.mass = b.scale;
  b.setCollider("spiral", -2, 2, 55);

  //use to generate the noise wandering
  b.noisePosition = random(0, 1000);
  //image rotates toward the direction
  b.rotateToDirection = true;

  b.maxSpeed = 2;

  bigs.add(b);

}

//function to create little fish & add to group
function createlittle(x, y) {
  var l = createSprite(x, y);
  l.addAnimation("little", littleFish);

  //set a random speed
  l.setSpeed(2, random(0, 360));
  l.scale = random(0.3, 0.7);
  //slower speed than bigs so they will never stick to them
  l.maxSpeed = 1.8;
  l.mass = l.scale;
  l.setCollider("spiral", -2, 2, 55);
  l.life = 500;
  //image rotates toward the direction
  l.rotateToDirection = true;
  littles.add(l);

}

//function to create food particles & add to group
function createFood(x, y) {
  var f = createSprite(x, y);
  f.scale = 0.4;
  f.addAnimation("food", "https://i.imgur.com/FTsnjxr.png");
  f.velocity.y += random(-2, 2);
  f.velocity.x += random(-2, 2);
  foods.add(f);
}
//function to create algae & add to group
function createAlgae(x, y) {
  var a = createSprite(x, y);
  a.addAnimation("algae", "https://i.imgur.com/qnqf1gs.png");
  a.life = 800;
  algaes.add(a);
}

//start game after spacebar pressed by changing the state
function keyPressed() {
  if (state === "title" & keyCode === 32) {
    state = "gameplay";
  }
}

 

This Project is a small ecosystem that is reliant on user interaction for it the eco system to flourish. Unfortunately I wasn’t able to take this project to the level I originally wanted to but coding with a different library was a learning experience for me.

ifv-LookingOutwards-12

Chris Johnson’s Digital Ecosystems

 

Gameplay of Tap Tap Fish AbyssRium

In the mobile game Tap Tap Fish AbyssRium the player taps on the rock to generate ‘vitality’ points which the player can use to upgrade certain parts of the aquarium and purchase new fish with. Its marketed as a relaxation game but really is meant to be addictive and encourages in-app purchases for upgrades. I really like the style and fish animations in this game, the movements are realistic, so are the fishes designs except they are made to be a cuter than the real fish they are based on. I wish the game was more relaxing. I really admire the atmosphere in Chris Johnson’s digital ecosystems (they are both unsettling and calming) and how he explores the various kinds of ecosystems and how they are all connected by the presence of a cycle. I think Johnson’s piece is good as an art piece but doesn’t hold as strong as a game with replay-ability.

ifv-Project-12-Proposal

For my final project I want to make a interactive small pond ecosystem (a koi pond) using p5.play, ((I want to expand on a very rough version of an ecosystem coded for 60-210)). A random amount of each element will appear when the sketch is loaded (the lily pads generate in a cluster and stay in the same position for the duration of the program). When the user clicks food pellets will appear and the larger fish will swim towards them, if they touch the pellet they will “eat” it and if the amount of fish present in the sketch is less than a certain amount a baby fish will appear and slowly grow to a full size fish over time. The little brown fish eat the algae and reproduce. The algae amount affects how green the background is, if a food particle overlaps with the algae it will the food and reproduce.

ifv-LookingOutwards-11

 Ge Wang makes computer music aiming to use computers and phones to make new kinds of instruments. He created a computer music programming language called ChucK. Programs made with this language can be run with various interfaces. In the embedded TedTalk he showcases various instruments he has made. One example is a repurposed game controller that can be set to create a variety of noises (mostly futuristic/science fiction sounding) the other is a ‘wind’ instrument which is played by blowing into the phones microphone and can be altered by holding various buttons on the screen that mimic holes/buttons that would exist on a traditional instrument.

ifv-Project-11

sketch

//Isabelle Vincent
//Section E
//ifv@andrew.cmu.edu
//Project-11

function turtleLeft(d) {
    this.angle -= d;
}


function turtleRight(d) {
    this.angle += d;
}


function turtleForward(p) {
    var rad = radians(this.angle);
    var newx = this.x + cos(rad) * p;
    var newy = this.y + sin(rad) * p;
    this.goto(newx, newy);
}


function turtleBack(p) {
    this.forward(-p);
}


function turtlePenDown() {
    this.penIsDown = true;
}


function turtlePenUp() {
    this.penIsDown = false;
}


function turtleGoTo(x, y) {
    if (this.penIsDown) {
      stroke(this.color);
      strokeWeight(this.weight);
      line(this.x, this.y, x, y);
    }
    this.x = x;
    this.y = y;
}


function turtleDistTo(x, y) {
    return sqrt(sq(this.x - x) + sq(this.y - y));
}


function turtleAngleTo(x, y) {
    var absAngle = degrees(atan2(y - this.y, x - this.x));
    var angle = ((absAngle - this.angle) + 360) % 360.0;
    return angle;
}


function turtleTurnToward(x, y, d) {
    var angle = this.angleTo(x, y);
    if (angle < 180) {
        this.angle += d;
    } else {
        this.angle -= d;
    }
}


function turtleSetColor(c) {
    this.color = c;
}


function turtleSetWeight(w) {
    this.weight = w;
}


function turtleFace(angle) {
    this.angle = angle;
}


function makeTurtle(tx, ty) {
    var turtle = {x: tx, y: ty,
                  angle: 0.0,
                  penIsDown: true,
                  color: color(128),
                  weight: 1,
                  left: turtleLeft, right: turtleRight,
                  forward: turtleForward, back: turtleBack,
                  penDown: turtlePenDown, penUp: turtlePenUp,
                  goto: turtleGoTo, angleto: turtleAngleTo,
                  turnToward: turtleTurnToward,
                  distanceTo: turtleDistTo, angleTo: turtleAngleTo,
                  setColor: turtleSetColor, setWeight: turtleSetWeight,
                  face: turtleFace};
    return turtle;
}

function lines(t1){
  for(var j = 0; j<4;j++){
    t1.penDown();
    t1.forward(10);
    t1.left(180);
  }
}

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

function draw(){
  //inverse the stroke and bg colors
  var v = map(mouseY,0,height,0,255);
  var b = map(mouseY,height,0,0,255);
  background(v);
  var t1 = makeTurtle(mouseX,mouseY);
  t1.setColor(b);
  t1.setWeight(6);
  t1.penUp();
  //t1.forward(20);
  //t1.penDown();
  //t1.left(90);
  //t1.left(10);
  for(var i=0; i<1000; i++){
      t1.penUp();
      //go out from center
      var dist=(-(mouseY+mouseX)/2) +1 + i *1
      t1.forward(dist);
      //draw
      lines(t1);
      //come back
      t1.penUp();
      t1.left(180);
      t1.forward(dist);
      t1.left(180);

      //rotate by some angle
      t1.left(10);
  }
}

ifv-LookingOutwards-10

Orb 11, 2015 

Sara Ludy

The artists I chose to look at was Sara Ludy. Ludy is based in Los Angeles, California and Vancouver, British Columbia. Ludy received her BFA from The School of the Art Institute of Chicago she initially went for painting but ended up studying in the video, sound and art and technology department I liked the whole series but the one that stood out the most to me was Orb 11, 2015 I liked how the stills looked were presented on her site. This particular piece has a video attached that has an animation style that makes the orb almost look like a deep sea creature.

ifv-Project-10-Landscape

sketch

//Isabelle Vincent
//Section E
//ifv@andrew.cmu.edu
//Project-10
var buildings = [];
var persons = [];

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

    // create an initial collection of buildings
    for (var i = 0; i < 10; i++){
        var rx = random(width);
        buildings[i] = makeBuilding(rx);
    }
    frameRate(50);
}


function draw() {
    background(200);

    displayStatusString();
    displayHorizon();

    updateAndDisplayBuildings();
    updateAndDisplayPersons();
    print(persons.length);
    removeBuildingsThatHaveSlippedOutOfView();
    addNewBuildingsWithSomeRandomProbability();
    removePersonsThatHaveSlippedOutOfView();
    addNewPersonsWithSomeRandomProbability();
}


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 updateAndDisplayPersons(){
    // Update the building's positions, and display them.
    for (var i = 0; i < persons.length; i++){
        persons[i].move();
        persons[i].display();
    }
}


function removeBuildingsThatHaveSlippedOutOfView(){
    // If a building has dropped off the left edge,
    // remove it from the array.  This is quite tricky, but
    // we've seen something like this before with particles.
    // The easy part is scanning the array to find buildings
    // to remove. The tricky part is if we remove them
    // immediately, we'll alter the array, and our plan to
    // step through each item in the array might not work.
    //     Our solution is to just copy all the buildings
    // we want to keep into a new array.
    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 removePersonsThatHaveSlippedOutOfView(){

    var personsToKeep = [];
    for (var i = 0; i < persons.length; i++){
        if (persons[i].x + persons[i].thick > 0) {
            personsToKeep.push(persons[i]);
        }
    }
    persons = personsToKeep; // remember the surviving people (tragic)
}


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 addNewPersonsWithSomeRandomProbability() {
    // With a very tiny probability, add a new building to the end.
    var newPersonLikelihood = 0.007;
    if (random(0,1) < newPersonLikelihood) {
        persons.push(makePerson(width));
    }
}


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

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

// draw the building and some windows
function buildingDisplay() {
    var floorHeight = 20;
    var roofHeight = random(8,20);
    var bHeight = (this.nFloors * floorHeight)/2;
    fill(35, 28, 64);
    noStroke();
    push();
    translate(this.x, height - 40);
    rect(0, -bHeight, this.breadth, bHeight);
    triangle(-20, -bHeight,this.breadth/2,(bHeight)-height,this.breadth+20,-bHeight);

    pop();
}

function personDisplay() {
    var headSize = 15;
    var bodyheight = this.tall;
    var bodythick = this.thick;
    var headCenter = bodyheight+headSize/2;
    var bodyCenter = bodyheight/2;
    fill(198, 28, 64,90);
    noStroke();
    push();
    translate(this.x,this.y);
    ellipseMode(CENTER);
    ellipse(0,-bodyCenter,bodythick,bodyheight);
    ellipse(0,-headCenter,headSize,headSize);
    pop();
}

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

function makePerson(birthLocationX){
  var person = {x: birthLocationX,
              y:height-50,
              tall: random(30,60),
              thick: random(15,40),
              speed: -1.0,
              eyeballs: random(1,4),
              move: personMove,
              display: personDisplay}
  return person;
}

function displayHorizon(){

  noStroke();

  var green = color(198, 28, 64);
  var yellow = color(229, 199, 31);

  var gradientSteps = 20;//how detailed will the gradient be
  var gradientStripWidth = width/gradientSteps;//compute how many strips of the same width to fill the sketch

  for(var i = 0; i < gradientSteps; i++){//for each gradient strip
    var t = map(i,0,gradientSteps,0.0,1.0);//compute i mapped from 0-gradientSteps to 0.0->1.0
    //this value will plug into lerpColor which does the color interpolation
    var interpolatedColor = lerpColor(green,yellow,t);
    //finally, use the color and draw some boxes
    fill(interpolatedColor);
    rect(0,i*gradientStripWidth,height,gradientStripWidth);
  }

    fill(35, 28, 64);
    rectMode(CORNER);
    rect(0,height-50,width,height-50)
}


function displayStatusString(){
    noStroke();
    fill(0);
    var statusString = "# Buildings = " + buildings.length;
    text(statusString, 5,20);
}

I wanted to make a haunted forest because I’m sad halloween has ended. The trees are sparse and skinny because they are based on the trees I remember in a certain forest in Oregon. I decided to make the ghosts a a transparent version of the red in the sky instead of white (which most people default to) bc it has better visual harmony.

LookingOutwards-09

gyueunp – Looking Outwards 05

The Looking outwards Im referencing

VOID from Chris Bjerre on Vimeo.

This project was interesting to me because it shows how art & coding intersects with commercial product. Also the visuals were unsettling in a poetic way where the coding of pattern did not feel forced and the sole focus, more a tool used in a larger narrative. The part I found most interesting was Bjerre’s project titled ‘VOID’ which Gyueun linked in her post. I agree with Gyueun’s attraction towards the “simple yet complex visual structures” in the linked projects. Bjerre’s work aims to unsettle the viewer through visuals and audio and VOID was a project that did both of these things along with an original non-dialogue narrative.  

ifv-Project-09

sketch

//Isabelle Vincent
//ifv@andrew.cmu.edu
//Section E
//Project-09
var underlyingImage;
var dpx = 0;
var dpy = 0;

function preload() {
    var myImageURL = "https://i.imgur.com/u2jqeuv.jpg";
    underlyingImage = loadImage(myImageURL);
}

function setup() {
    createCanvas(480, 480);
    background(0);
    underlyingImage.loadPixels();
    frameRate(10);
}

function draw() {
  //expand region where drawing outwards in all directions starting frm center
  var xxc = (width/2) - dpx;
  var xyc = (width/2) + dpx;

  var yxc = (height/2) - dpy;
  var yyc = (height/2) + dpy;


    dpx += 1;
    dpy += 1;
//wait til dpx is greater than width to reset in center so program has time to draw in entire canvas
    if (dpx >= width){
      dpx = 0;
      dpy = 0;
    }
    var px = random(xxc,xyc);
    var py = random(yxc,yyc);
    var ix = constrain(floor(px), 0, width-1);
    var iy = constrain(floor(py), 0, height-1);
    var theColorAtLocationXY = underlyingImage.get(ix, iy);
//vary 'pixel' size
    var rd = random(6,14);

    noStroke();
    fill(theColorAtLocationXY);
    rect(px, py, rd, rd);
    if(mouseIsPressed){
//draw accurate pixels by moving mouse over canvas while clicking & dragging
      var theColorAtTheMouse = underlyingImage.get(mouseX, mouseY);
      fill(theColorAtTheMouse);
      rect(pmouseX, pmouseY, rd, rd);
    }

}

My portrait randomly displays pixels within a constrained region, this region expands originating from the center of the canvas and once it has reached a certain point outside of the canvas (to provide more draw-time) starts again at the center. You can also click and drag to draw pixels to speed up the image making process. Theres a slight randomized difference in pixel size, I liked the effect this had on the image, making it blocking but more precise.

ifv LookingOutwards-08

“phosphere” Rhizomatiks Research x ELEVENPLAY

Daito Manabe’s: site

Daito Manabe studied math, science, technology/programming and art, Manabe’s art reflects this intersection. I enjoy the aesthetics of his work, it takes simple visual elements and uses them as building blocks to make a more interesting visual. I admire “phosphere” Rhizomatiks Research x ELEVENPLAY which Daito was the visual director for. I was unable find his talk from the festival but he is listed as one of the artists listed for the 2013 iteration, some of his work involves video so a vimeo search of name brings plenty of results. I think an artist’s site is another personalized curation of their work similar to how they would in a lecture. Manabe’s site is very coherent and knows how to present his work within a format that matches the work’s aesthetics. I really like the stills from ELEVENPAY so I linked them above.