import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.util.*;

public class SpriteDemo extends Applet implements Runnable {
  /**
   *Implements a demonstration of multiple sprites running around on
   *a playfield.  This includes all init() stuff that needs to be done
   *after reading in the sprite parameters from the HTML file, and
   *redefining the paint(), etc. procedures
   */
  Playfield playfield;  //the playfield which contains everything that is drawn
  AnimatedSprite sprite;  //the current sprite being created
  Image output;  //the output image to the applet (shows animations, background)
  Image spriteImages;  //the composite of sprite frames that is read in
  Thread animate;  //this thread

  public void init() {
    /**
     *Read in all the parameters from the HTML call of this applet
     *Then create the playfield and sprites according to these parameters
     */
    //read the numSprites parameter
    int numSprites=Integer.parseInt(getParameter("numSprites"));
				  
    //create the playfield using the background parameter
    playfield = new Playfield(getImage(getDocumentBase(), 
				       getParameter("background")),
			      numSprites);

    //Read  in each of the sprites in turn
    for (int curSprite=0; curSprite<numSprites; curSprite++) {
      //get the parameters for the current sprite
      String spriteParams= getParameter("sprite"+Integer.toString(curSprite));
      //break up the parameters string into the actual tokens
      StringTokenizer tokens= new StringTokenizer(spriteParams, " ,\t\n\r");
      //the first item in paramter string is the image
      String spriteImage= tokens.nextToken();
      //the next item is the number of Frames
      int numFrames=Integer.parseInt(tokens.nextToken()); 
      //create the animated sprite with these parameters
      sprite= new AnimatedSprite(getImage(getDocumentBase(),spriteImage),numFrames);
      
      while (tokens.hasMoreTokens()) {
	//for each state in the sprite, read the parameter items and then create
	//the state
	int track= Integer.parseInt(tokens.nextToken());
	int frame= Integer.parseInt(tokens.nextToken());
	int ticks= Integer.parseInt(tokens.nextToken());
	int dx= Integer.parseInt(tokens.nextToken());
	int dy= Integer.parseInt(tokens.nextToken());
	sprite.addState(track, frame, ticks, dx, dy);
      }
      //add the sprite to the playfield
      playfield.addSprite(curSprite, sprite);
    }
    renderPlayfield();  //Draw the playfield for the first time
  }
  
  public void start() {
    //start the thread
    animate = new Thread(this);
    animate.start();
  }

  public void stop() {
    //stop the thread
    animate = null;
  }
    
  public void run() {
    //run the thread with a delay between each redrawing of the playfield
    while (true) {
      try {
	animate.sleep(200);
      } catch (InterruptedException e) {
      }
      renderPlayfield( );
    }
  }
  
  void renderPlayfield() {
    //Draw the playfield and output this image to the repaint() method
    playfield.Draw();
    output = playfield.toImage();
    repaint();
  }
    
  public void paint(Graphics g) {
    //draw the image in output
    g.drawImage(output, 0, 0, this);
  }
    
  public void update(Graphics g) {
    paint(g);
  }

  public boolean mouseDown(Event e, int x, int y) {
    /**
     *Whenever the user points and clicks with the mouse, it will
     *reset the animate sprites to run from that point.
     */
    for (int s=0; s<playfield.totalSprites; s++) {
      playfield.sprite[s].startAtXY(x, y+s*120);
    }
    renderPlayfield();
    return true;
  }
}
