/* 
	Game.java - documented version

	[ more java @ mlab - 10-17.1.2000 - juhuu@katastro.fi ]

*/

/*

 These first lines tell the names of all the classes
 that this class (Game) wants to use. The names of the
 classes in the same directory are automatically imported
 so those don't have to be listed here, but they can
 be for the sake of documentation (to make it easier to
 understand which class uses which).

 you can use * to import the names of all the classes
 in a chosen package.

*/

import java.applet.Applet;
import java.awt.*;
import java.net.*;
import java.util.*;

/*

 The class Game extends the class Applet, which means that
 is can use (override) all the methods that the class Applet
 has (and it's parent classes).

 The class Game implements the interface Runnable, which means
 that it has a method called 'run' that takes care of the scheduling
 of the thread of this class. Threads are a way to control multi-tasking
 with java, ie. if there are many java applications running at the
 same time then the processing power has to be shared among them.

*/

public class Game extends Applet implements Runnable
{
	/*

	here we define all the variables that need to
	be visible in more than one method, and all the
	variables that need to maintain their state all
	the time (contrary to the variables that are defined
	inside methods that maintain their state only during
	the execution of the method and that are initialized
	each time the method is called.
 	
	*/

	/*

	two variables for the double buffering; since we cannot draw
	things directly on the screen (we would have to clear the screen
	and draw things separately, and this would cause flickering since
	the screen might be shown before we are finished drawing all the
	objects) we have to use a hidden buffer. We clear the buffer and
 	draw all the objects there and draw it only when we are finished with
	all the objects.

	*/

	Image		imgDoubleBuffer;
	Graphics	gDoubleBuffer;

	// pointer to the thread of this applet

	Thread		engine = null;
  
	// two integer variables to store the mose coordinates
	int		nMousex, nMousey;

	// boolean variable to store the information of
	// whether or not the mouse if pressed or not
	boolean 	bMouse_down;
	
	// variables to store the pointers to images
	Image 		imgPic;
	Image 		imgBackground;

	// two integers for the screen size
	int		nScr_width;
	int		nScr_height;

	// two integers to store the location
	// of the other image
	int		nX, nY;

	/*

	after the variables, we define the methods. the order in which
	these methods are defined has no effect whatsoever, the names
 	of the methods define how and when they are called. you can
	find more information about these from the documentation of
	the Applet class.

	*/

	// init method. this method is always called once when the applet
	// is started before any other methods. this is a place where you
	// can give initial values for different variables, load images & sounds etc.
	public void init() {
		// create an image (same size as the applet) for double
		// buffering.
		imgDoubleBuffer = createImage(size().width, size().height);
		// create an instance of the Graphics class to access
		// the double buffer Image. we cannot draw directly to Images,
		// all the drawing has to be done trough Graphics class.
		gDoubleBuffer = imgDoubleBuffer.getGraphics();
		// set the background color to white and fill the double buffer with that color
		gDoubleBuffer.setColor(Color.white);
		gDoubleBuffer.fillRect(0, 0, size().width, size().height);
	
		// store the screen size to these two variables
		nScr_width		= size().width;
		nScr_height		= size().height;

		// init the mouse variables : location 0,0 - mouse not pressed
		// these are updated to right values as soon as the mouse event
		// functions are called for the first time (the last functions
		// at the bottom of this source)

		nMousex 		= 0;
		nMousey 		= 0;
		bMouse_down		= false;

		// the location of the image

		nX			= 0;
		nY			= 100;
		
		// the names of the images as strings

		String sBackground	= "background.jpg";
		String sPic		= "test.gif";

		// create an instance of the MediaTracker class.
		// this call is used to keep track of loading and other
		// time consuming operations done for different media types.
		MediaTracker med = new MediaTracker(this);

		// load Image with name stored in variable sPic from the
		// same directory (getDocumentBase() returns the url of current
		// directory). getImage can also be used by calling it with
		// the absolute address of the Image (getImage(URL));
		imgPic = getImage(getDocumentBase(), sPic);
		// add the Image to the MediaTracker. the second parameter
		// tells the index number of the Image, this should be unique
		// to each Image.
		med.addImage(imgPic, 0);

		imgBackground = getImage(getDocumentBase(), sBackground);
		med.addImage(imgBackground, 1);

		/*
		 wait for all the images to load.

		 if the loading if interrupted, an InterruptedException is generated
		 and the applet prints the text "error with loading images" to the
		 java console (or java message window).		
		*/

		try
		{
			med.waitForAll();
			}	catch (InterruptedException e) {
			System.out.println("error with loading images");
		}
  }

//----------------------------------------------------

	public void paint(Graphics g) {

	  // clear the screen

		// this would fill the screen with white color (clear the screen)
		// but it doesn't do it since it has been commented out of the source.
	//    	gDoubleBuffer.setColor(Color.white);
	//    	gDoubleBuffer.fillRect(0, 0, size().width, size().height);

		// make sure that we have the background image loaded before
		// we try to draw it.
		if (imgBackground != null)
		{
			// draw the background image
			gDoubleBuffer.drawImage(imgBackground, 0, 0, null);

			// make sure that the other image is loaded as well
			if (imgPic != null)
			{	
				// draw the other image at location nX, nY
				gDoubleBuffer.drawImage(imgPic, nX, nY, null);
			}
		}

	  // draw all the stuff from the double buffer to the screen
	  g.drawImage(imgDoubleBuffer, 0, 0, null);				
	}


//----------------------------------------------------


	// start the applet
	public void start() {
		if (engine == null)
		{
			engine = new Thread(this);
			engine.start();
		}
		showStatus(getAppletInfo());
	} 

	// stop the applet
	public void stop() {
		if (engine != null && engine.isAlive())
		{
			engine.stop();
		}

		engine = null; 
	}

	// the main loop of the thread
	public void run()
	{                  
		// loop forever (as long as this applet is active)
		while (true)
		{
			try
			{
				// send a request to paint the screen. after some
				// time, this function call results in a call to
				// the update() function, which in turn calls the
				// paint function.
				repaint();
				// sleep for 10 milliseconds and let the other threads run
				Thread.sleep(10);
			} catch (InterruptedException e) {
				stop();
			}
		}
	}

	// update() function, which in it's default implementation clears the
	// screen with default background color (usually gray or white). since
	// we don't want this to happen because we are using double buffering, we
	// override this function.
	public void update(Graphics g) {    
		paint(g);
	}

	// print the text to console & browserstatus
	private void print(String s) {
		System.out.println(s); 		// console
		showStatus(s);         		// browser status  
	}

//---

	// mouse down function, which gets information about the
	// event in an instance of the Event class and the coordinates
	// of the mouse. we ignore the event information and the coordinates
	// and store only the information that the mouse is now being pressed.
	public boolean mouseDown(Event e, int x, int y)
	{
		bMouse_down = true;
		return true;  
	}

	// same as mouseDown but for the mouse up event
	public boolean mouseUp(Event e, int x, int y)
	{
		bMouse_down = false;
		return true;  
	}

	// this method is called each time the mouse is moved.
	// we store the coordinates each time.
	public boolean mouseMove(Event e, int x, int y)
	{
		nMousex = x;
		nMousey = y;
		return true;  
	}

	// this method is called each time the mouse is dragged
	// (mouse button is held down and the mouse is moved).
	public boolean mouseDrag(Event e, int x, int y)
	{
		nMousex = x;
		nMousey = y;
		return true;  
	}
//---
}
