stahlworks technologies
 
 
 
 
 
 
 
 
 
 
Fast Image Loading within Java Games

and how to start the action even before everything's loaded:
a tutorial with free source code for download.

fast image loading is achieved through a combination of techniques, namely compression, bundling, background loading, and loading on demand.

compression

All images are converted from the original PNG form to a combination of JPEG (usually 80 percent quality) and a ZIP mask file. The resulting JPEG plus the ZIP is usually four times smaller than the original PNG, due to JPEG's compression.
-> see the source of d3conv.java, which is part of the d3caster package.

bundling

Loading many images by just using the applet's getImage() method will result in many separate GET requests to the webserver, which is slower than just loading one large file with a single request. Therefore the most important images are bundled within a JAR file, by a command like "jar cfM images.jar *.jpg *.zip". Actually, d3caster currently uses two separate jar's, one for the jpg's, and one for the zip's.
-> see the do-convert-images batch for the whole image compression process.
Notice that not simply ALL images from pic256/ are placed therein, but just the most important ones.

avoid to load everything at game startup

As a general rule, if you show the user a screen that doesn't change for longer than 5 seconds, you risk that he will simply CANCEL your applet, and surf away. In the role of a user, we're all very impatient.

So restrict your applet to load only the most important stuff immediately, and everything else later. Important is, of course, everything that can be seen from the start - some wall textures, some objects, a rocket shape. Not important are wall pictures which can be found three rooms later; maybe the player never reaches that room, so why load the stuff? So these things will be loaded on demand.

background image loading, and loading on demand

So, if only some images are loaded immediately, the rest must be loaded in background - typically in an own thread, the image loader (-> see runImageLoader()). This enables the player to have full action, and immediate system feedback, although some work is still done in the background.

But what images should be loaded next? Simple answer: those that we're looking at. An example:


looking at a new wall segment
 
a moment later

To the left: as we enter a new area, we find ourselves looking at a a new wall segment, whose texture isn't loaded yet. Nevertheless, the action must continue. So we show a default texture - the woody basetext.jpg. This is one of the first images loaded at startup, and it's guaranteed to be available immediately.

But what happens then? Because we look at the texture, the renderer sets a flag called "touched" on the corresponding d3texture object, signalling the image loader that this thing should be loaded next. A getImage() is started in the background. Be aware that network activity takes time, but nearly no CPU time, so the game continues at full speed while the data is loaded. A short moment later, the image is fully loaded, and the d3texture is updated, as seen on the right.

This way, we can add tons of images to our game, without long, boaring startup times. The user may see a strange default texture from time to time, but he isn't stopped within action, so this is far less irritating than waiting.

Find the whole source code in d3caster.java, provided within the d3caster package.