[翻译]XNA 3.0 Game Programming Recipes之fifty-one
PS:自己翻译的,转载请著明出处
7-4 循环声音
问题
你想要循环声音去播放背景音乐或者播放一个持续的声音,例如汽车引擎的噪音。
注意:由于Zune不支持XACT,你想要使用三个重载的SoundEffect.Play()方法去循环你的声音,正如7-1节相应的内容。
解决方案
使用XACT声音工具,它是非常的容易去表示一个声音应该持续循环。你想要去创建并跟踪Cue对象在你的XNA代码,因为你需要能够暂停或者停止正在播放的声音。
你同样可以编程的方式检测当一个声音是否已经完成了播放,这是非常有用的,如果你想要选择背景音乐。通过检查Cue的IsStopped成员来实现这个。
它是如何实现的
Looping a Sound Indefinitely(无限循环一个声音)
你可以很容易产生一个循环通过设置它的LoopEvent属性到Infinite在XACT音频工具。为了实现这个,打开你的XACT项目,并且选择在你的sound bank中这个你想要循环的声音。一旦你已经选择这个声音,这Play Wave的条目应该可见在Sound Bank 框架的右上角。点击Play Wave节点,如图7-2显示的。
在点击Play Wave节点,它的属性应该可见在属性合子里在你的XACT窗口的左下角。找到LoopEvent属性,并设置它到Infinite.确保你保存你的XACT属性。
现在,当你重新编译你的XNA项目并且播放cue使用从前面中的代码,它将无限循环。由于你想要某些种类的控制,它允许你去停止cue,你需要创建一个Cue对象去保存一个相关的cue:
2 cue1.Play();
2 cue1.Resume();
3 cue1.Stop(AudioStopOptions.Immediate);
注意:在你已经停止一个正在播放的cue,你不可以简单的调用Play在cue上。你首先需要从soundBank通过调用它的GetCue方法去加载它
Checking Whether a Sound Has Finished Playing/Changing Background Music
通过它的IsStopped属性,你可以检查一个声音cue是否已经播放:
2 //do something
2 Cue currentCue;
3 int currentCueNr=0;
这个方法它初始化cue名字的数组,并且开始第一个cue:
2 {
3 audioEngine=new AudioEngine("Content/Audio/MyXACTproject.xgs");
4 waveBank=new WaveBank(audioEngine,"Content/Audio/myWaveBank.xwb");
5 soundBank=new SoundBank(audioEngine,"Content/Audio/mySoundBank.xsb");
6 bgCueNames=new string[5];
7 bgCueNames[0]="bgAudio1";
8 bgCueNames[1]="bgAudio2";
9 bgCueNames[2]="bgAudio3";
10 bgCueNames[3]="bgAudio4";
11 bgCueNames[4]="bgAudio5";
12 PlayBGCue(0);
13 }
2 {
3 currentCue=soundBank.GetCue(bgCueNames[cueNr]);
4 currentCue.Play();
5 }
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
如果当前的cue已经正在播放了,你增加currentCueNr,同时设置它回到0,如果已经比可播放cues的数量大,在这种情况下是5。最后,你调用PlayBGCue,所以下一个音频开始播放。
注意:在currentCueNr之前++表示你想要currentCueNr的值去增加在整个行前得到评估。如果你写了currentCueNr++,这个条件将会是false,如果currentCueNr是4,并且在此之后,这个值增加到5,这将得到一个OutOfRange异常在GetCue方法中。通过写++currentCueNr,如果currentCueNr是4,这个值首先增加到5,这样这个条件将会是true,并且值将重新设置成0。
通过把Update访问在这个方法中的audioEngine,在这个Update方法中所有你不得不调用的是UpdateSounds方法。
代码
直到你可以找到所有的代码为本章前面这个背景播放列表的循环,下面的代码开始一个循环默认的声音在这节的第一部分,通过压下空格键并且通过Enter键结束它:
2 {
3 GamePadState gamePadState=GamePad.GetState(PlayerIndex.One);
4 if(gamePadState.Buttons.Back==ButtonState.Pressed)
5 this.Exit();
6 KeyboardState keyState=Keyboard.GetState();
7 if(keyState.IskeyDown(Keys.Space)||(gamePadState.Buttons.B==ButtonState.Pressed))
8 {
9 if((cue1==null)||(cue1.IsStopped))
10 {
11 cue1=soundBank.GetCue("audio1");
12 cue1.Play();
13 }
14 }
15 if(keyState.IsKeyDown(Keys.Enter)||(gamePadState.Buttons.A==ButtonState.Pressed))
16 if(cue1!=null)
17 cue1.Stop(AudioStopOptions.Immediate);
18 audioEngine.Update();
19 base.Update(gameTime);
20 }
再一次,注意,你需要去重新创建这个cue1变量(通过调用GetCue方法)在cue已经停止之后。
源代码:http://shiba.hpe.cn/jiaoyanzu/WULI/soft/xna.aspx?classId=4
(完)