In order to ensure timely loading when creating textures, or other file-based objects, the GWT backend of LibGDX employs a Preloader which downloads and caches all of the assets before loading the actual game. This is great when you need to have access to those assets at creation time, but in the case of larger games this may needlessly extend the time it takes to get to the game. I recently spent a little bit of time investigating the best way to defer loading of those assets not needed immediately, and made some changes in LibGDX’s GWT Preloader mechanism to allow for this. It does take a bit of configuration, but I think it can be worth it when warranted. In this post, I’ll describe the steps involved in setting this up.
About the Preloader
The Preloader is not something that most LibGDX users have to be concerned about. It just does its thing and that is that. But when you want to customize how or when things are loaded, it’s good to have a basic understanding of how it works.
The Preloader mechanism consists of both a compile time generator and a run time loader. At compile time, the generator collects all of the files from the assets directory (located in the Android project, if using the typical LibGDX setup), copies them to the GWT output directory (the war directory), and then creates a descriptor file which indicates the location and type of each file. This generation process can be augmented by providing your own AssetFilter, which serves to give you the opportunity to say which files are copied, define their type and, now, specify to which bundle they belong.
Setting Up Your AssetFilter
As previously stated, you’ll use an AssetFilter to put your assets into bundles for the Preloader. To do this we’ll create a class that extends DefaultAssetFilter (so we can get all of its awesomeness) and override the getBundleName() method.
Next, we’ll tell GWT about our AssetFilter by adding a configuration property to our project’s gwt.xml file.
Note, that you must include the fully qualified name of your AssetFilter.
Defining Asset Bundles
Now that we have our AssetFilter set up, it is time to define which assets will go into which bundles. For the sake of example, we’ll pretend that our assets are arranged such that each level has a folder. Let’s say our level assets are saved in their own folder in “data/levels/” and each level should have its own bundle. This probably won’t be the case but it makes it easy to illustrate. Here’s what our new AssetFilter looks like…
With this in place, when we compile the GWT version of our game, we’ll end up with the main “assets.txt” that we usually get, plus an additional descriptor for each level. At run time, the Preloader will automatically load the default “assets.txt” for us. This is a good place to preload any assets we need right away, such as title and menu images. Then, when we are ready to go into a level, we just need to ask the Preloader to load our bundle for that level. Of course, if we are doing things the LibGDX way, we don’t want to leak platform specific code into our core project so we’ll create a simple interface.
Preloading Asset Bundles
Let’s create a simple interface through which we may request a bundle to be preloaded.
Using this interface is as simple as creating an instance of the appropriate PreloaderInterface and handing it to your game class. Then, when you need a particular bundle, just get the PreloaderInterface instance and call preloadBundle(String, Callback). When you get the callback, continue loading.
Something that might be useful when preloading may take some time is to display a loading screen so people know something is happening. It should be no different than creating any other loading screen in LibGDX so I did not implement it here.
Note: The functionality described here requires use of the LibGDX nightly builds (as of 7/7/2013), or a stable release of 0.9.9 or higher.