Top

A Reusable XACT Component

March 27, 2008

xact_title.jpgThis isn’t a how-to article, it’s more of a let’s discuss article. Sound and music often take a back seat when we’re developing a game, and maybe we want it to stay that way. How would you go about creating a reusable XACT wrapper class that would suit just about any purpose? Here’s how I did mine.

The idea here is pretty simple. We want to do all of our sound management in XACT, and we simply want a sound manager object which we can call on whenever we want to play a sound effect or start/stop/swap our music. How you specifically go about doing this depends on your game. For example, if you are building the next Guitar Hero, you probably won’t want to use a drop in component to manage your sound. But if you want to do what 90% of games do, something simple is probably the way to go.

For my needs, that means I want a simple way to play music, stop music, switch songs, and quickly play effects in a single line of code. I’d also like not to have to manage the cues, update the audio engine, or worry about loading/unloading the XACT project. I’d also like to be able to use the sound manager globally, meaning I want to make sure I have access to it everywhere.

Let’s look at a very basic sound manager class:

  1. namespace PaperTetris.GameElements {
  2.     class SoundManager : GameComponent {
  3.         private static AudioEngine audioEngine;
  4.         private static WaveBank waveBank;
  5.         private static SoundBank soundBank;
  6.         private static Cue musicCue;
  7.  
  8.         public SoundManager(String ePath, String sPath, String wPath) {
  9.             if (audioEngine == null)
  10.                 audioEngine = new AudioEngine(ePath);
  11.  
  12.             if (waveBank == null)
  13.                waveBank = new WaveBank(audioEngine, wPath);
  14.  
  15.             if (soundBank == null)
  16.                 soundBank = new SoundBank(audioEngine, sPath);
  17.  
  18.         }
  19.  
  20.         public void PlayMusic(String cue) {
  21.             if (musicCue != null)
  22.                 musicCue.Stop(AudioStopOptions.AsAuthored);
  23.  
  24.             musicCue = soundBank.GetCue(cue);
  25.  
  26.             musicCue.Play();
  27.  
  28.         }
  29.  
  30.         public void PlaySound(String cue) {
  31.             soundBank.PlayCue(cue);
  32.         }
  33.  
  34.         public override void Update(GameTime gameTime) {
  35.             audioEngine.Update();
  36.         }
  37.  
  38.     }
  39.  
  40. }

First, we make our SoundManager class inherit from GameComponent. We do this so we can add it to the Components list and thus ensure that Update gets called automatically. Boom, that’s out of the way.

Why is everything static? Basically this is just a convenience, to make sure that if we need the SoundManager, but for some reason it’s out of reach, we can create a new object without reloading the project. Since the SoundManager will be created as a member of the Game object, presumably it will always be a couple references away, but just in case, this makes it easy to get access to functionality in a hurry.

We’ve also got some super simple cue management. For music, we hold onto the cue, and check to see if it exists before switching to another song. If it does, we stop the current song, and load up a new one. More complicated versions of this might maintain a list of cues, if we need multiple music pieces playing at once.

So, what do you use? Do you have anything wrapping up the XACT classes, or do you just use the AudioEngine, SoundBank and WaveBank objects as is?

Comments

Got something to say?





Bottom