///// Dynamic sketch (modularized) with dog.
//// B.A.Martin: '9918

String title=  "Dynamic sketch (modularized) with dog.";
String hints=  "Click resets link to mouse position\n" 
      + "r resets randomly, d to reset dog, q to quit\n"
      + "+/- to speedup/slowdown link; f to freeze link";
String author=  "B.A.Martin: '9918";

float horizon;
float linkX, linkY, linkDX, linkDY;
float mushX, mushY, mushDX, mushDY;
float sunX, sunY;
float rate;
boolean day=true, bug=false;


//// SETUP:  size & modes
void setup() 
{
  size( 600, 400 ); 
  smooth();
  horizon=  height/3;
  reset();
  dogReset();
}
void reset() {
  sunX=10;
  sunY=50;
  linkX=  random(50, width/2);
  linkY=  random(horizon, height-20);
  linkDX=  random(1, 3);
  linkDY=  random(1, 2);
}
void dogReset() {
  rate=  frameRate;
  mushX=  random(width/2, width-50);
  mushY=  random(horizon, height-20);
}

//// NEXT FRAME:  scene, action, show
void draw() 
{
  scene();
  action();
  credits();
}

//// Scene:  sky & grass
void scene() {
  // Sky & sun/moon
  if (day) { 
    background( 150, 200, 250 );      // day sky
    fill( 255, 255, 100 ); 
  }
  else { 
    background( 100, 150, 200 );      // nite sky
    fill( 250, 200, 150 ); 
  }
  ellipse( sunX, sunY, 30, 30 );
  // grass
  fill( 20, 200, 100 ); 
  rect( 0, horizon, width, height-horizon );  // grass
  fill( 255, 255, 0 );
  // house
  fill( 255, 0, 0 ); 
  rect( 100,horizon-60, 100,60 );
  triangle( 90,horizon-60, 150,horizon-90, 210,horizon-60 );
  fill(0);
  rect(  120,horizon-40, 20,40 );    // door
  fill(255);
  rect( 125,horizon-35, 10,15 );    // windows
  rect( 160,horizon-40, 20,30 );
}
void credits() {
  fill(0);
  textSize(20);
  text( title, width/4, 24);
  textSize(12);
  fill(0,0,255);
  text( hints, width/2, 60 );
  fill(150,0,0);
  text( author, 20, height-20);
  // Debugging info
  if (bug) {
    fill(100);
    text( "link:\n" +linkDX+ "\n" +linkDY, width-200, height-50 );
    text( "dog:\n" +mushDX+ "\n" +mushDY, width-100, height-50 );
  }
}

//// Action:  Dog chases link, who follows mouse.
void action() {
  // Sun arcs across sky
  sunX=  sunX + 1;             
  sunY=  horizon - horizon* sin( PI * (sunX/width) );
  if (sunX>width) {
    day = ! day;
    sunX= 0;
  }
  // Move link
  if (linkX<10 || linkX>width-10) linkDX = -linkDX;
  linkX=  linkX + linkDX;
  if (linkY<horizon-30 || linkY>height-50) linkDY = -linkDY;
  linkY=  linkY + linkDY;
  showHero();
  // Dog chases link.
  mushDX=  (linkX-mushX) / rate / 2;
  mushDY=  (linkY-mushY) / rate / 3;
  mushX=  mushX + mushDX;
  mushY=  mushY + mushDY;
  showDog();
}


//// Show:  draw link & dog.
void showHero() {
  // link
  fill( 255, 150, 200 );                // head
  ellipse( linkX, linkY, 30, 40 );
  fill( 255 );                          // eyes
  ellipse( linkX-6, linkY-6, 10, 10 );
  ellipse( linkX+6, linkY-6, 10, 10 );
  fill( 0,0,255 );
  ellipse( linkX-6, linkY-6, 4,4 );
  ellipse( linkX+6, linkY-6, 4,4 );
  fill( 0, 255, 255 );                  // body
  rect( linkX-25, linkY+18, 50, 80 );
  fill(255,0,0);
  text( "L i n k", linkX-18, linkY+40 );
}
void showDog() {
  fill( 126, 0, 0 );
  rect( mushX,mushY, 30,20 );            // head
  rect( mushX-40,mushY+20, 60,30 );
}

//////// EVENT HANDLERS ////////
void mousePressed() {
  linkX=  mouseX;
  linkY=  mouseY;
}
void keyPressed() {
  if (key == 'q')  { exit(); }
  if (key == 'r')  { reset(); }
  if (key == 'd')  { dogReset(); }
  if (key == '!')  { bug = ! bug; }
  if (key == 'n')  { day = ! day; }
  if (key == 'f')  {
    // Freeze link;
    linkDX=0;
    linkDY=0;
  }
  if (key == '+')  {
    linkDX=  linkDX * 2;    // Faster
    linkDY=  linkDY * 2;
  }
  if (key == '-')  {
    linkDX=  linkDX * 0.75;  // Slower
    linkDY=  linkDY * 0.75;
  }
}
