Java Swing - GUIs
TOPIC 06 – ANIMATION

 

LESSON NOTE

 

 

ANIMATION

 

We will now learn to create simple animations.  Our applications will consist of two classes.  One that extends JFrame and one that extends JPanel. 

 

Our specialized JPanel class will take care of drawing the animation.  It will have the paint method to paint the panel and we will include an update method that updates the state of the animation and then calls repaint.

 

Our specialized JFrame class will have a Timer object that will drive the animation.  Whenever the timer triggers an event, the JPanel's update method is called.

 

EXAMPLE 1 – DIFFERENT SHAPES ANIMATION

 

This simple application simply displays different shapes every 2 seconds. 

 

In the first file, we have our specialized JFrame.  It contains a Timer object and our specialized JPanel.  Every time the timer is triggered, it calls the update method for the JPanel.

 

In the second file, we have our specialized JPanel.  It's data fields hold all the information needed for the animation.  It takes care of painting the animation based on the data fields.  Finally, it has an update method that updates all of the data fields each time it is called and then calls repaint.

 

 

public class AnimationApp extends JFrame implements ActionListener

{

     public Timer t;

     public AnimationPanel ap;

    

     public AnimationApp()

     {

          t = new Timer(2000,this); 

         

          Container cp = this.getContentPane();

          cp.setLayout(new FlowLayout());

         

          ap = new AnimationPanel();

          ap.setPreferredSize(new Dimension(400,400));

          cp.add(ap);

         

          this.setTitle("Simple Animation Application");

          this.setSize(430,430);

          this.setVisible(true);

         

          t.start();

     }

    

     public void actionPerformed(ActionEvent e)

     {

          ap.update();

     }

    

     public static void main(String[] args)

     {

          AnimationApp tc = new AnimationApp();

     }

}

public class AnimationPanel extends JPanel

{

     public int shapeNumber;

     public int totalShapes;

 

     public AnimationPanel()

     {

          shapeNumber = 0;

          totalShapes = 5;

     }

    

     public void paint(Graphics g)

     {

          super.paint(g);

 

          if (shapeNumber == 0)

          {   

             g.setColor(Color.RED);

             g.fillOval(100, 100, 200, 200);

          }

          else if (shapeNumber == 1)

          {   

             g.setColor(Color.BLUE);

             g.fillOval(100, 50, 200, 300);

          }

          else if(shapeNumber == 2)

          {

             g.setColor(Color.PINK);

             g.fillRect(100, 100, 200, 200);             

          }

          else if(shapeNumber == 3)

          {

             g.setColor(Color.GREEN);

             g.fillOval(25, 100, 350, 200);    

          }

          else if(shapeNumber == 4)

          {

             g.setColor(Color.YELLOW);

             g.fillRect(125, 100, 150, 200);             

          }

     }

    

     public void update()

     {

        updateShapeNumber();

        repaint();

     }

    

     public void updateShapeNumber()

     {

        shapeNumber++;

        if (shapeNumber >= totalShapes)

        {

          shapeNumber = 0;

        }    

     }

}

 

EXAMPLE 2 – BOUNCING BALL ANIMATION

 

In this animation, we have a ball move around and bounce off the borders of the JPanel.

 

The first file, the specialized JFrame, is essentially the same as in the previous example except that the rate of timer events is faster (once every 50 milliseconds).

 

The second file, the specialized JPanel, takes care of painting our ball.  The ball will move as the update method is called. 

 

 

public class BouncingBallApp extends JFrame implements ActionListener

{

     public Timer t;

     public AnimationPanel ap;

    

     public BouncingBallApp()

     {

          t = new Timer(50,this); 

         

          Container cp = this.getContentPane();

          cp.setLayout(new FlowLayout());

         

          ap = new AnimationPanel();

          ap.setPreferredSize(new Dimension(400,400));

          ap.setBorder(BorderFactory.createLineBorder(Color.black));

          cp.add(ap);

         

          this.setTitle("Bouncing Ball Animation");

          this.setSize(430,450);

          this.setVisible(true);

         

          t.start();

     }

    

     public void actionPerformed(ActionEvent e)

     {

       ap.update();

     }

    

     public static void main(String[] args)

     {

          BouncingBallApp tc = new BouncingBallApp();

     }

}

public class AnimationPanel extends JPanel

{

     int ballX;

     int ballY;

     int speedX;

     int speedY;

 

     public AnimationPanel()

     {

          ballX = 100;

          ballY = 150;

          speedX = (int)(Math.random() * 10 + 5);

          if(Math.random() < 0.5)  //50% chance

          {

              speedX = speedX * -1;

          }

 

          speedY = (int)(Math.random() * 10 + 5);

          if(Math.random() < 0.5) //50% chance

          {

              speedY = speedY * -1;

          }

     }

    

     public void paint(Graphics g)

     {

        super.paint(g);

        g.drawOval(ballX, ballY,25,25);

     }

    

     public void update()

     {

        updateBall();

        repaint();

     }

    

     public void updateBall()

     {

        ballX = ballX + speedX;

        ballY = ballY + speedY;

        //check to see if bounce is needed

        if(ballX > 375)  //375 is 400 - 25

        {

             ballX = 375 - (ballX - 375);

             speedX =speedX * -1;

        }

        else if (ballX < 0)

        {

             ballX = Math.abs(ballX);

             speedX = speedX * -1;

        }

        if(ballY > 375)  //375 is 400-25

        {

             ballY = 375 - (ballY - 375);

             speedY =speedY * -1;

        }

        else if (ballY < 0)

        {

             ballY = Math.abs(ballY);

             speedY =speedY * -1;

        }

    }

}

 

EXAMPLE 3 – SPRITE ANIMATION

 

In this example, we create a very simple sprite animation.  It simply uses three different images and cycles through them based on the current frame number. 

 

The JFrame file is exactly the same as in the previous examples.

 

The JPanel file keeps track of the frame count and based on that, it updates the image that has to be drawn.

 

 

public class SpriteApp extends JFrame implements ActionListener

{

     public Timer t;

     public AnimationPanel ap;

    

     public SpriteApp()

     {

          t = new Timer(50,this);

         

          Container cp = this.getContentPane();

          cp.setLayout(new FlowLayout());

         

          ap = new AnimationPanel();

          ap.setPreferredSize(new Dimension(170,170));

          cp.add(ap);

         

          this.setTitle("Angry Bird Animation");

          this.setSize(200,220);

          this.setVisible(true);

         

          t.start();

     }

    

     public void actionPerformed(ActionEvent e)

     {

         ap.update();

     }

    

     public static void main(String[] args)

     {

          SpriteApp tc = new SpriteApp();

     }

}

public class AnimationPanel extends JPanel

{

     public int frame;

     public BufferedImage img1;

     public BufferedImage img2;

     public BufferedImage img3;

     public BufferedImage currentImg;

    

     public AnimationPanel()

     {

          frame = 0;

          try

          {

              img1 = ImageIO.read(new File("angryBird01.png"));

              img2 = ImageIO.read(new File("angryBird02.png"));

              img3 = ImageIO.read(new File("angryBird03.png"));

              currentImg = img1;

          }  

          catch (IOException e)

          {

              System.out.println("Error");

              e.printStackTrace();

          }

     }

 

     public void paint(Graphics g)

     {

          super.paint(g);

          g.drawImage(currentImg,0,0,null);

     }

 

     public void update()

     {

          frame++;

          updateSprite();

          repaint();

     }

 

     //=======================

     //Sprite animation

     //Frame rate = 20 fps

     //

     //Frames 01-60   - img1 normal

     //Frames 61-70   - img2 blink

     //Frames 71-140  - img1 normal

     //Frames 141-150 - img2 blink

     //Frames 151-220 - img1 normal

     //Frames 221-280 - img3 smile

     //then restart

     //=======================

    

     public void updateSprite()

     {

       if (frame % 280 < 60)

       {

       currentImg = img1;

       }

       else if (frame % 280 < 70)

       {

       currentImg = img2;           

       }

       else if (frame % 280 < 140)

       {

       currentImg = img1;           

       }

       else if (frame % 280 < 150)

       {

       currentImg = img2;           

       }

       else if (frame % 280 < 220)

       {

       currentImg = img1;           

       }

       else if (frame % 280 < 280)

       {

       currentImg = img3;           

       }

     }

}