To play a sprite contained in a howler.js sound sprite, we simply pass an argument of the sprite name to any howler.js object’s play method. A good first example is the asteroid-explosion sound.
The Asteroid Explosion
The code for dealing with missiles fired by the spaceship takes place inside of a callback function that executes very frequently. Inside of that function a number of game logic functions are performed on whatever game objects are on the screen. The following is the logic for the missiles.
web/public/game.js
$(".playerMissiles").each(function(){
var posx = $(this).x();
if(posx > PLAYGROUND_WIDTH){
$(this).remove();
return;
}
$(this).x(MISSILE_SPEED, true);
var groupName = ".asteroid,." + $.gQ.groupCssClass;
var collided = $(this).collision(groupName);
if(collided.length > 0){
collided.each(function(){
$(this).setAnimation(asteroid["explode"],function(node){$(node).remove();});
$(this).removeClass("asteroid");
});
$(this).setAnimation(missile["explode"],function(node){$(node).remove();});
$(this).removeClass("playerMissiles");
sounds.play('asteroid');
} });
First, a jQuery lookup is done with the selector .playerMissiles to find all the missiles on the screen. The code updates the position of each of these, removing them if they’re offscreen, and then uses the collision function to look for any asteroids each missile has collided with.
It iterates through each of these asteroids, if any, tells them to play their explosion animation and remove themselves, and then tells the current missile to play its explosion animation and remove itself. Finally, at the end of all this, if a collision occurred we play the asteroid sprite of the sounds object, which is the low boom sound from the patch.
The Ship Collision
The code for determining if an asteroid has hit the ship is very similar.
web/public/game.js
In the context of iterating through each asteroid object jQuery finds on the screen, offscreen asteroids are cleaned up, and any asteroids that have collided with the ship cause the ship damage. If two asteroids have hit the ship so far, this third collision should cause the ship’s damage method to return true, and the helper method explodePlayer is called to animate the ship’s explosion off of the screen. If the ship has exploded three times, the game is over.
Finally, if any collision has occurred, no matter if it causes an explosion, we play the sounds object’s ship sound sprite.
The Missile-Firing Sound
The missile-firing sound is triggered in some key-handling code, shown here.
web/public/game.js
var playerposy = $("#player").y();
var name = "playerMissile_"+Math.ceil(Math.random()*1000);
var options = {
animation: missile["player"], posx: playerposx + 90, posy: playerposy + 14, width: 22, height: 10 };
$("#playerMissileLayer").addSprite(name,options);
$("#"+name).addClass("playerMissiles");
sounds.play('missile');
break;
If the game isn’t over and the player’s ship isn’t hit and exploding off of the screen, a switch statement decides if a key we care about has been pressed.
If the key code is 75 or 32, a k key or spacebar, then a missile is added to the screen at the ship’s current position. This takes a few lines to accomplish, but at the end we trigger the missile sprite of the sounds object.
The Thruster Sound
Now let’s look back to the thruster sound. In the initialization code, we finished by playing the thruster sound and then muting it because we don’t want to play a separate thruster sound each time the player presses a movement key.
That would sound like a bunch of thruster sounds all at once. Instead we just want to turn one sound on or off depending on if the player is moving the ship.
At first I thought I’d simply play the thruster sound and mute or unmute it, but I ran into a problem with Firefox during testing. The current solution is still not perfect on Firefox, but most of the time it’s fairly close to what we want. Again, dealing with browser inconsistencies is the web developer’s lot in life.
The following is the code to deal with turning the thruster sound on and off.
web/public/game.js
function fireThruster(fire) {
// thruster.mute seems to not work on Firefox if (fire) {
thruster.volume(1);
} else {
thruster.volume(0);
} }
Continuing the key-down handler code from where the missile-firing keys are caught, here we deal with the movement keys being pressed.
web/public/game.js
And finally, in this key-up handler code, we turn the thruster sound off if the key code matches a movement key.
web/public/game.js
That covers all of the sounds that the game design called for, integrated into the code and triggered through the howler.js objects.
Things to Think About
Here are a few things to think about with regard to the game’s implementation:
I mentioned that I thought about a “red alert” alarm sound for when an asteroid hits the ship. Try creating one. Instead of the falling tones that are in most of the sections of the patch, try a rising tone that goes from one given frequency to another.
Do users always want sound? We’ve at least not started out the game by automatically making noise, but it’d also be good to add a volume control, or at least a mute button.
The howler.js documentation on global methods is a good place to start.
Next Up
Designing sounds for a game is fun. It poses creative challenges and, depending on the delivery platform, some logistical issues to deal with. As this chapter shows, Pure Data is still a handy tool if used only for the sound design, recording, and exporting the final assets for use in other platforms.
In this chapter we covered a lot. We discussed some of the characteristics that define the sound of 8-bit consoles, and then we saw a patch that repro-duced some fun, sci-fi sound effects emulating these characteristics. The patch also built on what we’ve done before with exporting sound files from Pd and showed a more practical example of how to do this.
You saw some of the challenges we face when delivering sound to the web platform, and a few possible solutions to overcome these, courtesy of the howler.js audio library.
Next we’ll go through one more project example on native mobile platforms, which allows us to do away with the need to work with static audio files. We’ll build an app for Android and iOS and use an excellent library that allows us to embed Pd directly in the apps.