import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


/**
 *  This program opens a window on the screen that shows a simple
 *  animation.  The animation repeats approximately every 10 seconds.
 *  The animation continues to play until the window is closed.
 *
 *  The animation is driven by a "Timer" that "ticks" every 50 milliseconds
 *  (that is, 20 times per second).  Each time the timer ticks, the variable
 *  named tickCount is increased by one, and the window is repainted.
 *  The tickCount variable can be used in the paintComponent() method that 
 *  draws the content of the window.  By basing the picture that is drawn
 *  on the value of tick count, the paintComponent() can draw a series of
 *  different images.  These images are the "frames" in the animation.
 *  As long as the changes from one frame to the next are not too large,
 *  the user will see a reasonably smooth animation.
 */
public class FirstAnimation extends JPanel implements ActionListener {

   int tickCount;  // This variable counts the number of times that the timer has
                   // ticked.  It can be used in the paintComponent() method.
   
   
   /**
    *  The main routine creates the window and shows it on the screen.  It also
    *  sets up the timer that will drive the animation.
    */
   public static void main(String[] args) {
      JFrame window = new JFrame("First Animation");
      FirstAnimation canvas = new FirstAnimation();
      canvas.setPreferredSize(new Dimension(800,600)); // Sets size of the display area.
      window.setContentPane(canvas);
      window.pack();
      window.setLocation(200,100);
      window.setResizable(false);
      window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      window.setVisible(true);
      Timer timer = new Timer(50, canvas);  // Create the timer that will drive the animation.
                                            //   (The "50" is the number of milliseconds between ticks.)
      timer.setInitialDelay(1000);          // The animation pause for one second before starting.
      timer.start();                        // Starts the timer running.
   }
   
   
   /**
    *  This method is called by the system when the timer "ticks"; 
    *  it adds one to tickCount and repaints the display.
    */
   public void actionPerformed(ActionEvent evt) {
      tickCount++;
      repaint();
   }
   
   
   /**
    *  This is the method that draws the display.  It will be called over and
    *  over as long as the window is open, and the value of tickCount will
    *  change.  This method can use the value of tickCount to decide what
    *  to draw.   This sample animation draws the same 200 frames over and
    *  over.  The current frame number is computed as  tickCount % 200,
    *  a number between 0 and 199, and all the drawing is based on frameNumber,
    *  rather than tickCount.
    */
   protected void paintComponent(Graphics g) {
   
       // Fill the entire drawing area with a white background.
       
       g.setColor(Color.WHITE);
       g.fillRect(0,0,800,600);
   
       // Set up the basic data on which the calculation of the frame is based.
       // The total number of frames in the animatino is 200.

       int frameNumber;     // The number of the current frame, equal to tickCount % 200. 
       double fractionDone; // The fraction of the animation that has been played so far.
       frameNumber = tickCount % 200;
       fractionDone = ((double)frameNumber) / 200;
       
       // Show the tickCount and frameNumber (not really part of the animation).
       
       g.setColor(Color.BLACK);
       g.drawString("Tick count " + tickCount, 5, 15);
       g.drawString("Frame number " + frameNumber, 5, 30);

       // A red square moves across the bottom of the window.  Its x-position is
       // computed from the frameNumber, to make it move from left to right.
       
       int redSquareX;     // X-coordinate of upper-left corner of the square.
       redSquareX = (int)(100 + 550*fractionDone);
       g.setColor(Color.RED);
       g.fillRect(redSquareX,500,50,50);

       // A green square moves across the top of the window AND BACK.  In the
       // first half of the animation, it moves from left-to-right.  In the second
       // half it moves from right-to-left, returning to its starting point.
       // Here, I compute a different "fractionDone" for each half of the animation.

       int greenSquareX;
       if (frameNumber < 100) {  // We are in the firt half of the animation.
          double fractionHalf;  // Fraction of first part of animation that is done.
          fractionHalf = (double)frameNumber / 100;
          greenSquareX = (int)(100 + 550*fractionHalf);
       }
       else { // We are in the second part of the animation.
          double fractionHalf;  // Fraction of second part of animation that is done.
                                // (Note:  1 - fractionHalf is the fraction REMAINING.)
          fractionHalf = (double)(frameNumber - 100) / 100;
          greenSquareX = (int)(100 + 550*((1-fractionHalf)));
       }
       g.setColor(Color.GREEN);
       g.fillRect(greenSquareX,50,50,50);
       
       // Draw a figure that rotates about the center point (400,300).
       // The point (circleCenterX, circleCenterY) moves along a circle of radius
       // 200 around this point.  A blue circle, radius 100, is drawn with this
       // moving point as its center.  Also, a blue line is drawn from (400,300)
       // to the center of the blue circle.
       
       double angle;      // Rotation angle, ranges from 0 to 2*PI as the animation runs.
       int circleCenterX; // X-coordinate of the center point of the blue circle.
       int circleCenterY; // Y-coordinate of the center point of the blue circle.
       angle = 2*Math.PI * fractionDone;
       circleCenterX = (int)(400 + 200*Math.cos(angle));
       circleCenterY = (int)(300 + 200*Math.sin(angle));
       g.setColor(Color.BLUE);
       g.drawLine(400,300,circleCenterX,circleCenterY);
       g.fillOval(circleCenterX-50,circleCenterY-50,100,100);
       
       // Finally, draw a big, translucent yellow rectangle over the center of the
       // display.  This rectangle starts out invisible (opaqueness = 0) and becomes
       // more and more opaque as the animation procedes.
       
       int opaqueness = (int)(250*fractionDone);
       g.setColor(new Color(255,255,0,(int)(250*fractionDone))); // translucent yellow
       g.fillRect(200,200,400,200);
   }
   
}
