【问题标题】:XNA draw : using one spritebatch at whole gameXNA draw : 在整个游戏中使用一个 spritebatch
【发布时间】:2012-09-24 17:58:00
【问题描述】:

我正在开发一款 XNA 游戏。这是我对架构小心的时候了。直到今天,我一直都是这样实现自己的draw方法的:

public void Draw(SpriteBatch sb, GameTime gameTime)
{
    sb.Begin();
    // ... to draw ...
    sb.End();
}

我在挖DrawableGameComponent,看到Draw方法是这样来的:

public void Draw(GameTime gameTime)
{
    // ...
}

首先,我知道 SpriteBatch 可以在 Begin 和 End 之间收集许多 Texture2D,以便对它们进行排序或使用相同的效果进行绘制。

我的问题是关于通过 SpriteBatch 的性能和成本。在 DrawableGameComponent 中,如果 spritebatch 是公共的,则可以调用游戏对象的 spritebatch。

什么建议,xna-game程序员应该做什么?

感谢您的建议。

【问题讨论】:

    标签: xna spritebatch


    【解决方案1】:

    如果您偶然发现了这个问题,您可能正在寻找一个不错的通用解决方案。我建议你看看这个:

    https://gamedev.stackexchange.com/questions/14217/several-classes-need-to-access-the-same-data-where-should-the-data-be-declared/14232#14232

    我觉得有必要纠正这个问题,因为“最好的方法是将其作为参数传递。其他任何事情都很复杂。” 根本就是不正确

    就我个人而言,我现在在我的 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);
        }
    

    现在,由于您在 Game 类的 Initialize 方法中添加了 DrawableGameComponents,您将能够调用

        this.Game.Services.GetService(typeof(SpriteBatch))
    

    我会说这是解决问题的最干净的方法。

    【讨论】:

    • 我不同意这是最好的方法。如果连接不正确,在游戏中使用IoC 可能会产生大量的性能开销。这需要您提前注册所有类型,即使游戏在其生命周期中从未使用它们,这是一种资源浪费。根据您的目标设备和游戏类型,资源可能非常有限。 DI有它的位置。我只是不同意它的位置属于原型以外的任何类型的视频游戏。
    • @JohnathonSullinger 您提到的限制显然是正确的,因为这是 DI 的一个非常常见的“问题”。应该小心使用它,并对其进行监控以避免性能不佳 - 但大多数收集 DI 经验的人都知道
    【解决方案2】:

    DrawableGameComponent 的一个严重缺点是您被锁定在其提供的方法签名中。尽管 DrawableGameComponent 本身并没有什么“错误”,但不要将其视为“一个真正的架构”。你better off 认为它是可能的architecture 的一个例子。

    如果您发现自己需要将 SpriteBatch(或其他任何内容)传递给“游戏组件”的 draw 方法 - 最好的方法将其作为参数传递。其他任何事情都很复杂。

    显然这意味着你不能使用 XNA 提供的GameComponent 系统,你必须自己做选择。但这几乎是微不足道的:在最基本的层面上,它只是一些具有适当虚拟方法的基本类型的列表。


    当然,如果您必须使用 GameComponent - 或者您的游戏非常简单(例如:原型)以至于您并不真正关心架构 - 那么您基本上可以使用 any方法你喜欢得到一个SpriteBatch 到你的draw 方法。它们都有缺点。

    可能下一个在架构上最可靠的方法是将SpriteBatch 实例传递给每个组件的构造函数。这使您的组件与您的游戏类分离。

    另一方面,如果您将建筑抛在脑后,我建议您将MyGame.spriteBatch 字段设为public static。这是允许在任何地方访问它的最简单方法。它很容易实施,并且在以后需要时/如果需要也易于清理。


    回答您关于性能的问题:与传递 SpriteBatch 相关的任何事情对性能的影响几乎可以忽略不计(前提是对 Draw/Begin/End 的调用顺序保持不变)。不用担心。

    (如果您在代码中看到SpriteBatch whatever,则表示引用。引用是32 位值(在32 位程序中,所有XNA 游戏都是)。与int 的大小相同或float。它非常小而且非常便宜,可以通过/访问/等)

    【讨论】:

      【解决方案3】:

      如果DrawableGameComponent 应该是父级SpriteBatch 的一部分,那么只需通过构造函数将其传入并将其存储在私有成员中(如果您愿意,也可以将其公开为属性)。

      您也可以按照您的建议将SpriteBatch 公开为Game 类的属性,但每次引用this.Game 时,都需要将其转换为特定的Game 类输入。

      ((MyGame)this.Game).SpriteBatch.Draw(...)
      

      或者您可以让DrawableGameComponent 创建一个新的SpriteBatch。这没有什么问题(据我所见)。我想这取决于您将创建多少 DrawableGameComponents 以及创建频率。

      还可以浏览search for DrawableGameComponent 的结果 - 那里有很多很好的建议。

      【讨论】:

        猜你喜欢
        • 2011-06-09
        • 1970-01-01
        • 1970-01-01
        • 2011-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-26
        • 1970-01-01
        相关资源
        最近更新 更多