// 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.