Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
/***************************************************
 *File Name: Hair_Wash
 *Author: Sin I Lei
 *Date: Oct 15, 2016
 *Descrpition: An interactive toy featuring
 *a girl at a hair salon
 *Click on the bubble icon then her hair to apply shampoo
 *Click on the shower icon then her hair to rinse the bubbles
 **************************************************/

// Declare variables
Girl girl1;
IconBubble iconBubbleButton;
IconShower iconShowerButton;
IconBubble iconBubbleMouse;
IconShower iconShowerMouse;

// Declare array of bubbles
Bubbles[] bubbles = new Bubbles [60];

//Boolean to check which mode is on
Boolean bubbleMode = false;
Boolean showerMode = false;

//Timer variable to count the number of frames
int timer =0;




void setup () {
  size(400, 400);
  println("Click on the bubble icon then her hair to apply shampoo");
  println("Click on the shower icon then her hair to rinse the bubbles");

  // Initialize girl object
  girl1 = new Girl();

  // Initialize Bubble button at top
  iconBubbleButton = new IconBubble(240, 40);

  // Initialize Shower button at top
  iconShowerButton = new IconShower(150, 40);

  // Inialize bubbles array
  for (int i=0; i<bubbles.length; i++) {
    bubbles[i]=new Bubbles();
  }
}



void draw() {

  //background settings
  background(178, 235, 230);
  girl1.display();
  iconBubbleButton.display();
  iconShowerButton.display();

  //mode check
  bubbleCheck ();
  showerCheck ();
  bubbleMouse ();
  showerMouse ();


  //check if mouse is clicked on the hair when bubble mode is on
  for (int i=0; i<bubbles.length; i++) {
    bubbles[i].hairBubbleCheck();
  }

  //when mouse is pressed the timer starts counting
  timeCount();
  //update bubbles location every 10 frames if mouse clicks on hair while in bubble mode
  updateBubbles();
  //display bubbles
  displayBubbles();

  //check if mouse is clicked on the bubbles when shower mode is on
  for (int i=0; i<bubbles.length; i++) {
    bubbles[i].hairShowerCheck();
  }
  //make bubbles disappear if click on bubbles in shower mode
  rinseBubbles();
}



//////////////////////BUBBLE OR SHOWER MODE FUNCTIONS/////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

// Turn on bubble mode if mouse pressed on bubble button
void bubbleCheck () {
  if ((mousePressed==true) && (mouseX>230) && (mouseX<260) && (mouseY>30) && (mouseY<60)) {
    bubbleMode= true;
    showerMode= false;
  }
}

// Turn on shower mode if mouse pressed on shower button
void showerCheck () {
  if ((mousePressed==true) && (mouseX>130) && (mouseX<180) && (mouseY>30) && (mouseY<60)) {
    showerMode= true;
    bubbleMode= false;
  }
}

// Draw bubble as mouse cursor if bubble mode is on
void bubbleMouse () {
  if (bubbleMode==true) {
    iconBubbleMouse = new IconBubble(mouseX, mouseY);
    iconBubbleMouse.display();
  }
}

// Draw shower as mouse cursor if shower mode is on
void showerMouse () {
  if (showerMode==true) {
    iconShowerMouse = new IconShower(mouseX, mouseY);
    iconShowerMouse.display();
  }
}

///////////////////////CREATE BUBBLES AND RINSE BUBBLES FUNCTIONS////////////////////
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////


// Make bubbles disappear if mouse clicks on hair when shower mode is on
void rinseBubbles () {

  for (int i=0; i<bubbles.length; i++) {
    if (bubbles[i].hairClickShower==true) {
      bubbles[i].reset();
    }
  }
}

// Add time whenever mouse is clicked
void timeCount() {
  if (mousePressed==true) {
    timer++;
  }
}

// Update bubble when clicked on hair in bubble mode each time 10 frames has passed
void updateBubbles() {
  for (int i=0; i<bubbles.length; i++) {
    if (timer>=10 && bubbles[i].hairClickBubble==true && bubbles[i].releaseCheck==false) {
      bubbles[i].location= new PVector(mouseX, mouseY);
      //only release bubble that has not been released yet
      bubbles[i].releaseCheck=true;
      timer=0;
    }
  }
}

// Display bubbles that has been updated
void displayBubbles() {
  for (int i=0; i<bubbles.length; i++) {
    if (bubbles[i].releaseCheck==true ) {
      bubbles[i].update();
      bubbles[i].edgeLimit();
      bubbles[i].display();
    }
  }
}
class Bubbles {
  PVector location;
  PVector velocity;
  PVector acceleration;
  PVector mouse;
  PVector dir;
  float topspeed;
  //Boolean to check if mouse is clicked on hair in Bubble and Shower mode
  Boolean hairClickBubble = false;
  Boolean hairClickShower = false;
  //Boolean to check if bubble is released yet
  Boolean releaseCheck = false;

  Bubbles () {
    velocity = new PVector(random(-0.5, 0.5), random(-0.5, 0.5));
    acceleration = new PVector(0, 0);
    topspeed = 0.2;
  }

  void update() {
    // make bubbles slowly follow the mouse
    PVector mouse = new PVector(mouseX, mouseY);
    PVector dir = PVector.sub(mouse, location);
    dir.normalize();
    dir.mult(0.02);
    acceleration = dir;
    velocity.add(acceleration);
    velocity.limit(topspeed);
    location.add(velocity);
  }

  void edgeLimit() {
    // constrain bubbles to stay inside hair area
    if (location.x > 270 || location.x < 130 || ((location.x >160) && (location.x<240) && (location.y>200))) {
      velocity.x = velocity.x * -1;
    }
    if (location.y > 290 || location.y < 150 || ((location.x > 160) && (location.x < 240) && (location.y>200))) {
      velocity.y = velocity.y * -1;
    }
  }

  void display() {
    stroke(255);
    fill(255, 255, 255, 100);
    ellipse(location.x, location.y, 25, 25);
  }

  void reset() {
    // reset bubble location ouside of screen to seem like they disappear
    location= new PVector(500, 500);
    hairClickBubble= false;
    // when bubble disappear reset their release status to false
    releaseCheck = false;
  }

  // Check if mouse clicked on hair when bubble mode is on
  void hairBubbleCheck() {
    if ((mousePressed==true) && (bubbleMode==true) && (((mouseX>130) && (mouseX<160))  || ((mouseX>240) && (mouseX<270)) || ((mouseX>130) && (mouseX<270) && (mouseY>150) && (mouseY<200))) && (mouseY>150) && (mouseY<290)) {
      if (hairClickBubble == false)
      {
        hairClickShower=false;
      }
      hairClickBubble = true;
    } else
    {
      hairClickBubble = false;
    }
  }

  //Check if mouse clicked on hair when shower mode is on
  void hairShowerCheck() {
    // bubbles have no location before released so this function will crash, add if statement to make sure location is not null
    if (location != null)
    {
      if ((mousePressed==true) && (showerMode==true) && (dist(mouseX, mouseY, location.x, location.y))<30) {
        hairClickShower = true;
      }
    }
  }
}
class Girl {

  void display() {
    noStroke();

    //body
    fill (170, 70, 70);
    triangle(200, 220, 280, 400, 120, 400);

    //face
    fill(255, 251, 247);
    ellipse(200, 220, 120, 120);
    //eyes
    fill (0);
    ellipse(180, 220, 10, 20);
    ellipse(220, 220, 10, 20);
    //mouth
    stroke(0);
    fill(255, 251, 247);
    arc(200, 250, 60, 20, 0, PI);

    //hair
    noStroke();
    fill(252, 230, 161);
    triangle(160, 270, 160, 290, 130, 270);
    quad(160, 270, 160, 200, 130, 200, 130, 270);
    triangle(240, 270, 240, 290, 270, 270);
    quad(240, 270, 270, 270, 270, 200, 240, 200);
    arc(200, 200, 140, 100, PI, TWO_PI);
  }
}
class IconBubble {

  float iconBubbleX;
  float iconBubbleY;


  IconBubble (float x_, float y_) {
    iconBubbleX= x_;
    iconBubbleY= y_;
  }

  void display() {
    fill(255, 255, 255, 150);
    stroke(255);
    strokeWeight(3);
    ellipse(iconBubbleX, iconBubbleY, 20, 20);
    ellipse(iconBubbleX+10, iconBubbleY+10, 10, 10);
  }
}
class IconShower {

  float iconShowerX;
  float iconShowerY;


  IconShower (float x_, float y_) {
    iconShowerX= x_;
    iconShowerY= y_;
  }

  void display() {
    fill(150);
    stroke(0);

    //shower head
    quad(iconShowerX, iconShowerY-10, iconShowerX+10, iconShowerY, iconShowerX, iconShowerY+10, iconShowerX-10, iconShowerY);
    //shower handle
    quad(iconShowerX+10, iconShowerY, iconShowerX+25, iconShowerY+15, iconShowerX+20, iconShowerY+20, iconShowerX+5, iconShowerY+5);
    //water
    stroke(37, 138, 191);
    line(iconShowerX-7, iconShowerY+7, iconShowerX-15, iconShowerY+15);
    line(iconShowerX-15, iconShowerY+5, iconShowerX-20, iconShowerY+10);
    line(iconShowerX-5, iconShowerY+15, iconShowerX-10, iconShowerY+20);
  }
}