import java.applet.*;
import java.awt.*;
import java.awt.event.*;

/**
 *  Description of the Class
 *
 *@author     Robert Horowitz
 *@created    March 16, 2008
 */
public class space13 extends Applet implements Runnable, KeyListener, MouseListener {

	//Thread
	
	public Thread spaceThread = null;

	//Images
	
	public Image bufferImage;
	public Image flamingStar;
	public Image venus;
	public Image enemy;
	public Image player1;
	public Image player2;
	public Image player3;
	public Image player4;

	//Sounds

	AudioClip click;
	AudioClip crunch;
	AudioClip laser;
	AudioClip siren;
	AudioClip levelUp;

	//Font
	Font f = new Font("Helvetica", Font.PLAIN, 12);

	//Variables
	public long tm = System.currentTimeMillis();
	public int playerPosition = 1, newPlayerPosition = 1, enemyPosition = 1, newEnemyPosition = 1;
	public int elapsedTime = 0, enemyTimer = 100, MAXTIMER = 100, lives = 3, score = 0;
	public boolean startGame = true, resetEnemy = true, fireWeapon = false, death = false, endGame = false;
	public final int HEIGHT = 400, WIDTH = 400, EHEIGHT = 30, EWIDTH = 30, PWIDTH = 60, PHEIGHT = 60, RADIUS = 20, BUFFERSPACE = 10, RADIUSPLUS = RADIUS + BUFFERSPACE;

	//MediaTracker
	MediaTracker tracker;

	public void init() {
		//Sounds
		click = getAudioClip(getCodeBase(), "click.au");
		crunch = getAudioClip(getCodeBase(), "crunch.au");
		laser = getAudioClip(getCodeBase(), "laser.au");
		siren = getAudioClip(getCodeBase(), "siren.au");
		levelUp = getAudioClip(getCodeBase(), "levelup.au");

		//Images
		tracker = new MediaTracker(this);

		player1 = getImage(getDocumentBase(), "player1.png");
		tracker.addImage(player1, 0);
		player2 = getImage(getDocumentBase(), "player2.png");
		tracker.addImage(player2, 1);
		player3 = getImage(getDocumentBase(), "player3.png");
		tracker.addImage(player3, 2);
		player4 = getImage(getDocumentBase(), "player4.png");
		tracker.addImage(player4, 3);
		enemy = getImage(getDocumentBase(), "enemy2.png");
		tracker.addImage(enemy, 4);
		flamingStar = getImage(getDocumentBase(), "flaming_star_thumb.jpg");
		tracker.addImage(flamingStar, 5);
		venus = getImage(getDocumentBase(), "venus2.gif");
		tracker.addImage(venus, 6);

		try {
			tracker.waitForAll();
		} catch (InterruptedException e) {}

		//Buffer
		bufferImage = createImage(HEIGHT, WIDTH);

		//Keyboard and Mouse
		addKeyListener(this);
		addMouseListener(this);
	}

	public void paint(Graphics g) {
		g.drawImage(bufferImage, 0, 0, this);
		return;
	}

	public void update(Graphics g) {
		paint(g);
	}

	public void start() {
		if (spaceThread == null) {
			spaceThread = new Thread(this, "spaceThread");
			spaceThread.setPriority(5);
			spaceThread.start();
		}
	}

	public void stop() {
		spaceThread = null;
		destroy();
	}

	public void destroy() {
	}

	public void run() {
		while (Thread.currentThread() == spaceThread) {
			tm = System.currentTimeMillis()+50;
			prepareBuffer();
			repaint();
			try {
				Thread.sleep(Math.max(0, tm - System.currentTimeMillis()));
			} catch (InterruptedException e) {}
		elapsedTime++;
		}
	}

	public void prepareBuffer() {
		Graphics g = bufferImage.getGraphics();
		//Check that all pictures loaded then give instructions screen
		if ((!tracker.checkAll()) || (startGame)) {
			pregame(g);
		}
		//Play game
		else {
			g.drawImage(flamingStar, 0, 0, this);
			g.drawImage(venus, WIDTH / 2 - RADIUS, HEIGHT / 2 - RADIUS, RADIUS * 2, RADIUS * 2, this);
			drawEnemy(g);
			drawPlayer(g);
			if (fireWeapon) {
				fire(g);
			}
			if (elapsedTime > enemyTimer) {
				playerDeath(g);
			}
		}
		return;
	}

	public void playerDeath(Graphics g) {
		death = true;
		siren.play();
		g.setColor(Color.yellow);
		switch (enemyPosition) {
		case 1:
			g.drawLine(EWIDTH, HEIGHT / 2, WIDTH / 2, HEIGHT / 2);
			break;
		case 2:
			g.drawLine(WIDTH / 2, EHEIGHT, WIDTH / 2, HEIGHT / 2);
			break;
		case 3:
			g.drawLine(WIDTH - EWIDTH, HEIGHT / 2, WIDTH / 2, HEIGHT / 2);
			break;
		case 4:
			g.drawLine(WIDTH / 2, HEIGHT - EHEIGHT, WIDTH / 2, HEIGHT / 2);
			break;
		}
		crunch.play();
		g.setColor(Color.white);
		while (death) {
			g.drawString("Click to continue", WIDTH / 2 - 50, 60);
		}
		lives--;
		//If lives 0, give Score and End the Game
		if (lives < 1) {
			endGame = true;
			g.setColor(Color.black);
			g.fillRect(0, 0, 400, 400);
			g.setColor(Color.white);
			g.drawString("Game Over", WIDTH / 2 - 50, 40);
			g.drawString("Your score is " + score, WIDTH / 2 - 50, 60);
			while (endGame) {
				g.drawString("Refresh browser to restart", WIDTH / 2 - 50, 80);
			}
		}
		//else reset enemy
		enemyTimer = MAXTIMER;
		resetEnemy = true;
		elapsedTime=0;
	}

	public void fire(Graphics g) {
		fireWeapon = false;
		g.setColor(Color.white);
		switch (playerPosition) {
		case 1:
			g.drawLine(WIDTH / 2 - PHEIGHT - RADIUSPLUS, HEIGHT / 2, EWIDTH, HEIGHT / 2);
			break;
		case 2:
			g.drawLine(WIDTH / 2, HEIGHT / 2 - PHEIGHT - RADIUSPLUS, WIDTH / 2, EHEIGHT);
			break;
		case 3:
			g.drawLine(WIDTH / 2 + RADIUSPLUS + PHEIGHT, HEIGHT / 2, WIDTH - EWIDTH, HEIGHT / 2);
			break;
		case 4:
			g.drawLine(WIDTH / 2, HEIGHT / 2 + RADIUSPLUS + PHEIGHT, WIDTH / 2, HEIGHT - EHEIGHT);
			break;
		}
		laser.play();
		if (playerPosition == enemyPosition) {
			score = score + MAXTIMER - elapsedTime;
			elapsedTime = 0;
			resetEnemy = true;
			enemyTimer = enemyTimer - 5;
			if (enemyTimer < 5) {
				enemyTimer = 5;
			}
		} else {
			score = score - 50;
		}
	}

	public void pregame(Graphics g) {
		g.setColor(Color.black);
		g.fillRect(0, 0, 400, 400);
		g.setColor(Color.white);
		g.setFont(f);
		if (!tracker.checkAll()) {
			g.drawString("Loading Images...", 0, 80);
			return;
		} else {
			g.drawString("Use left/right arrows to move and space bar to fire weapon", 0, 40);
			g.drawString("Doubleclick anywhere on the applet to start", 0, 80);
			return;
		}
	}

	public void drawEnemy(Graphics g) {
		if (resetEnemy) {
			resetEnemy = false;
			do {
				newEnemyPosition = 1 + (int) (Math.random() * 4);
			} while (newEnemyPosition == enemyPosition);
			enemyPosition = newEnemyPosition;
		}
		switch (enemyPosition) {
		case 1:
			g.drawImage(enemy, 0, HEIGHT / 2 - EWIDTH / 2, EWIDTH, EHEIGHT, this);
			break;
		case 2:
			g.drawImage(enemy, WIDTH / 2 - EHEIGHT / 2, 0, EHEIGHT, EWIDTH, this);
			break;
		case 3:
			g.drawImage(enemy, WIDTH - EWIDTH, HEIGHT / 2 - EHEIGHT / 2, EWIDTH, EHEIGHT, this);
			break;
		case 4:
			g.drawImage(enemy, WIDTH / 2 - EHEIGHT / 2, HEIGHT - EWIDTH, EHEIGHT, EWIDTH, this);
			break;
		}
		return;
	}

	public void drawPlayer(Graphics g) {
		if (playerPosition != newPlayerPosition) {
			playerPosition = newPlayerPosition;
			click.play();
		}
		g.setColor(Color.white);
		switch (playerPosition) {
		case 1:
			g.drawImage(player1, WIDTH / 2 - PHEIGHT - RADIUSPLUS, HEIGHT / 2 - PWIDTH / 2, PHEIGHT, PWIDTH, this);
			break;
		case 2:
			g.drawImage(player2, WIDTH / 2 - PWIDTH / 2, HEIGHT / 2 - PHEIGHT - RADIUSPLUS, PWIDTH, PHEIGHT, this);
			break;
		case 3:
			g.drawImage(player3, WIDTH / 2 + RADIUSPLUS, HEIGHT / 2 - PWIDTH / 2, PHEIGHT, PWIDTH, this);
			break;
		case 4:
			g.drawImage(player4, WIDTH / 2 - PWIDTH / 2, HEIGHT / 2 + RADIUSPLUS, PWIDTH, PHEIGHT, this);
			break;
		}
		return;
	}


	//Mouse Methods

	public void mouseClicked(MouseEvent e) {
		//End Instructions, start game

		if (startGame) {
			startGame = false;
			e.consume();
			return;
		}
		if (death) {
			death = false;
			e.consume();
			return;
		}
		if (endGame) {
			stop();
		}
		return;
	}

	public void mouseReleased(MouseEvent e) { }
	public void mouseEntered(MouseEvent e) { }
	public void mouseExited(MouseEvent e) { }
	public void mousePressed(MouseEvent e) { }

	//Keyboard Methods

	public void keyPressed(KeyEvent e) {

		int keyCode = e.getKeyCode();
		//Left arrow pressed, move player counterclockwise
		if (keyCode == 37) {
			newPlayerPosition--;
			if (newPlayerPosition < 1) {
				newPlayerPosition = 4;
			}
		}
		//RIGHT arrow pressed, move player clockwise
		else if (keyCode == 39) {
			newPlayerPosition++;
			if (newPlayerPosition > 4) {
				newPlayerPosition = 1;
			}
		}
		//Fire Weapon
		else if (keyCode == 32) {
			fireWeapon = true;
		}
		e.consume();
		return;
	}

	public void keyReleased(KeyEvent e) { }
	public void keyTyped(KeyEvent e) { }

}

