[翻译]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:
1  Cue cue1;
                                 填充这个对象通过调用GetCue方法在你的soundBank变量中。在这个Cue对象,你可以调用这个Play方法去开始一个cue:
1  cue1 = soundBank.GetCue( " audio1 " );
2  cue1.Play();
                                 这将开始无限播放cue,正如你定义在XACT音频工具。只在这时,你有一个相关的cue,你可以使用它暂停,重新开始,或者停止这个cue:
1  cue1.Pause();
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是否已经播放:

1  if (currentCue.IsStopped)
2       // do something
                                 如果你想要你的XNA项目去通过一些背景声音来循环,你应该创建一个数组去保留cues的名字,并且不是cues它们自己,一旦它们已经播放,它将是没有用的。你需要这些额外变量去创建一个背景循环系统:

 

1  string [] bgCueNames;
2  Cue currentCue;
3  int  currentCueNr = 0 ;
                                 这个数组将保留被播放的背景cues的名字。currentCue将保留这个正在播放的cue,这样你可以检查是否它被完成了,并且currentCueNr变量被需要的,这样你的程序可以激活下一个cue.
                                 这个方法它初始化cue名字的数组,并且开始第一个cue:
 1  private   void  InitSounds()
 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  }
                                 你首先不得不创建一个XACT项目,如图7-1所示,包含五个cues.这个PlayBGCue方法,他实际上开始一个cue很容易:
1  private   void  PlayBGCue( int  cueNr)
2  {
3      currentCue = soundBank.GetCue(bgCueNames[cueNr]);
4      currentCue.Play();
5  }
                                 它保存一个相关的当前播放的cue在currentCue变量中,这样你可以检查它的IsPlayed属性在一个UpdateSounds方法中,这样你可以从你的主Update方法中调用:
ContractedBlock.gif ExpandedBlockStart.gif Code
 1 private void UpdateSounds()
 2 {
 3      if(currentCue.IsStopped)
 4      {
 5          if(++currentCueNr==bgCueNames.Length)
 6                  currentCueNr=0;
 7          PlayBGCue(currentCueNr);
 8      }
 9      audioEngine.Update();
10 }

                                 如果当前的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键结束它:

 1  protected   override   void  Update(GameTime gameTime)
 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变量将会是null。当用户压下Enter键,这个cue被停止。当用户再次压下空格键,这个cue被重新设置。
                                 再一次,注意,你需要去重新创建这个cue1变量(通过调用GetCue方法)在cue已经停止之后。
源代码: http://shiba.hpe.cn/jiaoyanzu/WULI/soft/xna.aspx?classId=4
(完)

转载于:https://www.cnblogs.com/315358525/archive/2009/09/04/1560155.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值