eeryan + yoonyouk_Final Project

sketch

// Erin Ryan and Yoon Young Kim
// eeryan@andrew.cmu.edu
// yoonyouk@andrew.cmu.edu
// Section C and Section E
//FINAL PROJECT - water animation


//HOME PAGE VARIABLES
//STARTING CODE WITH HOME PAGE
var animation = 0;
//text position variables
var textStart1 = 0;
var textStart2 = 140;
var textStart3 = 280;
var textStart4 = 420;
var textSpace = 140;

//RAINFALL ANIMATION VARIABLES
var numClicks = 0; 
var fall = false; //starting the animation off
var water = [];
var xr; //x position of water droplets

//COHESION ANIMATION VARIABLES
var move = false;
var drop1; //first water object 
var drop2; //second water object 
var opacity = 100; //variable to deal with changing opacity of fills and strokes of different water objects

//RIPPLE ANIMATION VARIABLES
var rx;
var ry;
var diam;

//SPLASH ANIMATION VARIABLES
var SPLASH = [];
var droplets = [];
var dropX = -50; //x coordinate of the water drop
var dropY = 0; // y coordinate of the water drop
var splashpoint = 150;
var numClick = 0;
var explodeTime;
var timeElapsed;
var splashed = false;

function preload(){
    var splashImgs = [];
    //img links of the splash droplets
    splashImgs[0] = "https://i.imgur.com/Aau3BBu.png";
    splashImgs[1] = "https://i.imgur.com/C156jX4.png";
    splashImgs[2] = "https://i.imgur.com/nnR9v06.png";

    //cycling images by pushing into SPLASH array
    for(var i = 0; i<3; i++){
        SPLASH.push(loadImage(splashImgs[i]));
    }
}

function setup() {
  createCanvas(400, 300);
  //object declaration for cohesion animation
  drop1 = makeDrop(120, height / 2, 100);
  drop2 = makeDrop(width - 120, height / 2,100);
  //pushes raindrop objects into the array water
  for(var i = 0; i < 300; i++){
    xr = random(0, width); 
    water.push(makeRain(xr, 20, 5, 0)); 
  }
}

function draw() {
  //default page
  if(animation === 0){ 
    background(173, 212, 255);
    textSize(20);
    fill(255, 255, 255);
    textFont("Courier New")
    text("let's play with water!", width / 2 - 130, 100);
    menuText(200);
  }
  //ripple animation
  if(animation == 1){ 
    background(238, 252, 255);
    noStroke();
    fill(80, 130, 200);
    textFont("courier", 16);
    textAlign(CENTER);
    text("click to touch the water...", width / 2, 30); // creates text guiding user to press a key
    ripple(rx, ry);
    if(diam < 550){
      diam += 1; //circle expands
      opacity -= 0.4; //circle becomes less opaque as it expands
    }
    menuText(275);
  }
  //splash animation
  else if(animation == 2){
    background(238, 252, 255);
    noStroke();
    fill(80, 130, 200);
    textFont("courier", 16);
    textAlign(CENTER);
    text("click to splash water droplets", width / 2, 30); // creates text guiding user to press a key
    fill(26, 133, 192);
    if(dropY > 0 & dropY < splashpoint){
        droplet(dropX, dropY);
        dropY++;
    }
    if(dropY == splashpoint){
        splashed = true;
        if(explodeTime == null){
          explodeTime = frameCount;  
        }
    }
    if(splashed == true){
        timeElapsed = frameCount - explodeTime;
    for(var i = 0; i < 12; i++){
        if(timeElapsed == i){
            imageMode(CENTER);
            image(SPLASH[floor(i / 4)], dropX, dropY);
            }
        }
    }
    menuText(275);
  }
  //rain code animation
  else if(animation == 3){ 
    background(238, 252, 255);
    fill(80, 130, 200);
    textFont("courier", 16);
    textAlign(CENTER);
    text("click once for to make it rain...", width / 2, 30); // creates text guiding user to press a key
    text("click again for clear skies", width / 2, 55);
    if(fall){ 
      for(var i = 0; i < water.length; i++){
        water[i].render();
        water[i].fall();
      }
    }
    menuText(275);
  }
  //cohesion animation
  else if(animation == 4){ 
    background(238, 252, 255);
    textAlign(CENTER);
    noStroke();
    fill(80, 180, 200);
    textFont("courier", 16);
    text("click to see cohesion...", width / 2, 30);
    drop1.render();
    drop2.render();
    if(dist(drop1.x, drop1.y, drop2.x, drop2.y) > 0 & move){// if the two objects are not on top of each other and move == true
      drop1.x++;                                            // move the two drops towards each other and lessen the opacity of their strokes
      drop2.x--;
      opacity -= 1.3;
    }
    menuText(275);
  }
}
    
function keyTyped(){ // assigns a different value to the variable animation based on the key pressed
    if (key == 'r'){ 
      animation = 1;
    }
    if (key == 's'){ 
      animation = 2;
    } 
    if (key == 'u'){ 
      animation = 3;
    }                                             
    if (key == 'c'){ 
      animation = 4;
    } 
    
}

function menuText(posY){ //makes menu scroll with instructions
    noStroke();
    fill(80, 130, 200);
    textSize(10);
    text("press R for ripples", textStart1, posY);
    text("press S for splash", textStart2, posY);
    text("press U for rain", textStart3, posY);
    text("press C for cohesion", textStart4, posY);
    textStart1++;
    textStart2++;
    textStart3++;
    textStart4++;
    if(textStart1 > width){
        textStart1 = -140;
    }    
    if(textStart2 > width){
        textStart2 = -140;
    }
    if(textStart3 > width){
        textStart3 = -140;
    }
    if(textStart4 > width){
        textStart4 = -140;
    }
}

function mousePressed(){
  //variable reset for ripple code
  diam = 0;
  opacity = 100;
  rx = mouseX;
  ry = mouseY;
  if(animation == 2){
    numClick++;
    dropX = mouseX;
    dropY = 1;
    splashpoint = mouseY;
  }

  //rain
  if(animation == 3){
    numClicks++;
    if(numClicks%2 == 1){
      fall = true;
    }
    else{
      fall = false;
    }
  }

  //cohesion
  if(animation == 4){
    move = true;
  }
}

function ripple(px, py){ //draws ripples
  noFill();
  strokeWeight(2.5);
  stroke(0, 0, 255, opacity);
  ellipse(px, py, diam, diam);
  strokeWeight(2);
  ellipse(px, py, diam / 2, diam / 2);
  strokeWeight(1.5);
  ellipse(px, py, diam / 4, diam / 4);
}

function droplet(x, y){
  fill(26, 133, 192);
  //using the map function in order to expand the drop as it moves down
  var xmap = map(dropY, 0, height, 5, 15);
  var ymap = map(dropY, 0, height, 10, 30);
  noStroke();
  beginShape();
  curveVertex(x, y);
  curveVertex(x, y);
  curveVertex(x - xmap, y + ymap);
  curveVertex(x, y + ymap + xmap);
  curveVertex(x + xmap, y + ymap);
  curveVertex(x, y);
  curveVertex(x, y);
  endShape();    
}

//object implementation for cohesion animation
function drawDrop(){ //draws water drop for cohesion animation
  stroke(80, 130, 200, opacity);
  strokeWeight(3);
  fill(230, 242, 255);
  ellipse(this.x, this.y, this.w, this.w);
  noStroke();
}

function makeDrop(posX, posY, diam){//make water drop object for cohestion animation
  var drop = {x:posX, y:posY, w:diam, render:drawDrop};
  return drop;
}

//object implementation for rain animation
function makeRain(px, py, diam, velocity){ //make rain object
  var raindrop = {x:px, y:py, d:diam, v:velocity, render: drawRain, fall:rainFall};
  return raindrop;
}

//draws raindrop
function drawRain(){
  noStroke();
  fill(0, 10, 150, 60);
  ellipse(this.x, this.y, this.d, this.d);
  triangle(this.x - (this.d)/2, this.y, this.x, this.y - 5, this.x + (this.d)/2, this.y);
}

function rainFall(){
  this.v = random(0,8); //randomizess velocity variable
  this.y += this.v; //adds velocity to current y value of each rain drop objects so they'll fal at different speeds
  if(this.y >= height){ //resets rain drops to the top once it hits the bottom of the page
    this.y = 0;
  }
}

For this project, I collaborated with Erin Ryan from Lab section C to make a series of four water-based animations using different animation, interactive, and object oriented techniques. We coded the four interactive animations and the home screen separately, then used a series of conditionals to allow the user to toggle between different animations. We tried to establish cohesive visual language through use of color and simple shapes.

 

Initial sketches of water animations

Leave a Reply