/**
@file World.java

World definition where the card are going to battle
*/
import javax.swing.*;
import javax.swing.event.*; 
import java.awt.*;
import java.util.*;
import java.io.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;


// ****************************************************
// ****************************************************
/**
 @brief World that contains the levels

 World contains all the members and functions for
 the logic and render asociated to the level

 @author Esteban Gallardo
*/
class World extends JPanel
{
	static int m_totalWitdhScrollWorld=-1;
	static int m_totalHeightScrollWorld=-1;
	
	static int m_seeAllLayers=0;						/**< @brief Will enable to see or not to see all the layers */
		
	byte[][] cMatrix;									/**< @brief Matrix that contains the collisions */
	String fileTileImages="";							/**< @brief The file with the names of the images */
	Image[] tileImages;								/**< @brief The images of tile map */

	int iState;										/**< @brief World state */
	int[] stackState;									/**< @brief Stack of state saved */
	int iPositionStack;				                                /**< @brief The position of the stack */

	int iMatrixWidth;									/**< @brief Number of cells of with of the matrix */
	int iMatrixHeight;									/**< @brief Number of cells of heigth of the matrix */	
	int iBlockLength_X;									/**< @brief Width of the length of the cell */
	int iBlockLength_Y;									/**< @brief Width of the length of the cell */
	
	// ++ Colision components ++
	int colTypeSelected=-1;							/**< @brief Colision cell to put */
	
	// ++ Render components ++
	int renTypeSelected=-1;							/**< @brief Render cell to put */
	
	// ++ Matrix components ++
	int matrix[][];
	Vector waypoints=new Vector();						/**< @brief List of waypoints */
	Vector conexions=new Vector();						/**< @brief List of conexions */
	int typeOperationMatrix=-1;							/**< @brief Type of operation to (ADD_WAYPOINT,EDIT_WAYPOINT,DELETE_WAYPOINT, NEXION, EDIT_CONEXION, DELETE_CONEXION) */

	boolean enableGrid=false;						/**< @brief Will enable or disable the grid in render mode */
	boolean enableGridColisions=false;						/**< @brief Will enable or disable the grid in render mode */
	
	// ++++ Render Components ++++
	Graphics _g = null;          						/**< @brief Static reference to graphics */
	Image buffer;                						/**< @brief Buffer for double buffering */
    
	int _iScreenWidth=-1; 		 						/**< @brief Screen width */
	int _iScreenHeight=-1; 		 						/**< @brief Screen heigth */
	Point2D _Camera;				 					/**< @brief Number of cells of heigth of the matrix */
	
	// Constants for selection
	public static final int COLLISION_MATRIX            = 0;   /**< @brief Constant to select render matrix */
	public static final int RENDER_MATRIX               = 1;   /**< @brief Constant to select render matrix */
	
	// World Type Constants	
	public static final int NORMAL               = 0;   /**< @brief Normal State/ follow the waypoint */
	public static final int UPDATE_WAYPOINT      = 1;   /**< @brief Update the current waypoint */
	public static final int TOTAL_PUSHED_STATES  = 10;  /**< @brief Number of states that can be pushed */
	
	// Cell Type Constants for Colision
	public static final int COLISION_TYPE_EMPTY  = 0;   /**< @brief Empty colision */
	public static final int COLISION_TYPE_STONE	= 1;   /**< @brief colision cell */	
	
	public static final int COLISION_TYPE_FRUIT_1 = 2;   /**< @brief Fruit */
	public static final int COLISION_TYPE_FRUIT_2 = 3;   /**< @brief Fruit */
	public static final int COLISION_TYPE_FRUIT_3 = 4;   /**< @brief Fruit */
	public static final int COLISION_TYPE_FRUIT_4 = 5;   /**< @brief Fruit */
	public static final int COLISION_TYPE_FRUIT_5 = 6;   /**< @brief Fruit */
	public static final int COLISION_TYPE_FRUIT_6 = 7;   /**< @brief Fruit */
	public static final int COLISION_TYPE_FRUIT_7 = 8;   /**< @brief Fruit */
	public static final int COLISION_TYPE_FRUIT_8 = 9;   /**< @brief Fruit */
	
	// ---------------------------------------------------
	/**
	 @brief Constructor of World
	 */
	World()
	{
	    _Camera=new Point2D(0,0);	    
	}

	// ---------------------------------------------------
	/**
	 @brief World initilization

	 @param pMatrixWidth width of matrix
	 @param pMatrixHeight height of matrix
	 @param pBlockLength Length of the block	 
	 */
	public void init( int pMatrixWidth, int pMatrixHeight, int pBlockLengthX, int pBlockLengthY ) throws IOException
	{
	 iState=NORMAL;
	 iPositionStack=-1;
	 stackState=new int[TOTAL_PUSHED_STATES];
	 for (int k=0;k<TOTAL_PUSHED_STATES;k++) stackState[k]=-1;

	 iMatrixWidth=pMatrixWidth;
	 iMatrixHeight=pMatrixHeight;
	 iBlockLength_X=TileMapEditor.gBlockSize_X;
	 iBlockLength_Y=TileMapEditor.gBlockSize_Y;

	 cMatrix=new byte[iMatrixWidth][iMatrixHeight];
	 	 
 	 for (int i=0;i<iMatrixWidth;i++)
	 {
		for (int j=0;j<iMatrixHeight;j++)
		{
			cMatrix[i][j]=COLISION_TYPE_EMPTY;
		}
	 }

 	  // m_totalWitdhScrollWorld=((iMatrixWidth*iBlockLength_X)/2)+((iMatrixHeight*iBlockLength_X)/2)-((iMatrixWidth-iMatrixHeight)*(iBlockLength_X/2));
 	  m_totalWitdhScrollWorld=((iMatrixWidth*iBlockLength_X)/TileMapEditor.gZoomApplied);
 	  m_totalHeightScrollWorld=((iMatrixHeight*iBlockLength_Y)/TileMapEditor.gZoomApplied);
 	  Dimension newArea=new Dimension(m_totalWitdhScrollWorld,m_totalHeightScrollWorld);
	  setPreferredSize(newArea);
	  revalidate();
	  repaint();
	}

	// ---------------------------------------------------
	/**
	 @brief World initilization

	 @param pMatrixWidth width of matrix
	 @param pMatrixHeight height of matrix
	 @param pBlockLength Length of the block	 
	 */
	public void setZoom( int pMatrixWidth, int pMatrixHeight, int pBlockLength_X, int pBlockLength_Y, int pZoom ) throws IOException
	{
	 iMatrixWidth=pMatrixWidth;
	 iMatrixHeight=pMatrixHeight;
	 iBlockLength_X=TileMapEditor.gBlockSize_X;
	 iBlockLength_Y=TileMapEditor.gBlockSize_Y;
		
 	  m_totalWitdhScrollWorld=((iMatrixWidth*iBlockLength_X)/pZoom);
 	  m_totalHeightScrollWorld=((iMatrixHeight*iBlockLength_Y)/pZoom);
		
 	  Dimension newArea=new Dimension(m_totalWitdhScrollWorld,m_totalHeightScrollWorld);
	  setPreferredSize(newArea);
	  revalidate();
	  repaint();
	}
	
	// ---------------------------------------------------
	/**
	 @brief World initilization

	 @param file where to find the world initialization
	 */
	public void init( String file ) throws IOException
	{
		iState=NORMAL;
		iPositionStack=-1;
		stackState=new int[TOTAL_PUSHED_STATES];
		for (int k=0;k<TOTAL_PUSHED_STATES;k++) stackState[k]=-1;

		FileInputStream is = new FileInputStream( file );
		
		readWorld(is,true);
		is.close();

		// Set dimension
	 	// m_totalWitdhScrollWorld=((iMatrixWidth*iBlockLength_X)/2)+((iMatrixHeight*iBlockLength_X)/2)-((iMatrixWidth-iMatrixHeight)*(iBlockLength_X/2));
		m_totalWitdhScrollWorld=((iMatrixWidth*iBlockLength_X)/TileMapEditor.gZoomApplied);
		m_totalHeightScrollWorld=((iMatrixHeight*iBlockLength_Y)/TileMapEditor.gZoomApplied);
	 	Dimension newArea=new Dimension(m_totalWitdhScrollWorld,m_totalHeightScrollWorld);
		setPreferredSize(newArea);
		revalidate();
		repaint();
		
	} // End init
	
	// ---------------------------------------------------
	/**
	 @brief Read the current world

	 @param file where to find the world initialization
	 
	 @return the number of blocks of this world
	 */
	int readWorld(FileInputStream is, boolean isBlock) throws IOException
	{
	
		// Read size
		iMatrixWidth=readShort(is);
		iMatrixHeight=readShort(is);
		iBlockLength_X=readShort(is);
		iBlockLength_Y=readShort(is);
		iBlockLength_X=TileMapEditor.gBlockSize_X;
		iBlockLength_Y=TileMapEditor.gBlockSize_Y;		
		TileMapEditor._NumberLayersCreated=(byte)(is.read() & 0xFF);
	    
		System.out.println("PASO 1:iMatrixWidth="+iMatrixWidth+";iMatrixHeight="+iMatrixHeight);
		
		cMatrix=new byte[iMatrixWidth][iMatrixHeight];
		
		System.out.println("PASO 2");
		
		// Fill the matrix cells
		for (int i=0;i<iMatrixWidth;i++)
		{
		    for (int j=0;j<iMatrixHeight;j++)
		    {
		        cMatrix[i][j]=(byte)(is.read() & 0xFF);
		    }
		}

		return (0);
	}

    // ---------------------------------------------------
    /**
     @brief Read a short number from file

     @param is the input stream where to extract the data
     @return data read
     */
	static int readShort(FileInputStream is) throws IOException
    {
	    int data=0;
	    data |= (is.read() << 8);
	    data |= is.read();
	    return (data);
    }

	   // ---------------------------------------------------
	   /**
	    @brief Read a int number from file
	
	    @param is the input stream where to extract the data
	    @return data read
	    */
  	static int readInt(FileInputStream is)  throws IOException
  	{ 
  	    int data=0;
  	    data = is.read() << 24;
  	    data |= (is.read() << 16);
  	    data |= (is.read() << 8);
  	    data |= is.read();
  	    return (data);
	}
	
	// ---------------------------------------------------
	/**
	 @brief Save the world in a file

	 @param file where to save the world
	 */
	public void saveWorld( String file ) throws IOException
	{
	  int p;
	  DataOutputStream out = new DataOutputStream(new FileOutputStream( file ));

	  // ++ Write the current world ++ 
	  packWorld(out);
	  
  	  out.close();
	}

	// ---------------------------------------------------
	/**
	 @brief Write the data of the current world

	 @param out stream to write the current world
	 */
	void packWorld(DataOutputStream out) throws IOException
	{
	   // Write matrix dimensions
	   System.out.println("packWorld:iMatrixWidth="+iMatrixWidth+";iMatrixHeight="+iMatrixHeight+";iBlockLength_X="+iBlockLength_X+";iBlockLength_Y="+iBlockLength_Y);
		 out.writeShort( iMatrixWidth );
	      out.writeShort( iMatrixHeight );
	      out.writeShort( iBlockLength_X );
	      out.writeShort( iBlockLength_Y );	      
	      
	      // ++ Write the number of layers used ++
	  	  out.writeByte( (byte) TileMapEditor._NumberLayersCreated );
	  	
	  	  for (int i=0;i<iMatrixWidth;i++)
		  {
			for (int j=0;j<iMatrixHeight;j++)
			{
				// Collision matrix
				out.writeByte( (byte) cMatrix[i][j] );
			}
		 }
	}


	// ---------------------------------------------------
	/**
	 @brief Write the data of the current world in XML

	 @param out stream to write the current world
	 */
	void saveWorldXML(String file) throws IOException
	{
	   String bufColision=new String ("");
	   for (int i=0;i<iMatrixWidth;i++)
	   {
		for (int j=0;j<iMatrixHeight;j++)
		{
			bufColision+=",";
			bufColision+=cMatrix[i][j];
		}
	   }
	   
	   // ++ WRITE IN FILE ++
	   PrintWriter myOutWriter=new PrintWriter(new DataOutputStream(new FileOutputStream( file )));
	   myOutWriter.println( "<level>" );
	   myOutWriter.println( "<matrix_width>"+iMatrixWidth+"</matrix_width>" );
	   myOutWriter.println( "<matrix_height>"+iMatrixHeight+"</matrix_height>" );
	   myOutWriter.println( "<block_width>"+iBlockLength_X+"</block_width>" );
	   myOutWriter.println( "<block_height>"+iBlockLength_Y+"</block_height>" );
	   myOutWriter.println( "<collision>"+bufColision.substring(1,bufColision.length())+"</collision>");
	   myOutWriter.println( "</level>" );
   	   myOutWriter.close();
	}
	 
	// ---------------------------------------------------
	/**
	 @brief Get orientation in byte form

	 @param gradius the gradius between [0,360]
	 @return the orientation discrette betwen [1,8]
	 */
	byte getByteOrientation( int gradius ) 
	{
		return ((byte)(gradius/10));
	}
	
	// ---------------------------------------------------
	/**
	 @brief The opposite of the last function
	 */
	int getRadiusByByteOrientation( byte byteOrientation ) 
	{
		return (byteOrientation*10);		
	}
	
	// ---------------------------------------------------
	/**
	 @brief Test if the position is inside the matrix

	 @param pos position to test
	 @return true if position is inside the matrix
	 */
	 boolean isCellCorrect(Point2D pos)
	 {
		if ((pos.x<0)||(pos.x>=iMatrixWidth))   return (false);
		if ((pos.y<0)||(pos.y>=iMatrixHeight))  return (false);
		return (true);
	}

	// ---------------------------------------------------
	/**
	 @brief Get the cell position in the matrix

	 @param pos position escaled with the scroll
	 @return the matrix cell where is position
	 */
	Point2D getPositionCell(Point2D pos)
	{
		return (new Point2D(pos.x/(iBlockLength_X/TileMapEditor.gZoomApplied),pos.y/(iBlockLength_Y/TileMapEditor.gZoomApplied)));
	}

	// ---------------------------------------------------
	/**
	 @brief Get the card in the selected matrix position

	 @param pos position of the matrix where to get
	 @param type of the matrix selected
	 @return the byte of the selected position
	 */
	byte getContentCell( Point2D pos, int type, int p_capa )
	{
		if (pos.x<0) return (COLISION_TYPE_STONE);
		if (pos.y<0) return (COLISION_TYPE_STONE);
		if (pos.x>=iMatrixWidth) return (COLISION_TYPE_STONE);
		if (pos.y>=iMatrixHeight) return (COLISION_TYPE_STONE);
		    return (cMatrix[pos.x][pos.y]);
	}

	// ---------------------------------------------------
	/**
	 @brief Get the card in the selected matrix position

	 @param x x coordinate of the matrix where to get
	 @param y y coordinate of the matrix where to get
	 @param type of the matrix selected
	 @return the card of the selected position
	 */
	byte getContentCell( int x, int y, int type, int p_capa )
	{
		if (x<0) return (COLISION_TYPE_STONE);
		if (y<0) return (COLISION_TYPE_STONE);
		if (x>=iMatrixWidth)  return (COLISION_TYPE_STONE);
		if (y>=iMatrixHeight) return (COLISION_TYPE_STONE);
		    return (cMatrix[x][y]);
	}

	// ---------------------------------------------------
	/**
	 @brief Sets the content of the cell with that value

	 @param x x coordinate of the matrix where to get the value
	 @param y y coordinate of the matrix where to get the value
	 @param type of the matrix selected
	 */
	void setContentCell(Point2D pos, byte value, int type, int p_capa)
	{
		if (!isCellCorrect(pos)) return;
		
	    cMatrix[pos.x][pos.y]=value;
	}

	// ---------------------------------------------------
	/**
	 @brief Get the position of the screen to paint the world point

	 @param ppos point in the world
	 @return a point in the screen
	 */
	Point2D getScreenPoint(Point2D ppos)
	{
		Point2D pos_output=new Point2D(ppos);
		int ref_x=_Camera.x;
		int ref_y=_Camera.y;

		// if (ref_x<LONGITUD_CASILLAS<<1) ref_x=LONGITUD_CASILLAS<<1;
		// if (ref_y<LONGITUD_CASILLAS<<1) ref_y=LONGITUD_CASILLAS<<1;
		// if (ref_x>ancho_marco_pantalla) ref_x=ancho_marco_pantalla;
		// if (ref_y>alto_marco_pantalla)  ref_y=alto_marco_pantalla;

		pos_output.x-=ref_x;
		pos_output.y-=ref_y;

		pos_output.x+=(_iScreenWidth>>1);
		pos_output.y+=(_iScreenHeight>>1);

		return (pos_output);
	}


	// ---------------------------------------------------
	/**
	 @brief Get the position of the screen to paint the world point

	 @param ppos point in the world
	 @return a point in the screen
	 */
	Point2D getScreenPoint(World root, Point2D ppos)
	{
		Point2D pos_output=new Point2D(ppos);
		int ref_x=root._Camera.x;
		int ref_y=root._Camera.y;

		// if (ref_x<LONGITUD_CASILLAS<<1) ref_x=LONGITUD_CASILLAS<<1;
		// if (ref_y<LONGITUD_CASILLAS<<1) ref_y=LONGITUD_CASILLAS<<1;
		// if (ref_x>ancho_marco_pantalla) ref_x=ancho_marco_pantalla;
		// if (ref_y>alto_marco_pantalla)  ref_y=alto_marco_pantalla;

		pos_output.x-=ref_x;
		pos_output.y-=ref_y;

		pos_output.x+=(root._iScreenWidth>>1);
		pos_output.y+=(root._iScreenHeight>>1);

		return (pos_output);
	}	

	
	// ---------------------------------------------------
	/**
	 @brief Gets the position in the matrix that correspond to the coordinate position

	 @param x x coordinate of mouse pressed
	 @param y y coordinate of mouse pressed
	 @return the position in the matrix selected
	 */
	Point2D getCellInsideMatrix(int x, int y)		
	{
	   Point2D pos=new Point2D();
	
	   for (int i=0;i<iMatrixWidth;i++)
	   {
	       for (int j=0;j<iMatrixHeight;j++)
	       {
	           int extremo_inf_x=i*(iBlockLength_X/TileMapEditor.gZoomApplied);
	           int extremo_inf_y=j*(iBlockLength_Y/TileMapEditor.gZoomApplied);
	           int extremo_sup_x=(i+1)*(iBlockLength_X/TileMapEditor.gZoomApplied);
	           int extremo_sup_y=(j+1)*(iBlockLength_Y/TileMapEditor.gZoomApplied);

	           if ((extremo_inf_x<=x)&&(extremo_inf_y<=y)&&(extremo_sup_x>x)&&(extremo_sup_y>y))
	           {
	               pos.x=i;
	               pos.y=j;
	           }
	       }
	   }
	   return (pos);
	}

	
	// ******************************************************************************************************
	// ******************************************************************************************************
	// ******************************************************************************************************
	//				    OPERATIONS OF WORLD CREATION
	// ******************************************************************************************************
	// ******************************************************************************************************
	// ******************************************************************************************************
	
	// ---------------------------------------------------
	/**
	 @brief Sets the cell that correpond to the mouse position

	 @param x x coordinate of mouse pressed
	 @param y y coordinate of mouse pressed
	 */
	void setPositionCell(int x, int y, int x2, int y2, int pEditionMode, int pEditionLayer)		
	{
	  switch (pEditionMode)
  	  {
		// ///////////////////////////////////////////////////////// 
		case ScrollWorld.EDITION_COLISION:
		{
			switch (colTypeSelected)
			{
			   case COLISION_TYPE_EMPTY:			
				if (colTypeSelected!=-1)
				{
					Point2D pos=getCellInsideMatrix(x, y);
					cMatrix[pos.x][pos.y]=(byte)colTypeSelected;
				}
				break;
			   
			  default:
			      if (colTypeSelected!=-1)
			      {
					Point2D pos=getCellInsideMatrix(x, y);
					cMatrix[pos.x][pos.y]=(byte)colTypeSelected;
			      }
			      break;
			}
			break; 
		}
	   }
	}

	// ---------------------------------------------------
	/**
	 @brief Logic of the world

	 Depending the state we will need to execute certain logic of the world
	 */
	void logic()
	{
	}


	// ---------------------------------------------------
	/**
	 @brief Render of the matrix of cards/cells

	 Only renders the matrix of cards/cells if is dirty
	 */
	void renderMatrix(int editionMode, int pEditionLayer)
	{
		int[] xpoints=new int[4];
		int[] ypoints=new int[4];
		Point2D shift=new Point2D(0,0);
        
		Point2D posCell=new Point2D();

		for (int i=0;i<iMatrixWidth;i++)
		{
			for (int j=0;j<iMatrixHeight;j++)
			{
				posCell.setLocation((i*(iBlockLength_X/TileMapEditor.gZoomApplied))+shift.x, (j*(iBlockLength_Y/TileMapEditor.gZoomApplied))+shift.y);
				posCell=getScreenPoint(posCell);
				if (editionMode==ScrollWorld.EDITION_COLISION)
				{
					_g.setColor( Color.black );
					_g.drawRect( posCell.x , posCell.y , (iBlockLength_X/TileMapEditor.gZoomApplied) , (iBlockLength_Y/TileMapEditor.gZoomApplied) );
				}
				
				switch (cMatrix[i][j])
				{
					  case COLISION_TYPE_EMPTY:
						      break;

					case COLISION_TYPE_STONE:
						_g.drawImage(TileMapEditor.m_type_collision, posCell.x, posCell.y, (iBlockLength_X / TileMapEditor.gZoomApplied), (iBlockLength_Y / TileMapEditor.gZoomApplied), this);
						break;

					case COLISION_TYPE_FRUIT_1:
						_g.drawImage(TileMapEditor.m_type_fruit_1,posCell.x,posCell.y,(iBlockLength_X/TileMapEditor.gZoomApplied),(iBlockLength_Y/TileMapEditor.gZoomApplied),this);
						break;		
						
					case COLISION_TYPE_FRUIT_2:
						_g.drawImage(TileMapEditor.m_type_fruit_2,posCell.x,posCell.y,(iBlockLength_X/TileMapEditor.gZoomApplied),(iBlockLength_Y/TileMapEditor.gZoomApplied),this);
						break;		
						
					case COLISION_TYPE_FRUIT_3:
						_g.drawImage(TileMapEditor.m_type_fruit_3,posCell.x,posCell.y,(iBlockLength_X/TileMapEditor.gZoomApplied),(iBlockLength_Y/TileMapEditor.gZoomApplied),this);
						break;		
						
					case COLISION_TYPE_FRUIT_4:
						_g.drawImage(TileMapEditor.m_type_fruit_4,posCell.x,posCell.y,(iBlockLength_X/TileMapEditor.gZoomApplied),(iBlockLength_Y/TileMapEditor.gZoomApplied),this);
						break;		
						
					case COLISION_TYPE_FRUIT_5:
						_g.drawImage(TileMapEditor.m_type_fruit_5,posCell.x,posCell.y,(iBlockLength_X/TileMapEditor.gZoomApplied),(iBlockLength_Y/TileMapEditor.gZoomApplied),this);
						break;		
						
					case COLISION_TYPE_FRUIT_6:
						_g.drawImage(TileMapEditor.m_type_fruit_6,posCell.x,posCell.y,(iBlockLength_X/TileMapEditor.gZoomApplied),(iBlockLength_Y/TileMapEditor.gZoomApplied),this);
						break;		

					case COLISION_TYPE_FRUIT_7:
						_g.drawImage(TileMapEditor.m_type_fruit_7,posCell.x,posCell.y,(iBlockLength_X/TileMapEditor.gZoomApplied),(iBlockLength_Y/TileMapEditor.gZoomApplied),this);
						break;

					case COLISION_TYPE_FRUIT_8:
						_g.drawImage(TileMapEditor.m_type_fruit_8,posCell.x,posCell.y,(iBlockLength_X/TileMapEditor.gZoomApplied),(iBlockLength_Y/TileMapEditor.gZoomApplied),this);
						break;
				}

			        
				if (enableGrid)
				{
					_g.setColor( Color.black );
					_g.drawRect( posCell.x , posCell.y , (iBlockLength_X/TileMapEditor.gZoomApplied) , (iBlockLength_Y/TileMapEditor.gZoomApplied) );
				}
			}
		}		
	}
	
	// ---------------------------------------------------
	/**
	 @brief Render of the world

	 Depending the state we will need to render different elements
	 */
	void render(int editionMode, int pEditionLayer)
	{
	   Point2D posCell=new Point2D();
		
	   // ++++++ Render Local Matrix ++++++
	   renderMatrix(editionMode, pEditionLayer);
	}

	// ---------------------------------------------------
	/**
	 @brief Gets the dimension of the screen and create a buffer for double buffering
	 */
	void getDimension(Dimension area)
	{
		try 
		{
			if ((_g == null)||(_iScreenWidth!=area.width)||(_iScreenHeight!=area.height))
			{
				_iScreenWidth=area.width;
				_iScreenHeight=area.height;
				buffer=createImage(_iScreenWidth,_iScreenHeight);
				_g=buffer.getGraphics();
			}
		} 
		catch (Exception e) {};
	}
	
}  // End Class World
