/** AnimatorApplet7 by John Pais, September 1998. **/


/** USE EXISTING JAVA CLASSES **/

import java.awt.*;
import java.applet.Applet;

/** EXTEND THE JAVA APPLET CLASS AND IMPLEMENT THE RUNNABLE INTERFACE **/

public class AnimatorApplet7 extends Applet implements Runnable
   {int frameNumber = -1;   
    int fps = 10;             
    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 backgroundWFMImage[];
    Image WorldForestMap;
    Image WorldForestMapLegend;          // Not currently being used.
    Image rocketshipImage;
    MediaTracker tracker;
    int WFMPositionIndex = -1;
    int xbackgroundscrollPosition = 0;
    int ybackgroundscrollPosition = 0;    
    int rval, gval, bval;           
    int backNumber = 0;
    int xscrollPosition = 0;
    int yscrollPosition = 0;
    int savexscrollPosition = 0;
    int saveyscrollPosition = 0;   	
    int shipstrIndex = 0;
    int xspeedUp = 0;
    int yspeedUp = 0;

    /** INITIALIZE THE APPLET **/

    public void init()
       {//setBackground(Color.cyan);
	setBackground(new Color(56,176,222));
	String str;
        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.
	
	backgroundWFMImage = new Image[2];
        tracker = new MediaTracker(this);    // Spawn the tracker background thread(s)
	
	WorldForestMap = getImage(getCodeBase(),"images/wfm.gif");
	tracker.addImage(WorldForestMap,0);
	WorldForestMapLegend = getImage(getCodeBase(),"images/wfmleg.gif");
	tracker.addImage(WorldForestMapLegend,0);
	rocketshipImage = getImage(getCodeBase(),"images/rocketship.gif");
	tracker.addImage(rocketshipImage,0);
	
	backgroundWFMImage[0] = WorldForestMap;
	tracker.addImage(backgroundWFMImage[0],0);
	backgroundWFMImage[1] = WorldForestMapLegend;
	tracker.addImage(backgroundWFMImage[1],0);
	}  

    /** 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.
	int delayLong = (fps > 0) ? (10000/fps): 1000;   // Convert fps to milisecond 
	int delayShort = (fps > 0) ? (1000/fps): 100;    // delay time between frames. 
        while (Thread.currentThread() == animatorThread)         // The animation loop.
           {frameNumber++;                               // Advance the frame number.
            repaint();                                   // Display the frame.
	    if (frameNumber > 0)                         // Start with a longer delay
	     {delay = delayShort;}                       // time for Frame 0, in order 
	    else                                         // to avoid timing problems
	     {delay = delayLong;}                        // when the thread starts up.  
            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.


    /** 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())                       // If the images aren't all
       {g.clearRect(0, 0, d.width, d.height);        // loaded, then clear the 
	g.setColor(new Color(0,0,156));
	g.setFont(waitfont);  
	waitstr1 = "Loading images, please wait... ";
	/*
	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 WorldForestMapWidth = backgroundWFMImage[0].getWidth(this);   // Get rocketship image 
	int WorldForestMapHeight = backgroundWFMImage[0].getHeight(this); // dimensions.    
	int xbackgroundscrollDistance = WorldForestMapWidth - d.width;
	int ybackgroundscrollDistance = WorldForestMapHeight - d.height - 20;                         

	if ((-xbackgroundscrollDistance < xbackgroundscrollPosition) && 
	    (xbackgroundscrollPosition <= 0) &&
	    (ybackgroundscrollPosition == 0))
	 {WFMPositionIndex++;                                               // Using WFMPositionIndex
	  xbackgroundscrollPosition = -WFMPositionIndex;                    // gets things started
	  }                                                                 // smoothly at [0,0].
	else if ((-xbackgroundscrollDistance == xbackgroundscrollPosition) &&    
		 (-ybackgroundscrollDistance < ybackgroundscrollPosition) && 
		 (ybackgroundscrollPosition <= 0))
	  {ybackgroundscrollPosition--;}  
	else if ((-xbackgroundscrollDistance <= xbackgroundscrollPosition) &&    
		 (xbackgroundscrollPosition < 0) &&
		 (-ybackgroundscrollDistance == ybackgroundscrollPosition)) 
	  {xbackgroundscrollPosition++;}
	else if ((0 == xbackgroundscrollPosition) &&
		 (-ybackgroundscrollDistance <= ybackgroundscrollPosition) &&
		 (ybackgroundscrollPosition < 0)) 
	 {ybackgroundscrollPosition++;
	  if (0 == ybackgroundscrollPosition)
	   WFMPositionIndex = -1; 
	  }  	 
	
	preImageGraphics.drawImage(                          
	   backgroundWFMImage[backNumber],               // Select background image. 
	   xbackgroundscrollPosition,ybackgroundscrollPosition,    
	   WorldForestMapWidth,WorldForestMapHeight, // Position and size image,
	   Color.black,this);                            // and set background color.
	   
	/*
	String xstr = " " + xbackgroundscrollPosition + " " + xbackgroundscrollDistance + " ";
	String ystr = " " + ybackgroundscrollPosition + " " + ybackgroundscrollDistance + " ";			 				 
	titlestr = " "+WFMPositionIndex+" "+frameNumber+" "+xstr+ystr;		
	*/
	 
	rval =(int) Math.floor(Math.random()*127);      // Generate a random color
	gval =(int) Math.floor(Math.random()*256);      // red, green, blue mix.
	bval =(int) Math.floor(Math.random()*256);      // Note the "casting" here.
				       
	titlestr = "WELCOME TO THE ISO NEWS APPLET!";																		 										 						 
	preImageGraphics.setFont(titlefont); 
	if (frameNumber % 10 < 4)
	 {preImageGraphics.setColor(new Color(0,156,156));}
	else
	 {preImageGraphics.setColor(new Color(0,0,156));} 
	preImageGraphics.drawString(
	   titlestr,
	   (d.width - titlefontm.stringWidth(titlestr))/2,
	   titlefontm.getAscent());	
	   
	int rocketshipWidth = rocketshipImage.getWidth(this);   // Get rocketship image 
	int rocketshipHeight = rocketshipImage.getHeight(this); // dimensions.    
	int xscrollDistance = d.width + rocketshipWidth;                         
	int yscrollDistance = d.height + rocketshipHeight;  
	
	preImageGraphics.setColor(new Color(0,0,156));  
	
	if (backNumber == 0)                                   // Paint on background 0.
	  {if (yscrollPosition < d.height/2)
	    {xscrollPosition = (frameNumber % xscrollDistance) - rocketshipWidth;
	     yscrollPosition = (frameNumber % yscrollDistance) - rocketshipHeight;
	     savexscrollPosition = xscrollPosition;
	     //saveyscrollPosition = yscrollPosition;
	     }
	   else if (yscrollPosition >= d.height/2)
	    {xscrollPosition = savexscrollPosition;
	     yscrollPosition = d.height/2;
	     if (shipstrIndex == 0)
	      {xspeedUp++;
	       xscrollPosition = (frameNumber % xscrollDistance) - rocketshipWidth + xspeedUp*50;}
	     }
	      //(frameNumber % xscrollDistance) - rocketshipWidth + xspeedUp*50;
	      
	   preImageGraphics.drawImage(
	      rocketshipImage,
	      xscrollPosition,
	      yscrollPosition,this);	
	   preImageGraphics.setFont(shipfont);
	   String shipstr1 = "          Please drop in below at StLCOP on Friday, October 2, and";
	   String shipstr2 = " join us for International Night! Social Hour will begin at 5:00 PM ";
	   String shipstr3 = " with music and appetizers from various countries. At 6:00 PM there will";
	   String shipstr4 = " be a fashion show and dancing from around the world, hosted by Mousa";
	   String shipstr5 = " Dahdal and Azzah Jeddy. Dinner will be served at 7:30 PM, featuring a";
	   String shipstr6 = " menu of international delights.... This exciting program is brought";
	   String shipstr7 = " to you by the International Student Organization of the St. Louis";
	   String shipstr8 = " College of Pharmacy. Hope to see you there.... Bye!              ";
	   shipstr = shipstr1+shipstr2+shipstr3+shipstr4+shipstr5+shipstr6+shipstr7+shipstr8;
	   
	   //shipstr += shipstrpad + shipstrpad;                  // Pad shipstr with blanks.
	   if ((yscrollPosition > 0) && (xspeedUp == 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 = 0; 
	     //backNumber = 1;
	     xscrollPosition = 0;
	     yscrollPosition = 0;
	     shipstrIndex = 0;
	     xspeedUp = 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;
       }	
    }