[翻译]XNA 3.0 Game Programming Recipes之fifty-two


PS:自己翻译的,转载请著明出处

                                                        7-5 从相对于相机的3D位置播放一个声音:3D声音
问题
                                 为了添加一些更多的真实感觉到你的3D游戏中,你想要能够给你每个声音一个3D空间的位置。这样,一个爆炸在你的相机的右边,将会在右边的扬声器里播放,这样悠忽得到爆炸的效果仿佛真的在右边。甚至如果爆炸不在相机的视景内,用户将可能知道某些发生在他的右边。                               
注意:直到Zune不支持XACT工具,并且使用的Apply3D()方法在下面的解决方案里,只接收Cue对象,3D声音只支持在PC上和Xbox360上。

解决方案

                                XNA已经使这些变的很容易。每一个声音,你不得不设置相机的3D位置和声音的初始位置,使用声音的Cue对象的Apply3D方法。注意,每一次相机或者声源移动了,你需要去更新你的Cue通过调用这个方法。
它是如何实现的
                                如果你想要设置声源的3D位置,你首先需要创建一个AudioEmitter对象为这个声源和AudioListener对象为你的相机。当你传递Cue的Applay3D方法,XNA将计算这个声音是如何分布在连接在你系统里的扬声器中(或者耳机中)。
                                这个方法创建两个对象:
 1 private void UpdateSoundPosition(Cue cue,Vector3 sourcePos,Vector3 camPos,Vector3 camForward,Vector3 camUp)
 2 {
 3      AudioEmitter emitter=new AudioEmitter();
 4      emitter.Position=sourcePos;
 5      AudioListenter listener=new AudioListener();
 6      listener.Position=camPos;
 7      listener.Forward=camForward;
 8      listener.Up=camUp;
 9      cue.Apply3D(listener,emitter);
10 }
                                为了这个发射器(你的声源),你只需要去设置位置。为了听众(你的相机),虽然,你同样需要设置前面和Up向量,因为,当这个相机被旋转了180度,左右转换。
                                当你已经创建并添满两个对象,你可以传递它们到Cue的Apply3D方法中。这需要被做无论声源或者你的相机的移动。
                                你需要调用这个Apply3D方法在你首先调用cue的Play方法之前。因此,确保你不调用Play在你的Cue上:
1 protected override void Initialize()
2 {
3     fpsCam=new QuakeCamera(GraphicsDevice.Viewport,new Vector3(0,0,5),0,0);
4     audioEngine=new AudioEngine("Content/Audio/MyXACTproject.xgs");
5     waveBank=new WaveBank(audioEngine,"Content/Audio/myWaveBank.xwb");
6     soundBank=new SoundBank(audioEngine,"Content/Audio/mySoundBank.xsb");
7     cue1=soundBank.GetCue("audio1");
8     base.Initialize();
9 }
                               在你的Update方法中,无论你更新你的相机的位置或者声源的位置,你应该调用UpdateSoundPosition方法:
 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      MouseState mouseState=Mouse.GetState();
 7      KeyboardState keyState=keyboard.GetState();
 8      fpsCam.Update(mouseState,keyState,gamePadState);
 9      float time=(float)gameTime.TotalGameTime.TotalMillseconds/1000.0f;
10      Vector3 startingPos=new Vector3(0,0,-10);
11      Matrix rotMatrix=Matrix.CreateRotationY(time);
12      modelPos=Vector3.Transform(startingPos,rotMatrix);
13      UpdateSoundPosition(cue1,modelPos,fpsCam.Position,fpsCam.Forward,fpsCam.UpVector);
14      if(cue1.IsPrepared)
15         cue1.Play()p;
16      audioEngin.Update();
17      base.Update(gameTime);
18 }

                                这个方法的上半部分检查用户的输入和传递这个输入到你的3D相机里,如2-3节所解释的。代码的中间块更新你的声源的位置。随着你的相机和声源更新,你应该调用UpdateSoundPosition方法,这样你的cue1对象通知最近的位置。如果你的cue1没有正在播放,现在就开始播放它。
注意:3D效果通过控制单独的左右扬声器的音量实现。意思是任何在这个声音中的立体声信息将会丢失:首先这个声音被转换为单声道,然后左右音量被相应设置到对象的3D位置。

代码
        (略)                                                
课外阅读
                                这个XACT音频工具允许你去图形化添加一些非常不错的3D声音效果到你的cues中,例如距离的衰减和多铺勒转换。因为这是通过图象完成的,这可以证明一个电影比一本书好多了:http://creators.xna.com/站点包含很多非常不错的电影在添加3D声音效果到你的cues上!
源代码:http://shiba.hpe.cn/jiaoyanzu/WULI/soft/xna.aspx?classId=4
(完)

posted on 2009-09-04 11:12  一盘散沙  阅读(244)  评论(0编辑  收藏  举报

导航