> show canvas only <


/* built with Studio Sketchpad: 
 *   http://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   http://studio.sketchpad.cc/sp/pad/view/ro.TmKYsUi9LqY/rev.108
 * 
 * authors: 
 *   Dan Ha
 *   
 *   

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   http://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



int level = 1;
int maxLevel= 4;
int numWalls;
int gunProjectileOffset = 30;
Goal goal;
int numGuns;
Gun[] gun;
Target target;
Wall[] walls;
boolean drawBG = true;

int width = 1024, height = 690;
float maxVel = 10;
int INSTR_state = -2;
int HOME_state = -1;
int START_state = 0;
int WIN_state = 1;
int LOSE_state = 2;
int state = WIN_state;
int lives;
int CAN_FIRE_state = 0;
int BALL_IN_PLAY_state = 1;
int turn_state = CAN_FIRE_state;

PImage playAgain, nextLevel;
PImage youLose, youWin;
PImage fishdownimg, fishleftimg, fishrightimg, fishimg;
PImage fire;
PImage backgroundImage, home, turtle, life, seaweed, seaweedHoriz, level1, level2, level3, level4, quit, instructions;

String URLDirectory = "http://stanford.edu/~andien/CS147/data/";
//String URLDirectory = "";
void setup() {
    size(1024, 690, P2D);
  playAgain = loadImage(URLDirectory + "playAgain.png");
  youLose = loadImage(URLDirectory + "lose.png");
  youWin = loadImage(URLDirectory + "win.jpg");
  nextLevel = loadImage(URLDirectory + "nextLevel.png");
  fire = loadImage(URLDirectory + "swimButton.png");
  backgroundImage = loadImage(URLDirectory + "background.jpg");
  turtle = loadImage(URLDirectory + "turtle.png");
  life = loadImage(URLDirectory + "life.png");
  seaweed = loadImage(URLDirectory + "seaweed.png");
  seaweedHoriz = loadImage(URLDirectory + "seaweedHoriz.png");
  level1 = loadImage(URLDirectory + "level1.png");
  level2 = loadImage(URLDirectory + "level2.png");
  level3 = loadImage(URLDirectory + "level3.png");
  level4 = loadImage(URLDirectory + "level4.png");
  quit = loadImage(URLDirectory + "quit.png");
  home = loadImage(URLDirectory + "home.jpg");
  instructions = loadImage(URLDirectory + "instructions.jpg");
  fishdownimg = loadImage(URLDirectory + "fishDown.png");
  fishleftimg = loadImage(URLDirectory + "fishLeft.png");
  fishimg = loadImage(URLDirectory + "fish.png");
  fishrightimg = loadImage(URLDirectory + "fishRight.png");  
  state = HOME_state;
  reset();
}

void reset(){
  lives = 5;
  drawBG = true;
  size(width, height, P2D);
  Brain brain = new Brain(level);

  gun = brain.initGuns();
  goal = brain.initGoal();
  target = brain.initTarget();
  numGuns = brain.getNumGuns();
}

void update() {
  for(int i=0; i<numGuns; i++) {
    gun[i].update((int)target.posX, (int)target.posY);
  }
  if(goal.collided(target)) {
    state = WIN_state;
  } 
  else if(target.hitBounds) {
    state = LOSE_state;
  }
  else if(target.justStopped) {
    target.freeze();
    target.justStopped = false;
    if(lives <= 0) {
      state = LOSE_state;
    }
  }
}

void checkWallCollisions() {
  for(int i = 0; i < numWalls; i++) {
    walls[i].collided();
  }
}

void checkCollisions() {
  boolean deductLife = false;

  checkWallCollisions();

  for(int i = 0; i < numGuns; i++) {
    if(turn_state == BALL_IN_PLAY_state) gun[i].projectile.locked = true;
    else gun[i].projectile.locked = false;

    if(!gun[i].projectile.firing) continue;
    if(target.hitProjectile(gun[i].projectile)) {
      target.setVelocity(gun[i].projectile.velX, gun[i].projectile.velY, gun[i].projectile.getPscale());
      gun[i].projectile.die();
      deductLife = true;
    }
  }
  if(deductLife) lives--;
}

void drawLives() {
  for(int i = 0; i < lives; i++) {
    image(life, 35 + i * 25, 10);
  }
}

void drawWalls() {
  for(int i = 0; i < numWalls; i++) {
    walls[i].display();
  }
}

void draw() 
{
  if(!drawBG) return;
  image(backgroundImage,0,0);
  if(state==START_state) {
    if(level==1) image(level1,0,0);
    else if(level==2) image(level2,0,0);
    else if(level==3) image(level3,0,0);
    else if(level==4) image(level4,0,0);
    target.display();
    update();

    checkCollisions();
    drawLives();
    drawWalls();

    for(int i=0; i<numGuns; i++) {
      gun[i].display();
      gun[i].projectile.display();
    }  
    image(fire, width-150, height-150);
  }
  else if(state == HOME_state) {
    image(home,0,0);
    drawBG = false;
  }

  else if(state == INSTR_state) {
    image(instructions,0,0);
  }

  else if(state == WIN_state) {
    if(level == maxLevel) {
      image(playAgain, 350, 250); 
      state = HOME_state;
      level = 1;
      reset();
    }
    else image(nextLevel, width/2-nextLevel.width/2, 150);
    target.freeze();
    drawBG = false;
    return;
  }
  else if(state == LOSE_state) {
    image(youLose, width/2-youLose.width/2, -100); 
    image(playAgain, width-175, 200);
    image(quit, width-250, 100);
    target.freeze();
    return;
  }
}

void mouseReleased() {
  for(int i=0; i<numGuns; i++) {
    gun[i].projectile.mouseReleased();
  } 
  if(state == HOME_state) {
    if(mouseX>=width/2-75 && mouseX <= width/2+75 && mouseY >= height/2 && mouseY <= height/2+150) state = START_state;
    else if(mouseX>=width/2-50 && mouseX <= width/2+50 && mouseY >= height-50) state = INSTR_state;
  }
  else if(state == INSTR_state) {
    if(mouseX>=155 && mouseX <= 205 && mouseY >= 550 && mouseY <= 620) state = HOME_state;
  }
  else if(state == WIN_state) {
    if(mouseX>=width/2-50 && mouseX <= width/2+50 && mouseY >= height/2-50 && mouseY <= height/2+100) {
      if(level < maxLevel) level++;
      else level = 1;
      state = START_state;
      reset();
    }
  }
  else if(state == LOSE_state) {
    if(mouseX>=width-250 && mouseX <= width-150 && mouseY >= 100 && mouseY <= 200) {
      state = HOME_state;
      setup();
    }
    else if(mouseX>=width-175 && mouseX <= width-75 && mouseY >= 200 && mouseY <= 300) {
      state = START_state;
      setup();
    }
  }
  drawBG = true;
}

void mousePressed() {
  for(int i=0; i<numGuns; i++) {
    gun[i].projectile.mousePressed();
  }
  if(mouseX>width-150&&mouseY>height-150&&mouseX<width-50&&mouseY<height-50) {
    for(int i=0; i<numGuns; i++) {
      gun[i].fire(target);
    }
  }
}

class Brain {
  int level;
  int numGuns = 0;
  Goal goal;
  Gun[] guns;
  Target target;

  Brain(int l) {
    level = l;
    walls = new Wall[10];
    if(level == 4) {
      lives = 10;
      numWalls = 4;
      walls[0] = new Wall(width * .2, height * .8, width * .7, 10);
      walls[1] = new Wall(width * .2, height * .3, 20, height * .5);
      walls[2] = new Wall(width * .2, height * .3, width * .5, 10);
      walls[3] = new Wall(width * .5, height * .53, width * .4, 10);
    } 
    else if(level == 3) {
      lives = 6;
      numWalls = 3;
      walls[0] = new Wall(width * .75, 200, 10, height * .65 - 200);
      walls[1] = new Wall(width * .25, height * .4, 400, 10);
      walls[2] = new Wall(width * .25, height * .65, 550, 10);
    } 
    else if(level == 2) {
      numWalls = 1;
      walls[0] = new Wall(300, 200, 10, 200);
    } 
    else {
      numWalls = 0;
    }
  }

  Goal initGoal() {
    if(level == 4) {
      goal = new Goal(width/2 - 50, 0, 100, 20);
    } 
    else if(level == 3) { 
      goal = new Goal(width - 40, 70, 40, 100);
    } 
    else if(level == 2) { 
      goal = new Goal(0, 420, 20, 100);
    } 
    else {
      goal = new Goal(0, 300, 20, 80);
    }
    return goal;
  }

  Gun[] initGuns() {
    guns = new Gun[4];
    if(level == 4) {
      numGuns = 3;
      guns[0] = new Gun(2, 0);
      guns[1] = new Gun(3, 1);
      guns[2] = new Gun(4, 2);
    } 
    else if(level == 3) {
      numGuns = 3;
      guns[0] = new Gun(1, 0);
      guns[1] = new Gun(3, 1);
      guns[2] = new Gun(4, 2);
    } 
    else if(level == 2) {
      numGuns = 3;
      for(int i = 0; i < numGuns; i++) guns[i] = new Gun(i+1, i);
    } 
    else {
      numGuns = 1;
      guns[0] = new Gun(2, 0);
    }

    return guns;
  }

  Target initTarget() { 
    if(level == 4) {
      target = new Target(width * .8, height * .65, width, height);
    } 
    else if(level == 3) {
      target = new Target(width * .2, height * .6, width, height);
    } 
    else if(level == 2) {
      target = new Target(width * .8, height * .3, width, height);
    } 
    else {
      target = new Target(width/2, height/2, width, height);
    }
    return target;
  }

  int getNumGuns() {
    return numGuns;
  }
}
class Goal {
  float xpos, ypos, width, height;
  float  padding = 0;

  Goal(float xp, float yp, float w, float h) {
    xpos = xp; 
    ypos = yp; 
    width = w; 
    height = h;
  }

  void display() { //colorMode
    fill(color(00, 99, 00));
    rect(xpos, ypos, width, height);
  }

  boolean collided(Target t) {
    float xa = xpos - padding;
    float xb = xpos + padding + width;
    float ya = ypos;
    float yb = ypos + height;

    //CHECK CORNERS
    if (t.collided(xa, ya) || t.collided(xa, yb) || t.collided(xb, ya) || t.collided(xb, yb)) return true;

    //CHECK BETWEEN
    float tx = t.posX;
    float ty = t.posY;
    float tr = t.radius/2;

    if(xa <= tx - tr && tx - tr <= xb && ya <= ty - tr && ty - tr <= yb) {
      return true;
    }    

    if(xa <= tx + tr && tx + tr <= xb && ya <= ty + tr && ty + tr <= yb) {
      return true;
    }    

    return false;
  }
}
class Target {
  float posX, posY;
  float velocityX, velocityY, acceleration;
  float radius;
  float boundsX;
  float boundsY;
  float padding = 00;
  float margin = 5;
  float frictionX = 0;
  float frictionY = 0;
  boolean hitBounds = false;
  boolean justStopped = false;

  Target(float x, float y, float w, float h) {
    radius = 58;
    posX = x;
    posY = y;
    boundsX = w;
    boundsY = h;
    acceleration = 0;
  }

  void reset() {
    posX = boundsX/2;
    posY = boundsY/2;
    acceleration = 0;
    velocityX = 0;
    velocityY = 0;
  }

  //returns true if a point x, y is colliding with the target
  boolean collided(float x, float y) {
    if(x >= (posX-radius/2) && y >= (posY-radius/2)) {
      if(x <= (posX+radius/2) && y <= (posY+radius/2)) {
        return true;
      }
    }
    return false;
  }

  boolean hitProjectile(Projectile p) {
    return p.collision;
  }

  void checkBounds() {
    if(posX - radius/2 <= padding) {
      hitBounds = true;
      freeze();
      posX = radius/2;
      //velocityX = abs(velocityX);
      velocityX = 0;
    }
    if(posX + radius/2 >= boundsX - padding) { 
      hitBounds = true;
      freeze();
      posX = boundsX - radius;
      velocityX = 0;//velocityX = -abs(velocityX);
    }
    if(posY - radius/2 <= padding) {
      hitBounds = true;

      freeze();
      posY = radius/2;
      velocityY = 0;//velocityY = abs(velocityY);
    }
    if(posY + radius/2 >= boundsY - padding) {

      freeze();
      hitBounds = true;
      posY = boundsY - radius/2;
      velocityY = 0;//velocityY = -abs(velocityY);
    }
  }

  void setVelocity(float x, float y, float scale) {
    velocityX += x*scale;
    velocityY += y*scale;
    frictionX = velocityX / 40;
    frictionY = velocityY / 40;
  }

  void setPos(float x, float y) {
    posX = x;
    posY = y;
  }

  void updateVelocity() {
    velocityX += acceleration;
    velocityY += acceleration;
  }  

  void moveTarget() {
    if(abs(velocityX) <= 0.25 && velocityX != 0) {
      frictionX = 0;
      velocityX = 0; 
      justStopped = true;
    }

    if(abs(velocityY) <= 0.25 && velocityY != 0) {
      frictionY = 0;
      velocityY = 0; 
      justStopped = true;
    }

    if(velocityX < 0) {
      velocityX += abs(frictionX);
    } 
    else {
      velocityX -= abs(frictionX);
    }
    if(velocityY < 0) {
      velocityY += abs(frictionY);
    } 
    else {
      velocityY -= abs(frictionY);
    }

    posX += velocityX;
    posY += velocityY;
    checkBounds();
    updateVelocity();
  }

  void freeze() {

    velocityX = 0;
    velocityY = 0;
    frictionY = 0;
    acceleration = 0;
    frictionX = 0;
  }

  void display() {
    moveTarget();
    image(turtle, posX-turtle.width/2, posY-turtle.height/2);
  }
}
class Wall {
  float xpos, ypos, wallWidth, wallHeight;
  float  padding = 0;

  Wall(float xp, float yp, float w, float h) {
    xpos = xp; 
    ypos = yp; 
    wallWidth = w; 
    wallHeight = h;
  }

  void display() {
    if(wallWidth>wallHeight) image(seaweedHoriz, xpos, ypos, wallWidth, seaweedHoriz.height);
    else image(seaweed, xpos, ypos, seaweed.width, wallHeight);
  }

  void collided() {
    float xa = xpos;
    float xb = xpos + wallWidth; 
    float ya = ypos;
    float yb = ypos + wallHeight;

    float tx = target.posX;
    float ty = target.posY;
    float tr = target.radius/2;

    if(target.velocityX == 0 && target.velocityY != 0) {
      if((xa < tx - tr && tx - tr < xb) || (xa < tx + tr && tx + tr < xb)) {
        //CHECK IF TOP OF BALL IS INSIDE THE BOUNDS
        //CHECK IF BOTTOM OF BALL IS INSIDE THE BOUNDS
        if(target.velocityY < 0) {
          if(ya <= ty - tr && ty - tr <= yb) {
            target.velocityY = abs(target.velocityY);
            target.posY += target.velocityY;
          }
        } 
        else if(target.velocityY > 0) {
          if(ya <= ty + tr && ty + tr <= yb) {
            target.velocityY = -abs(target.velocityY);
            target.posY += target.velocityY;
          }
        }
      }
    } 
    else if(target.velocityY == 0 && target.velocityX != 0) {
      if((ya < ty - tr && ty - tr < yb) || (ya < ty + tr && ty + tr < yb)) {
        if(target.velocityX < 0) {
          if(xa <= tx - tr && tx - tr <= xb) {
            target.velocityX = abs(target.velocityX);
            target.posX += target.velocityX;
          }
        } 
        else if(target.velocityX > 0) {
          if(xa <= tx + tr && tx + tr <= xb) {
            target.velocityX = -abs(target.velocityX);
            target.posX += target.velocityX;
          }
        }
      }
    } 
    else if (target.velocityY != 0 && target.velocityX != 0) {
      if(target.velocityY > 0) {
        if(target.velocityX > 0) {
          //FORWARD DOWN
          if(wallHeight > wallWidth) {
            if(ya - tr <= ty && ty <= yb + tr) {
              if(xa <= tx + tr && tx + tr <= xb) {
                target.velocityX = -abs(target.velocityX);
              }
            }
          } 
          else {
            if((xa - tr <= tx && tx <= xb + tr)) {
              if(ya <= ty + tr && ty + tr <= yb) {
                target.velocityY = -abs(target.velocityY);
              }
            }
          }
        } 
        else {
          //BACKWARD DOWN 
          if(wallHeight > wallWidth) {
            if(ya - tr <= ty && ty <= yb + tr) {
              if(xa <= tx - tr && tx - tr <= xb) {
                target.velocityX = abs(target.velocityX);
              }
            }
          } 
          else {
            if((xa - tr <= tx && tx <= xb + tr)) {
              if(ya <= ty + tr && ty + tr <= yb) {
                target.velocityY = -abs(target.velocityY);
              }
            }
          }
        }
      } 
      else {
        if(target.velocityX > 0) {
          //FORWARD UP
          if(wallHeight > wallWidth) {
            if((ya < ty - tr && ty - tr < yb) || (ya < ty + tr && ty + tr < yb)) {            
              if(xa <= tx + tr && tx + tr <= xb) {
                target.velocityX = -abs(target.velocityX);
              }
            }
          } 
          else {
            if((xa - tr <= tx && tx <= xb + tr)) {
              if(ya <= ty - tr && ty - tr <= yb) {
                target.velocityY = abs(target.velocityY);
              }
            }
          }
        } 
        else {
          //BACKWARD UP
          if(wallHeight > wallWidth) {
            if((ya < ty - tr && ty - tr < yb) || (ya < ty + tr && ty + tr < yb)) {
              if(xa <= tx - tr && tx - tr <= xb) {
                target.velocityX = abs(target.velocityX);
              }
            }
          } 
          else {
            if((xa - tr <= tx && tx <= xb + tr)) {
              if(ya <= ty - tr && ty - tr <= yb) {
                target.velocityY = abs(target.velocityY);
              }
            }
          }
        }
      }
    }
  }
}

class Gun { 
  float xpos, ypos; // position of the ball
  float gunX, gunY;
  int deviceSide; // deviceSide: the side of the iPad when held vertically; 1 = top, clockwise.
  float gunWidth, gunHeight, dimWidth, dimHeight;
  float buttonWidth, buttonHeight;
  float buttonX, buttonY, trackX1, trackX2, trackY1, trackY2;
  Projectile projectile;
  int index;

  Gun(int ds, int i) {  
    index = i;
    dimWidth = 100; // dimesnions of the gun as a vertical shape, never changes
    dimHeight = 150;
    gunWidth = 80; // dimensions of shape displayed (depends on orientation)
    gunHeight = 120;
    buttonWidth = 50;
    buttonHeight = 50;
    deviceSide = ds; 
    projectile = new Projectile(ds, i);
    projectile.update(xpos, ypos, trackX1, trackX2, trackY1, trackY2);
  } 
  void update(float x, float y) { // x and y are ball coordinates
    if(deviceSide==1) {
      xpos = x + 10;
      ypos = 0;
      buttonX = xpos;
      buttonY = 15;
      trackX1 = xpos + gunProjectileOffset;
      trackX2 = xpos + gunProjectileOffset;
      trackY1 = 25;
      trackY2 = dimHeight-25;
      gunX = xpos-25;
      gunY = 0;
      gunWidth = dimWidth;
      gunHeight = dimHeight;
    }
    else if(deviceSide==2) {
      xpos = width-buttonHeight;
      ypos = y;
      buttonX = width-buttonHeight-15;
      buttonY = ypos + 15;
      trackX1 = width-dimHeight+25;
      trackX2 = width-25;
      trackY1 = ypos + gunProjectileOffset;
      trackY2 = ypos + gunProjectileOffset;
      gunX = width-dimHeight;
      gunY = ypos-25;
      gunWidth = dimHeight;
      gunHeight = dimWidth;
    }
    else if(deviceSide==3) {
      xpos = x;
      ypos = height-gunHeight;
      buttonX = xpos+15;
      buttonY = height-buttonHeight-15;
      trackX1 = xpos + gunProjectileOffset;
      trackX2 = xpos + gunProjectileOffset;
      trackY1 = height-gunHeight+25;
      trackY2 = height-25;
      gunX = xpos-25;
      gunY = height-gunHeight;
      gunWidth = dimWidth;
      gunHeight = dimHeight;
    }
    else if(deviceSide==4) {
      xpos = 0;
      ypos = y;
      buttonX = 15;
      buttonY = ypos+15;
      trackX1 = 25;
      trackX2 = dimHeight-25;
      trackY1 = ypos + gunProjectileOffset;
      trackY2 = ypos + gunProjectileOffset;
      gunX = 0;
      gunY = ypos-25;
      gunWidth = dimHeight;
      gunHeight = dimWidth;
    }
    projectile.update(xpos, ypos, trackX1, trackX2, trackY1, trackY2);
  }
  void display() {
    fill(25);
    // rect(gunX,gunY,gunWidth,gunHeight); // gun body
    strokeWeight(10);
    stroke(50,30);
    // projectile track
    line(trackX1,trackY1,trackX2,trackY2);
    noStroke();
  } 
  boolean checkFire() {
    if(mouseX>buttonX&&mouseY>buttonY&&mouseX<buttonX+buttonWidth&&mouseY<buttonY+buttonHeight) return true;
    return false;
  }
  boolean checkInside() {
    if (mouseX>gunX&&mouseY>gunY&&mouseX<gunX+gunWidth&&mouseY<gunY+gunHeight) return true;
    else return false;
  }
  void fire(Target t) {
    projectile.fire(t);
  }
}
class Marker {
  float posX; 
  float posY;
  float radius = 50;
  color cl;

  Marker(float x, float y) {
    posX = x;
    posY = y;
  }

  boolean collided(Target t) {
    return (t.collided(posX-radius, posY-radius) &&
      t.collided(posX, posY));
  }

  void setColor(color c) {
    cl = c;
  } 

  void draw() {
    fill(cl);
    ellipse(posX, posY, radius, radius);
    fill(color(0,0,0));
  }
}

class Projectile { 
  float xpos, ypos;
  float xpace, ypace;
  int orientation; // orientation matches deviceSide in Gun. (down=1, left=2, up=3, right=4)
  float gunX, gunY;
  float fixedX, fixedY;
  float trackX1, trackX2, trackY1, trackY2, tracklength;
  float pscale;
  PImage arrow;
  float firelength = 0;
  boolean firing;
  boolean adjusted, hidden;
  boolean dragging=false;
  float velX = 10, velY = 10;
  boolean locked = false;
  float maxPscale = 1;
  float minPscale = 0;
  boolean collision = false;
  int collisionCounter = -1;
  float maxVel = 10;
  int gunNum = 0;

  Projectile (int o, int gn) {  
    gunNum = gn;
    hidden = true;
    orientation = o; 
    pscale = minPscale;
    if(orientation==1) {
      arrow = fishdownimg;
      ypos=25;
      velX = 0;
    }
    else if(orientation==2) {
      arrow = fishleftimg;
      xpos=width-arrow.width*pscale-25;
      velX = -velX;
      velY = 0;
    }
    else if(orientation==3) {
      arrow = fishimg;
      ypos=height-arrow.height*pscale-25;
      velY = -velY;
      velX = 0;
    }
    else if(orientation==4) {
      arrow = fishrightimg;
      xpos=25;
      velY = 0;
    }
    firing=false;
  } 
  void update(float x, float y, float tx1, float tx2, float ty1, float ty2) { // x and y are gun coordinates, t-variables denote the track.
    gunX = x;
    gunY = y; 
    trackX1 = tx1;
    trackX2 = tx2;
    trackY1 = ty1;
    trackY2 = ty2;
    if(orientation==1 || orientation==3) tracklength = abs(trackY2-trackY1);
    else tracklength = abs(trackX2-trackX1);
    if(orientation==1) {
      xpos = trackX1 -arrow.width/2;
      if(dragging && !firing) {
        if(mouseX>trackX1-25&&mouseX<trackX2+25) {
          if(mouseY>trackY1&&mouseY<trackY2) pscale = (mouseY-trackY1)*1.0/tracklength;
          else if(mouseY<=trackY1) pscale = minPscale;
          else if(mouseY>=trackY2) pscale= maxPscale;
          if(pscale > minPscale) adjusted = true;
          fixedY = ypos;
          velX = 0;
          velY = maxVel * pscale;
        }
      }
      if(firing) {
        ypos+=(ypace);
      }
      if(ypos>height) {
        die();
      }
    }
    else if(orientation==2) {
      ypos = trackY1 -arrow.height/2;
      if(dragging  && !firing) {
        if(mouseY>trackY1-25&&mouseY<trackY2+25) {
          if(mouseX>trackX1&&mouseX<trackX2) {
            xpos=mouseX;
          }
          else if(mouseX<=trackX1) {
            float llength = trackX2 - trackX1;
            xpos=trackX1;
          }
          else {
            xpos=trackX2;
          }

          fixedX=xpos;
          pscale = (trackX2-fixedX)*1.0/tracklength;
          if(mouseX > trackX2 || pscale < .1) pscale = minPscale;
          if(pscale > minPscale) adjusted = true;

          pscale = (pscale > maxPscale) ? maxPscale : pscale;
          velX = maxVel * pscale * -1;
          velY = 0;
        }
      }
      if(firing) {
        xpos+= (xpace);
      }
      if(xpos<0-arrow.width) {
        die();
      }
    }
    else if(orientation==3) {
      xpos = trackX1 -arrow.width/2;
      if(dragging && !firing) {
        if(mouseX>trackX1-25&&mouseX<trackX2+25) {
          if(mouseY>trackY1&&mouseY<trackY2) ypos=mouseY;
          else if(mouseY<=trackY1 && mouseY>trackY1-100) ypos=trackY1;
          else {
            ypos=trackY2;
          }
          fixedY=ypos;
          pscale = (trackY2-fixedY)*1.0/tracklength;
          if(pscale < .2) pscale = minPscale;          
          pscale = (pscale > maxPscale) ? maxPscale : pscale;
          if(pscale > minPscale) adjusted = true;
          velX = 0;
          velY = maxVel * pscale * -1;
        }
      }
      if(firing) {
        ypos+=(ypace);
      }
      if( ypos< 0-arrow.height) {
        die();
      }
    }
    else if(orientation==4) {
      ypos = trackY1-arrow.height/2;
      if(dragging && !firing) {
        if(mouseY>trackY1-25&&mouseY<trackY2+25) { 
          if(mouseX>trackX1+5&&mouseX<trackX2) pscale = (mouseX-trackX1)*1.0/tracklength;
          else if(mouseX<=trackX1+5) pscale= minPscale;
          else if(mouseX>=trackX2) pscale = maxPscale;
          fixedX=xpos;
          velX = maxVel * pscale;
          velY = 0;
          xpos = (mouseX > trackX2) ? trackX2 : mouseX;
        }
      }

      if(pscale > minPscale) adjusted = true;
      if(firing) {
        xpos+=(xpace);
      }
      if(xpos>width) {
        die();
      }
    }
  }

  void display() {
    if(adjusted) hidden = false;
    if(hidden) return;
    if(orientation==1) {
      image(arrow, xpos - 10 - gunProjectileOffset +arrow.width/2-arrow.width*pscale/2, ypos, arrow.width*pscale, tracklength*pscale);
    }
    else if (orientation==3) {
      float moveYOffset = 0;
      image(arrow, xpos - gunProjectileOffset +arrow.width/2-arrow.width*pscale/2, ypos, arrow.width*pscale, tracklength*pscale);
    }
    else if (orientation == 2) {
      if(pscale > 0) {
        if(firing && firelength == 0) firelength = trackX2 - xpos;
        if(firing) image(arrow, xpos, ypos - gunProjectileOffset+arrow.height/2-arrow.height*pscale/2, firelength, arrow.height*pscale);
        else image(arrow, xpos, ypos - gunProjectileOffset+arrow.height/2-arrow.height*pscale/2, trackX2 - xpos, arrow.height*pscale);      
      }
    }
    else if (orientation == 4) {
      float moveXOffset = 0;
      if(firing) {
        moveXOffset = xpos - 20 - trackX1;
        image(arrow, trackX1 + moveXOffset, ypos - gunProjectileOffset+arrow.height/2-arrow.height*pscale/2, tracklength - 20, arrow.height*pscale);
      }
      else {
        image(arrow, trackX1 + moveXOffset, ypos - gunProjectileOffset+arrow.height/2-arrow.height*pscale/2, xpos - 20, arrow.height*pscale);
      }
    }

    collisionCounter--;
    if(collisionCounter == 0) {
      collision = true;
      collisionCounter = -1;
    }
  } 
  void fire(Target t) {
    if(adjusted) {
      if(!locked) {
        firing=true;
        int pace = 40;
        if(orientation == 1) ypace = (t.posY - (ypos + trackY2-trackY1)) / pace;
        if(orientation == 2) xpace = (t.posX - xpos) / pace;
        if(orientation == 3) ypace = (t.posY - ypos) / pace;
        if(orientation == 4) {
          xpos = trackX1;
          xpace = (t.posX - (xpos + trackX2-trackX1)) / pace;
        }
        collisionCounter = pace;
        adjusted = false;
      }
    }
  }

  float getPscale() {
    return (pscale > maxPscale) ? maxPscale : pscale;
  }
  void die() {
    firelength = 0;
    collision = false;
    hidden = true;
    xpace = 0;
    ypace = 0;
    pscale = 0;
    if(orientation==1) {
      firing=false;
      adjusted = false;
      ypos=25;
      fixedY=ypos;
    }
    else if(orientation==2) {
      adjusted = false;
      firing=false;
      xpos=trackX2-arrow.width*pscale;
      fixedX=xpos;
    }
    else if(orientation==3) {
      adjusted = false;
      firing=false;
      ypos=trackY2-arrow.height*pscale;
      fixedY=ypos;
    }
    else if(orientation==4) {
      adjusted = false;
      firing=false;
      xpos=trackX1;
      fixedY=ypos;
      ;
    }
  }
  void mousePressed() {
    if(gun[gunNum].checkInside()) dragging=true;
  }
  void mouseReleased() {
    dragging=false;
  }

  float tipX() {
    return ypos; 
  }

  float tipY() {
    return xpos;
  }

  float velX() {
    return velX;
  }

  float velY() {
    return velY;
  }
}