Introduction/Catalog
I have developed some games on Windows Phone. Here, I'll share my experiences and gradually upload some classes, no good name, I just call it WPXNA. (Some example code may not be stringent enough.)
- Resource Type
- Identify Resources
- Resources Management
- Use the Resources
Resource Type
In some simple 2D games, we usually use the resources as font, image and sound. So here is not related to video and model, it will spend a lot of time to make video and 3D models.
Here, I created an enum
ResourceType
to distinguish different types of resources:
internal enum ResourceType
{
Image,
Font,
Sound,
Music,
}
In the above code, Image
represents an image resource, Font
represents the font resource. Sound
and Music
are sound resources, the Music
will play by the MediaPlayer
class (usually MP3 files), and Sound
generally refers to certain small wav files.
Identify Resources
I created a Resource
structure that identifies a resource, it has three internal fields, Name
is the name for the resource. Type
is the type of the resource, which is the ResourceType
mentioned above. Path
is the location of resource files in the project, as shown in the following figure:
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;
}
}
Resources Management
Then, we can use the ResourceManager
to manage the resources.
In the constructor, we accept an array of Resource
structure, that needs to be managed.
internal readonly IList<Resource> Resources;
internal ResourceManager ( IList<Resource> resources )
{ this.Resources = null == resources ? new Resource[] { } : resources; }
Of course, the ResourceManager
is not able to load resources, so we need to use the ContentManager
class:
private ContentManager contentManager;
internal World World;
private readonly Dictionary<string, Texture2D> textures = new <Dictionarystring, 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 { }
}
Call the LoadContent
method of the ResourceManager
to load a resource, in the LoadContent
method, we will create a new ContentManager
object, and use the Load
method to load the resources.
To create a ContentManager
object, we also need to set the World
field of ResourceManager
(you can also modify it to a property). So, before you call the LoadContent
, you need to ensure that the World
field is not null
.
You can also call the UnloadContent
method to release resources:
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 ( );
}
In the above code, we call the Dispose
method for all resources, and then call the Unload
method of the ContentManager
.
Use the Resources
Finally, we used the ResourceManager
in our World
class:
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;
}
In the constructor of the World
, we create a ResourceManager
object, and pointed out that we need a picture and a wave file.
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 ( );
}
Use the GetTexture
and GetSound
method to get a picture and sound, just passing the name of the resource.
Finally, you will also need to call UnloadContent
method of the ResourceManager
at a suitable position.
Get the code here: http://wp-xna.googlecode.com/, for more contents, please visit WPXNA.