Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
/*
 Due Oc 2 2017 10PM on SLATE
 Restricted to Ch 1-7 of Processing Text
 Intro to Media Computation
 Instructor: Nicolas Hesler
 "Seal Friend?" Interactive Toy Assignment
 By Catherine Doherty
 
 -click to make flickery fish and fishball darken, click to stop darkening
 -click on seal to make seal lighter, click out of seal to make seal darker
 -move seal with mouse
 -move seal to touch fishball to make fish red again, and fishball water blue again
 -hover over sky with mouse to make sky darken to a purple nightsky
 -hover mouse off sky to make sky lighten to day again
 */

////////////////////////////////////////////////////////////////////////////////
//////////////////// Declare (user-defined) variables:
////////////////////////////////////////////////////////////////////////////////

// Variables related to the Fish:
boolean fishColourClickToChangeDarknessBoolean = false;
float randomFishColour;
float redFishColourTurnsBlack=255;

// Variables related to the Fish Ball:
int diametreBall = 160;
int leftEdgeOfAreaForBall = 0;
int limitForBall = leftEdgeOfAreaForBall + (diametreBall/2);
float blueSphereColourTurnsBlack =255;
float bouncingFishBallX;
float bouncingFishBallY;
float bouncingFishBallXSpeed = 3;
float bouncingFishBallYSpeed = 3;

// Variables related to the Bouncing Ball Sun
float bouncingBallSunX;
float bouncingBallSunY;
float bouncingBallSunXSpeed = .5;
float bouncingBallSunYSpeed = 2;
float skyValueGreen = 240;

// Variables related to the Seal:
float sealHeadCentreX;
float sealHeadCentreY;
float sealColourGrey=100;
int diametreSealHead=120;
int leftEdgeOfAreaForSeal=40;
int limitForSeal = leftEdgeOfAreaForSeal + (diametreSealHead/2);
float diametreSealAndBall = diametreBall + diametreSealHead;

void setup () {
  // Set size of sketch window and rectmode to corners for convenience.
  size(400, 400);
  rectMode(CORNERS);
}

void draw () {
  // SKY - box for SKY with varialbe so it can become purple on mouseover
  fill(190, skyValueGreen, 245);
  rect(0, 0, width, 125);


  // Call these functions first so that they're behind the mountains.
  // THE STARS, THE SUN
  drawStars ();
  drawBouncingBallSun ();

  ////////////////////////////////////////////////////////////////////////////////
  ////////////////////Make Loops for MOUNTAINS
  ////////////////////////////////////////////////////////////////////////////////

  // Red Mountains
  for (int backfrontMountainLoopVariable = 0; backfrontMountainLoopVariable<9; backfrontMountainLoopVariable=backfrontMountainLoopVariable+1) {
    fill(100, 0, 0);
    triangle(backfrontMountainLoopVariable*50-10, 110, backfrontMountainLoopVariable*50+15, 90, backfrontMountainLoopVariable*50+40, 110);
  }

  // Green Mountains
  for (int middlefrontMountainLoopVariable = 0; middlefrontMountainLoopVariable<9; middlefrontMountainLoopVariable=middlefrontMountainLoopVariable+1) {
    fill(0, 100, 0);
    triangle(middlefrontMountainLoopVariable*100-20, 150, middlefrontMountainLoopVariable*100+40, 60, middlefrontMountainLoopVariable*100+80, 150);
  }

  // Blue Mountains
  for (int frontMountainLoopVariable = 0; frontMountainLoopVariable<9; frontMountainLoopVariable=frontMountainLoopVariable+1) {
    fill(0, 0, 100);
    triangle(frontMountainLoopVariable*100-70, 130, frontMountainLoopVariable*100-10, 80, frontMountainLoopVariable*100+30, 130);
  }

  // Call these functions, in this order so water is at back, seal is in front.
  // THE WATER, THE BALL, THE FISH, THE SEAL
  drawWater();
  drawBall();
  drawFish();
  drawSeal();

  // WATER - Transparent water in front of seal, so seal looks like its underwater (nose can poke over surface).
  noStroke();
  fill(10, 160, 240, 70);
  rect(0, 250, width, height);

  ////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////make FISHBALL stay in its box
  ////////////////////////////////////////////////////////////////////////////////////////////

  // Move the fishball.
  bouncingFishBallX = bouncingFishBallX + bouncingFishBallXSpeed;
  bouncingFishBallY = bouncingFishBallY + bouncingFishBallYSpeed;

  // If the fishball gets off the screen, turn it around. 
  if (bouncingFishBallX>width || bouncingFishBallX<0) {
    bouncingFishBallXSpeed = bouncingFishBallXSpeed*(-1);
  }
  if (bouncingFishBallY>170 || bouncingFishBallY<0) {
    bouncingFishBallYSpeed = bouncingFishBallYSpeed*(-1);
  }

  ////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////make SEAL stay in its box
  ////////////////////////////////////////////////////////////////////////////////////////////

  // Move the seal.
  if (abs(mouseX-sealHeadCentreX)>0.1) {
    sealHeadCentreX = sealHeadCentreX + (mouseX - sealHeadCentreX);
  }
  if (abs(mouseY-sealHeadCentreY)>0.1) {
    sealHeadCentreY = sealHeadCentreY + (mouseY - sealHeadCentreY);
  }

  // Constrain seal to under the water (except for nose).
  sealHeadCentreX = constrain(sealHeadCentreX, limitForSeal, width - limitForSeal);
  sealHeadCentreY = constrain(sealHeadCentreY, limitForSeal+205, height);

  ////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////make BOUNCING BALL SUN bounce
  ////////////////////////////////////////////////////////////////////////////////////////////

  // move the ball
  bouncingBallSunX = bouncingBallSunX +bouncingBallSunXSpeed;
  bouncingBallSunY = bouncingBallSunY +bouncingBallSunYSpeed;

  //if the ball gets off the screen, turn it around
  if (bouncingBallSunX>width || bouncingBallSunX<0) {
    bouncingBallSunXSpeed = bouncingBallSunXSpeed*(-1);
  }
  if (bouncingBallSunY>width/4 || bouncingBallSunY<0) {
    bouncingBallSunYSpeed = bouncingBallSunYSpeed*(-1);
  }

  ////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////make FISHBALL COLLISION WITH SEAL change fishball colour
  ////////////////////////////////////////////////////////////////////////////////////////////
  // When the seal's nose and the fishball come into contact, fish turns red again and water blue.

  // You can click to start and stop darkening, but you can't get back to light blue unless nose touches fishball:
  // if you get a number lower than the combined diametres of the seal and ball when 
  // you subtract the Y and X coordinants of the seal from the X and Y coordinants of the ball,
  // it means they're in contact: so turn fish and fishball back to light blue.
  // I multiplied X-coordinant distances by 5 because I only want the contact point (nose and tip of ball) to change the colour,
  // so you actually have to move the seal most of the time.
  // The collision thing below is modified from something Phill said in Discord:
  // if (abs(ax - bx) * 2 < (awidth + bwidth)) && (abs(ay - by) * 2 < (aheight + bheight)){do something}
  if (abs(bouncingFishBallX - sealHeadCentreX)*5<diametreSealAndBall && abs(bouncingFishBallY - sealHeadCentreY)*2<diametreSealAndBall) {
    redFishColourTurnsBlack=255;
    blueSphereColourTurnsBlack=255;
  }

  // FISH - Click to make fish dark flickering grey and water dark.
  if (fishColourClickToChangeDarknessBoolean) {
    redFishColourTurnsBlack = redFishColourTurnsBlack-1;
    blueSphereColourTurnsBlack = blueSphereColourTurnsBlack-1;
  }

  // SKY - If you hover cursor over sky, sky turns purple and can see the stars, if hover off of sky, sky turns back to greenish/bluish.
  // I wrote it this way, because otherwise it counts up infinitely so that it looks like it has stopped working after hovering over one too long.
  if (mouseY > 0 && mouseY < 125 && skyValueGreen > 0) {
    skyValueGreen = skyValueGreen-1;
  } else if (mouseY > 125 && skyValueGreen < 240) {
    skyValueGreen = skyValueGreen+1;
  }

  ////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////William Lu's MOUSE POSITION AID ////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////////
  // Modified from William Lu's San Francisco piece, to see pointer's (x,y) coordinants: 
  //fill (0);
  //text(" x: "+mouseX+" y: "+mouseY+"  ", 10, 15);

  ////////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////end of draw
  ////////////////////////////////////////////////////////////////////////////////////////////
}

////////////////////////////////////////////////////////////////////////////////////////////
////////////////////Make a function to draw STARS
////////////////////////////////////////////////////////////////////////////////////////////

void drawStars () {
  stroke(255);
  point(5, 80);
  point(27, 17);
  point(42,7);
  point(75, 58);
  point(157, 70);
  point(175, 22);
  point(254, 38);
  point(310, 66);
  point(320, 60);
  point(375, 79);
  point(381, 4);
}

////////////////////////////////////////////////////////////////////////////////////////////
////////////////////Make a function to draw THE WATER in the background
////////////////////////////////////////////////////////////////////////////////////////////

void drawWater() {
  //water modified from last assignment (my Interactive Art assignment called "Rain Maker")
  noStroke();
  fill(0, 150, 255);
  rect(0, 125, width, height);
  fill(0, 147, 252);
  rect(0, 128, width, height);
  fill(0, 142, 247);
  rect(0, 136, width, height);
  fill(0, 134, 239);
  rect(0, 149, width, height);
  fill(0, 121, 226);
  rect(0, 170, width, height);
  fill(0, 87, 192);
  rect(0, 204, width, height);
  //white line to mark difference between surface and underwater
  fill(255); 
  rect(0, 248, width, height);
  fill(0, 50, 107);
  rect(0, 250, width, height);
}

////////////////////////////////////////////////////////////////////////////////////////////
////////////////////Make a function to draw THE BOUNCING BALL SUN
////////////////////////////////////////////////////////////////////////////////////////////

void drawBouncingBallSun () {
  fill(250, 250, 0);
  stroke(255);
  ellipse(bouncingBallSunX, bouncingBallSunY, 25, 25);
  noStroke();
}

////////////////////////////////////////////////////////////////////////////////////////////
////////////////////Make a function to draw THE BALL
////////////////////////////////////////////////////////////////////////////////////////////

void drawBall() {
  // THE BALL
  fill(blueSphereColourTurnsBlack-200, blueSphereColourTurnsBlack-42, blueSphereColourTurnsBlack);
  ellipse(bouncingFishBallX, bouncingFishBallY, diametreBall, diametreBall);
  // AIR SPACE - draw at the top
  fill(190, 240, 245);
  arc(bouncingFishBallX, bouncingFishBallY, diametreBall, diametreBall, radians(240), radians(300));
}

////////////////////////////////////////////////////////////////////////////////////////////
////////////////////Make a function to draw THE FISH
////////////////////////////////////////////////////////////////////////////////////////////

void drawFish() {
  // FLICKER - using random:
  randomFishColour = random(20, 80);
  //want to be able to make fish dark, so red is also a variable:
  fill(redFishColourTurnsBlack, randomFishColour, 50);

  noStroke();

  // FINS
  triangle(bouncingFishBallX-20, bouncingFishBallY-5, bouncingFishBallX+10, bouncingFishBallY-30, bouncingFishBallX+10, bouncingFishBallY-15);
  triangle(bouncingFishBallX-15, bouncingFishBallY+5, bouncingFishBallX+10, bouncingFishBallY+5, bouncingFishBallX+10, bouncingFishBallY+30);

  // TAIL
  triangle(bouncingFishBallX+25, bouncingFishBallY, bouncingFishBallX+50, bouncingFishBallY-30, bouncingFishBallX+50, bouncingFishBallY+30);

  // DIVIT - cover tail with blue triangle that darkens when fishball darkens
  fill(55, blueSphereColourTurnsBlack-42, blueSphereColourTurnsBlack);
  triangle(bouncingFishBallX+50, bouncingFishBallY-5, bouncingFishBallX+45, bouncingFishBallY, bouncingFishBallX+50, bouncingFishBallY+5);

  //BODY
  //degrees translated into radians for fish body arcs
  //lower arc
  fill(redFishColourTurnsBlack, randomFishColour, 50);
  arc(bouncingFishBallX, bouncingFishBallY-5, 60, 48, radians(10), radians(170));
  //upper arc
  arc(bouncingFishBallX, bouncingFishBallY+5, 60, 48, radians(190), radians(350));

  // MOUTH
  stroke(0);
  line(bouncingFishBallX-30, bouncingFishBallY, bouncingFishBallX-20, bouncingFishBallY);

  // GILLS
  line(bouncingFishBallX-10, bouncingFishBallY+10, bouncingFishBallX, bouncingFishBallY);
  line(bouncingFishBallX-5, bouncingFishBallY+15, bouncingFishBallX+5, bouncingFishBallY+5);

  // EYE
  fill(255);
  strokeWeight(1.5);
  ellipse(bouncingFishBallX-13, bouncingFishBallY-8, 6, 6);
  //put strokeWeight back to normal
  strokeWeight(1);
}

////////////////////////////////////////////////////////////////////////////////////////////
////////////////////Make a function to draw THE SEAL
////////////////////////////////////////////////////////////////////////////////////////////

void drawSeal() {
  // Seal's whiskers, neck, nose, head, eyes:

  // WHISKERS
  stroke(0);
  line(sealHeadCentreX, sealHeadCentreY-60, sealHeadCentreX+60, sealHeadCentreY-50);
  line(sealHeadCentreX-60, sealHeadCentreY-50, sealHeadCentreX, sealHeadCentreY-60);
  line(sealHeadCentreX, sealHeadCentreY-56, sealHeadCentreX+30, sealHeadCentreY-60);
  line(sealHeadCentreX-30, sealHeadCentreY-60, sealHeadCentreX, sealHeadCentreY-56);

  // NECK
  fill(sealColourGrey);
  noStroke();
  quad(sealHeadCentreX-60, sealHeadCentreY, sealHeadCentreX+60, sealHeadCentreY, 300, 400, 100, 400);

  // NOSE 
  fill(255, 173, 182);
  // To make it easier to follow mouse, briefly set rectMode to centre:
  rectMode(CENTER);
  // Rect's 5th parametre is for rounded corners.
  rect(sealHeadCentreX, sealHeadCentreY-60, 20, 20, 7);
  // Back to corners mode for everything that follows.
  rectMode(CORNERS);

  // HEAD
  fill(sealColourGrey);
  ellipse(sealHeadCentreX, sealHeadCentreY, diametreSealHead, diametreSealHead);

  // EYES
  // Thicker black stroke:
  stroke(0);
  strokeWeight(3);
  line(sealHeadCentreX+15, sealHeadCentreY-45, sealHeadCentreX+30, sealHeadCentreY-40);
  line(sealHeadCentreX-30, sealHeadCentreY-40, sealHeadCentreX-15, sealHeadCentreY-45);
  // Reset stroke weight to 1 for everything that follows.
  strokeWeight(1);
}


////////////////////////////////////////////////////////////////////////////////////////////
////////////////////Make a MOUSE CLICK do a thing
////////////////////////////////////////////////////////////////////////////////////////////

// Things that clicking the mouse causes:
// If click (once) on sketch window, fish and fishball start to turn darker until dark grey -  
// click to stop, but only turns light again if ball touches seal nose.
// If click (repeatedly) on water surface or above, or to either side of seal, seal turns darker.
// If click (repeatedly) on seal, seal turns lighter.
void mousePressed() {
  fishColourClickToChangeDarknessBoolean = !fishColourClickToChangeDarknessBoolean;
  if (mouseX > 40 && mouseX < 360 && mouseY > 250) {
    sealColourGrey=sealColourGrey+5;
  } else {
    sealColourGrey=sealColourGrey-5;
  }
}