ContentManage作为Game类的一个非常重要的助手,负责个所有Content的加载和管理工作。从Texture、SpritFont到Model、Effect都是通过该类的Load方法获得。Load方法的部分代码如下:
public virtual T Load<T>(string assetName){
object obj2;
if (this.loadedAssets.TryGetValue(assetName, out obj2)){
if (!(obj2 is T)){
throw new ContentLoadException("......");
}
return (T) obj2;
}
T local = this.ReadAsset<T>(assetName, null);
this.loadedAssets.Add(assetName, local);
return local;
}
首先检查loadedAssets的Dictionary中是否有key为assetName的元素。如果存在,说明之前已经加载进来了,只需要将该元素的值返回;否则,调用ReadAsset方法,从内容管道加载。
protected T ReadAsset<T>(
string assetName,Action<IDisposable>recordDisposableObject){
using (Stream stream = this.OpenStream(assetName)){
using (ContentReader reader =
new ContentReader(this, stream, assetName, recordDisposableObject)){
return reader.ReadAsset<T>();
}
}
}
调用OpenStream方法将二进制流从本地加载进来,然后调用ContentReader的ReadAsset方法,并返回其结果。
internal T ReadAsset<T>(){
T local;
try{
int sharedResourceCount = this.ReadHeader();
T local2 = this.ReadObject<T>();
this.ReadSharedResources(sharedResourceCount);
local = local2;
}catch (IOException exception){
throw this.CreateContentLoadException("....");
}
return local;
}
这段代码很容易读懂,首先调用ReadHeader方法,读取数据流的头部,然后调用ReadObject读取数据流实体,整个加载的关键就在这两个方法上(尤其是后一个方法)。
msdn上是这样解释ContentReader类的"A worker object that implements most of ContentManager.Load."也就是说它完成了几乎所有的Load过程。ReadHeader方法结构看了一下:
private int ReadHeader()
{
int typeCount = base.Read7BitEncodedInt();
this.typeReaders = ContentTypeReaderManager.ReadTypeManifest(typeCount, this);
int num2 = base.Read7BitEncodedInt();
if (num2 > 0)
{
this.sharedResourceFixups = new List<Action<object>>[num2];
for (int i = 0; i < num2; i++)
{
this.sharedResourceFixups[i] = new List<Action<object>>();
}
}
return num2;
}
ContentTypeReaderManager类是一个对ContentTypeReader管理的一个类,里面有3个Dictionary用于存放已加载进来的ContentTypeReader。这段代码主要是通过读取数据流检测当前数据流的ContentTypeReader,然后缓存等作用(即预处理的工作)。
ReadObject<T>()方法最终调用的是自己类的InvokeReader<T>方法:
private T InvokeReader<T>(ContentTypeReader reader, object existingInstance)
{
T local;
ContentTypeReader<T> reader2 = reader as ContentTypeReader<T>;
if (reader2 != null)
{
T local2 = (existingInstance == null) ? default(T) : ((T) existingInstance);
local = reader2.Read(this, local2);
}
else
{
object obj2 = reader.Read(this, existingInstance);
if (obj2 != null)
{
if (!(obj2 is T))
{
throw this.CreateContentLoadException(".......");
}
local = (T) obj2;
}
else
{
local = default(T);
}
}
if (existingInstance != null)
{
if (!object.ReferenceEquals(existingInstance, local))
{
throw new InvalidOperationException(".......");
}
return local;
}
if (!reader.TargetIsValueType)
{
IDisposable disposable = local as IDisposable;
if (disposable == null)
{
return local;
}
if (this.recordDisposableObject != null)
{
this.recordDisposableObject(disposable);
return local;
}
this.contentManager.RecordDisposableObject(disposable);
}
return local;
}
这段代码应该还是比较好看懂,首先的一个if分子说明,如果当前的ContentTypeReader对象是ContentTypeReader<T>类型的,那么不为空,执行if块,执行ContentTypeReader<T>的
Read(ContentReader input, T existingInstance)方法,否则进入else快,执行
ContentTypeReader的Read(ContentReader input, object existingInstance)方法。注意ContentTypeReader<T>类是ContentTypeReader的直接子类,他重写了父类的Read(ContentReader input, object existingInstance)方法:
public abstract class ContentTypeReader<T> : ContentTypeReader
{
protected ContentTypeReader() : base(typeof(T)){}
protected internal override object Read(ContentReader input, object existingInstance)
{
T local;
if (existingInstance == null)
{
local = default(T);
}
else
{
if (!(existingInstance is T))
{
throw input.CreateContentLoadException(".....");
}
local = (T) existingInstance;
}
return this.Read(input, local);
}
protected internal abstract T Read(ContentReader input, T existingInstance);
}
}
这段代码中,前面的方法,重写了父类对应的方法,但是最终返回的是
this.Read(input, local),该方法是一个抽象的方法,由其子类完成。现在条理清楚了,关键就在于所有子类的此方法。下面仅仅列出几个关键的子类:
namespace Microsoft.Xna.Framework.Content
{
using Microsoft.Xna.Framework.Graphics;
using System;
internal class EffectReader : ContentTypeReader<Effect>
{
private static Microsoft.Xna.Framework.Graphics.EffectPool sharedEffectPool;
protected internal override Effect Read(ContentReader input, Effect existingInstance)
{
int count = input.ReadInt32();
return new Effect(input.GraphicsDevice, input.ReadBytes(count), CompilerOptions.None, EffectPool);
}
internal static Microsoft.Xna.Framework.Graphics.EffectPool EffectPool
{
get
{
if (sharedEffectPool == null)
{
sharedEffectPool = new Microsoft.Xna.Framework.Graphics.EffectPool();
}
return sharedEffectPool;
}
}
}
}
namespace Microsoft.Xna.Framework.Content
{
using Microsoft.Xna.Framework.Graphics;
internal class TextureReader : ContentTypeReader<Texture>
{
protected internal override Texture Read(ContentReader input, Texture existingInstance)
{
return existingInstance;
}
}
}
namespace Microsoft.Xna.Framework.Content
{
using Microsoft.Xna.Framework.Graphics;
internal class ModelReader : ContentTypeReader<Model>
{
protected internal override Model Read(ContentReader input, Model existingInstance)
{
return Model.Read(input);
}
}
}
看了这么多,不难发现用户也可以自定义自己的ContenTypeReader:
public class TriangleTypeReader : ContentTypeReader<Triangle>
{
protected override Triangle Read(ContentReader input, Triangle existingInstance)
{
Vector3 p0 = input.ReadObject<Vector3>();
Vector3 p1 = input.ReadObject<Vector3>();
Vector3 p2 = input.ReadObject<Vector3>();
Triangle newTriangle = new Triangle(p0, p1, p2);
return newTriangle;
}
}
具体解释呆讨论完ContentTypeWriter之后再讲~~~
分享到:
相关推荐
XNA4.0学习指南--源代码
XNA学习资料-XNA入门指南2.0,比较适合新手哈
XNA Tutorial Collision Series 1 - 2D Rectangle Collision
基于XNA开发的3D游戏源码,适合初学者!
XNA学习资料,XNAXNA学习资料,XNAXNA学习资料,XNAXNA学习资料,XNA
xna4.0 中文 + 源码 这个xna教程很不错。源码也在里面。
《XNA4.0学习指南》书籍源码-1 ,由于上传限制,分了两部分上传的。这个是第一部分。
一本没有翻译的英文书籍,关于XNA游戏框架开发
XNA学习指南_中文_附源代码[XNA学习必备] 菜鸟 高手 均可参考
XNA2版的俄罗斯方块源码,visual studio2005环境测试
XNA实现Billboard示例源码
cocos2d-x for xna 2D游戏引擎源码 xna cocos2d-x是一个用C#编写的2D游戏引擎,基于[cocos2d-x][1]和使用MIT 协议。 引擎由 [cocos2d-x][1] 和 [OpenXLive][2] 联合开发。 cocos2d-x for xna is a 2D game ...
xna Game studio 小游戏源码
英文版下载地址:http://disanji.net/2011/02/13/ebook-learning-xna-4-0-game-development-for-the-pc-xbox-360-and-windows-phone-7/ 本书中彩色插图下载:http://u.115.com/file/f1a55ef495 本书源代码下载:...
xna_4.0 学习指南(xna learning)源码(全,45.9M)
XNA4.0指南源码 XNA4.0指南源码 XNA4.0指南源码XNA4.0指南源码XNA4.0指南源码
这是一个xna的实例,如何用2d的方法实现爆炸效果
XNA4.0GameDevelopmentByExample-英文原版.zip
1.操作键说明: 数字键:1 - 创建PC ;2 - 创建敌人 ;3 - 创建树木 方向键:A、S、D、W 射 击:J
用于在XNA中绘制2D基本形状的库。 该库具有用于绘制像素,直线,矩形,填充矩形,圆形和圆弧的方法。 开发移至:https://bitbucket.org/C3/2d-xna-primitives