import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.*;

class AnimatedSprite extends Sprite
{
  //initialize class variables
  public int frames;
  private Sprite frameArray[];
  private int currentframe;
  public int moveX, moveY;
  public int x, y;
  public int frameperiod;
  public int gravity;
  public int bounce;
  
  //constructor
  public AnimatedSprite()
  {}

  //constructor
  public AnimatedSprite(int framescount)
  {
    frames = framescount;
    frameArray = new Sprite[frames];
  }

  //constructor
  public AnimatedSprite(Image images, int framenum)
  {
    frames = framenum;
    frameArray = new Sprite[frames];
    parseImageBlock(images, framenum);
  }

  //returns the width of the current frame of the sprite
  public int getWidth()
  {
    return frameArray[currentframe].width;
  }

  //returns the height of the current frame of the sprite
  public int getHeight()
  {
    return frameArray[currentframe].width;
  }

  //Detects whether a given point on the playfield is on the current 
  //frame of the sprite (does not detect transparent parts of the sprite)
  //returns true if the point is part of the sprite.
  public boolean Overlap(int a, int b)
  {
    boolean hit = false;

    //test for location and transparency of pixel
    if ((a > x) && 
	(a < x + frameArray[currentframe].width) && 
	(b > y) && 
	(b < y + frameArray[currentframe].height) && 
	(frameArray[currentframe].getPixel(a-x,b-y) < 8388607 ))
      hit = true;

    return hit;
  }

  
  //takes a block of (frames) images and sets the AnimatedSprite's
  //frameArray to a list of the frames of the animation.
  private void parseImageBlock(Image images, int frames)
  {
    Raster rasters = new Raster(images);
    int framewidth = rasters.width/frames;
    
    //for every frame of the animation
    for (int i = 0; i < frames; i++)
      {
	//initialize the space in frameArray
	frameArray[i] = new Sprite(framewidth, rasters.height);

	//for every pixel in that section of the image block...
	for (int j = i*framewidth; j < (i+1)*framewidth; j++)
	  {
	    for (int k = 0; k < rasters.height; k++)
	      {
		//...assign that pixel to the correct frame in frameArray 
		int pix = rasters.getPixel(j,k);
		frameArray[i].setPixel(pix,j - i*framewidth,k);
	      }
	  }
      }
  }

  //set the current active frame (used to start an animation sequence,
  //or to force a particular sequence);
  public void setFrame(int framenumber)
  {
    currentframe = framenumber;
  }

  //assign the various variables for the AnimatedSprite.
  //grav is included for animation of gravity effects; it is 
  //the effect of gravity on the object.  Currently disabled.
  //frameperiod has not been used in this implementation; instead,
  //manipulation of the speed of the applet is done in HelloWorld.java.
  //bounce allows for 2 sorts of animated sprite motion; bounded by the
  //edge of the playfield, and clipped by the edge of the playfield.  
  public void addState(int frame, int ticks, int dx, int dy, int grav, int rebound)
  {
    frameperiod = ticks;
    moveX = dx;
    moveY = dy;
    x = x + moveX;
    y = y + moveY;
    gravity = grav;
    bounce = rebound;
  }

  //draw the current frame of animation on to the background
  //and update movement characteristics.
  public void DrawRebound(Raster bgnd)
  {
    if (frames != 0)
      {
	frameArray[currentframe].x = x;
	frameArray[currentframe].y = y;
	frameArray[currentframe].Draw(bgnd);

	//check to see if the last redraw brought the sprite into contact
	//with the border of the playfield
	if (x + frameArray[currentframe].width > bgnd.width)
	  moveX = -Math.abs(moveX);
	if  (x < 0) 
	  moveX = Math.abs(moveX);
	if (y + frameArray[currentframe].height > bgnd.height)
	  moveY = -Math.abs(moveY);
	if (y < 0)
	  moveY = Math.abs(moveY);
      }
  }

  //draw the current frame of animation on to the background.
  public void Draw(Raster bgnd)
  {
    if (frames != 0)
      {
	frameArray[currentframe].x = x;
	frameArray[currentframe].y = y;
	frameArray[currentframe].Draw(bgnd);
      }
  }

  //advance the animation to the next frame, cycling to beginning if
  //necessary, and increment motion (applying gravity if used).
  public void nextState()
  {
    if (currentframe > frames - 2)
      currentframe = 0;
    else
	currentframe = currentframe + 1;  

    x = x + moveX;
    y = y + moveY;
    // moveY = moveY + gravity;  //disabled for now.
  }

}




