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;
}
}
}
|
|