zoukankan      html  css  js  c++  java
  • 在XNA 3.0 项目添加声音——循环播放声音

    问题

    你想让声音循环播放,例如,播放背景音乐或播放连续的声音,例如一个汽车引擎的声音。

    注意:因为Zune不支持Xact,你需要使用SoundEffect.Play()的重载方法循环播放声音,可见教程7-1中的对应解释。

    解决方案

    使用XAct audio tool,可以很容易地表示一个声音是否要循环播放。你将在XNA代码中创建一个Cue对象,因为你需要能够在播放过程中进行暂停或停止操作。

    你还可以检测一个声音是否已经完成播放,这在你想切换背景音乐时很重要,这个操作可以通过检查Cue的IsStopped属性做到。

    工作原理

    循环播放一个声音你可以通过在Xact工具中将一个声音的LoopEvent属性设为Infinite让它循环播放。要做到这点,打开你的Xact项目,在sound bank中选择需要循环播放的sound。选择了sound后,在Sound Bank面板的右上方的Play Wave会变得可见,点击Play Wave节点,如图7-2所示。

    在点击了Play Wave节点后,它的属性在XAct 窗口的左下方的属性窗口中可见,找到LoopEvent属性,设置为Infinite,别忘了保存Xact项目。

    image

    图7-2 当选择了sound后Play Wave节点会变得可见

    现在当你重新编译XNA项目并使用前面的代码播放cue时,它就会无限循环播放。因为你想进行控制,可以在适当的时候停止播放这个cue,所以需要创建一个Cue对象储存对这个cue的引用:

    Cue cue1; 

    通过调用soundBank变量的GetCue方法对这个变量赋值,你可以通过调用Play方法播放这个cue:

    cue1 = soundBank.GetCue("audio1"); 
    cue1.Play();

    这会让cue循环播放,这是你在XAct audio tool中设置号好的。但这次,你有了指向cue的引用,所以可以暂停、继续或停止这个cue:

    cue1.Pause(); 
    cue1.Resume(); 
    cue1.Stop(AudioStopOptions.Immediate);

    当心:当你从播放中停止一个cue后,你无法简单地在这个cue再次调用Play。你首先需要调用它的GetCue 方法才能从soundBank中再次调用它。

    检查一个Sound是否已经停止播放/改变背景音乐

    你可以通过sound的IsStopped属性检查一个sound cue是否已经完成播放:

    if (currentCue.IsStopped) 
        //do something

    如果你想让XNA程序循环播放一些背景音乐,你需要创建一个数组保存cue的名称而不是cue本身,当cue开始播放后cue本身会变得无用。你需要一些额外的变量创建一个背景循环系统:

    string[] bgCueNames; 
    Cue currentCue;
    int currentCueNr = 0;

    这个数组保存要播放的背景cue的名称,currentCue保存当前正在播放的cue,这样你可以检查它是否已经结束,currentCueNr变量用于激活下一个cue。

    下面的方法初始化cun名称数组并开始第一个cue:

    private void InitSounds()
    ...{
        audioEngine = new AudioEngine("Content/Audio/MyXACTproject.xgs"); 
        waveBank = new WaveBank(audioEngine, "Content/Audio/myWaveBank.xwb"); 
        soundBank = new SoundBank(audioEngine, "Content/Audio/mySoundBank.xsb");
    
        bgCueNames = new string[5]; 
        bgCueNames[0] = "bgAudio1"; 
        bgCueNames[1] = "bgAudio2"; 
        bgCueNames[2] = "bgAudio3"; 
        bgCueNames[3] = "bgAudio4"; 
        bgCueNames[4] = "bgAudio5";
    
        PlayBGCue(0); 
    }

    首先你需要创建一个教程7-1所示的Xact项目,包含5个cue。开始一个cue的PlayBGCue方法是简单的:

    private void PlayBGCue(int cueNr)
    ...{
        currentCue = soundBank.GetCue(bgCueNames[cueNr]); 
        currentCue.Play();
    }

    它在currentCue变量中存储了当前正在播放的cue的引用,所以你可以在UpdateSounds方法中检查它的IsPlayed属性,而UpdateSounds方法放在了主Update方法中:

    private void UpdateSounds() 
    ...{
        if (currentCue.IsStopped) 
        ...{
            if (++currentCueNr == bgCueNames.Length)
                currentCueNr = 0;
    
            PlayBGCue(currentCueNr); 
        }
        audioEngine.Update(); 
    }

    如果当前cue已经完成播放,则增加currentCueNr,如果它大于播放的cue数量(本例中为5)则设为0。最后调用PlayBGCue播放下一个sound。

    注意:在currentCueNr之前的 ++ 表示你想在求值前增加currentCueNr的值。如果写成currentCueNr++,当currentCueNr为4时判断结果为false,之后当值为5时,会抛出 a GetCue方法的OutOfRange错误。通过写成++currentCueNr,如果currentCueNr为4,这个值首先被增加到5,这样判断结果为true,这个值会被设置为0。

    通过在这个方法中放置audioEngine的Update方法,在Update调用的所有东西就是这个UpdateSounds方法。

    代码

    前面的章节中你可以找到循环播放背景音乐列表的所有代码,下面的代码通过按下空格键开始循环播放本教程第一部分中定义的sound,按Enter键停止:

    protected override void Update(GameTime gameTime)
    ...{
        GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);
    
        if (gamePadState.Buttons.Back == ButtonState.Pressed) 
            this.Exit();
    
        KeyboardState keyState = Keyboard.GetState();
    
        if (keyState.IsKeyDown(Keys.Space) || (gamePadState.Buttons.B == ButtonState.Pressed))
    ...    {
            if ((cue1 == null) || (cue1.IsStopped))
    ...        {
                cue1 = soundBank.GetCue("audio1");
                cue1.Play(); 
            }
        }
        if (keyState.IsKeyDown(Keys.Enter) || (gamePadState.Buttons.A ButtonState.Pressed))
            if (cue1 != null)
                cue1.Stop(AudioStopOptions.Immediate);
    
        audioEngine.Update();
        base.Update(gameTime); 
    }

    当空格键第一次被按下时,cue1变量为null。只要用户按下了Enter键,cue就会停止。当用户再次按下空格键,cue会重新播放。

    再次提醒,在cue停止后你需要重新创建cue1变量(通过调用GetCue方法)。

  • 相关阅读:
    .NET中非对称加密RSA算法的密钥保存
    WGS84经纬度坐标到北京54高斯投影坐标的转换[转]
    [APPS] HTC Footprints & HTC Locations for MikG 2.x Read more:
    firefox+ssh无法看youtube视频的解决方案
    【转】sdemon命令实践
    How to share a custom ArcMap command (DLL)
    【转】sdemon命令实践
    红旗桌面版本最新运用法子和结果解答100例8
    红旗Linux桌面4.1文本安装过程图解(二)
    Ubuntu把在效能器范畴起更重要的脚色
  • 原文地址:https://www.cnblogs.com/AlexCheng/p/2120088.html
Copyright © 2011-2022 走看看