
import java.awt.geom.AffineTransform;
import java.awt.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
public
class Sprite1 extends java.applet.Applet implements 
      MouseListener, KeyListener, Runnable{
  boolean md;
  int k=0;
  boolean keyIsDown [] = new boolean[KeyEvent.KEY_LAST];
  public void mousePressed(MouseEvent e) {md=true;}
  public void mouseReleased(MouseEvent e){md=false;}
  public void mouseEntered(MouseEvent e) { }
  public void mouseExited(MouseEvent e) { }
  public void keyTyped(KeyEvent e) { }
  public void keyPressed(KeyEvent e){keyIsDown[e.getKeyCode()]=true;}
  public void keyReleased(KeyEvent e){keyIsDown[e.getKeyCode()]=false;}
  int frame;
  int delay;
  Thread animator=null;

  Dimension offDimension;
  Image offImage;
  Graphics2D offGraphics;
  Sprite s;
  Button startButton;

  public void init() {
    String str = getParameter("fps");
    int fps = (str != null) ? Integer.parseInt(str) : 10;
    delay = (fps > 0) ? (1000 / fps) : 100;
    //setLayout(new FlowLayout());
    startButton = new java.awt.Button("Click Here To Start");
    add(startButton);
    startButton.addMouseListener(this);
  }

  public void mouseClicked(MouseEvent e) {
    //The user cannot control unless the applet has focus.
    //We need a "click to start"
    if (s==null){
      s = new Sprite();
      animator = new Thread(this);
      animator.start();
      remove(startButton);
      this.requestFocus();
    }
  }

  public void start() {
    Graphics g = this.getGraphics();
    g.setColor(Color.black);
    g.drawString("Click to start...",20,20);
    g.fillRect(50,50,20,20);
    addMouseListener(this);
    addKeyListener(this);
  }

  public void run() {
  // Remember the starting time
  long tm = System.currentTimeMillis();
  while (Thread.currentThread() == animator) {
  // Display the next frame of animation.
    repaint();

       // Delay depending on how far we are behind.
    try {
     tm += delay;
     Thread.sleep(Math.max(0, tm - System.currentTimeMillis()));
    } catch (InterruptedException e) {
      break;
    }

       // Advance the frame
    frame++;
    s.tick(keyIsDown);
    }
  }

  public void stop() {
    animator = null;
    offImage = null;
    offGraphics = null;
  }

    /**
     * Update a frame of animation.
     */
  public void update(Graphics g) {
    Dimension d = size();
    if (animator==null){
      g.setColor(Color.black);
      g.drawString("Click here to start.",10,30);
      return;
    }
	// Create the offscreen graphics context
    if ((offGraphics == null)
     || (d.width != offDimension.width)
     || (d.height != offDimension.height)) {
      offDimension = d;
      offImage = createImage(d.width, d.height);
      offGraphics = (Graphics2D)offImage.getGraphics();
    }

    // Erase the previous image
    offGraphics.setColor(getBackground());
    offGraphics.fillRect(0, 0, d.width, d.height);
    offGraphics.setColor(Color.black);

    // Paint the frame into the image
    AffineTransform tmp = offGraphics.getTransform();
    s.paintFrame(offGraphics,keyIsDown);
    offGraphics.setTransform(tmp);
    // Paint the image onto the screen
    g.drawImage(offImage, 0, 0, null);
  }

    /**
     * Paint the previous frame (if any).
     */
  public void paint(Graphics2D g) {
    if (animator==null){
      g.setColor(Color.black);
      g.drawString("Click here to start.",10,30);
      return;
    }
    if (offImage != null) {
      g.drawImage(offImage, 0, 0, null);
    }
  }
}


