Tutorial 4 - Resource Loaders and the Sound Engine
If you'd like, you can download the source for this tutorial here. See Tutorial 1 for basic engine setup.Loading Resources?
Your game will probably need more than just what the engine provides. Everything from game art to sounds will typically exist in external files. Luckily, The Render Engine comes with many objects for just that purpose. Every one of them extends from the ResourceLoader class. This class, at its heart, provides caching of the resources it loads. Objects loaded are keyed with a unique name in the resource loader
This allows your game to access these resources as needed, without having to reload them each time. Each loader has its own cache, so you can reuse keys across loaders. This may come in handy if you have images and sounds that go together. It's really up to you!
The place for resource loaders is in your game object. The reason is that your game object will be consistent across the entire game, rather than loading in and out as needed. So, in your game.js file, add the following include:
// Include the resource loaders
Engine.include("/resourceloaders/loader.image.js");
Engine.include("/resourceloaders/loader.sound.js");
You can either access the resource loaders as public fields of your game object, or you could create getter methods for them. I chose the former option (because it was less to write). Then in the setup() method for the game object, we'll create them.
// References to the resource loaders
imageLoader: null,
soundLoader: null,
loadTimeout: null,
/**
* Called to set up the game, download any resources, and initialize
* the game to its running state.
*/
setup: function(){
// Set the FPS of the game
Engine.setFPS(this.engineFPS);
$("#loading").remove();
// Create the render context
this.fieldBox = Rectangle2D.create(0, 0, this.fieldWidth, this.fieldHeight);
this.renderContext = CanvasContext.create("Playfield",
this.fieldWidth, this.fieldHeight);
this.renderContext.setBackgroundColor("black");
// Add the new rendering context to the default engine context
Engine.getDefaultContext().add(this.renderContext);
// The resource loaders
this.imageLoader = ImageLoader.create();
this.soundLoader = SoundLoader.create();
After we've created the resource loaders, we use them to get the assets we need. The first one, the ImageLoader, loads images of gif, jpg, and png types. The getFilePath() method exists on the Game object and will expand the given path relative to your game class. The second loader, the SoundLoader, loads MP3 sounds and initializes the SoundManager 2 sound engine. Additionally, including the loader also includes the Sound object which abstracts the individual sounds.
// Begin the loading process
this.imageLoader.load("keys", this.getFilePath("resources/fingerboard.png"),
220, 171);
this.soundLoader.load("c1", this.getFilePath("resources/low_c.mp3"));
this.soundLoader.load("d1", this.getFilePath("resources/dee.mp3"));
this.soundLoader.load("e1", this.getFilePath("resources/eee.mp3"));
this.soundLoader.load("f1", this.getFilePath("resources/eff.mp3"));
this.soundLoader.load("g1", this.getFilePath("resources/gee.mp3"));
this.soundLoader.load("a1", this.getFilePath("resources/ay.mp3"));
this.soundLoader.load("b1", this.getFilePath("resources/bee.mp3"));
this.soundLoader.load("c2", this.getFilePath("resources/hi_c.mp3"));
// Wait until the image and sounds are loaded before proceeding
var self = this;
this.loadTimeout = Timeout.create("wait", 250, function() {
self.waitForResources();
});
this.waitForResources();
},
Finally, you'll notice that we're using a Timeout to wait until our resources are ready before actually running the game. Before we create the Timeout you might notice the line which says:
var self = this;
A little JavaScript background:
The assignment of this to the variable self will allow us to refer to this (in this case, the game object) within the anonymous function being used by the Timeout. Otherwise, if we used this, it would refer to the function itself. It's a trick, but a handy one... learn it well.
Waiting to Start the Game
It is essential, in our game, that it doesn't start until all of the resources are ready. We've written a simple method that checks the resource loaders to see if the assets are ready. You can either query for all of the assets, or a single one, depending on how you call the isReady() method.
Our method uses the all assets version, so that we can make sure that all sounds are loaded, as well as the image we need. If they aren't ready, the Timeout is restarted via the restart() method.
When the resources are all loaded, we destroy the time and then call the run() method to actually start the game.
/**
* Wait for resources to become available before starting the game
* @private
*/
waitForResources: function(){
if (this.imageLoader.isReady() && this.soundLoader.isReady()) {
this.loadTimeout.destroy();
this.run();
return;
}
else {
// Continue waiting
this.loadTimeout.restart();
}
},