import java.applet.*;
import java.awt.*;
import java.util.Vector;
import Sprite;

/********************************************************
 * AnimatedSprite contains the frames and sequences of 
 * an animated image and is responsible for the controlling
 * the animation
 *********************************************************/
class AnimatedSprite extends Sprite {
  int frames;         // frames in sprite
  Sprite sprites[];   // array of images in frames
  Vector tracks;      // vector of tracks
  Vector states;      // vector of states
  State curstate;     // current state
  int curstateindex;  // index of current state
  int tickcount;      // number of ticks  elapsed in current state

  public AnimatedSprite(Image images, int framenum) {
    super(images);
    frames = framenum;
    sprites = new Sprite[framenum];
    // set image in first frame
    addImage (0, images);
    tracks = new Vector();
    states = new Vector();
    curstate = null;
  }

  // add an image in the specified frame
  void addImage(int frame, Image img) {
    sprites[frame] = new Sprite(img);
  }

  // add a state to a specified track
  public void addState(int track, int frame, int ticks, int dx, int dy) {
    Vector usetrack;
    // add new track(s)
    while (track >= tracks.size())
      tracks.addElement (new Vector());
    // select the right track
    usetrack = (Vector) tracks.elementAt(track);
    // add the state
    usetrack.addElement(new State(frame, ticks, dx, dy));
  }

  public void Draw(Raster bgnd) {
    sprites[curstate.frame].Draw(bgnd);
  }

  // move sprites
  public void moveRel(int shiftx, int shifty) {
    // move all frames of the sprite
    for (int cursprite = 0; cursprite < frames; cursprite++)
      sprites[cursprite].moveRel(shiftx, shifty);
  }

  // returns whether mouse pointer is over an opaque pixel of sprite
  public boolean isOverSprite(int mousex, int mousey) {
    // if not within sprite frame...
    return (sprites[curstate.frame].isOverSprite(mousex, mousey));
  }

  // move to next state
  public void nextState() {
    curstateindex++;
    curstateindex =
      ((curstateindex < states.size()) ? curstateindex : 0);
    // retrieve next state
    curstate = (State) states.elementAt(curstateindex);
    // move sprite if needed
    moveRel(curstate.dx, curstate.dy);
  }

  // set current track
  public void setTrack(int t) {
    states = (Vector) tracks.elementAt(t);
    curstate = (State) states.firstElement();
    tickcount = 0;
  }

  // update number of ticks elapsed in current state
  public void tick() {
    tickcount++;
    if (tickcount == curstate.ticks) {
      tickcount = 0;
      nextState();
    }
  }
}

/********************************************************
 * State is basically a structure for variables
 * relating the a state in animation
 *********************************************************/
class State extends Object{
  int frame;
  int ticks;
  int dx;
  int dy;

  public State(int newframe, int newticks, int newdx, int newdy) {
    frame = newframe;
    ticks = newticks;
    dx = newdx;
    dy = newdy;
  }

  public String toString() {
    return "frame: " + frame + " ticks: " + ticks + " dx: " + dx
      + " dy: " + dy;
  }
}
