/*
	Star.class

	Implements a starfield effect, using pre-scaled GIFs for the stars

	Parameters (optional):

	    NO_GIFS	- No of GIFs used for scaling		[1]
			  (GIFS named star0.gif .. star<n-1>.gif  Last GIF is
			   smallest star)
	    NO_STAR	- Number of stars to draw		[100]
	    MAX_X	- Maximum x co-ord of star		[10000]
	    MAX_Y	- Maximum y co-ord of star		[10000]
	    MAX_Z	- Initial z co-ord of star		[100000]
	    INC_Z	- Speed of stars (number is +ve)	[2000]

*/
import java.applet.Applet;
import java.awt.*;

public class Star extends Applet implements Runnable
{

    /* State
    */
    final int	ZCONST	=400;
    int		MAX_X	=10000;
    int		MAX_Y	=10000;
    int		MAX_Z	=100000;
    int		INC_Z	=2000;

    final int	WEIGHT	=8;

    int[]	sx;
    int[]	sy;
    int[]	sz;

    int		nospr=1;
    int		sprscale;
    Image[]	spr;
    Image	img;
    int		imgw,imgh;

    int		no=100;
    int		cx,cy;
    int		width,height;
    Color	bg;
    Color	fg;

    Thread	task;

    /* Local utils
    */

    private int Param(String s,int def)
    {
	String param;

	param=getParameter(s);

	if (param!=null)
	    return (Integer.valueOf(param).intValue());
	else
	    return (def);
    }

    private void GetScreenSize()
    {
	width=size().width;
	height=size().height;

	cx=width/2;
	cy=height/2;

	if ((img==null)||(width!=imgw)||(height!=imgh))
	    {
	    img=this.createImage(width,height);
	    imgw=width;
	    imgh=height;
	    }
    }


    private int RND(int i)
    {
	double res;

	res=Math.random();

	return ((int)(res*i));
    }


    private void NewStar(int f)
    {
	sx[f]=RND(MAX_X*2)-MAX_X;
	sy[f]=RND(MAX_Y*2)-MAX_Y;
	sz[f]=MAX_Z;
    }


    private int X3d(int f)
    {
	int x,z;

	x=sx[f];
	z=sz[f];

	x=x<<WEIGHT;
	z=z<<WEIGHT;

	z/=ZCONST;

	return (cx+(x/z));
    }


    private int Y3d(int f)
    {
	int y,z;

	y=sy[f];
	z=sz[f];

	y=y<<WEIGHT;
	z=z<<WEIGHT;

	z/=ZCONST;

	return (cy+(y/z));
    }


    public void DrawStars(Graphics g) 
    {
	int f;

	g.setColor(bg);
	g.fillRect(0,0,width,height);

	g.setColor(fg);

	for(f=0;f<no;f++)
	    {
	    sz[f]-=INC_Z;

	    if (sz[f]<100)
		{
		NewStar(f);
		}

	    g.drawImage(spr[sz[f]/sprscale],X3d(f),Y3d(f),null);
	    }
    }


    /* Main loop
    */
    public void run()
    {
	Thread.currentThread().setPriority(Thread.MAX_PRIORITY);

	while (true)
	    {
	    GetScreenSize();
	    DrawStars(img.getGraphics());
	    this.getGraphics().drawImage(img,0,0,this);

	    try
		{
		Thread.sleep(100);
		} catch (InterruptedException e);
	    }
    }

    /* Applet event hooks
    */
    public void init() 
    {
	String param;
	int f;

	bg=Color.black;
	fg=Color.white;

	no=Param("NO_STAR",no);
	nospr=Param("NO_GIF",nospr);
	MAX_X=Param("MAX_X",MAX_X);
	MAX_Y=Param("MAX_Y",MAX_Y);
	MAX_Z=Param("MAX_Z",MAX_Z);
	INC_Z=Param("INC_Z",INC_Z);

	GetScreenSize();

	sx=new int[no];
	sy=new int[no];
	sz=new int[no];

	spr=new Image[nospr];
	sprscale=(MAX_Z/nospr)+1;

	for(f=0;f<no;f++)
	    {
	    NewStar(f);
	    sz[f]=RND(MAX_Z);
	    }

	for(f=0;f<nospr;f++)
	    spr[f]=this.getImage(this.getDocumentBase(),"star"+f+".gif");
    }


    public void start() 
    {
	if (task==null)
	    {
	    task=new Thread(this);
	    task.start();
	    }
    }

    public void paint(Graphics g) 
    {
	// Leave the drawing to the thread.
    }

    public void stop() 
    {
	destroy();
    }

    public void destroy() 
    {
	if (task!=null)
	    {
	    task.stop();
	    task=null;
	    }
	img=null;
	sx=null;
	sy=null;
	sz=null;
    }
}
