很多时候,我发现自己想知道是否有一种简单的方法可以在 XNA 中只使用一个 spritebatch,发现微软的内置组件系统是一个好主意,但构建起来却很神秘。
我只能假设 XNA 的很多方式是由于向后兼容性或 Xbox 兼容性,这本身并不是坏事,而且我确信有一些细节会导致事情按照它们的方式开发,但主系统似乎有点神秘。
这就是我一直以来的想法,直到我意识到游戏“服务”的真正目的和能力,以及它们与装箱/拆箱和 .Net 类型系统的联系。
我承认微软的一个缺点是他们缺乏创造性的命名。起初我一直认为游戏服务与系统服务相关联,或者服务是某种特殊的类或接口。
事实上,游戏的服务集合只不过是对象的集合。服务允许任何已连接到游戏的游戏组件从游戏中检索数据。
SpriteBatch 就是一个例子。通过将 SpriteBatch 添加到游戏的服务中,并将其注册到 typeof(SpriteBatch),任何组件都可以通过将 typeof(SpriteBatch) 提供给 GetService 方法从服务中提取该 SpriteBatch。
下面是一些示例代码(未经测试,只是一个示例):
public namespace MyGame
{
public class MainGame:Game
{
SpriteBatch spriteBatch;
protected override void Initialize()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Services.AddService(typeof(SpriteBatch), spriteBatch);
base.Initialize();
}
}
public class DrawableComponent : DrawableGameComponent
{
SpriteBatch spriteBatch;
public override void Initialize()
{
spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
if(spriteBatch == null)
{ throw new Exception("No SpriteBatch found in services"); }
}
}
}
我在这里的例子也展示了一个非常被忽视的因素。Microsoft 的默认游戏模板将 SpriteBatch 创建放在加载内容方法中,导致许多人认为必须保留在那里。事实上,你可以自由地将它向前移动,直到初始化方法(但不是构造函数),这意味着它可以在任何组件初始化之前被移动到服务中,从而确保所有组件都从初始化方法中的服务将获得一个。
请务必注意,如果给定项目为 null,则添加到服务会引发异常,从它们中取出不会,它只会返回 null 并继续执行,因此必须尽快执行 null 检查。另请注意,如果在游戏中期创建组件,则不会调用其初始化,因此必须通过某种方式对其进行补偿。
这种技术的更多例子可以在这里找到:http: //itspaulsblog.blogspot.co.uk/2011/02/xna-common-sprite-batch-as-game-service.html