• 使用 AudioManager 类在 XNA 中播放控制声音和音乐,WPXNA(五)


    平方已经开发了一些 Windows Phone 上的一些游戏,算不上什么技术大牛。在这里分享一下经验,仅为了和各位朋友交流经验。平方会逐步将自己编写的类上传到托管项目中,没有什么好名字,就叫 WPXNA 吧,最后请高手绕道而行吧,以免浪费时间。(为了突出重点和减少篇幅,有些示例代码可能不够严谨。)

    管理音频

    在 XNA 中,你可以通过 SoundEffectInstance,SoundEffect 或者 MediaPlayer 类播放音频,其中 SoundEffectInstance 和 SoundEffect 都可以用来播放一些短小的声音文件,但他们也存在细微的差别,可以参考 XNA 中 SoundEffect 与 SoundEffectInstance 的区别。MediaPlayer 可以播放 mp3 等时间较长的文件。

    为了管理这些音频,平方创建了 AudioManager 类。首先,我们需要载入所需要的资源:

    private readonly Dictionary<string, SoundEffectInstance> sounds = new Dictionary<string, SoundEffectInstance> ( );
    private readonly Dictionary<string, Song> music = new Dictionary<string, Song> ( );
    
    internal void LoadContent ( ResourceManager resourceManager )
    {
    
        if ( null == resourceManager )
            return;
    
        foreach ( Resource resource in resourceManager.Resources )
            if ( resource.Type == ResourceType.Sound )
                this.sounds.Add ( resource.Name, resourceManager.GetSound ( resource.Name ) );
            else if ( resource.Type == ResourceType.Music )
                this.music.Add ( resource.Name, resourceManager.GetMusic ( resource.Name ) );
    
    }

    因为,我们所有的资源都是通过 ResourceManager 管理和加载的,所以这里的 LoadContent 方法将获取 ResourceManager 中所有类型为 Sound 和 Music 的资源,并将他们分别保存到字段 sounds 和 music 中。

    我们并不需要去释放音频资源,因为他们都是被 ResourceManager 来管理的,所以在 AudioManager 的 UnloadContent 方法中,我们只需要停止音频的播放即可。

    internal void UnloadContent ( )
    {
    
        this.StopAllSound ( );
    
        this.StopMusic ( );
    
        this.sounds.Clear ( );
        this.music.Clear ( );
    }
    
    internal void StopAllSound ( )
    {
    
        foreach ( SoundEffectInstance sound in this.sounds.Values )
            sound.Stop ( );
    
    }
    
    internal void StopMusic ( )
    {
    
        if ( !MediaPlayer.GameHasControl || !this.isMusicPlaying )
            return;
    
        MediaPlayer.Stop ( );
        this.isMusicPlaying = false;
    }

    在上面的代码中,StopAllSound 和 StopMusic 方法,分别用来停止播放声音和音乐。对于方法 StopMusic,我们使用了类 MediaPlayer,因此,我需要使用属性 GameHasControl 判断游戏对 Media Player 的控制权。此外,你还需要在 WMAppManifest.xml 文件中,增加一个功能 ID_CAP_MEDIALIB,否则将不能播放音乐:

    使用 PlaySound 和 PlayMusic 来播放音频,其中,你可以使用 isLoop 参数来指定是否循环播放音乐。每一次你调用 PlayMusic 都会立刻从开始播放音乐。

    internal void PlaySound ( string name )
    {
    
        if ( !IsSoundOn || string.IsNullOrEmpty ( name ) || !this.sounds.ContainsKey ( name ) )
            return;
    
        if ( this.sounds[name].State != SoundState.Playing )
            this.sounds[name].Play ( );
    
    }
    
    internal void PlayMusic ( string name, bool isLoop )
    {
    
        if ( !IsMusicOn || !MediaPlayer.GameHasControl || string.IsNullOrEmpty ( name ) || !this.music.ContainsKey ( name ) )
            return;
    
        if ( MediaPlayer.State != MediaState.Stopped )
            MediaPlayer.Stop ( );
    
        try
        {
            MediaPlayer.Play ( this.music[name] );
    
            MediaPlayer.IsRepeating = isLoop;
            this.isMusicPlaying = true;
        }
        catch { }
    
    }

    字段 IsSoundOn 和 IsMusicOn 用来控制是否播放声音和音乐。

    internal static bool IsSoundOn = true;
    internal static bool IsMusicOn = true;

    使用 AudioManager

    像以前的例子一样,我们需要定义一个 ResourceManager。

    private readonly ResourceManager resourceManager;
    private readonly AudioManager audioManager;
    private int step = 1;

    在构造函数中,我们定义所需要的音频资源并创建 AudioManager。

    public World ( Color backgroundColor )
        : base ( )
    {
        // ...
        
        this.resourceManager = new ResourceManager ( new Resource[] {
            new Resource ( "click.s", ResourceType.Sound, @"sound\click" ),
            new Resource ( "music1", ResourceType.Music, @"sound\music1" )
        } );
        this.resourceManager.World = this;
    
        this.audioManager = new AudioManager ( );
    }

    页面载入后,我们使用 ResourceManager 载入所有资源,并将资源传递给 AudioManager,这样 AudioManager 就可以控制音频了。

    protected override void OnNavigatedTo ( NavigationEventArgs e )
    {
        // ...
        
        this.resourceManager.LoadContent ( );
        this.audioManager.LoadContent ( this.resourceManager );
    
        base.OnNavigatedTo ( e );
    }

    最后,平方编写了一段简单的代码。

    private void OnUpdate ( object sender, GameTimerEventArgs e )
    {
        this.step++;
    
        if ( this.step <= 60 )
            this.audioManager.PlaySound ( "click.s" );
        else if ( this.step == 61 )
            this.audioManager.PlayMusic ( "music1" );
        else if ( this.step == 300 )
            this.audioManager.StopMusic ( );
    
    }

    本期视频 http://v.youku.com/v_show/id_XNTYzODcwMDYw.html
    项目地址 http://wp-xna.googlecode.com/

    更多内容 WPXNA
    平方开发的游戏 http://zoyobar.lofter.com/
    QQ 群 213685539

    欢迎访问我在其他位置发布的同一文章:http://www.wpgame.info/post/decc4_65cbf7

  • 相关阅读:
    TAdvStringGrid控件使用技巧[转]
    char, array of char, PChar
    C#操作xml文件入门
    用C#实现生成PDF文档(附源码)
    使用DDE技术,为您的应用程序增辉
    我要减肥了
    查询一个表中相同的记录
    获得Windows特殊目录
    用VB创建快捷方式(无需第三方DLL)
    为office编写插件
  • 原文地址:https://www.cnblogs.com/zoyobar/p/wpxna5.html
Copyright © 2020-2023  润新知