在2D游戏开发中,资源管理是一个关键环节,它涉及到图像、字体、声音和音乐等不同类型的资源。本文将介绍如何对这些资源进行分类、识别、管理和使用。
首先,定义了一个枚举类型ResourceType
来区分不同类型的资源。例如,图像资源、字体资源、声音资源和音乐资源。
internal enum ResourceType
{
Image,
Font,
Sound,
Music,
}
在这个枚举中,Image
代表图像资源,Font
代表字体资源,而Sound
和Music
代表声音资源。通常,Music
用于播放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 Resources;
internal ResourceManager(IList resources)
{
this.Resources = null == resources ? new Resource[] { } : resources;
}
当然,ResourceManager
本身并不能加载资源,因此需要使用ContentManager
类。
private ContentManager contentManager;
internal World World;
private readonly Dictionary textures = new Dictionary();
private readonly Dictionary fonts = new Dictionary();
private readonly Dictionary sounds = new Dictionary();
private readonly Dictionary music = new Dictionary();
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(resolution + resource.Path));
break;
case ResourceType.Font:
this.fonts.Add(resource.Name, this.contentManager.Load(resource.Path));
break;
case ResourceType.Sound:
this.sounds.Add(resource.Name, this.contentManager.Load(resource.Path).CreateInstance());
break;
case ResourceType.Music:
this.music.Add(resource.Name, this.contentManager.Load(resource.Path));
break;
}
}
}
catch { }
}
在LoadContent
方法中,将创建一个新的ContentManager
对象,并使用Load
方法来加载资源。
最后,在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
对象,并指定了需要的图片和声音文件。
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();
}
使用GetTexture
和GetSound
方法来获取图片和声音,只需要传递资源的名称。
最后,还需要在合适的位置调用ResourceManager
的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();
}