December 19, 2014
Hot Topics:

Using the Full-Screen Exclusive Mode API in Java

  • May 30, 2006
  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

Java Programming Notes # 1496


Preface

Oh for the good old days

Do you have a secret longing for the "good old days" when you could write a program that would take over the entire screen and wouldn't be bothered by a lot of pesky other programs competing for screen space.  If so, those days are back.  In this lesson, I will show you how to use the Full-Screen Exclusive Mode API to write programs that take over the entire screen, as shown by the output from the animation program in Figure 3.

Once your program has entered the Full-Screen Exclusive Mode, I will show you how to use active rendering as opposed to passive rendering to eliminate the overhead associated with passive rendering.

Viewing tip

You may find it useful to open another copy of this lesson in a separate browser window.  That will make it easier for you to scroll back and forth among the different listings and figures while you are reading about them.

Supplementary material

I recommend that you also study the other lessons in my extensive collection of online Java tutorials.  You will find those lessons published at Gamelan.com.  However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there.  You will find a consolidated index at www.DickBaldwin.com.

I also recommend that you pay particular attention to the lessons listed in the References section of this document.

General Background Information

Display many programs concurrently

Recent history would indicate that in most cases, it is probably best to have a multitude of programs running concurrently and sharing screen space, as indicated by the typical screen shot of my computer in Figure 1.

Dedicate display capacity to a single program

However, sometimes it might be best to dedicate the computational and display capacity of your computer screen to a single program as shown in Figure 3.  Dedicating the display capacity to a single program can be achieved by writing the program so that uses the Full-Screen Exclusive Mode API.

Active versus passive rendering

In addition to providing dedicated display space, the use of Full-Screen Exclusive Mode makes it possible to employ active rendering as opposed to passive rendering of the material on the screen.  This eliminates some of the rendering overhead, and should make the system more responsive when running simulation, game, and animation programs where a responsive screen display is important.

Preview

A screen shot (showing the entire screen) of my computer screen during a typical working session is shown in Figure 1.


Figure 1

As you can see, there were several different applications competing for space on my screen when I captured the screen shot.

A sense of scale

I'm sure that you have no interest in what my computer screen happened to look like while I was writing this lesson.  Figure 1 is provided to give you a sense of scale (The purpose is similar to that of photographing a small object with a coin laying beside it so that the size of the object will be apparent.)  Because of the narrow publication format for this lesson, it was not possible for me to show screen shots in their full size.  Therefore, the size of the image in Figure 1 was reduced from 1024x768 pixels to 470x353 pixels for publication purposes.

The output from the program named FullScreen01

Figure 2 shows a screen shot of my computer screen while running the program named FullScreen01(Once again, Figure 2 shows my entire screen.)


Figure 2

A JFrame object in Full-Screen Exclusive Mode

As was the case in Figure 1, the screen-shot image in Figure 2 was also reduced to 470x353 pixels for inclusion in this lesson.  Briefly, Figure 2 shows a JFrame object displayed by a program using the Full-Screen Exclusive Mode API.

(In the remainder of this lesson, I will often refer to the Full-Screen Exclusive Mode simply as the full-screen mode.)

One button and four labels

For illustration purposes, the JFrame object shown in Figure 2 has a JButton object placed in the NORTH location, and has JLabel objects with colored backgrounds placed in the other four locations managed by the BorderLayout manager.

I will present and explain the code for the program named Layout01 later in this lesson.

A more substantive program

I will also present and explain a much more substantive program named FullScreen02 in this lesson.  A screen shot (showing the entire screen) of the output from the program named FullScreen02 is shown in Figure 3.


Figure 3

Figure 3 shows the result of running an animation program in full-screen mode. 

Based on an earlier animation lesson

The animation program named FullScreen02 is largely based on an animation program that I presented and explained in an earlier lesson entitled Fun with Java: Animated Sea Worms.  However, the version of the program that I will present and explain this lesson makes use of full-screen mode, and also includes some other modernization features relative to the earlier version.

Begin with FullScreen01

I will begin by explaining the program named FullScreen01.  The purpose of this program is to teach you how to implement full-screen mode while avoiding the additional complexity of a substantive application.

Then I will explain the more substantive program named FullScreen02, to teach you how to make productive use of full-screen mode once you know how to implement it.

Discussion and Sample Code

The Program Named FullScreen01

FullScreen01 is a skeleton program that implements the Full-Screen Exclusive Mode API.

An undecorated non-resizable JFrame object

The program places an undecorated non-resizable JFrame object on the screen in the Full-Screen Exclusive Mode.  The JFrame object is managed by a BorderLayout manager.  A JButton object appears in the NORTH location of the JFrame as shown in Figure 2.  Clicking the button causes the program to exit the full-screen mode, restore the original graphics mode, and terminate.

The program places red, green, and white JLabel objects in the EAST, WEST, SOUTH, and CENTER locations of the JFrame object, as shown in Figure 2.  This is done to demonstrate that the graphics object that occupies the entire screen is an undecorated non-resizable JFrame object.

A list of screen devices

The program displays a list of the available screen devices solely for information purposes in the command-line window.  (There is only one available screen device on my laptop computer, but there may be more than one on your computer.)  However, the command line window is hidden behind the full-screen version of the JFrame object and isn't visible until the full-screen mode is terminated.

Use only the first screen device in the list

Even though the program displays a list of all of the available screen devices, it operates only on the first screen device in the list.

Program testing

The program was tested using J2SE5.0 under WinXP.  J2SE 1.4 or later is required to support the setFullScreenWindow method of the GraphicsDevice object.

Will discuss in fragments

As is my custom, I will discuss the program in fragments.  You can view a complete listing of the program in Listing 26 near the end of the lesson.

The class definition begins in Listing 1.

public class FullScreen01 extends JFrame 
                                 implements ActionListener{

  private GraphicsDevice graphicsDevice;
  private DisplayMode origDisplayMode;
  private JButton exitButton = new JButton(
                                  "Exit Full-Screen Mode");

Listing 1

A container and an action listener

The class extends JFrame and implements ActionListener.  Thus an object of the class is a top-level container that can be placed directly on the computer screen as a GUI.  An object of the class is also suitable for being registered as an action listener on objects that fire action events.

The code in Listing 1 declares a couple of instance variables that will be used later.  It also declares, instantiates, and initializes a reference to the JButton object shown at the top of Figure 2.

The main method

The main method begins in Listing 2.

  public static void main(String[] args){

    GraphicsEnvironment graphicsEnvironment = 
         GraphicsEnvironment.getLocalGraphicsEnvironment();

    GraphicsDevice[] devices = 
                    graphicsEnvironment.getScreenDevices();

    for(int cnt = 0;cnt < 1;cnt++){
      System.out.println(devices[cnt]);
    }//end for loop

Listing 2

List all available screen devices

The main method begins by getting and displaying a list of all the available screen devices on the computer.  As you can see in Listing 2, getting the list of screen devices is a two-step process:

  1. Get a GraphicsEnvironment object that describes your computer.
  2. Invoke the getScreenDevices method on that object to get a list of available screen devices, each as a reference to an object of type GraphicsDevice.

The GraphicsEnvironment class and GraphicsDevice objects

Here is part of what Sun has to say about the GraphicsEnvironment class and GraphicsDevice objects:

"The GraphicsEnvironment class describes the collection of GraphicsDevice objects and Font objects available to a Java(tm) application on a particular platform. The resources in this GraphicsEnvironment might be local or on a remote machine. GraphicsDevice objects can be screens, printers or image buffers and are the destination of Graphics2D drawing methods. Each GraphicsDevice has a number of GraphicsConfiguration objects associated with it. These objects specify the different configurations in which the GraphicsDevice can be used."

This seems straightforward enough, and shouldn't require further explanation.

The getScreenDevices method

As you have probably also guessed, the Sun documentation for the getScreenDevices method of the GraphicsEnvironment class states that the method "Returns an array of all of the screen GraphicsDevice objects."  (The class provides several other interesting instance methods that you might want to investigate as well.)

Display the list of screen devices

After getting the list of available screen devices, the code in Listing 2 uses a for loop to display the items in the list in the command-line window.  On my laptop computer, the single-item list of screen devices reads as follows:

Win32GraphicsDevice[screen=0]

The remainder of the main method is shown in Listing 3.

    new FullScreen01(devices[0]);
  }//end main

Listing 3

The constructor for FullScreen01

The statement in Listing 3 instantiates an object of the FullScreen01 class, causing the constructor for the class, which begins in Listing 4, to be executed.

  public FullScreen01(GraphicsDevice graphicsDevice){

    this.graphicsDevice = graphicsDevice;

Listing 4

Note that the code in Listing 3 passes the first reference in the list of screen devices to the constructor that begins in Listing 4.  The code in Listing 4 saves this reference in one if the instance variables that was declared in Listing 1.  This reference will be used later when time comes to exit the full-screen mode.

The JFrame title

The code in Listing 5 sets the title property on the JFrame object.

    setTitle("This title will be hidden (undecorated)");


Listing 5

I included this code to remind me to mention that when the JFrame object is displayed as an undecorated object the title doesn't show.  (The JFrame object will be displayed as an undecorated JFrame in this lesson.)

Save the original display mode

Listing 6 gets and saves a reference to the original display mode in one of the instance variables declared in Listing 1.

    origDisplayMode = graphicsDevice.getDisplayMode();

Listing 6

This reference will be used later by the program to restore the original display mode before terminating.

The JButton object

Listing 7 registers this FullScreen01 object as an ActionListener on the JButton object that was instantiated in Listing 1.

    exitButton.addActionListener(this);
    
    getContentPane().add(exitButton, BorderLayout.NORTH);

Listing 7

I will discuss the behavior of the ActionListener object a little later in conjunction with the discussion of the actionPerformed method.

Then Listing 7 places the JButton object at the top of the JFrame object as shown in Figure 2.

Add some colored JLabel objects

Listing 8 places four colored (red, green, and white) JLabel objects in the remaining BorderLayout positions in the JFrame object to demonstrate that the screen is filled with an undecorated JFrame object as shown in Figure 2.

    //Place four labels in the JFrame solely for the
    // purpose of showing that it is a full-screen
    // undecorated JFrame.
    JLabel eastLabel = new JLabel("     East     ");
    eastLabel.setOpaque(true);
    eastLabel.setBackground(Color.RED);
    getContentPane().add(eastLabel,BorderLayout.EAST);
    
    JLabel southLabel = 
                 new JLabel("South",SwingConstants.CENTER);
    southLabel.setOpaque(true);
    southLabel.setBackground(Color.GREEN);
    getContentPane().add(southLabel,BorderLayout.SOUTH);
    
    JLabel westLabel = new JLabel("     West     ");
    westLabel.setOpaque(true);
    westLabel.setBackground(Color.RED);
    getContentPane().add(westLabel,BorderLayout.WEST);
    
    JLabel centerLabel = 
                new JLabel("Center",SwingConstants.CENTER);
    centerLabel.setOpaque(true);
    centerLabel.setBackground(Color.WHITE);
    getContentPane().add(centerLabel,BorderLayout.CENTER);

Listing 8

Switch to Full-Screen Exclusive Mode

Listing 9 invokes the isFullScreenSupported method to confirm that the device is capable of operating in Full-Screen Exclusive Mode, and if so, invokes the setFullScreenWindow method to switch the display to the Full-Screen Exclusive Mode.

    if (graphicsDevice.isFullScreenSupported()){
      // Enter full-screen mode with an undecorated,
      // non-resizable JFrame object.
      setUndecorated(true);
      setResizable(false);
      //Make it happen!
      graphicsDevice.setFullScreenWindow(this);
      validate();
    }else{
      System.out.println("Full-screen mode not supported");
    }//end else    

  }//end constructor

Listing 9

The isFullScreenSupported method

As you probably guessed from the syntax, the isFullScreenSupported method returns true if the GraphicsDevice object supports Full-Screen Exclusive Mode, and returns false otherwise.

The setFullScreenWindow method

Invoking the setFullScreenWindow method has a number of interesting ramifications in addition to switching the screen to Full-Screen Exclusive Mode.  I recommend that you go to the Sun documentation and read about those ramifications prior to using this mode in production programs.

An undecorated non-resizable JFrame object

Although it isn't a requirement to do so, Listing 9 sets the undecorated property of the JFrame object to true and the resizable property to false.

Setting the undecorated property to true eliminates the title bar at the top and the borders on the sides of the JFrame object as shown in Figure 2.  Although not required, this probably should be done, particularly if active rendering is to be used.  Otherwise, the JFrame object can be moved or iconified by the user to expose other windows behind it in the Z-order.

(Having eliminated the title bar and the borders, I suppose that setting the resizable property to false may be superfluous, because there is nothing to grab hold of with the mouse to change the size.  I don't know if it is possible to change the size of a JFrame object without the use of a mouse by using keystrokes alone.  If so, this is not superfluous and the resizable property should be set to false.)

The full-screen object should appear

Listing 9 signals the end of the constructor.  Once the constructor has executed, the JFrame object should fill the screen as shown in Figure 2

Figure 2 shows the results on my laptop computer with a screen size of 1024x768 pixels.  Your results may be somewhat different depending on your overall screen size in pixels, and the sizes of your fonts.  The font size determines the height of the JButton object at the top and the JLabel object at the bottom, as well as the widths of the two JLabel objects on the sides.

The ActionEvent handler

That leaves us with one more item to discuss for this program.  Listing 10 shows the actionPerformed method, which is invoked when the button at the top of Figure 2 is clicked.

  public void actionPerformed(ActionEvent evt){
    //Restore the original display mode
    graphicsDevice.setDisplayMode(origDisplayMode);
    //Terminate the program
    System.exit(0);
  }//end actionPerformed
}//end class

Listing 10

The setDisplayMode method

Listing 10 invokes the setDisplayMode method of the GraphicsDevice class, passing a reference to the DisplayMode object saved earlier in order to restore the display mode to the original display mode.  Then Listing 10 terminates the program.

Sun has this to say about the setDisplayMode method:

"Sets the display mode of this graphics device. This may only be allowed in full-screen, exclusive mode."

Sun has this to say about the DisplayMode class:

"The DisplayMode class encapsulates the bit depth, height, width, and refresh rate of a GraphicsDevice. Display modes are hardware-dependent and may not always be available."

May be superfluous

Setting the display mode in this manner at this point may be superfluous.  For this program on my computer, it doesn't seem to make any difference relative to the appearance of the display after the program terminates whether or not I invoke this method prior to termination.

The end of the program

Listing 10 signals the end of the class and the end of the program.

You should be able to use this skeleton to write programs that use the Full-Screen Exclusive Mode API.  As you will see in the next program named FullScreen02, this skeleton can be wrapped around a much more substantive application to control the display mode used by that application.

Shrink the Exit button

If you use the full-screen mode with an undecorated Frame or JFrame object, you should always provide an Exit button to terminate.  (The buttons that are typically in the upper-right corner of the frame will be unavailable.)  However, the Exit button needn't be as large as the one shown in Figure 2.  Rather, you should be able to use a different layout manager and place a small Exit button unobtrusively in one of the corners of the screen.

The Program Named FullScreen02

The purpose of this program is to demonstrate the use of the Full-Screen Exclusive Mode API for simulation and animation.

Update to an earlier program

This program animates colored sea worms on a background image in Full-Screen Exclusive Mode.  A screen shot of the program in operation is shown in Figure 3.  The program is an update to the program named Animate03, which I explained in the earlier lesson entitled Fun with Java: Animated Sea Worms.

This version of the animation code has been modernized to make use of the Swing Timer class as an animation timer, and also to use Active Rendering as opposed to Passive Rendering in Full-Screen Exclusive Mode.  The program has also been modernized to use generics.

Active rendering

You will find a good discussion of Active Rendering versus Passive Rendering in The Java Tutorial.

Because the program uses Active Rendering, it does not call the repaint method to ask the operating system to make a callback to the update method.  Rather, the program invokes a method named activeRenderer, which causes the animated sprites to be drawn on the screen without concern for sharing the screen with other applications.  (There are no other applications on the screen in Full-Screen Exclusive Mode.)

An undecorated, non-resizable JFrame object

As shown in Figure 3, the program places an undecorated non-resizable JFrame object on the screen in Full-Screen Exclusive Mode.  A JButton is placed in the NORTH location in the JFrame.  Clicking the button causes the program to exit the full- screen mode, restore the original graphics mode, and terminate.

A JPanel in the JFrame

A JPanel object is placed in the center of the JFrame object.  The colored worms are animated as sprites on the JPanel object.

A background image is drawn on the JPanel object at the beginning of each animation cycle.  This image erases the sprites that were previously there producing a clean slate for drawing the sprites in their new locations. 

Importance of the background image

The drawing of the background image can be eliminated by deleting one statement from the program.  If the background image is eliminated, the worms turn into long tubes because the old sprite images are never erased.

The background image that I used fits a 1024 x 768 screen in Full-Screen Exclusive Mode.  If your screen is a different size, a different size background image will be required.

The program was tested using J2SE5.0 under WinXP.  J2SE 1.4 or later is required to support the setFullScreenWindow method of a GraphicsDevice object.  However, J2SE 5.0 or later is required to support generics.

Will discuss in fragments

As usual, I will discuss this program in fragments.  You can view the program in its entirety in Listing 27 near the end of the lesson.

Won't discuss all of the code

Because this program is an update of the program named Animate03, which I explained in the lesson entitled Fun with Java: Animated Sea Worms, I will assume that you already understand that code, as well as the code in the other lessons listed in the References section of this document.  I won't repeat the explanation of that code in this lesson.

Also, this animation program is wrapped in the skeleton that I explained earlier in this lesson for the program named FullScreen01.  I will also assume that you understand that code and won't repeat the explanation of that code here.

Rather, I will explain only the code that is new and different in this program.

An abbreviated listing of the beginning of the class and the main method is shown in Listing 11.

class FullScreen02 extends JFrame 
                                 implements ActionListener{

  //Code deleted for brevity.
  
  public static void main(String[] args){
    //Code deleted for brevity.
  }//end main

Listing 11

The code in this part of the program is essentially the same as in the program named FullScreen01.  Therefore, I deleted that code from Listing 11 for brevity.  Once again, you can view the program named FullScreen02 in its entirety in Listing 27 near the end of the lesson.

The constructor for FullScreen02

The constructor begins in Listing 12.  Much of the code in this constructor is the same as in the earlier program.  Therefore, I deleted the repeated code for brevity.

  public FullScreen02(GraphicsDevice graphicsDevice){

    //Code deleted for brevity.
    
    getContentPane().add(new AnimationPanel());

    //Code deleted for brevity.    

  }//end constructor

Listing 12

An animation panel

The only significant difference between this constructor and the constructor that I explained earlier occurs in the single statement shown in Listing 12.  This statement instantiates an object of the class AnimationPanel and places it in the center of the JFrame object.  This is the mechanism by which the skeleton program wraps the Full-Screen Exclusive Mode around the animation program.

The actionPerformed method

Listing 13 shows the actionPerformed method, which is the same as before.

  public void actionPerformed(ActionEvent evt){
    //Code deleted for brevity.
  }//end actionPerformed

}//end class FullScreen02

Listing 13

Listing 13 also signals the end of the class definition for the class named FullScreen02.

The BackgroundImage class

Listing 14 shows an abbreviated version of a class named Background Image.

class BackgroundImage{
  //Code deleted for brevity.
}//end class BackgroundImage

Listing 14

This is a convenience class, from the earlier program named Animate03, which makes it a little easier to deal with the background image. Note, however, that this version is much simpler than the earlier version.  Much of the impetus for this class went away when the animation program named Animate03 was converted to full-screen mode.  Several convenience methods having to do with the size of the background image were eliminated in conjunction with that conversion.

The SpriteManager class

Listing 15 shows an abbreviated and slightly modified version of a class named SpriteManager from the earlier program named Animate03.

class SpriteManager{
  private ArrayList <Sprite> theSprites = 
                                   new ArrayList<Sprite>();
    //Code deleted for brevity.
}//end class SpriteManager

Listing 15

An object of this class manages a collection of animated sprites stored in an ArrayList object.  (A Vector object was used in the earlier version named Animate03.)  Note that this class also underwent some modernization with respect to the use of generics as shown by the boldface code near the beginning of Listing 15.

The Sprite class

Listing 16 shows an abbreviated and slightly modified version of the Sprite class from the earlier program named Animate03.

class Sprite{
  //Code deleted for brevity.
  private ArrayList <History> tailData = 
                                  new ArrayList<History>();

  //Code deleted for brevity.

  public void drawSpriteImage(Graphics g){
    //Code deleted for brevity.
    Iterator <History> iterator = tailData.iterator();
    //Code deleted for brevity.
  }//end drawSpriteImage()

  //Code deleted for brevity.

}//end Sprite class

Listing 16

As suggested by the name, this is the class from which the sprites are instantiated.

This class was also updated for generics as indicated by the boldface code in Listing 16.

The History class

Listing 17 shows an abbreviated version of the History class from the earlier program named Animate03.

class History{
  //Code deleted for brevity.
}//end class History

Listing 17

An object of this class is used to contain state information for each segment of each worm.

The AnimationPanel class

The animation is played out by drawing images on an object of the AnimationPanel class, which begins in Listing 18.  An object of this class is placed in the CENTER of an undecorated non-resizable JFrame object that is displayed in Full-Screen Exclusive Mode.

Most of the code in this class was applied directly to the JFrame object in the earlier program named Animate03, because in that program, the animation images were drawn directly on the JFrame object.

class AnimationPanel extends JPanel implements Runnable{

    //Code deleted for brevity.

  private int animationDelay = 83;
  private javax.swing.Timer animationTimer;

Listing 18

Uses a Swing Timer object

The first substantive difference between this code and the code in the earlier program named Animate03 is shown by the boldface code in Listing 18.  This program uses an object of the javax.swing.Timer class to control the animation timing, whereas the earlier program used a timer built around the sleep method of the Thread class.

The animationDelay value of 83 milliseconds shown in Listing 18 will result in an animation frame rate of approximately twelve frames per second.

Listing 18 declares an instance variable named animationTimer, which will be populated later with a reference to a Timer object.

The constructor for the AnimationPanel class

The constructor begins in Listing 19.

  public AnimationPanel(){//constructor
    // Load and track the images
    mediaTracker = new MediaTracker(this);
    
    //Get and track the background image.
    backGroundImage = Toolkit.getDefaultToolkit().
                              getImage("background03.gif");

Listing 19

When you run this program, you will need to have an image file named background03.gif with a size that matches the size of your computer screen.  In my case, that is 1024x768 pixels, but your screen may be a different size.  That image is loaded by the code in Listing 19.

The Timer object

The next substantive difference is shown by the code shown in Listing 20.

    animationTimer = new javax.swing.Timer(animationDelay,
      new ActionListener(){
        public void actionPerformed(ActionEvent e){
          //Update the sprites
          spriteManager.updateSprites();
          //Update the animation panel on the screen
          activeRenderer(getGraphics());
        }//end actionPerformed
      }//end new ActionListener
    );//end new javax.swing.Timer

  }//end constructor

Listing 20

The code in Listing 20 instantiates a Timer object and registers an anonymous ActionListener on it using the peculiar listener registration process for a Timer object.

(An ActionListener object is registered on a Timer object by passing the listener object's reference as the second parameter to the constructor for the Timer object.  Then the listener object is notified of an ActionEvent each time the Timer object ticks.  In this program, I set the Timer object to tick once every 83 milliseconds in Listing 18.  This later results in approximately twelve animation frames per second being drawn on the animation panel.)

The Timer object must be started before it will begin ticking.  It will be started in the run method of the animation thread after everything is set up and is ready to run.

The ActionEvent handler

Each time the Timer object ticks, the actionPerformed method shown in Listing 20 is executed.  The code in this method invokes the updateSprites method on the SpriteManager object.  This causes the state of each sprite to be updated in terms of location, color, direction of motion, etc.

Then the code in the actionPerformed method invokes the activeRenderer method to cause the background image and the updated sprites to be drawn on the animation panel.  Note that control does not flow through the operating system in a callback sense as is typically the case with passive rendering.  Instead, the activeRenderer method causes the material to be drawn directly on the screen without regard for sharing the screen with other programs.

The activeRenderer method

The activeRenderer method is shown in its entirety in Listing 21.

  private void activeRenderer(Graphics g){
    //Create the offscreen graphics context
    if(offScreenGraphicsCtx == null){
      offScreenImage = 
             createImage(getSize().width,getSize().height);
      offScreenGraphicsCtx = offScreenImage.getGraphics();
    }//end if

    // Draw the sprites offscreen
    spriteManager.drawScene(offScreenGraphicsCtx);

    // Draw the scene onto the screen
    if(offScreenImage != null){
      g.drawImage(offScreenImage,0,0,this);
    }//end if

  }//end activeRenderer method

Listing 21

The activeRenderer method is used to draw directly on the screen using active rendering without invoking the repaint method as is the case for passive rendering.

Same as earlier code

The code in the activeRenderer method is essentially the same as the code that I explained in the overridden update(Graphics g) method in the earlier program named Animate03.  Therefore, I won't repeat the explanation of that code here.

The big difference is the flow of control through which the two methods are called.  The activeRenderer method is called directly in this program.  The overridden update method in the earlier program is called in a callback sense after the program invokes the repaint method to send a message to the operating system requesting the callback.  The active rendering approach eliminates the overhead associated with that callback system, and therefore should be more responsive than passive rendering.

The makeSprite method

Listing 22 shows an abbreviated version of the makeSprite method.

  private Sprite makeSprite(Point position,int imageIndex){
    //Code deleted for brevity.
  }//end makeSprite()

Listing 22

This method is essentially the same as the version in the earlier program named Animate03, so I won't discuss it further.

The animation thread

The run method for the animation thread begins in Listing 23.

  public void run(){
    while(getWidth() == 0){
      System.out.print(".");
    }//end while loop
    while(getHeight() == 0){
      System.out.print(".");
    }//end while loop

Listing 23

Delay until size is stable

The run method begins by creating and adding sprites to the SpriteManager object.  First, however, the code in Listing 23 implements a loop to delay the process until the AnimationPanel is fully constructed and the width and height of the AnimationPanel has become stable in Full-Screen Exclusive Mode.

There is probably a better way to do this, but I don't know what it is right off the top of my head.  In any event, this happens only once while the program is getting started and is switching from normal mode to Full-Screen Exclusive Mode.  Therefore, I didn't worry too much about it.  If this were something that happens often during the running of the program, I would have given more thought towards a better solution to the problem.

Create and add 200 worms

Listing 24 creates 200 sprites (200 worms in Figure 3) and hands them off to the SpriteManager object.

    spriteManager = new SpriteManager(
                 new BackgroundImage(this,backGroundImage),
                 getWidth(),
                 getHeight());

    //Create 200 sprites from 6 gif files.
    for(int cnt = 0;cnt < 200;cnt++){
      Point position = 
                 spriteManager.getEmptyPosition(
                 new Dimension(gifImages[0].getWidth(this),
                 gifImages[0].getHeight(this)));
      spriteManager.addSprite(
                             makeSprite(position,cnt % 6));
    }//end for loop

Listing 24

Note that the published version of the earlier program named Animate03 only had fifteen worms swimming around in the fish tank.  However, that program operated in a small JFrame object where fifteen worms represented a crowd.  This program has the entire screen for the worms to swim in, so there is plenty of room for all 200 worms as shown in Figure 3.

Smooth animation up to 800 worms

As an interesting side note, I increased the number of sprites in this full-screen program to 800 worms with no apparent loss in smooth animation at twelve animation frames per second.  As the number of worms increased beyond 800, however, the quality of the animation began to deteriorate.

Let the show begin

Listing 25 causes the animation timer to start running and generating approximately twelve ticks per second.  That in turn causes the worms to start swimming.

    animationTimer.start();//Start the animation timer

  }//end run method

}//end AnimationPanel class

Listing 25

Once started, the worms will continue to swim until the user clicks the button at the top of Figure 3 to terminate the program.

Listing 25 also signals the end of the AnimationPanel class and the end of the program.





Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel