import java.awt.*;
import java.util.Random;

public class JumpBotv20 extends BufferedApplet
{
	final int APPLET_HEIGHT = 599;
	final int APPLET_WIDTH = 399;
	final int PANEL_BUFFER = 80;
	final int REFRESH = 1;
	
	final int STATE_STANDING = 0;
	final int STATE_PREJUMP = 1;
	final int STATE_JUMP= 2;
	final int STATE_FALL = 3;
	final int STATE_LAND = 4;
	final int STATE_MOVE_LEFT = 5;
	final int STATE_MOVE_RIGHT = 6;
		
	final int GRAVITY_MAX = -100;
	final int GRAVITY_MIN = -5;
	final int STRENGTH_MAX = 200;
	final int STRENGTH_MIN = 30;
	final int ENERGY_MAX = 10000;
	final int ENERGY_MIN = 0;
	
	final double LATERAL_MOVE = 12;
	final int OVAL_WIDTH = 14;
	final int PLATFORM_WIDTH = 120;
	final int PLATFORM_HEIGHT = 10;
	final int PLATFORM_HITSPACE_HEIGHT = 30;
	
	final int COLUMN_X = 0;
	final int COLUMN_Y = 1;
	final int DIR_LEFT = -1;
	final int DIR_RIGHT = 1;
	
	int iHeight, iWidth;
	int iBaseHeight = 0;
	int iBaseLateral = 0;
	int iTickCount = 0;
	int iCounter = 0;
	
	int iState = STATE_STANDING;
	int iGravity = -10;
	int iStrength = STRENGTH_MIN;
	int iEnergy = ENERGY_MAX;
	
	public int iVelocity = 0;
	public Matrix2D Matrix2D = new Matrix2D();
	static double MatrixTransform[][] = new double[3][3];
	static double MatrixTemp[][] = new double[3][3];

	boolean bIsInited = false;
	boolean bShouldJump = false;
	boolean bAlwaysJumping = false;
	boolean bShouldReplenish = false;
	
	//rectangles for buttons
	Rectangle RectPanel = new Rectangle();
	Rectangle RectJump = new Rectangle(160,605,80,30);
	Rectangle RectEnergy = new Rectangle(275, 610, 115, 30);
	Rectangle RectReplenish = new Rectangle(285, 645, 95, 20);
	Rectangle RectMode = new Rectangle(175, 640, 50, 20);
	
	Rectangle RectGravityUp = new Rectangle(100, 610, 15, 25);
	Rectangle RectGravityDown = new Rectangle(120, 610, 15, 25);
	Rectangle RectStrengthUp = new Rectangle(100, 640, 15, 25);
	Rectangle RectStrengthDown = new Rectangle(120, 640, 15, 25);
	
	//Colors
	Color clrPanel = new Color(200,200,200);
	Color clrButton = new Color(100,100,100);
	
	//these are coordinates for jumpbot, change them so he look much prettier		
	static double dPolyHorizBar[][] = { {2, 10, 1}, {73, 10, 1}, {73, 14, 1}, {2, 14, 1} };
	static double dPolyCockpit1[][] = { {28, 8, 1}, {32, 8, 1}, {32, 16, 1}, {28, 16, 1} };
	static double dPolyCockpit2[][] = { {43, 8, 1}, {47, 8, 1}, {47, 16, 1}, {43, 16, 1} };
	static double dPolyOvalCockpit[][] = { {30, 5, 1}, {45, 6, 1}, {45, 20, 1}, {31, 20, 1} };
	
	static double dRectLegTopLeft[][] = { {2, 5, 1}, {15, 0, 1}, {15, 34, 1}, {2, 34, 1} };
	static double dRectLegTopRight[][] = { {60, 0, 1}, {73, 5, 1}, {73, 34, 1}, {60, 34, 1} };
	static double dRectLegBotLeft[][] = { {0, 34, 1}, {17, 34, 1}, {17, 60, 1}, {-5, 60, 1} };
	static double dRectLegBotRight[][] = { {58, 34, 1}, {75, 34, 1}, {80, 60, 1}, {58, 60, 1} };
	
	static double dPlatform[][] = new double[4][3];
	static Rectangle PlatformHitSpace[] = new Rectangle[4];
	static boolean bIsOnPlatform[] = new boolean[4];
	static boolean bMouseOnPlatform[] = new boolean[4];
	static int iPlatformDir[] = new int[4];
	static Rectangle RectPlatform[] = new Rectangle[4];

	public void render(Graphics g)
	{
		if (bIsInited == false)
		{
			iHeight = bounds().height - PANEL_BUFFER;
			iWidth = bounds().width;
			RectPanel = new Rectangle(0,iHeight,iWidth, PANEL_BUFFER);
			
			//transform jumpbot to the right spot
			for (int i = 0; i < 4; i++)
			{
				Matrix2D.Translate(MatrixTransform, -38, -60);
				Matrix2D.Transform(MatrixTransform, dPolyHorizBar[i]);
				Matrix2D.Transform(MatrixTransform, dPolyCockpit1[i]);
				Matrix2D.Transform(MatrixTransform, dPolyCockpit2[i]);
				Matrix2D.Transform(MatrixTransform, dPolyOvalCockpit[i]);
				
				Matrix2D.Transform(MatrixTransform, dRectLegTopLeft[i]);
				Matrix2D.Transform(MatrixTransform, dRectLegTopRight[i]);
				Matrix2D.Transform(MatrixTransform, dRectLegBotLeft[i]);
				Matrix2D.Transform(MatrixTransform, dRectLegBotRight[i]);
				
				dPlatform[i][0] = 0;
				dPlatform[i][1] = (i+2)*-100;
				dPlatform[i][2] = 1;
				RectPlatform[i] = new Rectangle(0,(i+2)*-100, 
						PLATFORM_WIDTH, PLATFORM_HEIGHT);
				
				PlatformHitSpace[i] = new Rectangle((int)dPlatform[i][0], 
						(int)dPlatform[i][1] - PLATFORM_HITSPACE_HEIGHT / 2, 
						PLATFORM_WIDTH, PLATFORM_HITSPACE_HEIGHT);
				
				bIsOnPlatform[i] = false;
				bMouseOnPlatform[i] = false;
				iPlatformDir[i] = DIR_RIGHT;
			}			
			
			bIsInited = true;
		}
		// WHENEVER THERE IS "DAMAGE", WE NEED TO REDRAW
		if (iTickCount == REFRESH)
		{
			UpdatePos();
			Draw(g);
			iTickCount = 0;
		}
		iTickCount++;		
	}
	
	public void Draw(Graphics g)
	{
		// SET COLOR TO WHITE AND CLEAR THE APPLET WINDOW
		//gotta redo this whole thing, drawing something different
		g.setColor(Color.white);
		g.fillRect(0, 0, bounds().width, bounds().height);

		//draw everything in the JumpBot's worldspace first
		//draw the damned robot
		g.setColor(Color.black);
			//draw the horizontal bar
		g.fillPolygon(  ViewPort( Column(dPolyHorizBar, COLUMN_X, 4), COLUMN_X) ,
						ViewPort( Column(dPolyHorizBar, COLUMN_Y, 4), COLUMN_Y), 4);
			//draw the cockpit
		g.fillOval( Column(dPolyOvalCockpit, COLUMN_X, 4)[0] + iWidth/2, 
				Column(dPolyOvalCockpit, COLUMN_Y, 4)[0] + iHeight,
				OVAL_WIDTH, OVAL_WIDTH);
		
		g.setColor(Color.blue);
			//draw the sides of the cockpit
		g.fillPolygon(  ViewPort( Column(dPolyCockpit1, COLUMN_X, 4), COLUMN_X) ,
						ViewPort( Column(dPolyCockpit1, COLUMN_Y, 4), COLUMN_Y), 4);
		g.fillPolygon(  ViewPort( Column(dPolyCockpit2, COLUMN_X, 4), COLUMN_X) ,
						ViewPort( Column(dPolyCockpit2, COLUMN_Y, 4), COLUMN_Y), 4);
		
		g.setColor(Color.red);
			//draw top leg segments
		g.fillPolygon(  ViewPort( Column(dRectLegTopLeft, COLUMN_X, 4), COLUMN_X) ,
						ViewPort( Column(dRectLegTopLeft, COLUMN_Y, 4), COLUMN_Y), 4);
		g.fillPolygon(  ViewPort( Column(dRectLegTopRight, COLUMN_X, 4), COLUMN_X) ,
						ViewPort( Column(dRectLegTopRight, COLUMN_Y, 4), COLUMN_Y), 4);

		g.setColor(Color.blue);
		g.fillPolygon(  ViewPort( Column(dRectLegBotLeft, COLUMN_X, 4), COLUMN_X) ,
						ViewPort( Column(dRectLegBotLeft, COLUMN_Y, 4), COLUMN_Y), 4);
		g.fillPolygon(  ViewPort( Column(dRectLegBotRight, COLUMN_X, 4), COLUMN_X) ,
						ViewPort( Column(dRectLegBotRight, COLUMN_Y, 4), COLUMN_Y), 4);	

		//draw each platform
		g.setColor(Color.yellow);
		for (int i=0; i<4; i++)
		{
			if (bMouseOnPlatform[i] == true)
				g.setColor(Color.orange);
			else
				g.setColor(Color.yellow);
			g.fillRect( (int)dPlatform[i][0] + iWidth/2, (int)dPlatform[i][1] + iHeight,
					PLATFORM_WIDTH, PLATFORM_HEIGHT);
			
/*			g.setColor(Color.black);
			g.drawRect((int)PlatformHitSpace[i].getX() +iWidth/2, (int)PlatformHitSpace[i].getY() + iHeight, 
					PLATFORM_WIDTH, PLATFORM_HITSPACE_HEIGHT);
*/		}

		//then draw the control panel
		//fill in the panel
		g.setColor(clrPanel);
		g.fillRect((int)RectPanel.getX(), (int)RectPanel.getY(), 
				(int)RectPanel.getWidth(), (int)RectPanel.getHeight());

		//fill in the buttons)
		g.setColor(clrButton);
		g.fillRect((int)RectJump.getX(), (int)RectJump.getY(), 
				(int)RectJump.getWidth(), (int)RectJump.getHeight());
		g.fillRect((int)RectMode.getX(), (int)RectMode.getY(), 
				(int)RectMode.getWidth(), (int)RectMode.getHeight());
		g.fillRect((int)RectGravityUp.getX(), (int)RectGravityUp.getY(), 
				(int)RectGravityUp.getWidth(), (int)RectGravityUp.getHeight());
		g.fillRect((int)RectGravityDown.getX(), (int)RectGravityDown.getY(), 
				(int)RectGravityDown.getWidth(), (int)RectGravityDown.getHeight());
		g.fillRect((int)RectStrengthUp.getX(), (int)RectStrengthUp.getY(), 
				(int)RectStrengthUp.getWidth(), (int)RectStrengthUp.getHeight());
		g.fillRect((int)RectStrengthDown.getX(), (int)RectStrengthDown.getY(), 
				(int)RectStrengthDown.getWidth(), (int)RectStrengthDown.getHeight());
		g.fillRect((int)RectEnergy.getX(), (int)RectEnergy.getY(), 
				(int)RectEnergy.getWidth(), (int)RectEnergy.getHeight());
		if (bShouldReplenish == true)
			g.setColor(Color.red);
		g.fillRect((int)RectReplenish.getX(), (int)RectReplenish.getY(), 
				(int)RectReplenish.getWidth(), (int)RectReplenish.getHeight());
		
		g.setColor(Color.white);
		g.fillRect((int)RectGravityUp.getX() - 50, (int)RectGravityUp.getY(), 
				45, (int)RectGravityUp.getHeight());
		g.fillRect((int)RectStrengthUp.getX() - 40, (int)RectStrengthUp.getY(), 
				35, (int)RectGravityUp.getHeight());

		
		if (bShouldReplenish == true)
			g.setColor(Color.red);
		else
			g.setColor(Color.green);
			
		double dTemp = iEnergy;
		g.fillRect((int)RectEnergy.getX(), (int)RectEnergy.getY(), 
				(int)((dTemp/ENERGY_MAX)*RectEnergy.getWidth()), (int)RectEnergy.getHeight());

		//outline buttons
		g.setColor(Color.black);
		g.drawRect((int)RectJump.getX(), (int)RectJump.getY(), 
				(int)RectJump.getWidth(), (int)RectJump.getHeight());
		g.drawRect((int)RectMode.getX(), (int)RectMode.getY(), 
				(int)RectMode.getWidth(), (int)RectMode.getHeight());
				
		g.drawRect((int)RectGravityUp.getX(), (int)RectGravityUp.getY(), 
				(int)RectGravityUp.getWidth(), (int)RectGravityUp.getHeight());
		g.drawRect((int)RectGravityDown.getX(), (int)RectGravityDown.getY(), 
				(int)RectGravityDown.getWidth(), (int)RectGravityDown.getHeight());
				
		g.drawRect((int)RectStrengthUp.getX(), (int)RectStrengthUp.getY(), 
				(int)RectStrengthUp.getWidth(), (int)RectStrengthUp.getHeight());
		g.drawRect((int)RectStrengthDown.getX(), (int)RectStrengthDown.getY(), 
				(int)RectStrengthDown.getWidth(), (int)RectStrengthDown.getHeight());
				
		g.drawRect((int)RectReplenish.getX(), (int)RectReplenish.getY(), 
				(int)RectReplenish.getWidth(), (int)RectReplenish.getHeight());
		g.drawRect((int)RectGravityUp.getX() - 50, (int)RectGravityUp.getY(), 
				45, (int)RectGravityUp.getHeight());
		g.drawRect((int)RectStrengthUp.getX() - 40, (int)RectStrengthUp.getY(), 
				35, (int)RectGravityUp.getHeight());
		
		//draw the words, last
		g.drawString("JUMP!", (int)RectJump.getX()+20, (int)RectJump.getY()+20);
		
		g.drawString("Gravity:", 5, iHeight + 30);
		g.drawString("Strength:", 5, iHeight + 60);
		
		g.drawString("+", 105, iHeight + 30);
		g.drawString("-", 125, iHeight + 30);
		g.drawString("+", 105, iHeight + 60);
		g.drawString("-", 125, iHeight + 60);
		
		
		g.drawString("MODE:", (int)RectMode.getX()+5, (int)RectMode.getY()+14);
		if (bAlwaysJumping == true)
			g.drawString("Always Jumping", (int)RectMode.getX()-20, (int)RectMode.getY()+35);
		else
			g.drawString("Jump On Command", (int)RectMode.getX()-30, (int)RectMode.getY()+35);
			
		g.drawString("REPLENISH!", (int)RectReplenish.getX()+10, (int)RectMode.getY()+20);
		g.drawString("ENERGY", (int)RectEnergy.getX()+30, (int)RectEnergy.getY()+20);
		
		//draw the current gravity
		g.drawString(Double.toString(-(double)iGravity/10) + " G", (int)RectGravityUp.getX() - 42, (int)RectGravityUp.getY() + 18);
		
		//draw the current strength
		g.drawString(Integer.toString(iStrength), (int)RectStrengthUp.getX() - 30, (int)RectStrengthUp.getY() + 18);
	}
   
	public void UpdatePos()
		//Updates the position of JumpBot in the applet window
	{
		for (int i=0; i<4; i++)
		{
			if (bMouseOnPlatform[i] == false)
			{
				Matrix2D.Translate(MatrixTransform, (5+i*5)*(iPlatformDir[i]), 0);
				Matrix2D.Transform(MatrixTransform, dPlatform[i]);
				int iTemp = (int)Math.abs(dPlatform[i][0] - RectPlatform[i].getX());
				RectPlatform[i].translate(iPlatformDir[i]*iTemp, 0);
				PlatformHitSpace[i].translate(iPlatformDir[i]*iTemp, 0);
				
				if (dPlatform[i][0] > iWidth/2 - PLATFORM_WIDTH)
				{
					RectPlatform[i].translate((int)-(dPlatform[i][0] - (iWidth/2 - PLATFORM_WIDTH)), 0);
					PlatformHitSpace[i].translate((int)-(dPlatform[i][0] - (iWidth/2 - PLATFORM_WIDTH)), 0);
					dPlatform[i][0] = iWidth/2 - PLATFORM_WIDTH;
					iPlatformDir[i] = DIR_LEFT;
				}
				if (dPlatform[i][0] < -iWidth/2)
				{
					RectPlatform[i].translate((int)-(dPlatform[i][0] + iWidth/2),0);
					PlatformHitSpace[i].translate((int)-(dPlatform[i][0] + iWidth/2),0);
					dPlatform[i][0] = -iWidth/2;
					iPlatformDir[i] = DIR_RIGHT;
				}
			}
			
		}
		switch (iState)
		{
			case STATE_STANDING:
				iCounter = 0;
				if (bShouldJump == true)
				{
					iEnergy = iEnergy - (iStrength/2 * -iGravity);
					if (iEnergy <= 0) //no energy, do nothing
						iEnergy = 0;
					else if (iEnergy < 2500)
						bShouldReplenish = true;
					iVelocity = iStrength;
					ChangeState(STATE_PREJUMP);
				}
				break;
				
			case STATE_PREJUMP:
				ChangeState(STATE_JUMP);
				for (int i = 0; i < 4; i++)
					bIsOnPlatform[i] = false;				
				break;
				
			case STATE_JUMP:
			//JumpBot shoots into the air but is sucked
			//down by gravity, eventually falling		
				
				iBaseHeight = iBaseHeight + iVelocity;
				for (int i = 0; i < 4; i++)
				{
					Matrix2D.Translate(MatrixTransform, 0, -iVelocity);
					Matrix2D.Transform(MatrixTransform, dPolyHorizBar[i]);
					Matrix2D.Transform(MatrixTransform, dPolyCockpit1[i]);
					Matrix2D.Transform(MatrixTransform, dPolyCockpit2[i]);
					Matrix2D.Transform(MatrixTransform, dPolyOvalCockpit[i]);
					
					Matrix2D.Transform(MatrixTransform, dRectLegTopLeft[i]);
					Matrix2D.Transform(MatrixTransform, dRectLegTopRight[i]);
					Matrix2D.Transform(MatrixTransform, dRectLegBotLeft[i]);
					Matrix2D.Transform(MatrixTransform, dRectLegBotRight[i]);
				}
				iVelocity = iVelocity + iGravity;

				if (iVelocity < 0)
					ChangeState(STATE_FALL);
				break;
		
			case STATE_FALL:
				//first make jumpbot fall
				iBaseHeight = iBaseHeight + iVelocity;
				for (int i = 0; i < 4; i++)
				{
					Matrix2D.Translate(MatrixTransform, 0, -iVelocity);
					Matrix2D.Transform(MatrixTransform, dPolyHorizBar[i]);
					Matrix2D.Transform(MatrixTransform, dPolyCockpit1[i]);
					Matrix2D.Transform(MatrixTransform, dPolyCockpit2[i]);
					Matrix2D.Transform(MatrixTransform, dPolyOvalCockpit[i]);
					
					Matrix2D.Transform(MatrixTransform, dRectLegTopLeft[i]);
					Matrix2D.Transform(MatrixTransform, dRectLegTopRight[i]);
					Matrix2D.Transform(MatrixTransform, dRectLegBotLeft[i]);
					Matrix2D.Transform(MatrixTransform, dRectLegBotRight[i]);
				}
				iVelocity = iVelocity + iGravity;
				
/*				//check to see if he is standing on a platform now
				for (int i = 0; i < 4; i++)
				{
					if (PlatformHitSpace[i].contains(iBaseLateral, iBaseHeight-iHeight))
					{
						bIsOnPlatform[i] = true;
						iVelocity = 0;
						int iTemp = (int)dRectLegBotLeft[3][1];
						iTemp = iTemp - (int)dPlatform[0][1];
						System.err.println(iTemp);
						Matrix2D.Translate(MatrixTransform, 0, iTemp);					
						for (int j = 0; j < 4; j++)
						{
							Matrix2D.Transform(MatrixTransform, dPolyHorizBar[i]);
							Matrix2D.Transform(MatrixTransform, dPolyCockpit1[i]);
							Matrix2D.Transform(MatrixTransform, dPolyCockpit2[i]);
							Matrix2D.Transform(MatrixTransform, dPolyOvalCockpit[i]);
							
							Matrix2D.Transform(MatrixTransform, dRectLegTopLeft[i]);
							Matrix2D.Transform(MatrixTransform, dRectLegTopRight[i]);
							Matrix2D.Transform(MatrixTransform, dRectLegBotLeft[i]);
							Matrix2D.Transform(MatrixTransform, dRectLegBotRight[i]);
						}
						
						ChangeState(STATE_LAND);
					}
				}
*/				
				//check to see if he is on the ground
				if (iBaseHeight < 0)
				{
					//find the difference between teh bottom and the foot and
					//transform to it
					
					int iTemp = Column(dRectLegBotLeft, COLUMN_Y, 4)[3];
					
					if (iTemp == 0);
						//do nothing, youre good
					else
					{
						for (int i = 0; i < 4; i++)
						{
							Matrix2D.Translate(MatrixTransform, 0, -iTemp);
							Matrix2D.Transform(MatrixTransform, dPolyHorizBar[i]);
							Matrix2D.Transform(MatrixTransform, dPolyCockpit1[i]);
							Matrix2D.Transform(MatrixTransform, dPolyCockpit2[i]);
							Matrix2D.Transform(MatrixTransform, dPolyOvalCockpit[i]);
							
							Matrix2D.Transform(MatrixTransform, dRectLegTopLeft[i]);
							Matrix2D.Transform(MatrixTransform, dRectLegTopRight[i]);
							Matrix2D.Transform(MatrixTransform, dRectLegBotLeft[i]);
							Matrix2D.Transform(MatrixTransform, dRectLegBotRight[i]);
						}
					}
					ChangeState(STATE_LAND);
				}
				break;
				
			case STATE_LAND:
				ChangeState(STATE_STANDING);
				if (bAlwaysJumping == false)
					bShouldJump = false;
				else
					bShouldJump = true;
				break;
				
			case STATE_MOVE_LEFT:
				//transform the left leg and horizontal bar
				//transform the rest, should be pretty easy
				//decrement counter
				Matrix2D.Translate(MatrixTransform, -LATERAL_MOVE, 0);
				if (iCounter == 3)
				{
					for (int i = 0; i < 4; i++)
					{
						Matrix2D.Transform(MatrixTransform, dPolyHorizBar[i]);
						Matrix2D.Transform(MatrixTransform, dPolyCockpit1[i]);
						Matrix2D.Transform(MatrixTransform, dPolyCockpit2[i]);
						Matrix2D.Transform(MatrixTransform, dPolyOvalCockpit[i]);
						
						Matrix2D.Transform(MatrixTransform, dRectLegTopLeft[i]);
						Matrix2D.Transform(MatrixTransform, dRectLegBotLeft[i]);
					}
				}
				else if (iCounter == 1)
				{
					for (int i = 0; i < 4; i++)
					{
						Matrix2D.Transform(MatrixTransform, dRectLegTopRight[i]);
						Matrix2D.Transform(MatrixTransform, dRectLegBotRight[i]);
					}
				}
				else if (iCounter == 0)
				{
					ChangeState(STATE_STANDING);
					iBaseLateral -= LATERAL_MOVE;
				}
				iCounter--;			
				break;
				
			case STATE_MOVE_RIGHT:
				Matrix2D.Translate(MatrixTransform, LATERAL_MOVE, 0);
				if (iCounter == 3)
					for (int i = 0; i < 4; i++)
					{
						Matrix2D.Transform(MatrixTransform, dPolyHorizBar[i]);
						Matrix2D.Transform(MatrixTransform, dPolyCockpit1[i]);
						Matrix2D.Transform(MatrixTransform, dPolyCockpit2[i]);
						Matrix2D.Transform(MatrixTransform, dPolyOvalCockpit[i]);
						
						Matrix2D.Transform(MatrixTransform, dRectLegTopRight[i]);
						Matrix2D.Transform(MatrixTransform, dRectLegBotRight[i]);
					}
				else if (iCounter == 1)
					for (int i = 0; i < 4; i++)
					{
						Matrix2D.Transform(MatrixTransform, dRectLegTopLeft[i]);
						Matrix2D.Transform(MatrixTransform, dRectLegBotLeft[i]);
					}
				else if (iCounter == 0)
				{	
					iBaseLateral += LATERAL_MOVE;
					ChangeState(STATE_STANDING);
				}
				iCounter--;			
				break;
			
		}
	}
   
	public void ChangeState(int iNewState)
	//after Jumpbot's upgrade, he has super strong piston legs that do all the
	//jump work so all that changes in his different states is the amount the
	//pistons compress.  This is shown by a translation of all but the bottom
	//leg segments
	{
		iState = iNewState;
		int iTemp = 0;
		switch (iNewState)
			//each different state makes a different transformation matrix
		{
			case STATE_STANDING:
				iTemp = Column(dRectLegTopLeft, COLUMN_Y, 4)[3] - 
					Column(dRectLegBotLeft, COLUMN_Y, 4)[0];
				Matrix2D.Translate(MatrixTransform, 0, -iTemp);
				break;
				
			case STATE_PREJUMP:
				iTemp = Math.abs(iVelocity/10);
				Matrix2D.Translate(MatrixTransform, 0, iTemp);
				break;
				
			case STATE_JUMP:
				iTemp = Column(dRectLegTopLeft, COLUMN_Y, 4)[3] - 
					Column(dRectLegBotLeft, COLUMN_Y, 4)[0];
				Matrix2D.Translate(MatrixTransform, 0, -iTemp);
				break;
				
			case STATE_FALL:
				iTemp = Column(dRectLegTopLeft, COLUMN_Y, 4)[3] - 
					Column(dRectLegBotLeft, COLUMN_Y, 4)[0];
				Matrix2D.Translate(MatrixTransform, 0, -iTemp);
				break;
				
			case STATE_LAND:
				iTemp = Math.abs(iVelocity/10);
				Matrix2D.Translate(MatrixTransform, 0, iTemp);
				break;
				
			case STATE_MOVE_LEFT:
				Matrix2D.IdentityMatrix(MatrixTransform);
				iCounter = 3;
				break;

			case STATE_MOVE_RIGHT:
				Matrix2D.IdentityMatrix(MatrixTransform);
				iCounter = 3;
				break;
		
		}
		
		for (int i = 0; i < 4; i++)
			//the transformation matrix is then applied
			//to each of the parts
		{
			Matrix2D.Transform(MatrixTransform, dPolyHorizBar[i]);
			Matrix2D.Transform(MatrixTransform, dPolyCockpit1[i]);
			Matrix2D.Transform(MatrixTransform, dPolyCockpit2[i]);
			Matrix2D.Transform(MatrixTransform, dPolyOvalCockpit[i]);
			
			Matrix2D.Transform(MatrixTransform, dRectLegTopLeft[i]);
			Matrix2D.Transform(MatrixTransform, dRectLegTopRight[i]);
		}
	}
	
	public boolean mouseMove(Event e, int x, int y)
	//checks to see if the mouse is moved over one of the platforms
	{
		for(int i=0; i<4; i++)
		{
			if (RectPlatform[i].contains(x-iWidth/2,y-iHeight))
			{
				bMouseOnPlatform[i] = true;
			}
			else
				bMouseOnPlatform[i] = false;
		}
		return true;
	}
	
	public boolean mouseDrag(Event e, int x, int y)
	//checks to see if the mouse is dragging one of the platforms
	{
		for(int i=0; i<4; i++)
		{
			if (bMouseOnPlatform[i] == true)
			{
				if (x < 0)
					dPlatform[i][0] = -iWidth/2;
				else if (x > iWidth - PLATFORM_WIDTH)
					dPlatform[i][0] = iWidth/2 - PLATFORM_WIDTH;
				else		
					dPlatform[i][0] = x-iWidth/2;
				int iTemp = (int)(dPlatform[i][0] - RectPlatform[i].getX());
				RectPlatform[i].translate(iTemp,0);
				PlatformHitSpace[i].translate(iTemp,0);
			}
		}
		
		return true;
	}
	
	public boolean mouseUp(Event e, int x, int y)
	{
		if (RectJump.contains(x,y))
			bShouldJump = true;
			
		if (RectMode.contains(x,y))
		{
			if (bAlwaysJumping == true)
				bAlwaysJumping = false;
			else
				bAlwaysJumping = true;
		}
		
		if (RectReplenish.contains(x,y))
		{
			iEnergy = ENERGY_MAX;
			bShouldReplenish = false;
		}
		
		if (RectGravityUp.contains(x,y))
			//since gravity is inherently negative, this method is
			//a little deceptive.
			//subtracting from gravity makes it stronger
		{
			iGravity -= 5;
			if (iGravity < GRAVITY_MAX)
				iGravity = GRAVITY_MAX;
		}
		
		if (RectGravityDown.contains(x,y))
		{
			iGravity += 5;
			if (iGravity > GRAVITY_MIN)
				iGravity = GRAVITY_MIN;
		}

		if (RectStrengthUp.contains(x,y))
		{
			iStrength += 10;
			if (iStrength > STRENGTH_MAX)
				iStrength = STRENGTH_MAX;
		}

		if (RectStrengthDown.contains(x,y))
		{
			iStrength -= 10;
			if (iStrength < STRENGTH_MIN)
				iStrength = STRENGTH_MIN;
		}
				
		return true;
	} 

	public boolean keyUp(Event e, int key)
	{
		if (iState == STATE_STANDING)
		{
			switch (key)
			{
				case Event.LEFT:	ChangeState(STATE_MOVE_LEFT); break;
				case Event.RIGHT:   ChangeState(STATE_MOVE_RIGHT); break;
			}
		}
		return true;
	}
	
	public int[] Column(double Matrix[][], int col, int len)
	//returns a column from a 2D array, in this case, an array of X or Y
	//coordinates. Used to draw polygons
	{
		int ColumnArray[] = new int[len];
		for(int i=0; i<len; i++)
			ColumnArray[i] = (int)Matrix[i][col];
		return ColumnArray;
	}
	
	public int[] ViewPort(int Array[], int col)
	//converts the X and Y coordinates so that the origin will appear in the
	//center of the applet
	{
		int len = Array.length;
		if (col == COLUMN_X)
			for (int i=0; i<len; i++)
				Array[i] = Array[i] + iWidth / 2;
		else if (col == COLUMN_Y)
			for (int i=0; i<len; i++)
				Array[i] = Array[i] + iHeight;
		return Array;
	}

}

class BufferedApplet extends java.applet.Applet implements Runnable
{
/*
	THIS CLASS HANDLES DOUBLE BUFFERING FOR YOU, SO THAT THE IMAGE
	DOESN'T FLICKER WHILE YOU'RE RENDERING IT.  YOU DON'T REALLY
	NEED TO WORRY ABOUT THIS TOO MUCH, AND YOU'LL PROBABLY NEVER NEED
	TO CHANGE IT.  IT'S REALLY JUST USEFUL LOW LEVEL PLUMBING.
*/

	public void render(Graphics g) { }   // *you* define how to render
	public boolean damage = true;        // you can force a render
	
	private Image image = null;
	private Graphics buffer = null;
	private Thread t;
	private Rectangle r = new Rectangle(0, 0, 0, 0);
	
	// A BACKGROUND THREAD CHECKS FOR CHANGES ABOUT 30 TIMES PER SECOND
	
	public void start() { if (t == null) { t = new Thread(this); t.start(); } }
	public void stop()  { if (t != null) { t.stop(); t = null; } }
	public void run()   { try { while (true) { repaint(); t.sleep(30); } }
	                         catch(InterruptedException e){}; }
/*
	UPDATE GETS CALLED BY THE SYSTEM.
	IT CALLS YOUR RENDER METHOD, WHICH DRAWS INTO AN OFF-SCREEN IMAGE.
	THEN UPDATE COPIES THE IMAGE YOU'VE RENDERED ONTO THE APPLET WINDOW.
*/

	public void update(Graphics g) {
	  if (r.width != bounds().width || r.height != bounds().height) {
	     image = createImage(bounds().width, bounds().height);
	     buffer = image.getGraphics();
	     r = bounds();
	     damage = true;
	  }
	  damage = true;
	  render(buffer);
	  
	  if (image != null)
	     g.drawImage(image,0,0,this);
	}
}
