Chapter 4. Full-Screen Worms
A popular aim for
I'll look at three approaches to creating full-screen games:
FSEM is getting a lot of attention since its introduction in J2SE 1.4 because it has increased frame rates over traditional gaming approaches using repaint events and paintComponent( ) . However, comparisons between AFS, UFS, and FSEM show their maximum frame rates to be similar. This is due to my use of the animation loop developed in Chapter 2, with its active rendering and high-resolution Java 3D timer. You should read Chapter 2 before continuing.
The examples in this chapter will continue using the
WormChase
game, first introduced in Chapter 3, so you'd better read that chapter as well. By
The objective is to produce 80 to 85 FPS, which is near the limit of a typical graphics card's rendering capacity. If the game's frame rate
|
An Almost Full-Screen (AFS) Worm
Figure 4-1 shows the
WormChase
application running inside a
JFrame
that almost covers the entire screen. The
JFrame
's titlebar, including its close box and iconification/de-iconfication
Figure 4-1. An AFS WormChase
These
JFrame
and OS
Though the window can be
Figure 4-2 gives the class diagrams for the AFS version of
WormChase
, including the public
Figure 4-2. Class diagrams for the AFS version of WormChase
The AFS approach and the windowed application are similar as shown by the class diagrams in Figure 4-2 being identical to those for the windowed
WormChase
application at the start of Chapter 3. The differences are located in the private methods and the constructor, where the
WormPanel
is almost the same as before, except that
WormChase
The AFS WormChase Class
Figure 4-3 gives a class diagram for
WormChase
showing all its
The constructor has to work hard to obtain correct dimensions for the JPanel . The problem is that the sizes of three distinct kinds of elements must be calculated:
Figure 4-3. WormChase in detail
The insets of a container are the unused areas around its edges (at the top, bottom, left, and right). Typical insets are the container's border lines and its titlebar. The widths and heights of these elements must be subtracted from the screen's dimensions to get WormPanel 's width and height. Figure 4-4 shows the insets and GUI elements for WormChase .
The subtraction of the desktop and
JFrame
inset dimensions from the screen size is standard, but the calculation involving the on-screen
A subtle problem is that the dimensions of the
JFrame
insets and GUI elements will be unavailable until the game window has been
The answer is that the application must be constructed in stages. First, the
JFrame
and other pieces needed for the size calculations are put together. This fixes their sizes, so the drawing panel's area can be determined. The
public WormChase(long period)
{ super("The Worm Chase");
makeGUI( );
Figure 4-4. Dimensions in the AFS WormChase
pack( ); // first pack (the GUI doesn't include the JPanel yet)
setResizable(false); //so sizes are for nonresizable GUI elems
calcSizes( );
setResizable(true); // so panel can be added
Container c = getContentPane( );
wp = new WormPanel(this, period, pWidth, pHeight);
c.add(wp, "Center");
pack( ); // second pack, after JPanel added
addWindowListener( this );
addComponentListener( new ComponentAdapter( ) {
public void componentMoved(ComponentEvent e)
{ setLocation(0,0); }
});
setResizable(false);
setVisible(true);
} // end of WormChase( ) constructor
makeGUI( ) builds the GUI without a drawing area, and the call to pack( ) makes the JFrame displayable and calculates the component's sizes. Resizing is turned off since some platforms render insets differently (i.e., with different sizes) when their enclosing window can't be resized.
calcSizes( )
initializes two
private void calcSizes( )
{
GraphicsConfiguration gc = getGraphicsConfiguration( );
Rectangle screenRect = gc.getBounds( ); // screen dimensions
Toolkit tk = Toolkit.getDefaultToolkit( );
Insets desktopInsets = tk.getScreenInsets(gc);
Insets frameInsets = getInsets( ); // only works after pack( )
Dimension tfDim = jtfBox.getPreferredSize( ); // textfield size
pWidth
= screenRect.width
- (desktopInsets.left + desktopInsets.right)
- (frameInsets.left + frameInsets.right);
pHeight
= screenRect.height
- (desktopInsets.top + desktopInsets.bottom)
- (frameInsets.top + frameInsets.bottom)
- tfDim.height;
}
An
Insets
object has four public variables
top
,
bottom
,
left
, and
right
that hold the
Stopping Window Movement
Unfortunately, there is no simple way of preventing an application's window from being dragged around the screen. The best you can do is move it back to its starting position as soon as the
The WormChase constructor sets up a component listener with a componentMoved( ) handler. This method is called whenever a move is completed:
addComponentListener( new ComponentAdapter( ) {
public void componentMoved(ComponentEvent e)
{ setLocation(0,0); }
});
setLocation( ) positions the JFrame so its top-left corner is at the top left of the screen. Timings for AFSTiming results for the AFS WormChase are given in Table 4-1. Table 4-1. Average FPS/UPS rates for the AFS WormChase
{% if main.adsdop %}{% include 'adsenceinline.tpl' %}{% endif %}
WormChase
on the slow Windows 2000 machine is the worst performer again, as seen in Chapter 3, though its slowness is
The Windows 98 and XP boxes produce good frame rates when 80 FPS is requested, which is close to or inside my desired range (80 to 85 FPS). The
|