C# 新华社:一个简单的方法只使用一个spritebatch?
很多时候,我都在想,是否有一种简单的方法可以在XNA中只使用一个spritebatch,我发现微软的内置组件系统是一个好主意,但构建起来相当神秘C# 新华社:一个简单的方法只使用一个spritebatch?,c#,xna,xna-4.0,C#,Xna,Xna 4.0,很多时候,我都在想,是否有一种简单的方法可以在XNA中只使用一个spritebatch,我发现微软的内置组件系统是一个好主意,但构建起来相当神秘 我只能假设XNA的很多方式都是由于向后兼容性或Xbox兼容性,这本身并不是坏事,我确信有些细节导致事情按照现在的方式发展,但主系统可能看起来有点神秘。这是我一直认为的,直到我意识到游戏服务的真正目的和功能,以及它们与装箱/拆箱和.Net类型系统的链接 我承认微软的一个缺点是他们缺乏创造性的命名。起初,我一直认为游戏服务与系统服务相连,或者服务是某种特殊
我只能假设XNA的很多方式都是由于向后兼容性或Xbox兼容性,这本身并不是坏事,我确信有些细节导致事情按照现在的方式发展,但主系统可能看起来有点神秘。这是我一直认为的,直到我意识到游戏服务的真正目的和功能,以及它们与装箱/拆箱和.Net类型系统的链接 我承认微软的一个缺点是他们缺乏创造性的命名。起初,我一直认为游戏服务与系统服务相连,或者服务是某种特殊的类或接口 事实上,游戏的服务集合只不过是对象的集合。这些服务允许连接到游戏的任何游戏组件从游戏中检索数据 SpriteBatch就是一个例子。通过向游戏的服务中添加SpriteBatch,并将其注册为typeofSpriteBatch,任何组件都可以通过将typeofSpriteBatch提供给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"); }
}
}
}
我这里的例子也说明了一个被忽视的因素。
微软的默认游戏模板将SpriteBatch创建放在加载内容方法中,这让许多人相信它必须保留在那里。事实上,您可以自由地将其向前移动,直到初始化方法,而不是构造函数,这意味着可以在初始化任何组件之前将其移动到服务中,从而确保所有在其初始化方法中从服务中寻求SpriteBatch的组件都将获得SpriteBatch
请务必注意,当添加到服务时,如果给定的项为null,则会引发异常,而从中获取的项不会引发异常,它只会返回null并继续执行,因此必须尽快执行null检查。还要注意的是,如果一个组件是在游戏中期创建的,它将不会被调用其初始化,因此必须通过某种方式进行补偿
此技术的更多示例可在此处找到:
制作您自己的基类,替换DrawableGameComponent和相关的基础设施-基本上有一个列表。
修改该基类的Draw方法以获取SpriteBatch参数。
利润
请参阅讨论,并详细解释为什么这是一个好主意以及GameComponent和IServiceProvider的真正用途。一些澄清:除非您将值类型放入服务中,否则不会进行装箱/拆箱操作—这是一件非常奇怪的事情。和GameComponent。在游戏开始后,当该组件添加到组件中时,会调用Initialize。请注意,在调用LoadContent之前,不应访问GraphicsDevice。如果图形设备被重置,例如:游戏最小化或用户桌面被锁定,并且自动资源重新创建因任何原因失败,则会再次调用LoadContent方法,但不会初始化,以手动重新创建图形资源。您仅在Initialize中创建的任何内容都将保持无效,如果您使用它,则将崩溃。它们与可能使用值类型的链接是链接。我不知道最后一个,我以前从未注意到它发生过,所以我必须调查一下。至于图形设备问题,这没什么大不了的,有很多解决方法。我认为正确的解决方法可能包括编写某种ISpriteBatchService,类似于IGraphicsDeviceService,并以几乎相同的方式使用它。尽管我认为一个好的ISpriteBatchService接口会更复杂,但SpriteBatch是有状态的,而GraphicsDevice则不是这样。