/*
 *Final Project
 *
 * by Jason Dobrinski 
 * DisplayImage based off of Dave Small's Display Image code
 */
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
import java.util.ArrayList;
import java.lang.*;
import java.awt.geom.*; 
import javax.swing.Timer;
import java.applet.Applet;
import java.util.Random;
import java.applet.AudioClip;
class Weapon {
   String Type;
   boolean collision;
   BufferedImage animation = null;
   BufferedImage img;
   BufferedImage collisionImg;
   int Energy = 100;
   int knockbackX;
   int knockbackY;
   int hitPoints;
   int posX;
   int posY;
   protected int currentState;
   protected int currentAction;
   double weaponRotStart;
   double weaponRotDeg;
   double direction;
   int Trans;
   int veloX=0;
   int veloY=0;
   double Scale = 1.0;
   int actionFrame;
   boolean weaponAction = false;
   public void update() {}
   public void setPos(int posX, int posY) {
      this.posX = posX;
      this.posY = posY;
   }
   public void executeAction(String i) {}
   public void executeAction(String i, int x, int y) {}
}

class Sword extends Weapon {
   BufferedImage slashImg;
   final public int FRONT_SLASH = 8;
   final public int BACK_SLASH = 9;
   final public int FRONT_ATTACK = 10;
   final public int BACK_ATTACK = 11;
   final public int UP_ATTACK = 12;
   final public int DOWN_ATTACK = 13;
   final public int FRONT_SWIRL = 14;
   final public int BACK_SWIRL = 15;
   final public int UP_SWIRL = 16;
   final public int DOWN_SWIRL = 17;
   final public int DOWNFORWARD_ATTACK = 18;
   final public int UPFORWARD_ATTACK = 19;
   final public int DOWNBACK_ATTACK = 20;
   final public int UPBACK_ATTACK = 21;
   public Sword(String name) {
      Type = "sword";
      knockbackX=5;
      knockbackY=5;
      hitPoints = 5;
      File file1 = new File(name+".png");
      File file2 = new File(name+"Collision.png");
      File file3 = new File("heroSlash.png");
      try {
         img = ImageIO.read(file1);
         collisionImg = ImageIO.read(file2);
         slashImg = ImageIO.read(file3);
      }
      catch(IOException e) {}
   }
   public void update() {
      if(Energy<=0) {
            actionFrame = 0;
            weaponAction = false;
      }
      if(actionFrame == 0 && Energy<100)
         Energy++;
      switch(currentAction) {
         case FRONT_SLASH : 
            if(actionFrame == 0) {
               animation = slashImg;
               actionFrame = 10;
               weaponAction = true;
               veloX=8;
               weaponRotStart = Math.PI/2;
               weaponRotDeg = Math.PI/2;
            }
            actionFrame--;
            if(actionFrame == 0) {
               animation = null;
               veloX=0;
               currentAction = 0;
               weaponRotStart = 0;
               weaponRotDeg = 0;
               weaponAction = false;
            }
            break;
         case BACK_SLASH : 
            if(actionFrame == 0) {
               animation = slashImg;
               actionFrame = 10;
               weaponAction = true;
               veloX=-8;
               weaponRotStart = -Math.PI/2;
               weaponRotDeg = -Math.PI/2;
            }
            actionFrame--;
            if(actionFrame == 0) {
               animation = null;
               veloX=0;
               currentAction = 0;
               weaponRotStart = 0;
               weaponRotDeg = 0;
               weaponAction = false;
            }
            break;
         case FRONT_ATTACK :
            if(actionFrame ==0) {
               actionFrame = 5;
               weaponAction = true;
               weaponRotStart = Math.PI/2;
            }
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         case BACK_ATTACK :
            if(actionFrame ==0) {
               actionFrame = 5;
               weaponAction = true;
               weaponRotStart = -Math.PI/2;
            }
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         case UP_ATTACK :
            if(actionFrame ==0) {
               actionFrame = 5;
               weaponAction = true;
               weaponRotStart = 0;
            }
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         case DOWN_ATTACK :
            if(actionFrame ==0) {
               actionFrame = 5;
               weaponAction = true;
               weaponRotStart = Math.PI;
            }
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         case DOWNFORWARD_ATTACK :
            if(actionFrame ==0) {
               actionFrame = 5;
               weaponAction = true;
               weaponRotStart = Math.PI/1.5;
            }
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         case DOWNBACK_ATTACK :
            if(actionFrame ==0) {
               actionFrame = 5;
               weaponAction = true;
               weaponRotStart = -Math.PI/1.5;
            }
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         case UPFORWARD_ATTACK :
            if(actionFrame ==0) {
               actionFrame = 5;
               weaponAction = true;
               weaponRotStart = Math.PI/3.5;
            }
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
            case UPBACK_ATTACK :
            if(actionFrame ==0) {
               actionFrame = 5;
               weaponAction = true;
               weaponRotStart = -Math.PI/3.5;
            }
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         case FRONT_SWIRL :
            if(actionFrame == 0) {
               actionFrame = 20;
               weaponAction = true;
               if(direction == 1)
                  weaponRotStart = Math.PI/3.5;
               else 
                  weaponRotStart = Math.PI/1.5;
               weaponRotDeg = .1*direction;
            }
            weaponRotStart+=weaponRotDeg;
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         case BACK_SWIRL :
            if(actionFrame == 0) {
               actionFrame = 20;
               weaponAction = true;
               if(direction == 1)
                  weaponRotStart = -Math.PI/3.5;
               else 
                  weaponRotStart = -Math.PI/1.5;
               weaponRotDeg = -.1*direction;
            }
            weaponRotStart+=weaponRotDeg;
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         case DOWN_SWIRL :
            if(actionFrame == 0) {
               actionFrame = 25;
               weaponAction = true;
               weaponRotStart = Math.PI/2*direction;
               weaponRotDeg = .1*direction;
            }
            weaponRotStart+=weaponRotDeg;
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         case UP_SWIRL :
            if(actionFrame == 0) {
               actionFrame = 25;
               weaponAction = true;
               weaponRotStart = -Math.PI/2*direction;
               weaponRotDeg = .1*direction;
            }
            weaponRotStart+=weaponRotDeg;
            actionFrame--;
            if(actionFrame == 0) {
               weaponAction = false;
               currentAction = 0;
            }
            break;
         }
   }
   public void executeAction(String string) {
      int actionString = Integer.parseInt(string);
      switch(actionString) {
         case 1:
            Scale = -1.0;
            Trans = 15;
            currentAction = DOWNBACK_ATTACK;
         break;
         case 2:
            Scale = -1.0;
            Trans = 5;
            currentAction = BACK_ATTACK;
            break;
         case 3:
            Scale = -1.0;
            Trans = -5;
            currentAction = UPBACK_ATTACK;
         break;
         case 6:
            Scale = 1.0;
            Trans = 5;
            currentAction = FRONT_ATTACK;
            break;
         case 4:
            Trans = -5;
            currentAction = UP_ATTACK;
            break;
         case 5:
            Trans = -5;
            currentAction = UPFORWARD_ATTACK;
            break;
         case 7:
            Trans = 15;
            currentAction = DOWNFORWARD_ATTACK;
            break;
         case 8:
            Trans = 15;
            currentAction = DOWN_ATTACK;
            break;
         case 321:      
         case 318:      
            direction =1;
            Trans = 5;
            Scale = -1.0;
            currentAction = BACK_SWIRL;
            break;
         case 26:
            Trans = 5;
            Scale = 1.0;
            currentAction = FRONT_SLASH;
            break;
         case 567:
         case 57:         
            direction = 1;
            Trans = 5;
            Scale = 1.0;
            currentAction = FRONT_SWIRL;
            break;
         case 765:
         case 75:         
            direction = -1;
            Trans = 5;
            Scale = 1.0;
            currentAction = FRONT_SWIRL;
            break;
         case 62:
            Trans = 5;
            Scale = -1.0;
            currentAction = BACK_SLASH;
            break;
         case 187:
            direction = -1.0;
            Trans = 30;
            currentAction = DOWN_SWIRL;
            break;   
         case 781:
            direction = 1.0;
            Trans = 30;
            currentAction = DOWN_SWIRL;
            break;   
         case 25:
         case 24:
         case 245:
         case 247:
            Trans = -5;
            direction = 1;
            currentAction = UP_SWIRL;
            break;
         case 52:
         case 42:
         case 542:
         case 5432:
         case 742:
            Trans = -5;
            direction = -1;
            currentAction = UP_SWIRL;
            break;               
      }
   }
   
   
   
}

class Axe extends Weapon {

   public Axe(String name) {
      Type = "axe";
      knockbackX=30;
      knockbackY=30;
      hitPoints = 30;
      File file1 = new File(name+".png");
      File file2 = new File(name+"Collision.png");
      try {
         img = ImageIO.read(file1);
         collisionImg = ImageIO.read(file2);
      }
      catch(IOException e) {}
      
   }
   public void update() {
   
   }
   public void executeAction(String action) {
     String string = "" + action;
     
   }
}

class Lance extends Weapon {
   int releasedX;
   int releasedY;
   int state = 0;
   BufferedImage slashImg;
   BufferedImage jumpImg;
   public Lance(String name) {
      Type = "lance";
      knockbackX=5;
      knockbackY=5;
      hitPoints = 50;
      File file1 = new File(name+".png");
      File file2 = new File(name+"Collision.png");
      File file3 = new File("heroSlash.png");
      File file4 = new File("heroJump.png");
      
      try {
         img = ImageIO.read(file1);
         collisionImg = ImageIO.read(file2);
         slashImg = ImageIO.read(file3);
         jumpImg = ImageIO.read(file4);
      }
      catch(IOException e) {}
    } 
   public void update() {
      if(Energy<=0 || collision== true) {
            actionFrame = 0;
            weaponAction = false;
            animation = null;
      }
      if(actionFrame == 0 ) {
         animation = null;
         weaponAction = false;
         if(Energy<100)
            Energy++;
      }
      if(actionFrame == 1) {
         Energy-=5;
         switch (state) {
         case 73:
            veloX=-10;
            veloY=-10;
            if(posX<releasedX+20 && posX>releasedX-20
            || posY<releasedY+20 && posY>releasedY-20) {
               actionFrame = 0;
               weaponAction = false;
               animation = null;
            }
            break;
         case 62:
            veloX=-10;
            veloY=0;
            if(posX<releasedX+20 && posX>releasedX-20) {
               actionFrame = 0;
               weaponAction = false;
               animation = null;
            }
            break;
         case 37:
            veloX=10;
            veloY=10;
            if(posX<releasedX+20 && posX>releasedX-20
            || posY<releasedY+20 && posY>releasedY-20) {
               actionFrame = 0;
               weaponAction = false;
               animation = null;
            }
            break;
         case 84:
            veloX=0;
            veloY=-10;
            if(posY<releasedY+20 && posY>releasedY-20) {
               actionFrame = 0;
               weaponAction = false;
               animation = null;
            }
            break;
         case 51:
            veloX=-10;
            veloY=10;
            Scale = -1;
            if(posX<releasedX+20 && posX>releasedX-20
            || posY<releasedY+20 && posY>releasedY-20) {
               actionFrame = 0;
               weaponAction = false;
               animation = null;
            }
            break;
         case 26:
            veloX=10;
            veloY=0;
            if(posX<releasedX+20 && posX>releasedX-20) {
               actionFrame = 0;
               weaponAction = false;
               animation = null;
            }
            break;
         case 15:
            veloX=10;
            veloY=-10;
            if(posX<releasedX+20 && posX>releasedX-20
            || posY<releasedY+20 && posY>releasedY-20) {
               actionFrame = 0;
               weaponAction = false;
               animation = null;
            }
            break;
         case 48:
            veloX=0;
            veloY=10;
            if(posY<releasedY+20 && posY>releasedY-20) {
               actionFrame = 0;
               weaponAction = false;
               animation = null;
            }
            break;
        default:
           state = 0;
      }
      }
   }
   public void executeAction(String action, int x, int y) {
      state = Integer.parseInt(action);
      releasedX = x;
      releasedY = y;
      animation = null;
      switch (state) {
         case 15:
            weaponRotStart = Math.PI/3.5;
            actionFrame = 1;
            weaponAction = true;
            Scale = 1;
            animation = slashImg;
            break;
         case 62:
            weaponRotStart = -Math.PI/2;
            actionFrame = 1;
            weaponAction = true;
            Scale = -1;
            animation = slashImg;
            break;
         case 51:
            weaponRotStart = -Math.PI/1.5;
            actionFrame = 1;
            weaponAction = true;
            Scale = -1;
            animation = slashImg;
            break;
         case 84:
            weaponRotStart = 0; 
            actionFrame = 1;
            weaponAction = true;
            animation = jumpImg;
            break;
         case 73:
            Scale = -1;
            weaponRotStart = -Math.PI/3.5;
            actionFrame = 1;
            weaponAction = true;
            animation = slashImg;
            break;
         case 26:
            weaponRotStart = Math.PI/2;
            actionFrame = 1;
            weaponAction = true;
            Scale = 1;
            animation = slashImg;
            break;
         case 37:
            weaponRotStart = Math.PI/1.5;
            actionFrame = 1;
            weaponAction = true;
            Scale = 1;
            animation = slashImg;
            break;
         case 48:
            weaponRotStart = Math.PI;
            actionFrame = 1;
            weaponAction = true;
            animation = slashImg;
            break;
        default:
           actionFrame = 0;
           state = 0;
           animation = null;
           break;
      }
   }
}

class Ball extends Weapon {

   public Ball(String name) {
      Type = "ball";
      knockbackX=10;
      knockbackY=10;
      hitPoints = 20;
      weaponRotDeg = .4;
      File file1 = new File(name+".png");
      File file2 = new File(name+"Collision.png");
      try {
         img = ImageIO.read(file1);
         collisionImg = ImageIO.read(file2);
      }
      catch(IOException e) {}
   }
   public void update() {
      if(Energy<=0) {
            actionFrame = 0;
            weaponAction = false;
      }
      if(actionFrame>0) {
         weaponRotStart+= (direction*weaponRotDeg);
         actionFrame--;
         Energy-=7;
       }
      else {
       weaponAction = false;
       if(Energy<100)
         Energy++;
      
      }
   }
   public void executeAction(String string) {
      int choice;
      if(string.length()>1)
         choice = Integer.parseInt(string.substring(1,2));
      else
         choice = 0;
      switch (choice) {
         case 1:
            weaponRotStart = -Math.PI/3.5;
            break;
         case 2:
            weaponRotStart = -Math.PI/2;
            break;
         case 3:
            weaponRotStart = -Math.PI/1.5;
            break;
         case 4:
            weaponRotStart = 0; 
            break;
         case 5:
            weaponRotStart = Math.PI/3.5;
            break;
         case 6:
            weaponRotStart = Math.PI/2;
            break;
         case 7:
            weaponRotStart = Math.PI/1.5;
            break;
         case 8:
            weaponRotStart = Math.PI;
            break;
      }
      actionFrame = (string.length())*3;
      weaponAction = true;
         direction = 1;
      if(string.length()>2)
      if(choice>Integer.parseInt(string.substring(2,3))) {
        direction = -1;
      }
      
   }
}

class Hero extends Sprite {
   BufferedImage jumpImg;
   BufferedImage idleImg;
   BufferedImage slashImg;
   BufferedImage walkImg[] = new BufferedImage[9];
   final AudioClip walking =  Applet.newAudioClip(getClass().getResource("walking.wav"));
   Weapon currWeapon;
   Sword sword;
   Sword axe;
   Lance lance;
   Ball ball;
   int Life = 100;
   double direction;
   final public int IDLE = 1;
   final public int JUMP = 2;
   final public int FALL = 3;
   final public int WALK_LEFT = 4;
   final public int WALK_RIGHT = 5;
   final public int RUN_LEFT = 6;
   final public int RUN_RIGHT = 7;
   protected int currentState;
   protected int TOPLEFT = 1;
   protected int TOPRIGHT = 2;
   protected int BOTTOMLEFT = 3;
   protected int BOTTOMRIGHT = 4;
   double weaponRotStart;
   double weaponRotDeg;
   protected int frame=0;
   protected int actionFrame = 0;
   String actionString = "0";
   double Scale = 1.0;
   int Trans = 5;
   
   
   public Hero(String name) {
      File file = new File(name +".png");
      File file2 = new File(name+"Collision.png");
      File file3 = new File(name+"Slash.png");
      File file4 = new File(name+"Jump.png");
      
      try {
         img = ImageIO.read(file);
         idleImg = img;
         slashImg = ImageIO.read(file3);
         jumpImg = ImageIO.read(file4);
         collision = ImageIO.read(file2);
         
      }
      catch(IOException e) {}
      for(int i=0;i<9;i++) {
            
            File file5 = new File(name+"Walk"+i+".png");
            try {
               walkImg[i] = ImageIO.read(file5);
            }
            catch(IOException e) {}
         }
      
      this.posX = 10;
      this.posY = 0;
      width = img.getWidth();
      ball = new Ball("ball");
      sword = new Sword("sword");
      axe = new Sword("axe");
      axe.knockbackX = 30;
      axe.knockbackY = 30;
      lance = new Lance("lance");
      currWeapon = sword;
      height = img.getHeight();
      currentState = IDLE;
   }
   public BufferedImage getWeapon() {
      return currWeapon.img;
   }
   public BufferedImage getWeaponCollision() {
      return currWeapon.collisionImg;
   }
   public int checkCollision(Enemy temp, BufferedImage tempImg){
      int x = posX+(width/2);
      int y = posY+(height/2);
      
      for(int i =x-5; i<x+5;i++) { 
         for(int j =y-5; j<y+5;j++) {
            if(i>0 && i<800 && j>0 && j<800)
               if(tempImg.getRGB(i,j) == temp.color)
                  return 1;
         }
      }
      return 0;
   }
   public void setCurrentState(int STATE) {
      currentState = STATE;
   }
   public boolean weaponAction() {
      return currWeapon.weaponAction;
   }
   public void setCurrentAction(int ACTION) {
      currWeapon.currentAction = ACTION;
   }
   public int getCurrentState(){
      return currentState;
   }
   public void update() {
      switch(currentState){
         case IDLE : 
         if(currWeapon.currentAction<8) {
            if(veloX < 0)
              veloX++;
            if(veloX>0)
              veloX--;
              veloY = 0; 
         }
           if(actionFrame==0);
              img = idleImg;
           break;
         case WALK_LEFT :
            SwingUtilities.invokeLater(new Runnable() 
	         {			    
		       public void run() 
		      {				
				   walking.play();
		      }	
	         } );         
            Scale = -1.0;
            if(frame>8)
               frame = 0;
            img = walkImg[frame];
            frame++;
            if(veloX<2) veloX-=1; 
            break;
         case WALK_RIGHT : 
            SwingUtilities.invokeLater(new Runnable() 
	         {			    
		       public void run() 
		      {				
				   walking.play();
		      }	
	         } );
            Scale = 1.0;
            if(frame>8)
               frame = 0;
            img = walkImg[frame];
            frame++;            
            if(veloX>-2) veloX+=1; 
            break;
         case RUN_LEFT : 
            Scale = -1.0;
            if(frame>8)
               frame = 0;
            img = walkImg[frame];
            frame++;
            if(veloX>-5) veloX-=1; 
            break;
         case RUN_RIGHT :
            Scale = 1.0;
            if(frame>8)
               frame = 0;
            img = walkImg[frame];
            frame++;
            if(veloX<5) veloX+=1; 
            break;
         case JUMP : if(veloY == 0) {
                        img = jumpImg;
                        veloY = -16;
                     }
                        veloY++;
                     if(veloY == 0) {
                       img = idleImg;
                        currentState = FALL;
                     }                     
                     break;
         case FALL : 
         veloY++; 
         if(veloY>10)
            veloY=10;
         break;
         
      }
      currWeapon.update();
      currWeapon.setPos(posX, posY);
      if(currWeapon.actionFrame!=0) {
         Scale = currWeapon.Scale;
         if(currWeapon.veloX!=0)
            veloX = currWeapon.veloX;
         if(currWeapon.veloY!=0)
            veloY = currWeapon.veloY;
      }
      posX+=veloX;
      posY+=veloY;
      if(currWeapon.animation!=null) {
         img = currWeapon.animation;
      }
      
   }
   public void loadWeapon(String name) {
      
   }
   public void addAction(int color) {
            if(color ==  -16711936){
                  if(actionString.charAt(actionString.length()-1)!='3')
                     actionString+="3";
            }
            else if(color == -16776961   ){
                  if(actionString.charAt(actionString.length()-1)!='4')
                     actionString+="4";
            }
            else if(color ==  -65281){
                  if(actionString.charAt(actionString.length()-1)!='5')
                     actionString+="5";
            }
            else if(color == -13312){
                  if(actionString.charAt(actionString.length()-1)!='2')
                     actionString+="2";
            }
            else if(color == -3407668){
                  if(actionString.charAt(actionString.length()-1)!='6')
                     actionString+="6";
            }
            else if(color == -16777201){
                  if(actionString.charAt(actionString.length()-1)!='1')
                     actionString+="1";
            }
            else if(color ==  -16777009){
                  if(actionString.charAt(actionString.length()-1)!='8')
                     actionString+="8";
            }
            else if(color == -1048576){
                  if(actionString.charAt(actionString.length()-1)!='7')
                     actionString+="7";
            }
   }
   public void executeAction() {
      currWeapon.executeAction(actionString);
      actionString = "0";
   }
   public void executeAction(int x, int y) {
      currWeapon.executeAction(actionString, x, y);
      actionString = "0";
   }
}

class Sprite {
   BufferedImage img;
   BufferedImage collision;
   protected int posX;
   protected int posY;
   protected int width;
   protected int height;
   protected int veloX;
   protected int veloY;
   public BufferedImage getSprite() {
      return img;
   }
   public BufferedImage getSpriteCollision() {
      return collision;
   }
   public int getPosX() {
      return posX;
   }
   public int getPosY() {
      return posY;
   }
   public void setPosX(int posX) {
      this.posX = posX;
   }
   public void setPosY(int posY) {
      this.posY = posY;
   }
   public void setVeloY(int veloY) {
      this.veloY = veloY;
   }
   public int getWidth() {
      return width;
   }
   public int getHeight() {
      return height;
   }
   
}

class Terrain extends Sprite {
   public Terrain(String name) {
      File file = new File(name +".png");
      File file2 = new File(name+"Collision.png");
      try {
         img = ImageIO.read(file);
         collision = ImageIO.read(file2);
      }
      catch(IOException e) {}
      this.posX = 0;
      this.posY = 0;
      width = img.getWidth();
      height = img.getHeight();
   }
}

class Enemy extends Sprite {
   boolean alive;
   int hitPoints;
   int life;
   int speed;
   int frame = 1;
   int color;
   int deathCount=0;
   BufferedImage frame1Img;
   BufferedImage frame2Img;
   public Enemy(String name, int life) {
      this.life = life;
      hitPoints = new Random().nextInt(3)+1;
      File file = new File(name + "1.png");
      File file2 = new File(name + "2.png");
      try {
         frame1Img = ImageIO.read(file);
         frame2Img = ImageIO.read(file2);
      }
      catch(IOException e) {}
      this.posX = 0;
      this.posY = 0;
      width = frame1Img.getWidth();
      height = frame1Img.getHeight();
      alive = true;
      speed = new Random().nextInt(3);
      if(speed==0)
         speed=1;
      color = new Random().nextInt(1000000) + 0xFF000000;
   }
   public void setAlive(boolean alive) {
      this.alive = alive;
   }
   public BufferedImage getSprite() {
     if(frame == 1) {
        frame = 2;
        return frame1Img;
     }
     else {
        frame = 1;
        return frame2Img;
     }
     
   }
}

class gameFrame extends JFrame implements KeyListener, MouseListener, MouseMotionListener{
  protected int WIDTH;
  protected int HEIGHT;
  String display;
  int keyPressed[] = new int[256];
  Hero hero = new Hero("hero");
  ArrayList Enemies = new ArrayList();
  ArrayList Level = new ArrayList();
  GamePanel gamePanel;
  Container container;
  JTextField score = new JTextField();
  boolean Start = false;
  Timer timer;
  int time = 0;
  public gameFrame(int WIDTH, int HEIGHT) {
     container = this.getContentPane(); 
     container.setLayout(new BorderLayout());     
     this.setTitle("CAP 3027 2008 - Final Project - Jason Dobrinski");
     this.setSize(WIDTH,HEIGHT);
     hero.loadWeapon("sword");
     addKeyListener(this);
     addMouseListener(this);
     addMouseMotionListener(this);
     gamePanel = new GamePanel("game");
     addMenu();
     timer = new Timer(time, new ActionListener() {
         public void actionPerformed(ActionEvent evt) {
            timer.stop();
               if(Start == true){
                  startGame();
               }
            timer.restart();
         }
      });
      
  }
  
   protected void addMenu() {
    JMenu fileMenu = new JMenu("File");
    JMenuItem  gameStart = new JMenuItem("Game Start");
    gameStart.addActionListener(new ActionListener()
  {   public void actionPerformed(ActionEvent event)  { 
          Start = true;
          container.add(gamePanel, BorderLayout.CENTER);
          timer.start();
  }   }   );
  fileMenu.add( gameStart);
  JMenuItem  gameStartC = new JMenuItem("Game Start (Collision Display)");
    gameStartC.addActionListener(new ActionListener()
  {   public void actionPerformed(ActionEvent event)  { 
          Start = true;
          Start = true;
          gamePanel = new GamePanel("collisionImg");
          container.add(gamePanel, BorderLayout.CENTER);
          timer.start();
  }   }   );
  fileMenu.add( gameStartC);
JMenuItem  gameReStart = new JMenuItem("Game ReStart");
    gameReStart.addActionListener(new ActionListener()
  {   public void actionPerformed(ActionEvent event)  { 
          Start = true;
          gamePanel = new GamePanel("game");
          hero.setPosX(0);
          hero.setPosY(0);
          hero.setCurrentState(hero.IDLE);
          hero.Life = 100;
          container.add(gamePanel, BorderLayout.CENTER);
          timer.start();
  }   }   );
  fileMenu.add( gameReStart);
 JMenuItem exitItem = new JMenuItem("Exit");
 exitItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) {System.exit(0); } });
 fileMenu.add(exitItem);

 JMenuBar menuBar = new JMenuBar();
 menuBar.add(fileMenu);
 this.setJMenuBar(menuBar);
}

   public void startGame() {
      if(!gamePanel.checkFloorCollision(hero) && hero.getCurrentState() != hero.JUMP) {
            hero.setCurrentState(hero.FALL);
      }
      else if(gamePanel.checkFloorCollision(hero) && hero.getCurrentState() == hero.FALL) {
         hero.setCurrentState(hero.IDLE);
         hero.setVeloY(0);
      }
      if(keyPressed[KeyEvent.VK_A]!=0) 
            if(hero.getCurrentState()!=hero.FALL && hero.getCurrentState()!=hero.JUMP)
               hero.setCurrentState(hero.RUN_LEFT);
      if(keyPressed[KeyEvent.VK_D]!=0)
            if(hero.getCurrentState()!=hero.FALL && hero.getCurrentState()!=hero.JUMP)
               hero.setCurrentState(hero.RUN_RIGHT);
      if(keyPressed[KeyEvent.VK_W]!=0)
            if(hero.getCurrentState()!=hero.FALL && hero.getCurrentState()!=hero.JUMP)
               hero.setCurrentState(hero.JUMP);
      double wall = gamePanel.checkWallCollision(hero);
      if(wall!=0) {
         hero.currWeapon.veloX = 0;
         hero.currWeapon.veloY = 0;
         hero.currWeapon.collision = true;
         if(hero.Scale>0)
            hero.veloX = -2;
         else
            hero.veloX = 2;
            
      }
      else {
          hero.currWeapon.collision = false;
      }
      
      
      SwingUtilities.invokeLater(new Runnable() 
	  {			    
		 public void run() 
		{				
				hero.update();
            if(hero.Life<=0) {
         timer.stop();
         System.out.println("GAME OVER");
         gamePanel.update(true);
         Start = false;
         
      }
            if(hero.getPosY()>gamePanel.game.getHeight()) {
         hero.setPosX(0);
         hero.setPosY(0);
         hero.Life-=10;
         hero.veloX = 0;
      }
            for(int i=0; i<gamePanel.enemies.length; i++) {
         if(gamePanel.enemies[i].alive) {
            if(hero.checkCollision(gamePanel.enemies[i], gamePanel.collisionImg)>0) {
               hero.Life-=gamePanel.enemies[i].hitPoints;
               gamePanel.enemies[i].setPosX(gamePanel.enemies[i].getPosX()+30);
               
            }            
         }
      }
      
      }	
	 } );
  
      
      
      
      
      gamePanel.updateEnemies(hero.getPosX(), hero.getPosY());
      gamePanel.setSprite(hero);
      gamePanel.drawCollisions();
      gamePanel.update(false);
      validate();
   }
   public void keyPressed(KeyEvent e) {
      int key = e.getKeyCode();
      keyPressed[e.getKeyCode()] = 1;
   }
   public void keyReleased(KeyEvent e) {
      keyPressed[e.getKeyCode()] = 0;
      hero.setCurrentState(hero.IDLE);
   }
   public void keyTyped(KeyEvent e) {
      if(e.getKeyChar() == '1')
        hero.currWeapon = hero.sword;
        
      if(e.getKeyChar() == '2')
        hero.currWeapon = hero.lance;
        
      if(e.getKeyChar() == '3')
        hero.currWeapon = hero.axe;
        
      if(e.getKeyChar() == '4')
        hero.currWeapon = hero.ball;
   }
   public void mouseClicked(MouseEvent e) {}
   public void mouseEntered(MouseEvent e) {}
   public void mouseExited(MouseEvent e) {}
   public void mousePressed(MouseEvent e) {
      hero.addAction(gamePanel.heroClick.getRGB(e.getX(),e.getY()-50));
   }
   public void mouseReleased(MouseEvent e) {
      if(hero.currWeapon.Type == "lance") {
            hero.executeAction(e.getX(), e.getY());
            }
      hero.executeAction();
   }
   public void mouseDragged(MouseEvent e) {
      hero.addAction(gamePanel.heroClick.getRGB(e.getX(),e.getY()-50));
   }
   public void mouseMoved(MouseEvent e) {}
   
}

class GamePanel extends JPanel {
   int Points = 0;
   boolean gameover = false;
   final AudioClip hit = Applet.newAudioClip(getClass().getResource("hit.wav"));
   String display;
   BufferedImage game;
   BufferedImage heroControlImg;
   BufferedImage heroClick;
   BufferedImage collisionImg;
   Terrain terrain = new Terrain("background");
   Enemy enemies[] = new Enemy[10];
   boolean collision = false;
   Graphics g;
   Hero sprite = null;
   double radians = .5;
   public GamePanel(String name) {
      display = name;
      game = new BufferedImage(terrain.img.getWidth(),terrain.img.getHeight(), BufferedImage.TYPE_INT_ARGB);
      heroClick = new BufferedImage(terrain.img.getWidth(),terrain.img.getHeight(), BufferedImage.TYPE_INT_ARGB);
      collisionImg = new BufferedImage(terrain.img.getWidth(),terrain.img.getHeight(), BufferedImage.TYPE_INT_ARGB);
      for(int i = 0;i<enemies.length; i++) {
        enemies[i] = new Enemy("enemy", (new Random().nextInt(5)+50));
        enemies[i].setPosX(new Random().nextInt(1000));
        enemies[i].setPosY(new Random().nextInt(1000));
      }
      File file = new File("heroControl.png");
      try {
         heroControlImg = ImageIO.read(file);
      }
      catch(IOException e) {}
      
   }
   public void updateEnemies(int x, int y) {
      if(sprite!=null)
      for(int i = 0;i<enemies.length; i++) {
        if(enemies[i].alive) {
           if(enemies[i].getPosX()<x+sprite.getWidth()/2)
              enemies[i].setPosX(enemies[i].getPosX()+enemies[i].speed);
           else
              enemies[i].setPosX(enemies[i].getPosX()-enemies[i].speed);
           if(enemies[i].getPosY()<y-5+(sprite.getHeight()/2))
              enemies[i].setPosY(enemies[i].getPosY()+enemies[i].speed);
           else
              enemies[i].setPosY(enemies[i].getPosY()-enemies[i].speed);
        }
        if(!enemies[i].alive) {
           enemies[i].deathCount++;
           if(enemies[i].deathCount == 10) {
             enemies[i].alive=true;
             enemies[i].life = new Random().nextInt(5)+5;
             enemies[i].setPosX(new Random().nextInt(15)*100);
             enemies[i].setPosY(new Random().nextInt(15)*100);
             enemies[i].deathCount =0;
           }
        }
     }
   
   }
   public void setSprite(Hero sprite){
      this.sprite = sprite;
   }
   public void drawCollisions() {
      Graphics2D g2 = (Graphics2D)heroClick.getGraphics();
      Graphics2D g3 = (Graphics2D)collisionImg.getGraphics();
      g3.setColor(Color.WHITE);
      g3.fillRect(0,0,800,800);
      g2.setColor(Color.WHITE);
      g2.fillRect(0,0,800,800);
         if(sprite!=null) {
            g2.drawImage(heroControlImg,sprite.getPosX()-(heroControlImg.getWidth()/2)+(sprite.getWidth()/2),sprite.getPosY()-(heroControlImg.getHeight()/2)+(sprite.getHeight()/2),this);
            g3.drawImage(terrain.getSpriteCollision(),0,0,this);
            BufferedImage weapon = sprite.getWeaponCollision();
            AffineTransform transformRot = new AffineTransform();
            AffineTransform transformTrans = new AffineTransform();
            transformRot.rotate(sprite.currWeapon.weaponRotStart, weapon.getWidth()/2, 
            weapon.getHeight()/2);
           
            if(sprite.Scale<0)
               transformTrans.translate(-5,sprite.Trans);
            else
               transformTrans.translate(0,sprite.Trans);
            AffineTransformOp op = new AffineTransformOp(transformTrans, 
         AffineTransformOp.TYPE_BILINEAR);
         weapon = op.filter(weapon, null);
          op = new AffineTransformOp(transformRot, 
         AffineTransformOp.TYPE_BILINEAR);
         weapon = op.filter(weapon, null);
            g3.setColor(Color.RED);
            //g3.fillRect(sprite.getPosX(),sprite.getPosY(),sprite.getWidth(), sprite.getHeight());
            //g3.drawImage(heroControlImg,sprite.getPosX()-(heroControlImg.getWidth()/2)+(sprite.getWidth()/2),sprite.getPosY()-(heroControlImg.getHeight()/2)+(sprite.getHeight()/2),this);
            if(sprite.weaponAction())
              g3.drawImage(weapon,sprite.getPosX()-25,sprite.getPosY()-15+sprite.Trans,this);
            if(enemies != null) {
               for(int i = 0; i<enemies.length; i++){
                  if(enemies[i] != null) {
                     if(enemies[i].alive) {
                        if(!checkEnemyCollision(enemies[i].getPosX(), enemies[i].getPosY(), enemies[i].getWidth(), enemies[i].getHeight())){
                           enemies[i].life -= sprite.currWeapon.hitPoints;
                           enemies[i].posX+= sprite.currWeapon.knockbackX;
                           enemies[i].posY+= sprite.currWeapon.knockbackY;
                           if(enemies[i].life<0)
                              enemies[i].setAlive(false);
                        }
                        g3.setColor(new Color(enemies[i].color));
                        g3.fillRect(enemies[i].getPosX(),enemies[i].getPosY(),enemies[i].getWidth(),enemies[i].getHeight());
                        
                     }
                  }
               }
            }
         }
         
   }
   public boolean checkFloorCollision(Hero hero) {
      for(int i = hero.getPosX()+5; i<hero.getPosX()-5+hero.getWidth();i++) {
         if(i>0 && i<terrain.img.getWidth() && hero.getPosY()+hero.getHeight()>0 && hero.getPosY()+hero.getHeight()<terrain.img.getHeight())
         if(collisionImg.getRGB(i, hero.getPosY()+hero.getHeight()) == 0xFF0000FF) {
            return true;
         }
      }
      return false;
   }
   public int checkWallCollision(Hero hero) {
      int wall;
      if(hero.veloX==0) {
         return 0;
      }
      if(hero.Scale>0) {
         wall = hero.getPosX()+hero.getWidth();
      }
      else {
         wall = hero.getPosX()-1;
      }
      for(int i = hero.getPosY(); i<hero.getPosY()+hero.getHeight()-10;i++){
         if(i>0 && i<terrain.img.getWidth() && wall>0 && wall<terrain.img.getWidth())
         if(collisionImg.getRGB(wall, i) == 0xFF0000FF) {
            return -5;
         }
      }
      return 0;
   }
   public boolean checkEnemyCollision(int x, int y, int width, int height) {
      for(int i = x; i<x+width; i++) {
         for(int j = y; j<y+height; j++) {
            if(i>0 && i<terrain.img.getWidth() && j>0 && j<terrain.img.getWidth())
            if(collisionImg.getRGB(i,j) == 0xFF00FF00) {
               Points+=5;
               SwingUtilities.invokeLater(new Runnable() 
	            {			    
		          public void run() 
		          {				
				      hit.play();
		          }	
               } );
              return false;
               
            }
         }
      }
      return true;
   }
   public void update(boolean gameover) {
      this.gameover = gameover;
      collision = false;
      repaint();
      validate();
   }
   public void paint(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D)game.getGraphics();
      g2.drawImage(terrain.getSprite(),0,0,this);
         if(enemies != null) {
            for(int i = 0; i<enemies.length; i++){
               if(enemies[i] != null) {
                  if(enemies[i].alive) {
                     g2.drawImage(enemies[i].getSprite(),enemies[i].getPosX(),enemies[i].getPosY(),this);
                  }
               }
            }
         }
         if(sprite!=null) {
         BufferedImage weapon = sprite.getWeapon();
         BufferedImage heroSprite = sprite.getSprite();
         AffineTransform transformRot = new AffineTransform();
         AffineTransform transformTrans = new AffineTransform();
         AffineTransform transformScale = new AffineTransform();
         transformRot.rotate(sprite.currWeapon.weaponRotStart, weapon.getWidth()/2, 
         weapon.getHeight()/2);
         if(sprite.Scale<0)
            transformTrans.translate(-5,sprite.Trans);
         else
            transformTrans.translate(0,sprite.Trans);
         AffineTransformOp op = new AffineTransformOp(transformRot, 
         AffineTransformOp.TYPE_BILINEAR);
         weapon = op.filter(weapon, null);
         
         if(sprite.Scale<0) {
            transformScale = 
            AffineTransform.getTranslateInstance(heroSprite.getWidth(),0);
            transformScale.scale(sprite.Scale,1.0);
            op = new AffineTransformOp(transformScale, AffineTransformOp.TYPE_BILINEAR);
            heroSprite = op.filter(heroSprite, null);
            
         }
         if(sprite.weaponAction())
            g2.drawImage(weapon,sprite.getPosX()-25,sprite.getPosY()-15+sprite.Trans,this);
         g2.drawImage(heroSprite,sprite.getPosX(),sprite.getPosY(),this);
         if(display == "collisionImg")
            g.drawImage(collisionImg,0,0,this);
         else
            g.drawImage(game,0,0,this);
         g.setColor(Color.RED);
         g.drawString("LIFE:" + sprite.Life, 15, 15);
         g.drawString("SCORE:" + Points, 150, 15);
         g.drawString("ENERGY:", 250, 15);
         g.fillRect(310,5,sprite.currWeapon.Energy, 10);
         if(sprite.Life<0)
            g.drawString("GAMEOVER", 150, 250);
         
         }
      }
}


public class finalProject {
  protected static final int WIDTH = 800;
  protected static final int HEIGHT = 850;

 public static void main(String[] args) {
	SwingUtilities.invokeLater(new Runnable() 
	  {			    
		 public void run() 
		{				
				createAndShowGUI();
		}	
	 } );
 } 
 		 
 public static void createAndShowGUI() {
  JFrame frame = new gameFrame( WIDTH, HEIGHT);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setVisible(true);
  }

}
