/** Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
  ** Extends Arthur van Hoff's animation template, to create an animation
  ** by loading, sizing, displaying, and moving a sequence of images.
  ** In addition to double buffering, MediaTracker is used to load all
  ** the images before starting the animation.
  **
  ** Modified to AnimatorApplet6 by John Pais, April 1998.             **/
 
Toggle your browser's Back and Forward buttons to compare the running applet to this code.
Click here to run a fresh copy of the applet:  AnimatorApplet6.html
 
/** USE EXISTING JAVA CLASSES **/

import java.awt.*;
import java.applet.Applet;

/** EXTEND THE JAVA APPLET CLASS AND IMPLEMENT THE RUNNABLE INTERFACE **/

public class AnimatorApplet6 extends Applet implements Runnable
   {int frameNumber = -1;
    int delay;
    Thread animatorThread;
    boolean frozen = false;
    Font waitfont=new Font("TimesRoman",Font.BOLD,14);
    FontMetrics waitfontm = getFontMetrics(waitfont);

    String waitstr1, waitstr2 = "";
    Font shipfont=new Font("TimesRoman",Font.PLAIN,10);
    FontMetrics shipfontm = getFontMetrics(shipfont);
    String shipstr = "";
    String shipstrpad = "                                                    ";
    Font titlefont=new Font("TimesRoman",Font.BOLD,24);
    FontMetrics titlefontm = getFontMetrics(titlefont);
    String titlestr = "";
    Color starblue = new Color(0,100,255);
    Dimension preImageDim;               // Define preImage variables needed to
    Image preImage;                            // create the offscreen copy of the image
    Graphics preImageGraphics;           // we want to paint on the screen.

    Image backgroundstarImage[];
    Image AndromedaImage;
    Image MilkywayHydrogenImage;
    Image PleiadesClusterImage;
    Image borgcubeImage;                   // Not currently being used.
    Image rocketshipImage;

    MediaTracker tracker;
    int backNumber = 0;
    int shipstrIndex = 0;
    int xspeedUp = 0;
    int yspeedUp = 0;
 
Toggle your browser's Back and Forward buttons to compare the running applet to this code.
Click here to run a fresh copy of the applet:  AnimatorApplet6.html
 
    /** INITIALIZE THE APPLET **/

    public void init()
      {setBackground(Color.black);
        String str;
        int fps = 10;                              // Define the default fps (frames per second).
        str = getParameter("fps");         // Possibly, get HTML string specifying the
        try                                           // fps.
         {if (str != null)
           {fps = Integer.parseInt(str);}  // If possible, convert HTML fps to an
          }                                            // integer.
        catch (Exception e) {}              // In case the try caused something strange.
        delay = (fps > 0) ? (1000/fps): 100; // Convert fps to the milisecond delay
                                                            // time between frames.
 
        backgroundstarImage = new Image[3];
        tracker = new MediaTracker(this);    // Spawn the tracker background thread(s)
        AndromedaImage = getImage(getCodeBase(),"images/am5hst.jpg");
        tracker.addImage(AndromedaImage,0);
        MilkywayHydrogenImage = getImage(getCodeBase(),"images/nHI_alt_skyview.jpg");
        tracker.addImage(MilkywayHydrogenImage,0);
        PleiadesClusterImage = getImage(getCodeBase(),"images/pleiades2.gif");
        tracker.addImage(PleiadesClusterImage,0);

        backgroundstarImage[0] = AndromedaImage;
        tracker.addImage(backgroundstarImage[0],0);
        backgroundstarImage[1] = MilkywayHydrogenImage;
        tracker.addImage(backgroundstarImage[1],0);
        backgroundstarImage[2] = PleiadesClusterImage;
        tracker.addImage(backgroundstarImage[2],0);
        //borgcubeImage = getImage(getCodeBase(),"images/borgcube.jpg");
        //tracker.addImage(borgcubeImage,0);
        rocketshipImage = getImage(getCodeBase(),"images/rocketship.gif");
        tracker.addImage(rocketshipImage,0);
        }
 
Toggle your browser's Back and Forward buttons to compare the running applet to this code.
Click here to run a fresh copy of the applet:  AnimatorApplet6.html
 
    /** CLICK TO START OR STOP THE APPLET **/

    public boolean mouseDown(Event e, int x, int y)
       {if (frozen)
         {frozen = false;
          start();}
        else
         {frozen = true;
          animatorThread = null;     // Instead of calling stop() here, since
           }                                   // stop() now nullifies our preImage context,
        return true;                       // nullify only the animation thread in case
        }                                      // we want to build on our current preImage.

    /** GENERATE AND/OR START THE ANIMATION THREAD **/

    public void start()
       {if (frozen) { }                            // The animation is supposed to stay frozen.
        else                                           // Otherwise, generate and/or start the
         {if (animatorThread == null)      // animation thread. Apparently, if run
           {animatorThread = new Thread(this);}  // breaks after catching an exception,
          animatorThread.start();                          // the animatorThread though not null
          }                                                          // will still need to be restarted.
        }

    /** CREATE AND DISPLAY FRAMES OF THE ANIMATION THREAD **/

    public void run()
      {try                                                             // Start loading the images and
        {tracker.waitForAll();}                               // wait until done before starting
        catch (InterruptedException e) {}                // the animation.
        Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // Set the priority low.
        long startTime = System.currentTimeMillis();             // Remember start time.
        while (Thread.currentThread() == animatorThread)    // The animation loop.
          {frameNumber++;                                   // Advance the frame number.
            repaint();                                               // Display the frame.
            try                                                         // Sleep for the delay period.
             {startTime += delay;
              Thread.sleep(Math.max(0,
                                    startTime-System.currentTimeMillis()));
              }
            catch (InterruptedException e) {break;}  // In case the try caused
            }                                                           // something strange, exit
        }                                                               // the while loop.
 
Toggle your browser's Back and Forward buttons to compare the running applet to this code.
Click here to run a fresh copy of the applet:  AnimatorApplet6.html
 
    /** CREATE THE CURRENT FRAME OF THE ANIMATION THREAD **/
 
    public void paint(Graphics g)                  // This technique of painting by calling
     {if (!frozen) update(g);}                       // update, prevents the default (and hidden)
                                                               // behavior of update, and instead allows
    public void update(Graphics g)               // the creation of an offscreen preImage
    {Dimension d = size();                          // preImage before painting the screen.
      if (!tracker.checkAll())
       {g.clearRect(0, 0, d.width, d.height);
         g.setColor(starblue);
         g.setFont(waitfont);
         waitstr1 = "Loading images, please wait...  Depending upon your computer ";
         waitstr2 = "and/or your connection speed, this may take several minutes...";
         g.drawString(waitstr1,
              (d.width - waitfontm.stringWidth(waitstr1))/2,
        d.height/2);
        g.drawString(waitstr2,
                            (d.width - waitfontm.stringWidth(waitstr2))/2,
                            (d.height/2) + waitfontm.getHeight());
        }
      else
       {if ((preImageGraphics == null) ||                  // When all images are loaded,
            (d.width != preImageDim.width) ||            // compare the current applet
            (d.height != preImageDim.height))            // viewing size to our preImage,
         {preImageDim = d;                                     // and if different, resize our
           preImage = createImage(d.width,d.height); // next preImage.
           preImageGraphics = preImage.getGraphics();
           }
        preImageGraphics.setColor(getBackground());  // Clear the previous preImage
        preImageGraphics.fillRect(0,0,d.width,d.height); // by filling with the current
                                                                               // background.
      int rocketshipWidth = rocketshipImage.getWidth(this);   // Get rocketship image
      int rocketshipHeight = rocketshipImage.getHeight(this); // dimensions.
      int xscrollDistance = d.width + rocketshipWidth;
      int yscrollDistance = d.height + rocketshipHeight;
      int xscrollPosition = 0;
      int yscrollPosition = 0;
 
Toggle your browser's Back and Forward buttons to compare the running applet to this code.
Click here to run a fresh copy of the applet:  AnimatorApplet6.html
 
      preImageGraphics.drawImage(
           backgroundstarImage[backNumber],              // Select background image.
           0,0,d.width,d.height,Color.black,this);              // Position and size image,
                                                                              // and set background color.
      preImageGraphics.setFont(titlefont);
      preImageGraphics.setColor(starblue);
      preImageGraphics.drawString(
           "Lost in Space ?  ",
           d.width - titlefontm.stringWidth("Lost in Space ?  "),
           titlefontm.getAscent());
 
      if (backNumber == 0)                                                         // Paint on background 0.
       {yscrollPosition = (frameNumber % yscrollDistance) - rocketshipHeight;
         if (yscrollPosition >= d.height/2) xspeedUp++;                   // Go to warp speed.
         xscrollPosition =
            (frameNumber % xscrollDistance) - rocketshipWidth + xspeedUp*50;
         preImageGraphics.drawImage(
              rocketshipImage,
              xscrollPosition,
              yscrollPosition,this);
         preImageGraphics.setFont(shipfont);
              shipstr = "          Hmmm..., looks like Andromeda... Let's warp in and check it out !";
              shipstr += shipstrpad + shipstrpad;                                 // Pad shipstr with blanks.
         if (yscrollPosition > 0)
          {preImageGraphics.drawString(
                 shipstr.substring(shipstrIndex,shipstrIndex + 11),          // Compute current substring
                 xscrollPosition + 27,                                                   // of shipstr to display.
                 yscrollPosition + rocketshipWidth/2);
            if (frameNumber % 2 == 0) shipstrIndex++;                     // Slow down shipstr display.
            if (shipstrIndex + 11 == shipstr.length()) shipstrIndex = 0;  // Start over at
            }                                                                                    // end of shipstr.
         if (xscrollPosition >= d.width)                                             // Setup for next background.
          {frameNumber = -1;
            backNumber = 1;
            shipstrIndex = 0;
            xspeedUp = 0;
            }
         }
 
Toggle your browser's Back and Forward buttons to compare the running applet to this code.
Click here to run a fresh copy of the applet:  AnimatorApplet6.html
 
      else if (backNumber == 1)                                                    // Paint on background 1.
       {yscrollPosition = 3*(d.height/4) - (frameNumber % yscrollDistance);
         if (yscrollPosition <= .1*d.height) xspeedUp++;
          xscrollPosition =
             (frameNumber % xscrollDistance) - rocketshipWidth + xspeedUp*50;
         preImageGraphics.drawImage(
              rocketshipImage,
              xscrollPosition,
              yscrollPosition,this);
         preImageGraphics.setFont(shipfont);
         shipstr = "          Where am I ?? This looks like a Hydrogen-only view of the Milky Way... Bye !";
         shipstr += shipstrpad + shipstrpad;
         if (yscrollPosition < .62*d.height)
          {preImageGraphics.drawString(
                 shipstr.substring(shipstrIndex,shipstrIndex + 11),
                 xscrollPosition + 27,
                 yscrollPosition + rocketshipWidth/2);
           if (frameNumber % 2 == 0) shipstrIndex++;
           if (shipstrIndex + 11 == shipstr.length()) shipstrIndex = 0;
           }
         if (xscrollPosition >= d.width)                                                   // Setup for next background.
          {frameNumber = -1;
            backNumber = 2;
            shipstrIndex = 0;
            xspeedUp = 0;
            }
         }
 
Toggle your browser's Back and Forward buttons to compare the running applet to this code.
Click here to run a fresh copy of the applet:  AnimatorApplet6.html
 
      else if (backNumber == 2)                                                          // Paint on background 2.
       {xscrollPosition =
            (frameNumber % xscrollDistance) - rocketshipWidth + xspeedUp*50;
         yscrollPosition = d.height/2 + yspeedUp*30;
         preImageGraphics.drawImage(
              rocketshipImage,
              xscrollPosition,
              yscrollPosition,this);
         preImageGraphics.setFont(shipfont);
         shipstr = "          The Pleiades Cluster ?? With HyperDrive you never know... Uh Oh !";
         shipstr += shipstrpad + shipstrpad;
         if (xscrollPosition > 0)
          {preImageGraphics.drawString(
                 shipstr.substring(shipstrIndex,shipstrIndex + 11),
                 xscrollPosition + 27,
                 yscrollPosition + rocketshipWidth/2);
           if (frameNumber % 2 == 0) shipstrIndex++;
           if (shipstrIndex + 11 == shipstr.length()) shipstrIndex = 0;
           }
         if (xscrollPosition >= d.width/3)
          {xspeedUp++;
            yspeedUp++;
            }
         if (xscrollPosition >= d.width)                      // Setup for next background.
          {frameNumber = -1;
            backNumber = 0;
            shipstrIndex = 0;
            xspeedUp = 0;
            yspeedUp = 0;
            }
        }                                                             // Offscreen preImage completed.
      g.drawImage(preImage,0,0,this);                 // Paint preImage on the screen.
       }
     }
 
    /** STOP THE ANIMATION THREAD **/
 
    public void stop()
     {animatorThread = null;                    // The user either clicked to stop or left the page,
       preImageGraphics = null;                // so wipe out the current thread and preImage context.
       preImage = null;
       }
    }
 
Toggle your browser's Back and Forward buttons to compare the running applet to this code.
Click here to run a fresh copy of the applet:  AnimatorApplet6.html