
Star Defense XNA Game Tutorial Series – Part Twelve – Audio
Note: I’m trying out a new way of prepping my tutorial
pages, so this page may look a bit different than the previous installments.
Now that XNA 3.0 is live, we will finish up the Star Defense
tutorial series by adding sound effects to our game. Prior to version 3.0,
adding sound was a bit more complicated than it is now. You had to much about
with XACT and create sound banks and such. All of that is gone now, and the
Content Pipeline takes care of everything for us. Thanks Content Pipeline!
Under XNA 3.0, adding audio support is very simple. In
fact, it was harder to locate sound effects to use in the tutorial that it is
to add them to the game code.
The sample sound effects I’m going to use are from this web site:
http://www.grsites.com/archive/sounds/.
As far as I can tell, they are all free sound effects for non-commercial use.
Of course, you will want to either purchase or produce your own sound effects
for your game project if you intend to sell it.
I have put together a small package of the five sounds we
will be using. It can be downloaded from http://www.xnaresources.com/downloads/StarDefense_Sounds.zip
and contains sounds from the Battle and Scifi categories of the site listed
above.
In your Visual Studio project, right click on the Content
folder and click “New Folder…” and create a folder called “Sounds”. Extract
the .WAV files from the zip file above to the Sounds folder and add them to
your project just like you would add a texture. The Content Pipeline will
detect the .WAV format and set the appropriate content importer automatically.
As for the code, we will be working exclusively in the
Game1.cs file. We need to add a couple of declarations in our declarations
area for the sound effects we will be playing:
static int
iMaxExplosionSounds = 2;
private static SoundEffect[] PlayerShots = new SoundEffect[2];
private static SoundEffect[] ExplosionSounds = new SoundEffect[iMaxExplosionSounds];
private static SoundEffect PowerUpPickupSound;
Here we are simply declaring a few objects of type
SoundEffect (there is also a “Song” object type for playing longer background
song type files). We are actually doing a couple of things here, so:
·
The PlayerShots sound effect array holds two possible SoundEffect
objects. Recall that we can upgrade our weapons to dual cannons by picking up
a powerup object. So we will use two different sounds to represent the
different weapon levels.
·
The ExplosionSounds array has two (slightly) different explosion
sound effects in it. We will randomly play one whenever we need an explosion
sound to happen. If you have a larger variety of explosion sounds available,
simply increase iMaxExplosionSounds and load them in your LoadContent and you
can generate a little more sound effect variety.
·
The PowerUpPickupSound is played whenever the player … you
guessed it… picks up a Power Up.
On to LoadContent, where we just need to load these
resources just like we do our textures. Add the following to your LoadContent
method:
PlayerShots[0] = Content.Load<SoundEffect>(@"Sounds\Scifi002");
PlayerShots[1] = Content.Load<SoundEffect>(@"Sounds\Scifi050");
ExplosionSounds[0] = Content.Load<SoundEffect>(@"Sounds\battle003");
ExplosionSounds[1] = Content.Load<SoundEffect>(@"Sounds\battle004");
PowerUpPickupSound = Content.Load<SoundEffect>(@"Sounds\Scifi041");
Again, nothing new here. This is identical to the way we
load textures except for the Type specifier in Content.Load.
So now what we have our sounds, how do we play them? Very,
very simply. Scroll down to your FireBullet method and add the following to
the end:
if (iVerticalOffset==0)
PlayerShots[player.WeaponLevel].Play(1.0f, 0f, 0f, false);
The first line (if (iVerticalOffset==0)) is simply there to
prevent us from playing two sound effects when the player has dual cannons
(since we use the FireBullet method twice in that case, with the second one
having a -4 pixel vertical offset). What we are really interested in here is
the second line. We simply call the Play() method of the SoundEffect object, specifying
the following:
·
Volume – A value from 0.0f to 1.0f, indicating how loud (relative
to the volume of the actual file) the sound should be played. 0.0f would be
silent (and fairly pointless), while 1.0f is “full volume”.
·
Pitch – This float will shift the frequency of the sound up or
down. 0f is the “normal” pitch for the sound file.
·
Pan – If you are interested in simulating playing the sound in
3d-ish space, this float shifts the sound between the left speaker (-1.0f) and
the right speaker (1.0f). This isn’t really 3d sound, but more like turning
the balance knob on your car radio. The 0f value is “centered”.
·
Loop – If true, the sound will loop (forever) after it is
played. If false, it will play once and stop.
Executing the Play method creates an instance of the sound
playing, so it can be executed multiple times and will play multiple times
simultaneously. Although we are not using it here, the Play() method does
return something called a SoundEffectInstance, which gives you a handle to the
instance that is playing so you could do things like stop a “looping” sound
after it has been started.
For some good information on more details of this stuff,
check out Chase’s Techno Rants and Raves blog entry at http://geekswithblogs.net/bitburner/archive/2008/06/22/123061.aspx
Lets add the last bits of code we need for the rest of our
sound effects. In the DestroyEnemy method, add:
ExplosionSounds[rndGen.Next(0,
iMaxExplosionSounds)].Play(1.0f, 0f, 0f, false);
Here you can see we are picking a random explosion sound to
play, at full volume, normal pitch and pan, and non-looping. Next, we need to
add two things to the CheckPlayerHits method. Right after fPlayerRespawnCount
= 0.0f; add the following line:
ExplosionSounds[0].Play(1.0f, 0f, 0f, false);
And in the PowerUps section of the method, right after powerups[x].IsActive
= false; add:
PowerUpPickupSound.Play(1.0f, 0f, 0f, false);
And that’s all there is to it. Run your game and you should
have sound for player cannons, enemy/player ship explosions, and picking up
powerups.
Of course, you could add more sound effect for just about
anything you want. A superbomb will make a super explosion already with all of
the DestroyEnemy() calls firing off explosions, but you may want to add a sound
effect specifically for the bomb. Or perhaps a sound to play when the player
is “thrusting” the ship.
I’ve got a final wrap-up .ZIP file of the project for
download that contains everything in all 12 parts: