////  Monster Mash ////

String title="M O N S T E R   M A S H";
String subtitle="Click near hero, to move him away from danger!";
String subsub="         ( Press ? key for help.)";
String news="";
String author="Lorcan & bam  [version 3728c]";

Hero me;
Vampire dracula;
Monster frank;

float horizon, bottom;
float moonX,moonY;
float weedX=10, weedY=10;

float witchX=200, witchY=75, witchDX= -2;
float witchEyeX, witchEyeY;
float helpX, helpY, helpDY=0;

float treasureX, treasureY;


void setup() {
  size(700,500);
  horizon=  height * 1/4;
  bottom=  height;
  begin();  
}
void begin() {
  ////  Move creatures back to starting positions.
  moonX=  50 + random( width-100 );
  moonY=  witchY + random( 50 ); 
  helpX=width*2/3;
  helpY=height/3;
  treasureX=width-random(200);
  treasureY=  random(horizon,height-50);
  //
  me= new Hero();
  dracula = new Vampire();
  frank  = new Monster();
}

void draw() {
  //// Draw the frame.
  scene();        // Draw scene.
  witch();        // Witch flies past moon.
  //  
  me.move();
  me.draw();
  collisions();
  
  //// Monsters
  dracula.move();
  frank.move();
  //
  dracula.draw();
  frank.draw(); 
  //// Write messages last (so they always appear).
  messages();
}
void collisions() {
  //// Check for collisions ////
      if (me.near( treasureX, treasureY ) < 50) {
        me.score += 500;
        me.reset();
        news=  "Hero got the treasure!!!!";
        treasureX=width-random(200);
      }
      if (me.near( frank.x,frank.y ) < 50) {
        //// Caught by Frank!
        background(0,255,0);
        me.score -= 100;
        me.reset();
        frank.reset();
        news=  "Hero was attacked  by Frankenstein!";
      }        
      if (me.near( dracula.x,dracula.y ) < 50) {
        //// Caught by Dracula!
        //background(255,0,0);
        me.score -= 100;
        me.reset();
        dracula.reset();
        news=  "Hero was attacked by Dracula!";
      }        
      if (abs(witchX-moonX) < 25 ) {
        //// Witch crossing the moon.
        background(100,0,0);    // Flash (dark red)
        fill(255,255,0);
        text( "HEH \n     HEH      \n       HEH", witchX+50, witchY-50 );
        if (abs(witchX-moonX) < 2 ) me.score -= 10;
        news=  "The witch crossed the moon!  Hero loses 100 points.";
      }
}  


void scene() {
  //// Sky & grass;
    background( 100,100,255 );
    fill( 200,100,100 );
    noStroke();
    ellipse( moonX, moonY, 70, 70 );    // moon
    //// field
    fill( 100,200,100 );
    noStroke();
    rectMode(CORNER);
    rect(0, horizon, width, height-horizon );
    seaweed( bottom );
    // Treasure
    fill( 255,255,0);
    ellipse( treasureX, treasureY, 50,55 );
    fill( 255,200,150);
    ellipse( treasureX, treasureY, 40,44 );
     fill( 255,150,0);
    ellipse( treasureX, treasureY, 20,22 );
}
void seaweed( float y ) {
  //// Make seaweed across the width of the screen.
  if (frameCount %10 == 0) {
    weedX=  10 - random(0,20);
    weedY=  20 - random(0,4);
  }
  for (float x=0; x<width+30; x+=30 )
  {
    strokeWeight(2);
    stroke( 50,100,0 );          // Dark-green seaweed.
    line(x,y, x+weedX, y-weedY );
    noStroke();
    weedX = weedX -1 + random(2);
  }
}
void messages() {
  //// Messages on screen.
    //// Text on screen
    fill(0);
    textSize(32);
    text( title, 200, 40 );
    textSize(12);
    fill(0,127,0);
    text( subtitle, width/2, horizon+20 );
    text( subsub, width/2, horizon+35 );
    text( author, 20, height-20);
    // Score & help
    fill(255);
    if (me.score<0) fill(255,0,0);
    textSize(12);
    if (me.score != 0) text( "SCORE :", width*3/4, horizon-50 );
    textSize(18);
    if (me.score != 0) text( me.score, width*3/4, horizon-30 );
    text( news, width/2, horizon-10 );
    //
    helpX=  width/2;
    helpY=  horizon+20;
    fill(255);
    if (key == '?') help();
    if (key == '!') cheat();
    if (key=='D') debug();
}
void next( String s) {
  //// Display next message.
  text( s, helpX, helpY+12*helpDY );
  helpDY++;        //// Drop to next line.
  text( "helpDY:  "+helpDY, 400,400 );
}
void help() {
  //// Display help msgs???
  fill(0,0,150);
  next("H E L P");
  next("H E L P");
  next("H E L P");
}
void cheat() {
  //// Display cheat codes
  fill(0,150,0);
  next("CHEAT");
  next("CHEAT");
  next("CHEAT");
}
void debug() {
  //// Debugging messages (if "D" key is pressed)
  text( dracula.name+":  "+dracula.x+","+dracula.y, 100,100 );
  text( frank.name+":  "+frank.x+","+frank.y, 200,200 );
  text( "helpDY:  "+helpDY, 200,300 );
}

////// WITCH  //////
void witch() {
  //// Witch move & draw
  witchX += witchDX;
  if (witchX > 2000) witchDX=  -2; 
  if (witchX < 50) { 
    witchX=  random(5*width);
    witchY=  random(50,100);
    moonX=  random(width);
    moonY=  random(horizon);
    return;
  }
  drawWitch( witchX, witchY );
}
void drawWitch( float witchX, float witchY ) {
  //// Draw witch
  fill(100,50,50);
  rectMode(CENTER);
  rect( witchX, witchY, 40, 60 );    // Brown rectangle.
  fill(255,0,0);                      // Red face
  ellipse( witchX, witchY-40, 20, 20);
  // Yellow eye
  fill(255,255,0);
  ellipse( witchX-5, witchY-43, 5,5 );
  // Black hat.
  fill(0);
  triangle( witchX-10,witchY-50, witchX+10,witchY-50, witchX,witchY-70 );
  strokeWeight(3);
  stroke(0);
  line( witchX-20,witchY-50, witchX+20,witchY-50 );  // Hat brim.
  drawBroom( witchX-60, witchX+60, witchY+30 );
}
void drawBroom( float x1, float x2, float y ) {
  //// Broom from x1 to x2, at y
  strokeWeight(6);
  stroke(200,150,100);
  line( x1, y, x2, y );
  //// Bristles at x2.
  strokeWeight(1);
  float yy=  y-10;
  for (int j=0; j<8; j++ )
  {
    line( x2,yy, x2+40,yy );
    yy += 3;
  }
  noStroke();        // Reset
}



//// EVENT HANDLERS ////

void mousePressed() {
  //// Check for clicking on:  bird, witch, fish, octopus, etc.
      ////// Witch's eye adds 250 to score (and ends the night).
      if ( dist( mouseX,mouseY, witchX-20, witchY-50 )  <  15 ) { 
        background(0);
        me.score += 250;           // Witch's eye
        witchDX +=  1;
        me.x += 100;              // Hero jumps past witch.
        news=  "CLICKED on the Witch.  (Gain 250 points.)";
      }
      float far=  me.near( mouseX,mouseY+40 );
      if (far>50 && far<200) {
       float jump=  0.25 + random(0.25);    // jump towards me (25-50%); 
        me.x += (mouseX-me.x) * jump;
        me.y += (mouseY-me.y) * jump;
      }
}
    

void keyPressed() {
  //// Keys.
  if (key == 'q') exit();
}
  


class Vampire {
  float x=10,y=75, dx=5, dy=1;
  String name="Vlad";
  
  void move() {
    x += dx + random(3);
    y += dy -10 +random(20);
    if (x>width) x= 10;        // wrap
    if (x<0) x= 20;
    if (y>height-20) reset();    // revert to bat.
  }
  void draw() {
    if (y < horizon+50) {
      fill(0);
      //--  rect(x,y, 40,20);
      fill(0);
      triangle( x-20,y, x-10,y-30, x,y);
      triangle( x+20,y, x+10,y-30, x,y);
      fill(255,0,0);
      text(name,x-10,y+20);
    } else {
      fill(0);
      triangle( x-50,y+50, x,y-50, x+50,y+50);
      fill(255);
      triangle( x-20,y+50, x,y-20, x+20,y+50);
    }
  }
  void reset() {
        x=  50;
        y=  random(50, horizon-50 );
        //++++ Revert to bat shape.
  }
}

class Monster {
  String name="Frank";
  float x=400, y=300,  dx=-12, dy=15;
  float xleft=0, xright=0;
  
  void move() {
    if (frameCount % 15 == 0) {
      x += dx + random(6);
      y += dy - dy * random(2);
      if (x<20 || x>width-20) {    // bounce off walls
        dx= -dx;
        x += dx*10;
      }
      if (y<horizon+20 || y>height-20) {    // bounce off bottom & top
        dy= -dy;
        y += dy*10;
      }
      if (dx>0) {
        xleft=  -5-random(2*dx);
        xright=  5+random(2*dx);
      }
      if (dx<0) {
        xleft=  -5-random(2*dx);
        xright=  5+random(2*dx);
      }
    }
  }
  void draw() {
    fill(0,175,100);
    rect(x,y, 50,80);         // Body
    fill(0,150,100);
    rect(x,y-70, 40,40);      // Head
    rect(x,y-50, 20,20);      // Neck
    fill(255,0,0);
    text(name,x-20,y);
    // Eyes look in direction of motion .
    ellipse(x-8-xleft, y-80,4,4);
    ellipse(x+8-xleft, y-80,4,4);
    // Arms
    strokeWeight(12);
    stroke(0,100,50);
    line( x-20,y-30, x-18-3*xleft, y+40 );    // Left arm    
    line( x+20,y-30, x+18-3*xright, y+40 );    // Left arm    
    // Legs
    strokeWeight(12);
    stroke(0,100,50);
    line( x-20,y+45, x-18-xleft, y+95 );    // Left leg    
    line( x+20,y+45, x+18-xright, y+95 );    // Left leg    
    strokeWeight(0);
    fill( 100,50,0 );                        // Shoe color
    rect( x-24-xleft, y+95, 25,15 ); 
    rect( x+24-xright, y+95, 25,15 ); 
  }
  void reset() {
        x=  width-50;
        y=  random(horizon+50, height-50);
  }
}// class Monster //



class Hero {
  String name="Lorcan";
  float x=100, y=200,  dx=-12, dy=15;
  int score=0;
  int lives=0;
  
  void move() {
    /*
    if (mouseX>pmouseX) x += random(10);
    if (mouseX<pmouseX) x -= random(10);
    if (mouseY>pmouseY) y += random(5);
    if (mouseY<pmouseY) y -= random(5);
    */
  }
  void draw() {
    fill(0,200,255);
    rectMode(CENTER);
    rect(x,y, 40,60);
    fill(255,0,0);
    text(name,x-20,y-12);
    fill(150,0,0);
    text(lives,x,y+12);
    //
    fill(255,200,200);
    ellipse(x,y-50,35,35);
    fill(255);
    ellipse(x-10,y-50,15,12);
    ellipse(x+10,y-50,15,12);
    fill(0,0,200);
    // Eyes look toward mouse.
    int xx=0, yy=0;
    if ( mouseX-x > 100 ) xx=  +4;
    if ( mouseX-x < -100 ) xx=  -4;
    if ( mouseY-y > 100 ) yy=  +4;
    if ( mouseY-y < -100 ) yy=  -4;
    ellipse(x-10+xx,y-50+yy,4,4);
    ellipse(x+10+xx,y-50+yy,4,4);
  }
  float near( float xx, float yy ) {
    //// Is something near me?
    return dist( x,y, xx, yy );
  }
  void reset() {
        x=  50;
        y=  random(horizon+50, height-50 );
        lives++;
  }
}// class Hero //


