zoukankan      html  css  js  c++  java
  • 通过简单的 ResourceManager 管理 XNA 中的资源,WPXNA(二)

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

    资源的类型

    在一些简单的 2D 游戏设计中,我们通常用到的资源是一些字体,图像和声音。所以这里就不涉及视频和模型这些内容了,要制作视频和 3D 模型往往需要花费很多时间。

    这里,平方通过枚举类型 ResourceType 来区分不同的资源:

    internal enum ResourceType
    {
        Image,
        Font,
        Sound,
        Music,
    }

    在上面的代码中,Image 表示图像资源,Font 表示字体资源。Sound 和 Music 都表示声音资源,不同的是 Music 通过 MediaPlayer 类播放(一般是 mp3 文件),而 Sound 一般指一些小的 wav 文件。

    标识资源

    平方创建了一个 Resource 结构来标识一个资源,他有三个公开的字段,Name 是资源的名称,这个名称不能和其他资源重复。Type 是资源的类型,也就是上面提到的 ResourceType。Path 是资源的访问路径,也就是资源文件在项目中的位置,如下图所示:

    internal struct Resource
    {
    
        internal readonly string Name;
        internal readonly string Path;
        internal readonly ResourceType Type;
    
        internal Resource ( string name, ResourceType type, string path )
        {
    
            if ( string.IsNullOrEmpty ( name ) || string.IsNullOrEmpty ( path ) )
                throw new ArgumentNullException ( "name, path", "name, path can't be null" );
    
            this.Name = name;
            this.Type = type;
            this.Path = path;
        }
    
    }

    因为,只有正确的载入资源,游戏才能正常运行,所以在 Resource 类的构造函数中,平方对参数作了一些检查。

    管理资源

    然后,我们可以通过 ResourceManager 来管理资源。

    在构造函数中,我们接受一个 Resource 结构数组,他们也就是需要管理的资源。

    internal readonly IList<Resource> Resources;
    
    internal ResourceManager ( IList<Resource> resources )
    { this.Resources = null == resources ? new Resource[] { } : resources; }

    当然,ResourceManager 本身并不能够载入资源,所以我们需要使用 ContentManager 类:

    private ContentManager contentManager;
    internal World World;
    
    private readonly Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D> ( );
    private readonly Dictionary<string, SpriteFont> fonts = new Dictionary<string, SpriteFont> ( );
    private readonly Dictionary<string, SoundEffectInstance> sounds = new Dictionary<string, SoundEffectInstance> ( );
    private readonly Dictionary<string, Song> music = new Dictionary<string, Song> ( );
    
    public void LoadContent ( )
    {
    
        if ( null == this.contentManager )
            this.contentManager = new ContentManager ( this.World.Services, contentDirectory );
    
        try
        {
    
            foreach ( Resource resource in this.Resources )
                switch ( resource.Type )
                {
                    case ResourceType.Image:
                        this.textures.Add ( resource.Name, this.contentManager.Load<Texture2D> ( resolution + resource.Path ) );
                        break;
    
                    case ResourceType.Font:
                        this.fonts.Add ( resource.Name, this.contentManager.Load<SpriteFont> ( resource.Path ) );
                        break;
    
                    case ResourceType.Sound:
                        this.sounds.Add ( resource.Name, this.contentManager.Load<SoundEffect> ( resource.Path ).CreateInstance ( ) );
                        break;
    
                    case ResourceType.Music:
                        this.music.Add ( resource.Name, this.contentManager.Load<Song> ( resource.Path ) );
                        break;
                }
    
        }
        catch { }
    
    }

    调用 ResourceManager 的 LoadContent 方法来载入资源,在 LoadContent 方法中,我们会创建一个新的 ContentManager 对象,并通过他的 Load 方法载入我们事先接受的资源。

    要创建 ContentManager,我们还需要设置 ResourceManager 的 World 字段(你也可以将他修改为属性)。所以,在调用 LoadContent 之前,你需要确保 World 字段不为空。

    当你觉得这些资源已经没有用了的时候,调用 UnloadContent 方法来释放资源:

    public void UnloadContent ( )
    {
    
        foreach ( Texture2D texture in this.textures.Values )
            texture.Dispose ( );
    
        foreach ( SoundEffectInstance sound in this.sounds.Values )
            sound.Dispose ( );
    
        foreach ( Song song in this.music.Values )
            song.Dispose ( );
    
        this.textures.Clear ( );
        this.fonts.Clear ( );
        this.sounds.Clear ( );
        this.music.Clear ( );
    
        if ( !this.Resources.IsReadOnly )
            this.Resources.Clear ( );
    
        if ( null != this.contentManager )
            this.contentManager.Unload ( );
    
    }

    在上面的代码中,我们先对所有的资源调用了 Dispose 方法,然后调用了 ContentManager 的 Unload 方法。

    使用资源

    最后,我们在 World 类中具体的使用一下 ResourceManager 类。

    private readonly ResourceManager resourceManager;
    
    public World ( Color backgroundColor )
        : base ( )
    {
        // ...
    
        this.resourceManager = new ResourceManager ( new Resource[] {
            new Resource ( "bird", ResourceType.Image, @"image\bird" ),
            new Resource ( "click", ResourceType.Sound, @"sound\click" )
        } );
        this.resourceManager.World = this;
    
    }

    在 World 的构造函数中,我们创建了一个 ResourceManager,并指出我们需要一个图片和一个波形文件。

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

    当页面载入之后,我们调用 LoadContent 方法来载入图片和声音。之后,我们在 OnUpdate 和 OnDraw 方法中使用他们。

    private void OnUpdate ( object sender, GameTimerEventArgs e )
    {
        this.resourceManager.GetSound ( "click" ).Play ( );
    }
    
    private void OnDraw ( object sender, GameTimerEventArgs e )
    {
        this.GraphicsDevice.Clear ( this.BackgroundColor );
    
        this.spiritBatch.Begin ( );
        this.spiritBatch.Draw ( this.resourceManager.GetTexture ( "bird" ), new Vector2 ( 20, 20 ), Color.White );
        this.spiritBatch.End ( );
    }

    通过 ResourceManager 的 GetTexture 和 GetSound 方法可以获取指定的图片和声音,只需要传递资源的名称即可。

    最后,你还需要在一个适合的位置调用 ResourceManager 的 UnloadContent 方法。

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

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

    欢迎平方在其他位置发布的同一文章:http://www.wpgame.info/post/decc4_6329f7

  • 相关阅读:
    Feb292012 个人核心竞争力的构建
    让读书成为一种习惯
    软件工厂方法(二):软件工厂应用
    Scrum之 站立例会
    信息系统开发平台OpenExpressApp - AutoUI自动生成界面
    信息系统开发平台OpenExpressApp-内置支持的属性编辑方式
    信息系统开发平台OpenExpressApp - 订单示例(Getting Started)
    需求入门: 原型开发
    信息系统开发平台OpenExpressApp - 学习必备知识
    从IT方法论来谈RUP
  • 原文地址:https://www.cnblogs.com/zoyobar/p/wpxna2.html
Copyright © 2011-2022 走看看