Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 30 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
30
Dung lượng
1,02 MB
Nội dung
228 CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE Figure 8-11. The reverb after removing the peaking part For some final cleanup, we quiet the duplicate track a little by selecting Effect ➤ Amplify and entering a negative value of –5, clip off the remaining 5 seconds of silence, and apply a Cross Fade Out to the trailing bit. Figure 8-12 shows the final 50-cal sound for our game. Figure 8-12. 50-cal: the final product This should give you an idea of the basic functions that you can accomplish with Audacity and a good idea of how to collect and process audio. It will become more important to under- stand the workflow of creating a piece of audio as you develop your own games. In summary, the important audio we ended up with is as follows: •Gunshot •Hit • An assortment of crunching and splatter sounds CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE 229 We’ll use the crunches and splatters to add some flavor to our combat audio. Save all of the audio files as .wav files in ZombieSmashers\Content\sfx. Now let’s get all of this set up in XACT! Adding Audio to the Game With our audio files ready, we can now add sounds to the game. As you saw in Chapter 2, we use XACT for this task. XACT organizes sound in a hierarchical manner. You don’t need to be intimately familiar with the layout, but it helps to have a vague idea of what’s going on: • Waves are raw audio. A wave bank is a collection of wave (.wav) files that could be used in a game. • Sounds are composed of tracks that play simultaneously. Tracks contain events. Events can, among other things, play waves. A sound bank is the use of files in the wave bank and can apply certain properties to sound files. • Cues play sounds. Cues are what you tell your audio engine to play from within your game. Cues have their own properties that can be applied to sounds. To look at it from the application end of things, we’ll be telling our audio engine to play a cue, which will play a sound, which will play its tracks, which will fire their events, which will play waves. There’s going to be a bit of déjà vu at work here (XNAPong, anyone?), but we’ll still hit all of the steps, and in less of a rush this time. Let’s get started by setting up our XACT project. Setting Up the Game Audio in XACT Fire up XACT. From the Start Menu, you can find XACT in Microsoft XNA Game Studio 2.0 ➤ Tools. Once XACT is up and running, select File ➤ New Project, navigate to your ZombieSmashers\Content\sfx folder, and save the new project as sfxproj, as shown in Figure 8-13. Next, right-click the Wave Banks item in the navigation pane on the left and select New Wave Bank. Name the new wave bank sfxwavs. Then right-click the Sound Banks item, select New Sound Bank, and name it sfxsnds. XACT automatically gives us the following file paths: • sfxproj.xgs is the XACT project file. • sfxwavs.xwb is the XACT wave bank file. • sfxsnds.xwb is the XACT sound bank file. Down the road, we’ll be loading these three files from ZombieSmashers, so it’s a good idea to be vaguely familiar with what they’re called and what each represents. Start off by dragging all of the audio files into the wave bank. They’ll show up in red italics, meaning that they are not used in any cues, which we can now start to create. 230 CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE Figure 8-13. Creating a new XACT project XACT has a shortcut in which you drag a wave from the Wave Bank window into the Cue panel of the Sound Bank window, and let XACT take care of the rest. XACT will create a sound for the wave that has a track that contains the event play wave, as well as a cue that will play the sound we just created. In other words, we can insert a wave file, drag it into the Cue panel of our Sound Bank window, and not worry about all the stuff happening in between. This is what we did when we made XNAPong back in Chapter 2. We’re going to play around with this XACT hierarchy a bit more by making some variable zombie-smacking sounds. We’ll create three hit variation sounds that are all called by one cue, which we’ll call zomhit. Drag hit from the Wave Bank window to the Cue panel in the Sound Bank window. Now we have a sound named hit and a cue named hit. Rename the cue to zomhit. Since we want three hit sounds, drag the hit wave into the Sound panel in the Sound Bank window twice (not creating a cue), and rename the three sounds in the Sound panel zomhit1, zomhit2, and zomhit3. Drag zomhit2 and zomhit3, one after another, from the Sound panel into the zomhit cue in the Cue panel. Now we have one cue, zomhit, which will randomly play zomhit1, zomhit2, or zomhit3 when it is run. Right now, zomhit1, zomhit2, and zomhit3 play only the hit waves, so let’s add additional tracks to each sound. In our project, we have three gooey mayhem sounds called crunch, crush, CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE 231 and splatter. Adding tracks to sounds is as an easy drag-and-drop operation. Drag crunch to zomhit1, crush to zomhit2, and splatter to zomhit3. We now have a single cue, zomhit, which will play three different sound variations. Each sound plays the hit sound and a different flavor of splatter. Your XACT project should look like the one shown in Figure 8-14. Figure 8-14. One cue, three variations This looks nice enough, but how it sounds could be a very different story. Fortunately, we can listen to the sounds to hear how they will be in our game without actually putting them in the game. Let’s start testing and tweaking! Auditioning Audio Because XACT is set up to be cross-platform, audio auditioning is handled through a separate program: the XACT Auditioning Utility. You’ll find the XACT Auditioning Utility on the Start menu, under Microsoft XNA Game Studio 2.0 ➤ Tools ➤ XACT Auditioning Utility. Windows may give you some trouble about firewalls at some point; allow the program through and let it do its business. From XACT, select your zomhit cue and click the Play button. The XACT Auditioning Utility should subtly let you know it received a connection from XACT, as shown in Figure 8-15, and 232 CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE the sound should play. Try playing it a few times. It will behave just as it will in the game, giving you a different variation each time. Figure 8-15. XACT Auditioning Utility When we did this, we discovered that the flavoring sounds we put in (crunches, crushes, and splatters) were sometimes overpowering the hit sounds. We want the flavor sounds to be very subtle. Fortunately, we can modify the volume on individual tracks. For each sound, select the track that plays the flavor sound (it will be Track 2), and in the Properties panel, adjust the volume, as shown in Figure 8-16. You can click the sound in the Sound panel and play it to get a feel for how it’s working. Remember that sounds like this will be played quite a bit, so we don’t want them to be abrasive or annoying. Figure 8-16. Modifying track volume After tweaking, we ended up with only three cues for this iteration of sound project editing: zomhit, revol (for the revolver), and bullethit. We created bullethit by combining hit and crunch, making it quieter than the zomhit variations. The final Sound Bank window looks like Figure 8-17. Three cues is a good place to start. Our next task is to integrate the sounds into the ZombieSmashersXna project. We can always enrich our audio environment later. CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE 233 Figure 8-17. Our three cues Bringing Sound into the Game To bring audio functionality into Zombie Smashers XNA, we need to do three things: • Add the XACT project to our Content project. • Create a class to load our XACT project and play cues. • Hard-code some cues to play at specific spots in our game. Let’s start by adding the XACT project. In the Content project, with Show All Files enabled, refresh Solution Explorer. Then right-click sfx and choose Include in Project. Do the same for sfxproj.xap, which will automatically be given the proper Content Pipeline properties. Next, let’s create a class to play audio. We’ll make all the members public and static so that we can play sounds from anywhere. We are going to be using a special feature of static portions of a class: the static constructor. The static constructor is never declared with a scope (such as public or private) because it is automatically fired before any other static member or method is used. This bit of functionality in the language removes the dependency on creating a basic initialize method and making sure it is called only once. using System; using Microsoft.Xna.Framework.Audio; namespace ZombieSmashers.Audio { static class Sound { private static AudioEngine engine; private static SoundBank sound; private static WaveBank wave; 234 CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE static Sound() { engine = new AudioEngine(@"Content/sfx/sfxproj.xgs"); wave = new WaveBank(engine, @"Content/sfx/sfxwavs.xwb"); sound = new SoundBank(engine, @"Content/sfx/sfxsnds.xsb"); } public static void PlayCue(String cue) { sound.PlayCue(cue); } public static Cue GetCue(String cue) { return sound.GetCue(cue); } public static void Update() { engine.Update(); } } } Now in Game1, we need to make sure that we don’t forget to keep the engine updated. Failure to do so will result in terrible things happening (choppy playback, reduced game performance, loss of sleep while trying to determine why performance is going down the drain, and so on). Add Sound.Update() anywhere in Game1.Update(). Next, we’ll add some PlayCue() calls. Our first stop will be in HitManager. In CheckHit(), we basically have two big if blocks to choose from when we’ve hit something: a bullet hit if code block and a default hit if code block. In the bullet hit if statement, add the following: c[i].SetAnim("idle"); c[i].SetAnim("hit"); c[i].Slide(-100f); Sound.PlayCue("bullethit"); Further down, in the default hit if block, add this: c[i].SetAnim("idle"); c[i].SetAnim("hit"); Sound.PlayCue("zomhit"); We have one more sound to implement. In Character.FireTrig(), we need a switch where we create particles on a case-by-case basis. Let’s set it up to play the revol sound for all three pistol-firing triggers: CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE 235 case TRIG_PISTOL_ACROSS: pMan.MakeBullet(loc, new Vector2(2000f, 0f), face, ID); Sound.PlayCue("revol"); break; case TRIG_PISTOL_DOWN: pMan.MakeBullet(loc, new Vector2(1400f, 1400f), face, ID); Sound.PlayCue("revol"); break; case TRIG_PISTOL_UP: pMan.MakeBullet(loc, new Vector2(1400f, -1400f), face, ID); Sound.PlayCue("revol"); break; Great! Now Zombie Smashers has been brought, kicking and screaming, from the silent- movie era into XACT-enriched modern times. Playing audio at hard-coded points is working well enough so far, but what happens when we want to have a wrench-swishing sound? We couldn’t really hard-code that, because there are too many possibilities in a current combo system. So what do we do? The solution is to inte- grate audio controls into our character-scripting system. Scripting Audio We’ll start with the sound file. Find a “swing” sound—think swinging a baseball bat or, hey, a wrench! Drag your new swing.wav file into your XACT wave bank, and then drag it from there to the Cue panel in your Sound Bank window. Save the project. Let’s add a new script command to our character-scripting language. In the Commands enumeration, go ahead and add a new one at the end: enum Commands{ // PlaySound } Then, in our big switch case block in DoScript(), we need to add a case to act on our new command, as follows: case Commands.PlaySound: Sound.PlayCue(line.SParam); break; Finally, we need to add a case to the big switch case block in the constructor for ScriptLine to parse the command string into our script line command format. In the switch block in the constructor for ScriptLine, add this: case "play": command = Commands.PlaySound; sParam = split[1]; break; Now add the command play [sound] anywhere in the character script. 236 CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE Run the CharacterEditor application and load Guy. Let’s add play swing commands to our Guy character. For the swing-swing-swing-kick combo, add a play swing command near the start of every attack, as shown in Figure 8-18. Figure 8-18. Play swing! You can see how easy it would be to add sounds for landing, yelling, footsteps, and much, much more. We’ll leave that up to you! Adding Music We’ve covered a bit of what XACT has to offer, but there’s still a lot more ground in the audio department. A few simple things we can implement are streaming audio, looping audio, cate- gories, and compression—all things we’ll need for music implementation. Music audio can get large. It may not seem like a big deal now, but if we end up with 100MB of music audio in our game, it will make much more sense to load a couple kilobytes of it at a time, swapping blocks in and out of memory, so we’ve loaded only what we’re playing or about to play. This is the essence of streaming audio. This also used to be a big hassle to implement, but it’s a snap with XACT. Now we’ll add some music to our game. Of course, you’ll need a music track for this. We’ll leave this up to you—you can really use anything. We recommend that it be at least three minutes, and it doesn’t have to seamlessly loop. Again, FlashKit has some nice tracks available. Also, you can use the music provided with this book’s downloadable files, called music1.wav (we made this sample track using ACID software). In XACT, add the wave bank musicwavs and the sound bank musicsnds. Select musicwavs and, in the Properties panel, click the Streaming button. Figure 8-19 shows what’s going on. Notice how the wave bank icon now has “DVD” above it. This evidently indicates that these waves would stream from a DVD if our game were based on a DVD. Because it’s an XNA title, this won’t exactly be the case, but we can forgive Microsoft for this, can’t we? When we load this wave bank, we’ll need to set some special parameters to tell our audio engine how to stream, but we’ll get to that once we finish in XACT. Drag music1.wav into the musicwavs wave bank, and then drag the music1 wave into the Cue panel of the musicsnds Sound Bank window. To set music1 to loop, click music1 in the Sound panel of the Sound Bank window and check Infinite under Looping in the Properties panel, as shown in Figure 8-20. Also, set the category to Music. CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE 237 Figure 8-19. Setting up streaming audio in the wave bank properties ■Note Setting the sound category to Music will cause XNA to not play the audio if the Xbox 360 gamer is playing music through the dashboard—a handy feature! Finally, we can set the compression of the audio. Right-click Compression Presets and select New Compression Preset. Name the new preset music, and set the parameters. For Xbox 360, we set Quality to 38. For Windows, we set Samples Per Block to 64, as shown in Figure 8-21. You’ll need to play with the parameters a bit to see how heavily you can compress your audio before you start to hear artifacts. [...]... gamepad, and let the class know which gamepad it is in the constructor Our Rumble.Update() method will reduce our vibration values and set our gamepad vibration using System; using Microsoft .Xna. Framework; using Microsoft .Xna. Framework.Input; namespace ZombieSmashers.Shakes { class Rumble { private Vector2 rumbleValue = Vector2.Zero; private PlayerIndex playerIndex; public Rumble(int idx) { playerIndex =... void Draw(SpriteBatch sprite, Texture2D spritesTex) { sprite.Draw(spritesTex, GameLocation, new Rectangle(flag * 64, 0, 64, 64), new Color( new Vector4(r, g, b, a * frame)), rotation, new Vector2(32.0f, 32.0f), size, SpriteEffects.None, 1.0f); } Initializing and Killing the Character We’ll add some fields to the Character class to get it ready for the new functionality we’re going to throw at it: an... from which to launch into shaders (in Chapter 11) CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE We set up our render loop to draw everything to the backbuffer The backbuffer is a piece of texture memory that XNA uses for just this purpose We clear the backbuffer, draw to the backbuffer, and then present the backbuffer to the screen with the method base.Draw(gameTime) We’ll change our render loop to use a new... Zombies shamble • hp 65: A few spanner-whack combos will do it • ai zombie: Use the zombie AI, which we’ll get to in the “Adding AI” section There’s quite a bit of implementation to get to in ZombieSmashersXna We’ll start with our blood triggers CHAPTER 9 ■ SCRIPTING, AI, AND DEPTH (AND DEATH) Figure 9-4 The init animation Spraying Blood Let’s implement the triggers in the game First off, we’ll need to... BloodDust(loc, Rand.getRandomVector2(-30f, 30f, -30f, 30f), 1f, 0f, 0f, 4f, Rand.getRandomFloat(.025f, 125f), Rand.getRandomInt(0, 4))); } break; We’ll create our BloodDust class in our ZombieSmashersXNA.Particles namespace It’s almost the same as our Smoke class, but we’ve taken out the Update() and simplified Draw() a bit The idea behind all of these odd particle classes is to reduce functionality... smaller block sizes will cause our game music to stutter if things get hectic, but 16 seemed to work fine CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE using System; using System.Globalization; using Microsoft .Xna. Framework.Audio; namespace ZombieSmashers.Audio { static class Music { private static WaveBank wave; private static SoundBank sound; private static Cue musicCue; private static string musicStr; static . MORE 23 5 case TRIG_PISTOL_ACROSS: pMan.MakeBullet(loc, new Vector2 ( 20 00f, 0f), face, ID); Sound.PlayCue("revol"); break; case TRIG_PISTOL_DOWN: pMan.MakeBullet(loc, new Vector2(1 400 f,. pMan.MakeBloodSplash(p.Location, new Vector2(-50f * tX, -150f)); c[i].Trajectory.X = 100 f * tX; c[i].SetAnim("jhit"); c[i].SetJump( 700 f); Game1.SlowTime = 0. 125 f; QuakeManager.SetQuake(.5f); . Game1.Update(): 24 4 CHAPTER 8 ■ XACT AUDIO, RUMBLE, AND MORE QuakeManager.Update(); frameTime = (float)gameTime.ElapsedGameTime.TotalSeconds; Scroll += ((character [0] .Location - new Vector2( 400 f, 400 f))