Java games can be deployed using various types of deployment frameworks. This article helps you understand the three different kinds of deployment frameworks, and shows you how to deploy your games to all three types without having to recompile your code. It is excerpted from chapter two of Advanced Java Game Programming, written by David Wallace Croft (Apress; ISBN: 1590591232).
Understanding Deployment Frameworks (Page 1 of 4 )
Diligence is the mother of good luck. —Benjamin Franklin
In this chapter, you will learn about the different ways to deploy your Java games using the various types of deployment frameworks. By framework, I mean standardized mechanisms for a container to deploy, launch, run, and gracefully terminate your games on multiple platforms. The frameworks covered include browser applets, executable JARs, and Java Web Start. I detail a reusable framework that will permit you to deploy your games to all three of these environments without recompiling. I achieve this by identifying the methods required for animation thread management, then defining them within a common interface.
Deploying as an Applet
Applets are traditionally thought of as small Java programs that are used to display simple animations embedded within a web page. This is not strictly true, as applets can be large programs used for purposes other than animation, in containers other than web browsers. What is common to all applets, however, is that they all extend class java.applet.Applet, which lets you use them in anyApplet-compatible framework.
Implementing the Lifecycle Methods
I'll never forget the definition of the term framework given to me in a Design Patterns course I took a few years back. The instructor stated simply, “It is the Hollywood model: ‘Don’t call us, we’ll call you!’” For a container to initialize, start, stop, and destroy your game object, it must have access to pre-defined methods that it can call on the game object as required. Because these lifecycle methods are consistent within a given framework, any game written to that framework can run within a framework-compatible container regardless of the vendor or platform.
Classjava.applet.Appletdefines the four lifecycle methodsinit(),start(),stop(), anddestroy()which are called by a framework-compatible container such as a web browser.Applet subclass implementations override one or more of these empty methods to create the animation. There are some subtleties to the semantics so I recommend that you review the Javadoc for these methods. The following comments are supplementary.
You initialize your game using theinit()method. You load your images, audio files, and other static content here. You create any dynamic data you need to generate before the game can start in theinit()method as well. You may also load previously saved game data such as the high score in this method.
Keep in mind that theinit()method is never called twice on the sameApplet instance. None of the other methods in theAppletsubclass are called before theinit()method with the exception of the no-argument constructor method. This means you should not have to worry about the container attempting to display your applet by calling itspaint()method before it is ready.
I have always been told that you should perform all your initialization code in theinit()method and not in a constructor. In fact, before Java 1.4, theAppletclass did not even define a public constructor method that subclass implementations could override.
Thestart()method starts the game-loop thread that drives the animation. Thestart()method is not only used to start animation, or whatever the applet is doing, but also to resume animation after it has been stopped. A typical example of when a container may resume processing an applet is when a player minimizes and then maximizes the web page window. The container may call thestart()method many times throughout the life of an individual applet instance.
When implementing yourApplet subclass implementations, you should be prepared to receive a call to yourpaint()method by the container, usually a web browser, before the container ever calls yourstart()method for the first time. The idea that your code might be called upon to display its first frame of animation, or at least something, before the animation thread starts is not intuitive. If your code occasionally or even consistently throws aNullPointerExceptionfrom thepaint()method when the applet is first loaded, but not when it has warmed up, you probably have some of your graphics initialization code in yourstart()method. Move it to yourinit()method and all will be well.
Thestop()method is used to suspend the animation when the game is paused. According to the method definition, the container might call thestop()method multiple times throughout the life of the applet instance. Canstop()be called multiple times by the container without an intervening call tostart()? Canstart()be called multiple times by the container without an intervening call tostop()? I am not certain so I often write my implementations of these two methods in such a way that it does not matter.
Note also that thestop()method is guaranteed to be called right before thedestroy()method. I like to implement mydestroy()methods under the assumption that the container might or might not have already calledstop(). I do this because I do not trust the container to implement the framework contract properly, having created some slightly buggy home-grown applet containers myself. I also do this because the call tostop()might have failed and thrown an exception.
You can write an ill-behavedstop()method implementation. For example, when called by the container, yourstop()code can stall until the container finally kills the thread. Your code can also ignore the call tostop()and continue running, treating it as a suggestion rather than a command. I do not know about you, but when I implement code such as this, it is usually not on purpose.
The container calls thedestroy()method when the game ends to de-allocate any resources used by the game. Here are a few quick facts about thedestroy()method. The container never calls it more than once in the life of anAppletinstance. With the exception of thefinalize()method, no other method in theAppletis called afterward. A container never reuses anAppletinstance after itsdestroy()method is called by calling itsinit()method once again. Just as with thestop()method, you can write a rudedestroy()method implementation that does not do what is expected.
You might wonder why you need to even have adestroy()method. After all, the garbage collector should automatically reclaim or close all resources used when the container dereferences the applet. The problem with this logic is that the garbage collector might not process the applet right away. This means that your applet might hold on to resources such as unclosedSocketconnections, undisposedGraphicscontexts, and undisposedWindow native screen resources indefinitely. If you notice that your applet always crashes after being used several times, but never just after restarting your browser, you should suspect that you are not completely destroying all your initialized resources at the end of the applet lifecycle.
TheObjectclassfinalize()method is meant to be overridden by subclasses that want to perform some action, usually the release of resources held, right before an object is garbage collected. Do not use thefinalize()method. It is unreliable because there is no guarantee that it will ever be called. If there is sufficient memory, the garbage collector might not bother collecting garbage. If the JVM is shutting down, it might not bother to callfinalize()on its way.
In general, it is best to rely upon thedestroy()method for the timely release of system resources.