/***********************************************************************************************
	Klassenavn: hero
	Arver: sprite
	Beskrivelse: kontrollerer Cliffs bevegelser
************************************************************************************************/
import java.awt.*;
import java.applet.*;
import java.awt.image.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.lang.Math;
import sprite;

public class hero extends sprite {
      
	private final String rawImageName = "cliffies2.gif";
	private final int totalPics = 12;		// Totalt antall animasjonsbilder
	private final int picWidth = 32;		  // Bredden..
	private final int picHeight = 32; 		// ..og høyden på animasjonsbildene
			
	private Image pics[];					// Animasjonsbilder av clifford
	private Image rawImage;				// Animasjonsbilder uoppstykket
	private int picnr = 4;					// Det aktive animasjonsbildet som skal vises 
	private boolean swingUp = true;		// Om armsvingen skal være opp/ned i animasjon
	private int moveStatus = 0;				
	private boolean resetMoves = true;		// true hvis en forandrer retning uten å slippe opp taster
	private int move = 0;
	
	private final int leap = 4;			// Antall pixels pr. bevegelse i en vilkårlig retning       

	private Polygon moveLimit;				// Begrenser bevegelighet (x/y)
		
	private final int timeBetweenMoves = 50;		//	Tidsintervall mellom hver bevegelse i ms 
	private long timeSinceLastMove;							
	
	private boolean isBlinking = false;
	private int blinks = 0;
	private final int maxBlinks = 20;
	private boolean blinkSwitch = 	true;
	
	
	/***********************************************************************************************
		Metodenavn: hero (konstruktør)
		Beskrivelse: henter bilde og lyd, deler opp grafikken i 12 animasjonsbilder
	************************************************************************************************/
	public hero(Polygon p,MediaTracker mt,int mt_id, Graphics g, Applet applet){
		
		parentApplet = applet;
		offScrGC = g;		
		moveLimit = p;
		
		x_pos = 385;					// X-koordinatet til spriten  
		y_pos = 30;					// Y-koordinatet til spriten
		
		pics = new Image[totalPics];
		tracker = mt;
		
		collision = new Rectangle(6,17,19,13);	
								
		// Henter inn og deler opp bildet i animasjonsbilder:

		try {
		
			// Henter inn:
			rawImage = parentApplet.getImage(parentApplet.getCodeBase(), rawImageName);
		   	tracker.addImage(rawImage, mt_id);
		   		   	
			// Stykker opp:
			for (int i = 0; i < totalPics; i++){
				pics[i] = parentApplet.createImage(new FilteredImageSource(rawImage.getSource(),new CropImageFilter(i*picWidth,0,picWidth,picHeight)) );		 		
				tracker.addImage(pics[i], mt_id);		
			}
		
		} catch (Exception e) {e.printStackTrace();}
		
		timeSinceLastMove = System.currentTimeMillis();
	}
	
	/***********************************************************************************************
		Metodenavn: insideLimits
		Beskrivelse: sjekker om x og y er innenfor spritens kollisjons-polygon
	************************************************************************************************/
	private boolean insideLimits(int x,int y){
		if (moveLimit.inside(x+collision.x, y+collision.y) &&
			  moveLimit.inside(x+collision.x, y+collision.y+collision.height) &&
		    moveLimit.inside(x+collision.x+collision.width, y+collision.y) && 
		    moveLimit.inside(x+collision.x+collision.width, y+collision.y+collision.height)) 
			return true;
		else 	return false;
	}
	
	/***********************************************************************************************
		Metodenavn: checkMoves
		Beskrivelse: bestemmer Cliffs gange utfra keyboard-input
	************************************************************************************************/
	public void checkMoves(Event e){
	
		if (!insideLimits(x_pos,y_pos)){ // I de tilfeller der Cliff går over grensa..
			switch (move){
				case 1: do {x_pos++;} while (!insideLimits(x_pos,y_pos)); break;
				case 2: do {x_pos--;} while (!insideLimits(x_pos,y_pos)); break;
				case 3: do {y_pos++;} while (!insideLimits(x_pos,y_pos)); break;
				case 4: do {y_pos--;} while (!insideLimits(x_pos,y_pos)); break;
			}
		}
		
		move = 0;	// Står stille..
			
		switch (e.key){	// Sjekker om cliff kan gå i ønsket retning  
			case Event.LEFT:	if (insideLimits(x_pos-leap+2,y_pos)) move = 1; break;
			case Event.RIGHT:	if (insideLimits(x_pos+leap-2,y_pos)) move = 2; break;
			case Event.UP:		if (insideLimits(x_pos,y_pos+2-leap)) move = 3; break;
			case Event.DOWN:	if (insideLimits(x_pos,y_pos-2+leap)) move = 4; break;
		}

		if (moveStatus != move && resetMoves == false){
			resetMoves = true;
		}
		moveStatus = move;
	}
	
	/***********************************************************************************************
		Metodenavn: walk
		Beskrivelse: animerer Cliffs gange
	************************************************************************************************/
	public void walk(){
		
		// Returner hvis ingen bevegelse eller ventettid mellom bevegelse ikke er over:
		if (moveStatus == 0 || System.currentTimeMillis() - timeSinceLastMove < timeBetweenMoves) return;	
		
		timeSinceLastMove = System.currentTimeMillis();
		
		if (resetMoves){	// Sjekker om flere piltaster er inne samtidig
			switch (moveStatus){
				case 1:	picnr = 7; break;	// VENSTRE
				case 2:	picnr = 1; break;	// HØYRE
				case 3:	picnr = 10; break;	// OPP
				case 4:	picnr = 4; break;	// NED
			}
			resetMoves = false;
		}

 		if (swingUp == true) picnr++; // Animerer spritens gange
 		else picnr--;
		
		// Sjekker om armene skal svinge fram eller tilbake:
	
		if (picnr % 3 == 0) swingUp = true;
		else if ((picnr+1)% 3 == 0) swingUp = false;
	
		switch (moveStatus){ // Flytter spriten
			case 1:	x_pos -= leap; break;	// VENSTRE
			case 2:	x_pos += leap; break;	// HØYRE
			case 3:	y_pos -= leap; break;	// OPP
			case 4:	y_pos += leap; break;	// NED
		}
	}

	
	/***********************************************************************************************
		Metodenavn: stop
		Beskrivelse: stopper Cliff
	************************************************************************************************/
	public void stop(){
		moveStatus = 0;
		resetMoves = true;
	} 

	/***********************************************************************************************
		Metodenavn: startBlinking
		Beskrivelse: setter Cliff til å blinke 
	************************************************************************************************/
	public void startBlinking(){isBlinking = true;}
	

	/***********************************************************************************************
		Metodenavn: draw
		Beskrivelse: tegner Cliff til applet'ens offscreen-bilde
	************************************************************************************************/
	public void draw(){

		if (!isBlinking){
			offScrGC.drawImage(pics[picnr],x_pos,y_pos,parentApplet);
		} else {
			if (blinkSwitch ^= true) offScrGC.drawImage(pics[picnr],x_pos,y_pos,parentApplet);
			if (++blinks == maxBlinks){
				blinks = 0;
				isBlinking = false;
			}
		}
	}
	
	/***********************************************************************************************
		Metodenavn: resetPos
		Beskrivelse: flytter Cliff til start-posisjon
	************************************************************************************************/
	public void resetPos(){
		move(385,30);
		picnr = 4;		
	}
	

} // Class hero