import java.awt.*;
import java.awt.image.*;

class Sprite extends Raster
{
	protected int x,y;
	protected int xOff,yOff; // x and y offsets for sprite coordinates
	
	/// Constructors ///
	/**
	 * Argument-free constructor to permit future expansion
	 *
	 */
	public Sprite()
	{
		super();	// call superclass constructor
	}

	/**
	 * Permits construction of a sprite directly from an image.
	 * Places sprite at x,y with reference point in upper-left corner.
	 *
	 */
	public Sprite(Image img, int xx, int yy)
	{
		super(img);	// initialize raster
		x=xx; y=yy;	// set up position
		xOff=0;		// set offset to none
		yOff=0;
	}

	/**
	 * Construct with a different reference point.
	 *
	 */
	public Sprite(Image img, int xx, int yy, int xO, int yO)
	{
		super(img);	// initialize raster
		x=xx; y=yy; 	// set up position
		xOff=xO;	// set offset
		yOff=yO;
	}
		
	/**
	 * Since I can't create images with alpha, we use the
	 * red channel of another image of the same size.  This
	 * routine takes that image (already loaded into a raster)
	 * and steals its R field for our Alpha
	 *
	 */
	public boolean setAlpha(Raster alpha)
	{
		if((alpha.getWidth() != width) || (alpha.getHeight() != height))
			return false;	// not same size!
			
		int i, j;
		
		for(i=0;i<width;i++)
			for(j=0;j<height;j++)
				setPixel((getPixel(i,j)&0x00FFFFFF) |
					(alpha.getPixel(i,j)&0x00FF0000)<<8,i,j);
		// above just masks out all but red channel, moves to alpha
		
		return true;
	}
	
	public void setXY(int x, int y)
	{
		this.x=x;
		this.y=y;
	}

	public int getX( )
	{
		return x;
	}

	public int getY( )
	{
		return y;
	}

	/**
	 * Draw sprite onto its background
	 *
	 */
	public void draw(Raster bg)
	{
		int i,j;
		int sx,sy,ex,ey,si,sj; // starting and ending coordinates
		
		// clipping routines
		if(x-xOff < 0)	// are we off the edge of the screen?
			si=xOff-x;
		else
			si=0;
		
		if(x-xOff+width >= bg.getWidth())	// are we off the other edge?
			ex=bg.getWidth()+xOff-x;	// find the right edge in the sprite
		else
			ex=width;
			
		if(y-yOff < 0)	// now check the top
			sj=yOff-y;
		else
			sj=0;
		
		if(y-yOff+height >= bg.getHeight())	// off the bottom?
			ey=bg.getHeight()+yOff-y;	// find the bottom in sprite
		else
			ey=height;
			
		for(i=si;i<ex;i++)
			for(j=sj;j<ey;j++)
			{
				int c,pix;

				pix=getPixel(i,j);
				c=computeAlphaPixel(pix, bg.getPixel(x+i-xOff,y+j-yOff),						getAlpha(pix));
				bg.setPixel(c,x+i-xOff,y+j-yOff);
			}
	}

	/**
	 * extracts the alpha value from a pixel
	 *
	 */
	 protected float getAlpha(int pix)
	 {
	 	return ((pix>>24)&0xFF)/255.0f;
	 }

	/**
	 * computes pixel using alpha value
	 *
	 */
	protected int computeAlphaPixel(int cFg, int cBg, float alpha)
	{
		int r,g,b;
		
		b=(int)((cFg&0x000000FF)*alpha + (cBg&0x000000FF)*(1-alpha));
		g=(int)(((cFg&0x0000FF00)>>8)*alpha + ((cBg&0x0000FF00)>>8)*(1-alpha));
		r=(int)(((cFg&0x00FF0000)>>16)*alpha + ((cBg&0x00FF0000)>>16)*(1-alpha));
		
		return(0xFF000000|(r<<16)|(g<<8)|b);
	}

	/**
	 * Determine whether or not a requested pixel is active (ie, alpha != 0)
	 * returns True if active.  Coordinates are in screenspace
	 *
	 */
	public boolean activePixelP(int xx, int yy)
	{
		if((xx<x-xOff)||(yy<y-yOff)||(xx>x+width-xOff)||(yy>y+height-yOff))
			return false;	// out of range -- pixel not active

		if(getAlpha(getPixel(xx-x+xOff,yy-y+yOff))<1/255.0f) // alpha is 0
			return false;
		
		return true;	// alpha is nonzero => pixel active
	}		
}

