Posted on Saturday, April 16, 2011
The new loading system is in revision 108. It’s been a long time since the last update, and although there aren’t many changes some of them are quite big. One of the most important changes is the new loading system. There’s now a separate loading thread that loads the resources in the background. And while the loaderThread is loading the main thread will display a loading screen. This causes faster load times and PoA doesn’t freeze any more while loading.
How does it work?
The concept is quite simple, you have two threads running, the one loads the needed resources and the other waits until the resources are loaded. Although this sounds easy it turned out to be a real challenge. One of my first and biggest problem was the fact that openGL runs in one thread and isn’t thread safe. So any action requiring openGL commands must be run in the openGL thread. To “solve” this problem I’ve split the loading of resources in two, loading and preparing.
In the loading process the data is read from files as much as possible.
When the main thread has time left (at the end of an update cycle) the thread will prepare a resource if there’s one to be prepared.
The loading system consists of multiple components, these are divided over two threads, the main thread and the loader thread.
- ResourceHandler, contains all the resources of the game and checks if they are loaded when needed.
- ResourceLoader, used to communicate between the main thread and the load thread.
- Loader Thread, waits for resources to appear in the ResourceLoader’s load queue and loads them.
- Resource, an interface that can be implemented by classes so that they can be added to the ResourceLoader.
- ResourceStack, a special resource containing other resources which will be loaded and prepared after each other.
Following a resource
To explain the process of loading a resource I’m going to give an example of an NPC which is being loaded at the start of the game. The game starts and the player continues his save game. The main thread loads empty NPCs, Scenes, Items, etc…
They only contain there name, ID and location, which is used to determine if they should be loaded for a certain scene. The empty entities get added to the ResourceHandler’s list and that’s where our NPC is now, waiting to be loaded.
The game needs to load the scene to start with and asks the ResourceHandler if all the needed resources are loaded. If not, which is most likely at the start of a game, the game requests an ResourceStack. The ResourceHandler loops his list and adds any resource that’s inside the needed scene. And our NPC is in it.
Now the game gives the ResourceStack to the ResourceLoader which will put it in his load queue with the highest priority. And signals the LoaderThread. If the LoaderThread has finished a resource or is sleeping it will react and gets a new resource to load. In this case the resource stack, since it is set with the highest priority.
Now the loading begins and the ResourceStack loops his resources and call their load method. When it’s our NPC’s turn it will load his stand and walk images. To prevent rewriting a lot of code I made an Image wrapper which behaves almost the same as a normal Slick Image. The difference is that it will only load the image data and when needed prepares the Image for use in the main thread.
The ResourceStack finishes the loading and the LoaderThread reports back to the ResourceLoader and he will place the stack inside the prepare queue.
While the game updates it will check if there are resources being loaded. If so the main thread will in the meantime prepare resources since that needs to happen in the main/GL thread. And the images of our NPC are prepared.
Why the new loading system?
You might wonder why I’ve changed the loading system. One of the things you must realize is that the old loading system was rubbish. It loaded everything at the start, didn’t use some sort of deferred loading so the screen would render a loading screen and then freeze until everything was loaded.
Although it works it still contains a lot of bug. I hope to fix most of them in the next few weeks.