gargoyleguy guy;

void setup() {
  size(150,150);
  imageMode(CORNER);

  guy = new gargoyleguy(width/2, height/2);


  framerate(10);

}

boolean wingUp;

void loop() {
  background(225,225,255);
  guy.display();
  guy.move();


}
void mouseDragged(){
 guy.setTarget(mouseX,mouseY);
}
void mousePressed(){
  guy.setTarget(mouseX,mouseY);
}

void mouseReleased(){
  guy.clearTarget();
}



class gargoyleguy {
  final static int dirRIGHT = 1;
  final static int dirLEFT = 2;
  final static int FLYING = 1;
  final static int PERCHING = 2;
  final static int STANDING = 3;
  final static int WALKING = 4;
  float xpos, ypos;
  int currentdir;
  float currentdrift; 

  float targetX, targetY;
  boolean isTargeted;

  int currentBehavior;  
  float chanceOfFlyFromPerching = 60;
  float chanceOfFlyDirectionChange = 100;
  float chanceOfDrift = 5;
  float chanceOfWalkFromStanding = 20;
  float chanceOfStandFromWalking = 30;
  float chanceOfWalkSwitchDir = 70;
  float chanceOfFlyFromWalking = 60;
        
  framegroup currentAnim, animFlapLeft, animFlapRight, animPerchLeft,
      animPerchRight, animStandLeft,animStandRight, animWalkLeft, animWalkRight;
  gargoyleguy(int inx, int iny) {
    xpos = inx;
    ypos = iny;

    animFlapLeft = new framegroup();
    animFlapLeft.addFrame("fireflapleft1.gif");
    animFlapLeft.addFrame("fireflapleft2.gif");
    animFlapLeft.addFrame("fireflapleft3.gif");
    animFlapLeft.addFrame("fireflapleft2.gif");

    animFlapRight = new framegroup();
    animFlapRight.addFrame("fireflapright1.gif");
    animFlapRight.addFrame("fireflapright2.gif");
    animFlapRight.addFrame("fireflapright3.gif");
    animFlapRight.addFrame("fireflapright2.gif");

    animPerchLeft = new framegroup();
    animPerchLeft.addFrame("fireperchleft.gif");

    animPerchRight = new framegroup();
    animPerchRight.addFrame("fireperchright.gif");

    animStandLeft = new framegroup();
    animStandLeft.addFrame("firestandleft.gif");

    animStandRight = new framegroup();
    animStandRight.addFrame("firestandright.gif");

    
    animWalkLeft = new framegroup();
    animWalkLeft.addFrame("firewalkleft1.gif");
    animWalkLeft.addFrame("firewalkleft2.gif");
    animWalkLeft.addFrame("firewalkleft3.gif");
    animWalkLeft.addFrame("firewalkleft2.gif");

    animWalkRight = new framegroup();
    animWalkRight.addFrame("firewalkright1.gif");
    animWalkRight.addFrame("firewalkright2.gif");
    animWalkRight.addFrame("firewalkright3.gif");
    animWalkRight.addFrame("firewalkright2.gif");
            
    currentdir = dirRIGHT;

    currentAnim = animFlapRight;
    currentBehavior = FLYING;

  }


  void setTarget(float mx, float my){
    targetX = mx;
    targetY = my;
    isTargeted = true;
  
}
  void  clearTarget(){
    isTargeted = false;
  }
  

  void display() {
    currentAnim.display(xpos, ypos);
    currentAnim.advance();
  if(currentBehavior == FLYING){
      if (currentdir == dirLEFT) {
        xpos--;
      }
      else {
        xpos++;
      }
  } 
  }

  void move() {
    if(currentBehavior == FLYING){
      if (currentdir == dirLEFT) xpos -= .5;
      else xpos += .5;
       maybeFlySwitchDir(); 
       maybeChangeDrift();
       
       ypos += currentdrift;
       maybeBump();
       maybePerchFromFlying();
    } //end if FLYING
    if(currentBehavior == PERCHING){
        maybeFlyFromPerching();
    }
    if(currentBehavior == STANDING){
      maybeWalkFromStanding();
    }    
    if(currentBehavior == WALKING){
      if (currentdir == dirLEFT) xpos -= 1;
      else xpos += 1;
      maybeFlyFromWalking();
      if(currentBehavior == WALKING) {
        maybeWalkSwitchDir();
        maybeStandFromWalking();
        }
    }
  }
  
  void maybeWalkSwitchDir(){
   if(random(chanceOfWalkSwitchDir) < 1){
     if(currentdir == dirLEFT){
       currentdir = dirRIGHT;
       currentAnim = animWalkRight;
     } else {
       currentdir = dirLEFT;
       currentAnim = animWalkLeft;
     }
   }
  if(xpos < 0 || (isTargeted && xpos > targetX)){
       currentdir = dirRIGHT;
       currentAnim = animWalkRight;
  
     }   
  if(xpos > width - currentAnim.getMaxwidth() || (isTargeted && xpos < targetX)) {
      currentdir = dirLEFT;
       currentAnim = animWalkLeft;
   
  }
      
  
  }
  
  void maybeStandFromWalking(){
    if(random(chanceOfStandFromWalking) < 1) {
      currentBehavior = STANDING;
      if(currentdir == dirLEFT) currentAnim = animStandLeft;
      else currentAnim = animStandRight;
    }
  
  }
  
  void maybeWalkFromStanding(){
    if(random(chanceOfWalkFromStanding) < 1 || isTargeted) {
      currentBehavior = WALKING;
      if(currentdir == dirLEFT) currentAnim = animWalkLeft;
      else currentAnim = animWalkRight;
    }
  
  }
  
  
  void maybeBump(){
    if(ypos < 0) {
      ypos = 0;
    } 
    if(ypos > height - currentAnim.getMaxheight()){
      currentBehavior = STANDING;
      if (currentdir == dirLEFT) currentAnim = animStandLeft;
      else currentAnim = animStandRight;
      ypos = height - currentAnim.getMaxheight();
      
    }
  }
  
  void maybeChangeDrift(){
  if(isTargeted) {
      float centerY =  ypos + (currentAnim.getMaxheight() /2 );
      if(centerY > targetY) currentdrift = 1;
      else currentdrift  = -1;
   } else {
        if(random(chanceOfDrift) < 1){
          currentdrift = random(2) - 1;
      }
    }
    }

  
  void maybeFlySwitchDir(){
  if(isTargeted) {

    float centerX = xpos + (currentAnim.getMaxwidth() /2 );
    if(centerX > targetX){
             currentdir = dirRIGHT;
        currentAnim = animFlapRight; 
    } else {
           currentdir = dirLEFT;
        currentAnim = animFlapLeft;
    }
  } else {
     if(random(chanceOfFlyDirectionChange) < 1){
      if(currentdir == dirLEFT) {
        currentdir = dirRIGHT;
        currentAnim = animFlapRight;
      } else {
        currentdir = dirLEFT;
        currentAnim = animFlapLeft;
      
      }
    }
   }
  }

  void maybeFlyFromWalking(){
    if(random(chanceOfFlyFromWalking) < 1){
      currentBehavior = FLYING;
      if(currentdir == dirRIGHT) currentAnim = animFlapRight;
      else currentAnim = animFlapLeft;
      xpos = constrain(xpos,0, width - currentAnim.getMaxwidth());
      currentdrift = -1;
     }
  
  }

  void maybeFlyFromPerching(){
    if(random(chanceOfFlyFromPerching) < 1 || isTargeted){
      currentBehavior = FLYING;
      if(currentdir == dirRIGHT) currentAnim = animFlapRight;
      else currentAnim = animFlapLeft;
      xpos = constrain(xpos,0, width - currentAnim.getMaxwidth());
    }
  }

  void maybePerchFromFlying(){
      if (xpos <= 0) {
        xpos = 0;
        currentAnim = animPerchLeft;
        currentBehavior = PERCHING;
        currentdir = dirRIGHT;
      }
      if (xpos >=  width - currentAnim.getMaxwidth()) {
  
          currentAnim = animPerchRight;
        xpos = width - currentAnim.getMaxwidth();
        currentBehavior = PERCHING;
        currentdir = dirLEFT;
      }
  
      
  }

}

class framegroup {
  BImage image[] = new BImage[10]; //whoops, magic maximum number
  int imgcount = 0;
  int imgptr = 0;
  int maxwidth;
  int maxheight;

  public int getMaxwidth() {
    return maxwidth;
  }
 public int getMaxheight() {
    return maxheight;
  }
  void addFrame(String imgname) {

    BImage newimg = loadImage(imgname);

    image[imgcount] = newimg;
    imgcount++;
    if (newimg.width > maxwidth) {
      maxwidth = newimg.width;
    }
    if (newimg.height > maxheight) {
      maxheight = newimg.height;
    }

  }

  void display(float x, float y) {
    image(image[imgptr], x, y);
  }

  void advance() {
    imgptr++;
    if (imgptr >= imgcount) {
      imgptr = 0;
    }
  }

}