2007年10月11日 星期四

XNA Game Studio Express 聲音與 XACT

http://richielin-programer.blogspot.com/2007/10/xna-game-express-xact.html

聲音是遊戲很重要的一環,聲光效果都有的遊戲才會吸引人玩下去
在 XNA Framework 中,如果要加入音樂、音效等效果
必須使用 XACT - Microsoft Cross-Platform Audio Creation Tool 來幫忙達成
以下 XNA MSDN 的範例將一步步示範如果在遊戲中加入聲音

##CONTINUE##

準備工作,使用 XACT 建立聲音專案

開啟上一篇 XNA Game Studio Express 控制模組的移動 範例中的專案
並參考 XNA Game Studio Express 顯示 3D 模組 的文章中
由先前建立的 Spacewar Windows Starter Kit 專案取出聲音檔作示範
首先在開啟專案中先建立相關目錄 Content\Audio\Waves
並 Copy Spacewar Windows Starter Kit 專案中的
Ships\engine_2.wav 及 Weapons\hyperspace_activate.wav 到此專案的相同目錄下

1. 從 Windows 開始選單,選擇 所有程式 -> Microsoft XNA Game Studio Express -> Tools,執行 Microsoft Cross-Platform Audio Creation Tool (XACT)
2. 開啟 XACT 軟體後,儲存專案在此專案的 Contant\Audio 下名稱為 MyGameAudio
3. 新增 New Wave BankNew Sound Bank,並在 Wave Bank 下加入剛才 Copy 至專案目錄下的兩個聲音檔
image

將剛才加入 Wave Bank 的兩個聲音檔,拖曳到 Sound Bank 視窗的 Cue Name Panel 中
如下所示
image

最後,指定當我們播放 engine_2 聲音時,它必須不斷環境播放
這點就像是遊戲不斷環境播放的背景音樂一樣,總不希望背景音樂只播放一次就停止了吧
Sound Bank 視窗中選擇 engine_2 聲音,並在右上方視窗選擇 Play Wave 字樣
並在視窗最左下方 LoopEvent 中選擇 Infinite 指定環境播放
image

最後儲存離開 XACT 軟體
進行到此步驟,XACT 會將我們加入的聲音檔案指定相對目錄及聲音檔的播放動作
以 MyGameAudio.xap 描述檔儲存在 Content\Audio 這個指定的目錄下
接下來就可以將 XACT project 加入示範專案的 Content Pipeline 中

加入聲音至專案

回到 Visual Studio 2005 Express 示範專案中,在 Content\Audio 目錄按右鍵
加入 -> 現有項目,選擇剛才建立的 MyGameAudio.xap
image

在 Initialize 函式下加入以下程式碼將聲音資料載入遊戲中
AudioEngine: 讀入 XACT 專案,副檔名為 .xgs
WaveBank: 取出 AudioEngine 元件中 Wave Bank 的聲音資料,副檔名為 .xwb
SoundBank: 取出 AudioEngine 元件中 Sound Bank 的聲音資料,副檔名為 .xsb

AudioEngine audioEngine;
WaveBank waveBank;
SoundBank soundBank;

protected override void Initialize()
{
    audioEngine = new AudioEngine("Content\\Audio\\MyGameAudio.xgs");
    waveBank = new WaveBank(audioEngine, "Content\\Audio\\Wave Bank.xwb");
    soundBank = new SoundBank(audioEngine, "Content\\Audio\\Sound Bank.xsb");
    base.Initialize();
}

程式中使用 Cue 物件來處理聲音播放、停止的功能
在 update 函式中判斷鍵盤輸入及決定聲音的輸出與否
需注意的是,update 函式會不斷的被呼叫,必須判斷聲音播放的狀態決定執行的動作
避免已在播放中時還不斷的要求播放,造成系統的負載

// Cue so we can hang on to the sound of the engine.
Cue engineSound = null;

protected void UpdateInput()
{
    // Get the game pad state.
    KeyboardState keyboard_currentState = Keyboard.GetState();
    if (keyboard_currentState != null)
    {
        // Rotate the model using the left thumbstick, and scale it down.
        if (keyboard_currentState.IsKeyDown(Keys.Left) == true)
            modelRotation += 1 * 0.10f;
        if (keyboard_currentState.IsKeyDown(Keys.Right) == true)
            modelRotation -= 1 * 0.10f; 

        // Create some velocity if the right trigger is down.
        Vector3 modelVelocityAdd = Vector3.Zero; 

        // Find out what direction we should be thrusting, using rotation.
        modelVelocityAdd.X = -(float)Math.Sin(modelRotation);
        modelVelocityAdd.Z = -(float)Math.Cos(modelRotation); 

        // Now scale our direction by how hard the trigger is down.
        if (keyboard_currentState.IsKeyDown(Keys.Up) == true)
            modelVelocityAdd *= 3;
        if (keyboard_currentState.IsKeyDown(Keys.Down) == true)
            modelVelocityAdd *= 0.3F; 

        // Finally, add this vector to our velocity.
        modelVelocity += modelVelocityAdd; 

        // Set some audio based on whether we're pressing a trigger.
        if (keyboard_currentState.IsKeyDown(Keys.Up) == true)
        {
            if (engineSound == null)
            {
                engineSound = soundBank.GetCue("engine_2");
                engineSound.Play();
            } 
            else if (engineSound.IsPaused)
            {
                engineSound.Resume();
            }
        }
        else
        {
            if (engineSound != null && engineSound.IsPlaying)
            {
                engineSound.Pause();
            }
        } 

        // In case you get lost, press A to warp back to the center.
        if (keyboard_currentState.IsKeyDown(Keys.Space) == true)
        {
            modelPosition = Vector3.Zero;
            modelVelocity = Vector3.Zero;
            modelRotation = 0.0f; 

            // Make a sound when we warp.
            soundBank.PlayCue("hyperspace_activate");
        }
    } 

    // Get the game pad state.
    GamePadState currentState = GamePad.GetState(PlayerIndex.One);
    if (currentState.IsConnected)
    {
        // Rotate the model using the left thumbstick, and scale it down.
        modelRotation -= currentState.ThumbSticks.Left.X * 0.10f; 

        // Create some velocity if the right trigger is down.
        Vector3 modelVelocityAdd = Vector3.Zero; 

        // Find out what direction we should be thrusting, using rotation.
        modelVelocityAdd.X = -(float)Math.Sin(modelRotation);
        modelVelocityAdd.Z = -(float)Math.Cos(modelRotation); 

        // Now scale our direction by how hard the trigger is down.
        modelVelocityAdd *= currentState.Triggers.Right; 

        // Finally, add this vector to our velocity.
        modelVelocity += modelVelocityAdd; 

        GamePad.SetVibration(PlayerIndex.One, currentState.Triggers.Right,
            currentState.Triggers.Right); 

        // Set some audio based on whether we're pressing a trigger.
        if (currentState.Triggers.Right > 0)
        {
            if (engineSound == null)
            {
                engineSound = soundBank.GetCue("engine_2");
                engineSound.Play();
            } 
            else if (engineSound.IsPaused)
            {
                engineSound.Resume();
            }
        }
        else
        {
            if (engineSound != null && engineSound.IsPlaying)
            {
                engineSound.Pause();
            }
        } 

        // In case you get lost, press A to warp back to the center.
        if (currentState.Buttons.A == ButtonState.Pressed)
        {
            modelPosition = Vector3.Zero;
            modelVelocity = Vector3.Zero;
            modelRotation = 0.0f; 

            // Make a sound when we warp.
            soundBank.PlayCue("hyperspace_activate");
        }
    }
}

原本 XNA MSDN 範例中以 XBOX360 為示範平台
天秤將它改成以 PC 鍵盤輸入操作及聲音輸出
範例中按下上鍵時飛行器會加速,並發出加速的聲音,由於 engine_2 聲音在 XACT 中被指定為不斷播放,所以按住上鍵時會持續的播放直到放開
按下 Space 鍵時飛行器會回到預設值,並發出 hyperspace_activate 聲音

下載: 本範例程式碼及執行檔下載

0 意見: