Home arrow Java arrow Swing Animation
JAVA

Swing Animation


Have you ever been interested in creating a game using the Swing-based animation library? This article covers some important information to help you understand the backbone of this library. It is excerpted from the book Advanced Java Game Programming, written by David Wallace Croft (Apress, 2004; ISBN 1590591232).

Author Info:
By: Apress Publishing
Rating: 5 stars5 stars5 stars5 stars5 stars / 19
March 29, 2005
TABLE OF CONTENTS:
  1. · Swing Animation
  2. · RepaintCollector
  3. · SimpleRepaintCollector
  4. · CoalescingRepaintCollector
  5. · LoopGovernor
  6. · WindowedLoopGovernor
  7. · AnimatedComponent
  8. · Static method check()

print this article
SEARCH DEVARTICLES

Swing Animation
(Page 1 of 8 )

Do not squander time, for that is the stuff life is made of. —Benjamin Franklin

In this chapter, we examine in detail three interfaces and one class that form the backbone of the reusable Swing-based animation library. Additionally covered are one or more implementations of each interface. Understanding how these core classes operate is key to understanding the implementation trade-offs. It is also useful to understand how these classes work when it comes to creating and integrating your own animation classes to create a unique game.

  • ComponentAnimator

  • RepaintCollector

  • LoopGovernor

  • AnimatedComponent

These classes work together to generate successive frames in an animation loop with three major phases. In the first phase, the update phase, the Component-Animator updates the sprite positions and generates the repaint requests. These repaint requests are gathered and consolidated by the RepaintCollector. During the second phase, the paint phase, the RepaintCollector is queried for those regions of the component surface that need to be repainted. The Component-Animator then paints them. In the third phase, the delay phase, the LoopGovernor is used to delay the thread that is running the animation loop just long enough for it to slow down to the desired frame rate. The AnimatedComponent is the Swing component that brings it all together by providing the surface on which the painting occurs, the animation loop that calls the other classes, and the lifecycle methods that allow the animation to be integrated into a framework.

ComponentAnimator

Our first core animation class is ComponentAnimator. Implementations of interface ComponentAnimator are responsible for updating the sprite positions, identifying which areas of the component need to be repainted as a result, and then painting those regions on the surface of the component. An implementation of ComponentAnimator contains your game-specific code.

  package com.croftsoft.core.animation;
 public interface ComponentAnimator
 extends ComponentUpdater, ComponentPainter

ComponentAnimator is an interface that extends two other interfaces, ComponentUpdater and ComponentPainter. It defines no additional methods.

 public void update ( JComponent component );

Interface ComponentUpdater defines a single method, update(JComponent), which is used to update the positions of the sprites and request repaints of the component where necessary. update(JComponent) makes the repaint requests by calling the JComponent repaint methods, including those repaint methods inherited from the JComponent superclass Component. Note that the special JComponent subclass AnimatedComponent overrides its repaint() methods to improve animation performance. A ComponentUpdater can be used with any JComponent subclass, not just AnimatedComponent.

 public void paint (
 JComponent component,
 Graphics2D graphics );

The ComponentPainter interface defines an object that knows how and where to paint a graphical JComponent. Contrast the paint() method signature shown above with the paintIcon() method signature defined in the Swing interface Icon as shown below.

 public void paintIcon (
    Component c,
    Graphics g,
    int x,
    int y );

The comparison shows that a Swing Icon knows how to paint a component but not where. The “where” must be provided as x and y coordinates. A Component-Painter, however, is assumed to already know where to paint the component and will usually encapsulate these coordinates, if needed, as internal state.

A couple of other minor differences are that the ComponentPainter interface uses JComponent instead of the superclass Component, and Graphics2D instead of the superclass Graphics in its method arguments. This means that ComponentPainter implementations do not need to cast a Graphics reference to a Graphics2D reference to get at the extended functionality of a Graphics2D object.

Update and Paint Phases

A ComponentAnimator is usually accessed in two phases by the animation loop. First, its update() method is called to update the sprite positions and make repaint requests in the update phase. Second, its paint() method is called to paint the component with the sprites in their new positions in the paint phase.

These two operations are separated for two reasons. The first reason is to make it easy to repaint the component without having to update the sprite positions. This is often necessary, for example, when the animation is paused, but a repaint is needed because the component has been briefly covered and then uncovered by another window. The second reason is that it makes more sense to perform all of the sprite position updates and repaint requests at once before the paint event. This is because the sprites are moving simultaneously and you do not want to paint part of a sprite in its old position while painting another overlapping sprite in its new position. It also makes it easier to collect and then coalesce repaint requests, possibly merging them into a single request, before any paint operations.

Sprite Defined

Keep in mind that usually when I use the term sprite, I am using a very loose definition in which a sprite can be anything that can update some state, paint a component, or both when called upon to do so. In this book, I am usually referring to an implementation of a ComponentUpdater, ComponentPainter, or ComponentAnimator interface when I use that term without being specific as to which it is.

This differs from the traditional definition of sprite, or in some books actor, which seems to be an object that can both update state and paint a component like a ComponentAnimator, but with some additional qualifications. First, the term sprite usually refers to an iconic actor on the scene such as a character, as opposed to the background or a decoration. Under this definition, a spaceship object would qualify but an object that depicts a sliding field of stars in the background might not. Second, it usually defines some properties related to the physics of movement and methods for handling movement. In a later chapter, I introduce a subinterface of ComponentAnimator named Sprite that defines properties for spatial coordinates, velocity, and heading, and provides methods to determine if the object collided with another object in virtual space.

In this chapter, however, I do not get that specific. A sprite could be a background color for the component, a non-moving object in the scene, an overlying fog, text that displays the current score, or a swarm of bad guys treated as a single composite object. It could be just about anything that can be called from the animation loop to update state or paint the component.

ExampleAnimator

 package com.croftsoft.ajgp.anim;
 import java.awt.Graphics2D;
 import javax.swing.JComponent;
 import com.croftsoft.core.animation.ComponentAnimator;
 import com.croftsoft.core.lang.NullArgumentException;
public final class ExampleAnimator
   implementsComponentAnimator

////////////////////////////////////////////////////
////////////////////////////////////////////////////

 {
 private final String text;
 private final int     deltaX;
 private final int     deltaY;
 //
 private int x;
 private int y;

////////////////////////////////////////////////////
////////////////////////////////////////////////////

 public   ExampleAnimator (
    String   text,
    int       deltaX,
    int       deltaY )

//////////////////////////////////////////////////

{
 NullArgumentException.check ( this.text = text );
 this.deltaX = deltaX;
 this.deltaY = deltaY;
}

////////////////////////////////////////////////////
////////////////////////////////////////////////////

 public void update ( JComponent  component )

///////////////////////////////////////////////////

{
  x += deltaX;
  y += deltaY;
  int componentWidth = component.getWidth ( );
  int componentHeight = component.getHeight ( );
  if ( x > componentWidth )
  {
    x = 0;
  }
  else if ( x < 0 )
  {
   x = componentWidth;
  }
  if ( y > componentHeight )
  {
   y = 0; }
  else if ( y < 0 )
 {
   y = componentHeight;
 }
 component.repaint ( );
 }
public void paint (
  JComponent component,
  Graphics2D Graphics)

////////////////////////////////////////////////
{
  graphics.setColor ( component.getForeground ( ) );
  graphics.drawString ( text, x, y );
}

ExampleAnimator from package com.croftsoft.ajgp.anim is a simple Component-Animator implementation that slides text across a component. In the update() method, the x and y coordinates are shifted by deltaX and deltaY respectively with each new frame of the animation. If the text slides off the edge of the component, it is wrapped around to the other side. The final act of the update() method is to request a repaint of the entire component to show the updated position. When the repaint request is processed later, the paint() method simply paints the text at that position.

This article is excerpted from Advanced Java Game Programming by David Wallace Croft (Apress, 2004; ISBN 1590591232). Check it out at your favorite bookstore today. Buy this book now.


blog comments powered by Disqus
JAVA ARTICLES

- Java Too Insecure, Says Microsoft Researcher
- Google Beats Oracle in Java Ruling
- Deploying Multiple Java Applets as One
- Deploying Java Applets
- Understanding Deployment Frameworks
- Database Programming in Java Using JDBC
- Extension Interfaces and SAX
- Entities, Handlers and SAX
- Advanced SAX
- Conversions and Java Print Streams
- Formatters and Java Print Streams
- Java Print Streams
- Wildcards, Arrays, and Generics in Java
- Wildcards and Generic Methods in Java
- Finishing the Project: Java Web Development ...

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials