/***************************************************
*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);
}
}