§9.3Sound类

创建Sound类真的很简单。你已经在第一章看到了一些Sound类,sound cue回放非常简单。为了使使用起来更简单,您可以定义一个枚举包含所有的声音cue名称。通过这种方式可以确保每一个sound cue确实存在,而且你不会输错名称。这样做的另一个优点是智能感知,它将会显示隐藏在XACT项目中所有可用的sound cue。花费两分钟时间写这些枚举是值得的。在Sound类中的Play方法帮助下,现在播放sound cue很容易。

/// <summary>

/// Play

/// </summary>

/// <param name="soundName" /> Sound name

public static void Play(string soundName)

{

if (soundBank == null)

return;

try {

soundBank.PlayCue(soundName);

} // try

catch (Exception ex)

{

Log.Write("Playing sound " + soundName + " failed: " + ex.ToString());

} // catch

} // Play(soundName)

/// <summary>

/// Play

/// </summary>

/// <param name="sound" /> Sound

public static void Play(Sounds sound)

{

Play(sound.ToString());

} // Play(sound)

您也可以通过让字符串私有使得只允许声音枚举。如果sound bank无法在构造函数中初始化(例如,如果该文件丢失)此方法将立即返回而您无法播放任何声音。错误会被记录到日志文件中。接着你调用PlayCue播放并忘记sound cue。如果失败你只写入日志文件,因为你不想因为某些声音文件的丢失打断正常的程序逻辑。

正如你之前所见,您也可以使用GetCue方法记住一个sound cue,然后做多个事情。如果您想自己停止cue而不是等待声音放完,这样做是很有用的。作为一个例子,下面的代码用来停止播放音乐:

someSoundCue = soundBank.GetCue("SomeSound"); someSoundCue.Play(); ... someSoundCue.Stop(AudioStopOptions.Immediate);

本书中的游戏的Sound类中的大部分代码是相同的,下面看看不同和特殊功能(见图9-14)。

图9-14

图9-14

首先你会发现在Sound枚举中有不同的sound cue名称。Rocket Commander和赛车游戏使用自定义的picth cue。XNA Shooeter不使用任何特殊设置,你只需在游戏开始时播放音乐,然后播放所有音效。

为了使输入播放声音的代码更舒适,创建了几个辅助方法。例如,PlayExplosionSound只是取代了下面的代码使其能更快并更容易编写:

Sound.Play(Sound.Sounds.Explosion);

对于音乐播放添加了两个额外的方法:StartMusic和StopMusic,它们也保存了music cue的音轨。

每个sound类中还有一个单元测试用来检查回放声音是否正常,并检查音量是否正确。下面是Rocket Commander声音类中的单元测试:

/// <summary>

/// Test play sounds

/// </summary>

public static void TestPlaySounds()

{

TestGame.Start(

delegate

{

if (Input.MouseLeftButtonJustPressed || Input.GamePadAJustPressed)

Sound.Play(Sounds.Bomb);

else if (Input.MouseRightButtonJustPressed || Input.GamePadBJustPressed)

Sound.Play(Sounds.Click);

else if (Input.KeyboardKeyJustPressed(Keys.D1))

Sound.Play(Sounds.GameMusic);

else if (Input.KeyboardKeyJustPressed(Keys.D2))

Sound.Play(Sounds.MenuMusic);

else if (Input.KeyboardKeyJustPressed(Keys.D3))

Sound.Play(Sounds.Explosion);

else if (Input.KeyboardKeyJustPressed(Keys.D4))

Sound.Play(Sounds.Fuel);

else if (Input.KeyboardKeyJustPressed(Keys.D5))

Sound.Play(Sounds.Victory);

else if (Input.KeyboardKeyJustPressed(Keys.D6))

Sound.Play(Sounds.Defeat);

else if (Input.KeyboardKeyJustPressed(Keys.D7))

{

Sound.PlayRocketMotorSound(0.75f);

Sound.ChangeRocketMotorPitchEffect(0.5f);

} // else if

else if (Input.KeyboardKeyJustPressed(Keys.D8))

Sound.StopRocketMotorSound();

TextureFont.WriteText(2, 30, "Press 1-8 or A/B or left/right "+ "mouse buttons to play back sounds!");

}

);

} // TestPlaySounds()

最后,Update方法被BaseGame类中的Update方法自动调用。Update方法只为您确保在XACT中所有参数,循环,时间值的更新。

火箭发动机声音

快速看一下Rocket Commander中的火箭发动机声音。前面你已经看到完成这个工作所需的代码,下面是如何整合在一起并配合Rocket Commander游戏引擎,一开始这是用DirectSound写的,但在XACT中工作得也很好:

/// <summary>

/// Play rocket motor sound

/// </summary>

public static void PlayRocketMotorSound()

{

// Get new cue everytime this is called, else we get Xact throwing

// this: The method or function called cannot be used in the manner

// requested.

rocketMotorSound = soundBank.GetCue(Sounds.RocketMotor.ToString());

// Plays the sound looped, set in XACT

rocketMotorSound.Play();

// Make motor category a little silent

motorCategory.SetVolume(0.86f);

}

// PlayRocketMotorSound(volume)

/// <summary>

/// Change rocket motor pitch effect

/// </summary>

/// <param name="pitchFactor" />

Pitch factor public static void ChangeRocketMotorPitchEffect(float pitchFactor)

{

rocketMotorSound.SetVariable("Pitch", 55 * MathHelper.Clamp(pitchFactor - 1, -1, 1));

} // ChangeRocketMotorPitchEffect(pitchFactor)

/// <summary>

/// Stop rocket motor sound

/// </summary>

public static void StopRocketMotorSound()

{

rocketMotorSound.Stop(AudioStopOptions.Immediate);

} // StopRocketMotorSound()

游戏开始后你只需调用PlayRocketMotorSound方法就能播放火箭的声音,然后通过ChangeRocketMotorPitchEffect方法修改它:

// Adjust rocket playback frequency to flying speed

Sound.ChangeRocketMotorPitchEffect(0.66f + speed * 0.9f);

如果你失败或任务结束,则调用StopRocketMotorSound方法停止播放火箭的声音。

赛车游戏中的声音逻辑工作方法类似,但更加复杂,因为你有13个不同的发动机声音。看一下赛车游戏的sound类了解更多细节。

Whoosh,那是什么呀?

初版本的Rocket Commander使用自己的3D音效计算公式并使用DirectSound的音量和和panning属性。在XNA中不能改变panning。所有声音必须以在XACT中创建和设置的方式播放。对于3D声音,你应该使用真实的3D声音代码,在XNA电测版本中我写了一些播放3D声音的代码,并实现了一个在三维世界中的3D监听对象。

这个3D监听对象在XNA中被移除,现在您不能使用3D音效。希望将来会做出改变,如果3D可以被实现,我一定会更新这本书中的代码,但现在你只能播放单声道的声音,没有立体声或环绕声。

如果你可以使用X3DAudio和X3DAudioListener (这些类可能有不同的名称,重要的是您可以设置和播放3D音频效果,并且在3D listener类的帮助下确定玩家的位置),在设置了所有重要的cue后,下面的代码用于播放3D声音:

// Setup 3D listener for 3D sound

Sound.Listener = new X3DAudioListener( zAxis, yAxis, cameraPosition, movementVector);

现在,为每个声音设置发射器并播放3D音频实例。目前还没有C#代码可以做到这一点,如果你对此感到困惑,你可以看看下面的链接去了解X3Daudio类是如何使用C++的。在C#中做法类似,但希望能更容易编写。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/ audio_xact_overview_x3daudio.asp

菜单声音

这里有一些关于菜单提示声音的小技巧:


发布时间:2008/12/17 10:37:52  阅读次数:6287

2006 - 2024,推荐分辨率1024*768以上,推荐浏览器Chrome、Edge等现代浏览器,截止2021年12月5日的访问次数:1872万9823 站长邮箱

沪ICP备18037240号-1

沪公网安备 31011002002865号