Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
/***************************************************************
 * Interactive Firefly-powered Television Cabinet              *
 * By Connor "Ramtan" Gilhuly                                  *
 *                                                             *
 * Ever wanted an interactive television that can only be      *
 * powered inconvienently by a firefly (whose name is kind of  *
 * a misnomer, since he has more to do with electricity than   *
 * he does with actual fire)? Well then you're in luck!        *
 *                                                             *
 * Each television cabinet comes with three interactive        *
 * channels, and your own firefly pet to power the television! *
 * Simply wake him up whenever you want to watch TV, and it'll *
 * do the rest.                                                * 
 *                                                             *
 * This particular cabinet comes with 3 channels. Enjoy!       *
 ***************************************************************/


void setup (){
  size (400, 400);
  frameRate(60);
  println("(Click the Firefly to wake him up)");
  rectMode(CORNERS);
}

int ffx = 85;
int ffy = 320;

int sequence = 0;
int f = 0;
String face = "sleep";

int channel = 0;
boolean powered = false;
int search = 60;

boolean flying = false;
boolean animating = false;

void draw() {
  background(20);
  
  drawChannel();
  
  drawCabinet();
  
  updateFirefly();
  drawFirefly();
  
}

void keyPressed(){
  //If TV is on when Space is pressed, change channel. Randomly.
  if (key == ' ' && powered) {
    search = 60;
    channel ++;
    if (channel >= 3){
      channel = 0;
    }
  }
}

void mouseClicked(){
  if (!animating){
    if (!powered){
      if (mouseX >= 50 && mouseX <= 110 && mouseY >= 280 && mouseY <= 350 && sequence == 0){
        animating = true;
        sequence = 1;
        face = " ";
        println("Oh, I'm sorry! I'll get right to work!");
      } 
    } else if (mouseX >= 290 && mouseX <= 370 && mouseY >= 290 && mouseY <= 370 && sequence == 7){
        animating = true;
        face = "mad";
        sequence = 8;
        println("Hey! Don't touch me while I'm at work!");
    }
  }
}

//The fuzzy b/w screen that is shown for a moment when you change the channel.
void screenFuzz(int vis) {
  for (int x = 40; x < 360; x += 5){
    for (int y = 20; y < 280; y += 5){
      float shade = random(256);
      fill(shade, shade, shade, vis);
      noStroke();
      rect(x, y, x+5, y+5);
    }  
  }
}

void drawChannel() {
  if (powered) {
    if (search <= 0) {
        if (channel == 0){
          //Sirens singing
          //Sunset
          fill(255, 140, 0);
          rect(60, 40, 340, 260);
          fill(255, 255, 0);
          ellipse(200, 190, 100, 100);
          fill(255);
          ellipse(200, 190, 80, 80);
          
          //Musical Note
          fill(0);
          ellipse(mouseX, (mouseY/10)*10, 10, 8);
          stroke(0);
          line(mouseX+5, (mouseY/10)*10, mouseX+5, (mouseY/10)*10 - 25);
          if (((mouseY/10)*10) % 20 == 10){
            line(mouseX-9, (mouseY/10)*10, mouseX+9, (mouseY/10)*10);
          }
          noStroke();
          
          //Left Siren
          fill(#84D684);
          ellipse(135, sirenPos(140, 112), 8, 8);
          ellipse(145, sirenPos(140, 112), 8, 8);
          quad(132, sirenPos(140, 112), 138, sirenPos(140, 112), 130, sirenPos(140, 135), 125, sirenPos(140, 130));
          quad(148, sirenPos(140, 112), 142, sirenPos(140, 112), 150, sirenPos(140, 135), 155, sirenPos(140, 130));
          triangle(130, sirenPos(140, 135), 125, sirenPos(140, 130), 110, sirenPos(140, 145));
          triangle(150, sirenPos(140, 135), 155, sirenPos(140, 130), 170, sirenPos(140, 145));
          fill(140, 110, 255);
          rect(138, sirenPos(140, 112), 142, sirenPos(140, 150));
          ellipse(140, sirenPos(140, 110), 10, 10);
          ellipse(158, sirenPos(140, 120), 4, 4);
          ellipse(132, sirenPos(140, 125), 4, 4);
          strokeWeight(2);
          stroke(140, 110, 255);
          line(142, sirenPos(140, 114), 158, sirenPos(140, 120));
          line(138, sirenPos(140, 114), 132, sirenPos(140, 125));
          noStroke();
          ellipse(138, sirenPos(140, 119), 6, 6);
          ellipse(142, sirenPos(140, 119), 6, 6);
          
          //Mid Siren
          fill(#84D684);
          ellipse(195, sirenPos(200, 112), 8, 8);
          ellipse(205, sirenPos(200, 112), 8, 8);
          quad(192, sirenPos(200, 112), 198, sirenPos(200, 112), 190, sirenPos(200, 135), 185, sirenPos(200, 130));
          quad(208, sirenPos(200, 112), 202, sirenPos(200, 112), 210, sirenPos(200, 135), 215, sirenPos(200, 130));
          triangle(190, sirenPos(200, 135), 185, sirenPos(200, 130), 170, sirenPos(200, 145));
          triangle(210, sirenPos(200, 135), 215, sirenPos(200, 130), 230, sirenPos(200, 145));
          fill(200, 110, 255);
          rect(198, sirenPos(200, 112), 202, sirenPos(200, 150));
          ellipse(200, sirenPos(200, 110), 10, 10);
          ellipse(218, sirenPos(200, 120), 4, 4);
          ellipse(192, sirenPos(200, 125), 4, 4);
          strokeWeight(2);
          stroke(200, 110, 255);
          line(202, sirenPos(200, 114), 218, sirenPos(200, 120));
          line(198, sirenPos(200, 114), 192, sirenPos(200, 125));
          noStroke();
          ellipse(198, sirenPos(200, 119), 6, 6);
          ellipse(202, sirenPos(200, 119), 6, 6);
          
          //Right Siren
          fill(#84D684);
          ellipse(255, sirenPos(260, 112), 8, 8);
          ellipse(265, sirenPos(260, 112), 8, 8);
          quad(252, sirenPos(260, 112), 258, sirenPos(260, 112), 250, sirenPos(260, 135), 245, sirenPos(260, 130));
          quad(268, sirenPos(260, 112), 262, sirenPos(260, 112), 270, sirenPos(260, 135), 275, sirenPos(260, 130));
          triangle(250, sirenPos(260, 135), 245, sirenPos(260, 130), 230, sirenPos(260, 145));
          triangle(270, sirenPos(260, 135), 275, sirenPos(260, 130), 290, sirenPos(260, 145));
          fill(255, 40, 50);
          rect(258, sirenPos(260, 112), 262, sirenPos(260, 150));
          ellipse(260, sirenPos(260, 110), 10, 10);
          ellipse(278, sirenPos(260, 120), 4, 4);
          ellipse(252, sirenPos(260, 125), 4, 4);
          strokeWeight(2);
          stroke(255, 40, 50);
          line(262, sirenPos(260, 114), 278, sirenPos(260, 120));
          line(258, sirenPos(260, 114), 252, sirenPos(260, 125));
          noStroke();
          ellipse(258, sirenPos(260, 119), 6, 6);
          ellipse(262, sirenPos(260, 119), 6, 6);
          
          //Water and rocks
          noStroke();
          fill(200);
          ellipse(140, 195, 37, 120);
          ellipse(195, 200, 40, 140);
          ellipse(255, 197, 42, 134);
          fill(60, 60, 255);
          for (int w = 60; w <= 340; w += 20){
            triangle(w, 180, w+10, 190, w-10, 190);
          }
          rect(40, 190, 340, 260);
          
          //Then I noticed that nothing else in this program changes the stroke weight.
          strokeWeight(1);
          
          
        } else if (channel == 1) {
          //Just guess at what this is. Just guess.
          
          background(20);
          fill(130);
          rect(60, 40, 100, 260);
          rect(220, 40, 260, 260);
          rect(260, 140, 340, 260);
          fill(190);
          rect(230, 80, 250, 120);
          fill(255);
          rect(233, 83, 247, 97);
          fill(255, 0, 0);
          rect(233, 103, 247, 117);
          
          //Flickering Glowy eyes of potential doom.
          int showEyes = int(random(21));
          if (mouseX > 265 && showEyes < 10){
            fill(200);
            ellipse(305, 90, 18, 30);
            ellipse(275, 90, 18, 30);
            fill(255);
            ellipse(304, 92, 10, 20);
            ellipse(274, 92, 10, 20);
          }
          
          //Person who is probably going to die.
          fill(200);
          quad(202, 210, 207, 207, 220, 230, 212, 230);
          rect(230, 230, 242, 300);
          fill(#FF891A);
          quad(170, 160, 180, 150, 209, 209, 200, 212);
          rect(210, 230, 260, 240);
          fill(#4389FF);
          quad(187, 130, 230, 210, 210, 210, 175, 140);
          rect(183, 146, 195, 230);
          fill(#3D6CBC);
          quad(210, 210, 220, 230, 260, 230, 280, 210);
          rect(260, 210, 280, 300);
          fill(#FFF6DE);
          ellipse(190, 236, 20, 20);
          ellipse(170, 130, 44, 40);
          fill(0);
          ellipse(165, 114, 16, 8);
          fill(#FFF6DE);
          ellipse(165, 114, 14, 6);
          quad(165, 113, 159, 130, 148, 126, 160, 113);
          triangle(174, 112, 186, 102, 183, 120);
          fill(#4389FF);
          quad(130, 120, 142, 125, 150, 153, 145, 165);
          fill(0);
          quad(142, 125, 150, 153, 157, 157, 147, 104);
          ellipseMode(CORNERS);
          ellipse(187, 128, 187 - (mouseY/40.0 + 4), 128 + (mouseY/40.0 + 4));
          ellipseMode(CENTER);
          
          //And a slight video fuzz effect to add a bit of atmosphere :)
          screenFuzz(20);
          
          fill(255);
          text("CAM 0", 100, 70);
          
        } else if (channel == 2) {
          //Pole-dancing Bee
          background(#FF8ED0);
          fill(0);
          ellipse(200, 90, 16, 16);
          fill(50, 255, 50);
          rect(195, 40, 205, 210);
          ellipse(200, 210, 10, 5);
          stroke(0);
          line(192, 90, 190+(mouseX-200)/8, 110);
          noStroke();
          fill(255, 255, 255, 100);
          ellipse(246+(mouseX-200)/4, 90, 34, 100);
          ellipse(294+(mouseX-200)/4, 90, 34, 100);
          stroke(0);
          line(190+(mouseX-200)/8, 110, 240+(mouseX-200)/4, 130);
          line(260+(mouseX-200)/4, 110, 230+(mouseX-200)/4, 70);
          line(215+(mouseX-200)/4, 90, 230+(mouseX-200)/4, 70);
          line(260+(mouseX-200)/4, 110, 290+(mouseX-200)/4, 70);
          line(305+(mouseX-200)/4, 90, 290+(mouseX-200)/4, 70);
          noStroke();
          fill(250, 250, 0);
          ellipse(270+(mouseX-200)/4, 150, 48, 48);
          fill(#6A4216);
          ellipse(260+(mouseX-200)/4, 110, 60, 60);
          ellipse(255+(mouseX-200)/4, 178, 66, 66);
          rect(246+(mouseX-200)/4, 144, 294+(mouseX-200)/4, 156);
          stroke(0);
          fill(0);
          line(290+(mouseX-200)/4, 140, 304+(mouseX-200)/4, 160);
          line(304+(mouseX-200)/4, 160, 287+(mouseX-200)/4, 180);
          noStroke();
          ellipse(289+(mouseX-200)/4, 180, 10, 16);
          fill(250, 250, 0);
          ellipse(258+(mouseX-200)/4, 110, 54, 54);
          ellipse(250+(mouseX-200)/4, 182, 61, 61);
          fill(0);
          ellipse(248+(mouseX-200)/4, 108, 10, 20);
          ellipse(266+(mouseX-200)/4, 108, 10, 20);
          ellipse(245+(mouseX-200)/4, 187, 10, 10);
          triangle(245+(mouseX-200)/4, 182, 245+(mouseX-200)/4, 192, 214+(mouseX-200)/4, 200);
          fill(250, 250, 0);
          rect(238+(mouseX-200)/4, 94, 276+(mouseX-200)/4, 108);
        }
        
        //One quick note that I'm placing here because I'm not sure where else to put it:
        //The firefly finds channel 1 scary...
        if (channel == 1){
          face = "sad";
        } else {
          if (face != "mad"){
            face = " ";
          }
        }
    } else {
      screenFuzz(255);
      search--;
    }
  } 
}

int sirenPos(int x, int y){
  return (abs(x-mouseX)/2+y);
}

void updateFirefly(){
  /*If framerate is 60 fps, and f increases by 1
    with every frame, then 1 second should have
    passed when f == 60*/
  if (sequence == 1){
    f ++;
    if (f >= 180){
      sequence = 2;
      flying = true;
      f = 0;
    }
  } else if (sequence == 2) {
    ffy -= 1;
    if (ffy <= 160){
      sequence = 3;
    }
  } else if (sequence == 3) {
    ffx += 1;
    if (ffx >= 315){
      sequence = 4;
    }
  } else if (sequence == 4) {
    f ++;
    if (f >= 60){
      sequence = 5;
      f = 10;
    }
  } else if (sequence == 5) {
    if (ffy - f >= 340) {
      ffy = 340;
      sequence = 6;
      flying = false;
      animating = false;
      f = 0;
    } else {
      ffy -= f;
      f --;
    }
  } else if (sequence == 6) {
    f ++;
    if (f >= 100) {
      f = 0;
      sequence = 7;
      powered = true;
    }
  } else if (sequence == 8) {
    f++;
    if (f >= 200){
      face = " ";
      sequence = 9;
      f = 0;
      powered = false;
      println("I'm going back to bed!");
      flying = true;
    }
  } else if (sequence == 9) {
    ffy -= 1;
    if (ffy <= 160){
      sequence = 10;
    }
  } else if (sequence == 10) {
    ffx -= 1;
    if (ffx <= 85) {
      sequence = 11;
      println("Good night!");
    }
  } else if (sequence == 11) {
    f ++;
    if (f >= 60){
      f = 10;
      sequence = 12;
      face = "sleep";
    }
  } else if (sequence == 12){
    if (ffy - f >= 320) {
      ffy = 320;
      sequence = 0;
      flying = false;
      animating = false;
      f = 0;
    } else {
      ffy -= f;
      f --;
    }
  }
}

void drawFirefly(){
    //Tail
    noStroke();
    if (powered){
      fill(255, 255, 0, 150);
      ellipse(ffTailGloX(), ffTailGloY(), 80, 80);
    }
    fill(255, 255, 0);
    ellipse(ffTailX(), ffTailY(), 40, 40);
    
    //Torso
    fill(0, 255, 255);
    ellipse(ffTorsoX(), ffTorsoY(), 40, 40);
    quad(ffx+20, ffy, ffx-20, ffy, ffTorsoX()-20, ffTorsoY(), ffTorsoX()+20, ffTorsoY());
    quad(ffx, ffy+20, ffx, ffy-20, ffTorsoX(), ffTorsoY()-20, ffTorsoX(), ffTorsoY()+20);
    
    //Wings
    fill(255, 255, 255, 100);
    ellipseMode(CORNERS);  
    if (animating && frameCount%2==0){
      ellipse(ffx-2, ffy-5, ffx-25, ffy-70);
      ellipse(ffx+2, ffy-5, ffx+25, ffy-70);
    } else {
      ellipse(ffx-2, ffy-5, ffx-70, ffy-25);
      ellipse(ffx+2, ffy-5, ffx+70, ffy-25);
    }
    ellipseMode(CENTER);
    
    //Antannae
    stroke(0);
    strokeWeight(1);
    line(ffx-10, ffy-10, ffx-20, ffy-25);
    line(ffx-20, ffy-25, ffx-25, ffy-15);
    line(ffx+10, ffy-10, ffx+20, ffy-25);
    line(ffx+20, ffy-25, ffx+25, ffy-15);
    
    //Arms
    noFill();
    if (flying){
      curve(ffx+40, ffy, ffx-10, ffy+10, ffx-10, ffy+40, ffx+30, ffy+60);
      curve(ffx-40, ffy, ffx+10, ffy+10, ffx+10, ffy+40, ffx-30, ffy+60);
    } else {
      curve(ffx+100, ffy+10, ffx-10, ffy+10, ffx-10, ffy+20, ffx+100, ffy+20);
      curve(ffx-100, ffy+10, ffx+10, ffy+10, ffx+10, ffy+20, ffx-100, ffy+20);
    }
      
    //Head  
    noStroke();
    fill(0, 255, 255);
    ellipse(ffx, ffy, 40, 40);
  
    //Face (Handled in seperate function)
    ffFace();
    
    //Hands
    fill(0);
    if (flying){
      ellipse(ffx-10, ffy+40, 10, 10);
      ellipse(ffx+10, ffy+40, 10, 10);
    } else {
      ellipse(ffx-10, ffy+20, 10, 10);
      ellipse(ffx+10, ffy+20, 10, 10);
    }
}

//Draw the FF's eyes, then cover some of them to invoke some sort of facial expression.
void ffFace(){
  fill(255, 255, 0);
  ellipse(ffEyesX()-7, ffEyesY(), 7, 14);
  ellipse(ffEyesX()+7, ffEyesY(), 7, 14);
  fill(0, 255, 255);
  if (face == "sleep"){
      ellipse(ffEyesX()-7, ffEyesY(), 4, 10);
      ellipse(ffEyesX()+7, ffEyesY(), 4, 10);
      quad(ffEyesX()+12, ffEyesY(), ffEyesX()-12, ffEyesY(), ffEyesX()-10, ffEyesY()-7, ffEyesX()+10, ffEyesY()-7);
  }
  if (face == "mad"){
    triangle(ffEyesX()-3, ffEyesY(), ffEyesX()-10, ffEyesY()-7, ffEyesX()-4, ffEyesY()-7);
    triangle(ffEyesX()+3, ffEyesY(), ffEyesX()+10, ffEyesY()-7, ffEyesX()+4, ffEyesY()-7);
  }
  if (face == "sad"){
    triangle(ffEyesX()-11, ffEyesY(), ffEyesX()-10, ffEyesY()-7, ffEyesX()-4, ffEyesY()-7);
    triangle(ffEyesX()+11, ffEyesY(), ffEyesX()+10, ffEyesY()-7, ffEyesX()+4, ffEyesY()-7);
  }
  
}


void drawCabinet(){
  
  //Screen Border
  fill(0);
  noStroke();
  rect(40, 20, 360, 40);
  rect(40, 20, 60, 280);
  rect(340, 20, 360, 280);
  rect(40, 260, 360, 280);
  fill(100);
  rect(0, 0, 400, 20);
  rect(0, 0, 40, 400);
  rect(360, 0, 400, 400);
  rect(0, 280, 400, 400);
  
  //Cabinet Dashboard
  fill(140);
  rect(0, 310, 400, 400);
  
  //Power Spot
  fill(100);
  quad(300, 320, 360, 320, 380, 360, 280, 360);
  fill(120);
  rect(300, 320, 360, 360);
  fill(140);
  quad(300, 330, 360, 330, 370, 360, 290, 360);
  fill(200);
  ellipse(315, 345, 10, 5);
  ellipse(345, 345, 10, 5);
  stroke(0);
  line(307, 353, 318, 353);
  line(342, 353, 353, 353);
  line(346, 349, 349, 358);
  
  //Space Bar
  noStroke();
  textAlign(CENTER);
  textSize(20);
  if (keyPressed && key == ' '){
    fill(160);
    quad(145, 335, 255, 335, 270, 360, 130, 360);
    fill(0);
    text("SPACE", 200, 355);
  } else {
    fill(120);
    rect(130, 340, 270, 360);
    fill(160);
    quad(145, 315, 255, 315, 270, 340, 130, 340);
    fill(0);
    text("SPACE", 200, 335);
  }
  
  //Pillow
  fill(100);
  quad(20, 360, 120, 360, 100, 320, 40, 320);
  fill(#C061CB);
  ellipse(70, 310, 60, 10);
  stroke(#C061CB);
  curve(70, 310, 40, 310, 20, 350, 20, 380);
  curve(70, 310, 100, 310, 120, 350, 120, 380);
  curve(20, 300, 20, 350, 120, 350, 120, 300);
  quad(20, 350, 120, 350, 100, 310, 40, 310);
  stroke(#954C9D);
  ellipse(70, 320, 16, 6);
}

float ffTorsoX(){
  float x = (ffx-200)*0.1 + ffx;
  return x;
  
}

float ffTorsoY(){
  float y = (ffy-280)*(-0.1) + ffy;
  return y;

}

float ffTailX(){
  float x = (ffx-200)*0.2 + ffx;
  return x;
}

float ffTailY(){
  float y = (ffy-280)*(-0.2) + ffy;
  return y;
}

float ffTailGloX(){
  float x = (ffx-200)*0.22 + ffx;
  return x;
}

float ffTailGloY(){
  float y = (ffy-280)*(-0.33) + ffy;
  return y;
}

float ffEyesX(){
  float x = (ffx-200)*(-0.05) + ffx;
  return x;
}

float ffEyesY(){
  float y = (ffy-280)*(-0.1) + ffy;
  return y;
}