我正在开发 XNA 游戏。这是我对架构小心翼翼的时候了。直到今天,我一直以这种方式实现我自己的绘制方法:
public void Draw(SpriteBatch sb, GameTime gameTime)
{
sb.Begin();
// ... to draw ...
sb.End();
}
Run Code Online (Sandbox Code Playgroud)
我正在挖掘 DrawableGameComponent 并看到 Draw 方法是这样来的:
public void Draw(GameTime gameTime)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
首先,我知道SpriteBatch 可以在Begin 和End 之间收集许多Texture2D,以便对它们进行排序或使用相同的Effect 进行绘制很有用。
我的问题是关于通过 SpriteBatch 的性能和成本。在 DrawableGameComponent 中,如果 spritebatch 是公开的,则可以调用游戏对象的 spritebatch。
有什么建议,xna-game 程序员应该做什么?
谢谢指教。
其严重缺点之一DrawableGameComponent是您被锁定在其提供的方法签名中。虽然本质上没有什么“错误”,但DrawableGameComponent不要将其视为“一个真正的架构”。您最好将其视为可能的架构的示例。
如果您发现自己需要将 a SpriteBatch(或其他任何内容)传递给“游戏组件”的绘制方法 -最好的方法是将其作为参数传递。其他的事情都很复杂。
显然这意味着你不能使用XNA提供的GameComponent系统,你必须自己制作替代方案。但这几乎是微不足道的:在最基本的层面上,它只是一些具有适当虚拟方法的基本类型的列表。
当然,如果您必须使用GameComponent- 或者您的游戏非常简单(例如:原型)以至于您并不真正关心架构 - 那么您基本上可以使用您喜欢的任何方法来获取SpriteBatch绘制方法。它们都有缺点。
可能下一个架构上最稳健的方法是将SpriteBatch实例传递到每个组件的构造函数中。这使您的组件与游戏类分离。
另一方面,如果您将建筑抛在脑后,我建议您创建自己的MyGame.spriteBatch领域public static。这是允许在任何地方访问它的最简单的方法。它很容易实现,并且在以后需要时/如果需要的话也很容易清理。
回答有关性能的问题:任何与传递有关的事情对性能的影响几乎可以忽略不计(假设对//的SpriteBatch调用顺序保持不变)。别担心。DrawBeginEnd
(如果你SpriteBatch whatever在代码中看到,它代表一个引用。引用是一个 32 位值(在 32 位程序中,所有 XNA 游戏都是)。它的大小与 anint或 a相同float。它非常小而且非常便宜传递/访问/等等)
如果您偶然发现了这个问题,您可能正在寻找一个不错的通用解决方案。我建议你看看这个:
我觉得有必要纠正这个问题,因为“最好的方法是将其作为参数传递。其他任何事情都是令人费解的。” 根本不正确。
我个人现在在我的 GameBase 类中这样做:
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
SpriteBatch = new SpriteBatch(GraphicsDevice);
this.Services.AddService(typeof(SpriteBatch), SpriteBatch);
}
Run Code Online (Sandbox Code Playgroud)
现在,由于您在 Game 类的 Initialize 方法中添加了 DrawableGameComponents,您将能够调用
this.Game.Services.GetService(typeof(SpriteBatch))
Run Code Online (Sandbox Code Playgroud)
我会说这是解决问题的最干净的方法。