最佳实践:XNA中的高效精灵绘图

Rud*_*dey 13 c# xna drawing 2d sprite

在我的2D XNA游戏中绘制精灵的有效方法是什么?更具体地说,我把这个问题分成4个问题.


我过去常常声明Game1的spriteBatch 静态,SpriteBatch.Begin.Close在每个中调用IDrawable.Draw.这不太好用.给每个drawable它自己的SpriteBatch也不能很好地工作.

Q1:我认为最好有一个 SpriteBatch实例,只调用一次开始/关闭.它是否正确?


目前,我Game1.Draw看起来像这样:

spriteBatch.Begin();

base.Draw(gameTime); // draws elements of Game.Components

// ...

spriteBatch.End();
Run Code Online (Sandbox Code Playgroud)

Q2:这样,Begin只调用一次.这是要走的路吗?你们是怎么解决这个问题的?


问题3:此外,每个组件都有自己的IGameComponent.LoadContent方法.我应该在那里加载我的内容吗?或者在父类中加载内容是否更好Game1.LoadContent


我意识到我永远不应该加载相同的内容两次,所以我给了我的drawable组件静态和非静态组件Texture2D,并给了他们2个构造函数:

static Texture2D defaultTexture;
public Texture2D MyTexture;

public Enemy()
    : this(defaultTexture) { }

public Enemy(Texture2D texture)
{
    MyTexture = texture;
}

protected override void LoadContent()
{
    if (MyTexture == null)
    {
        if (defaultTexture == null)
        {
            defaultTexture = Content.Load<Texture2D>("enemy");
        }

        MyTexture = defaultTexture;
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,类的默认纹理只在第一次LoadContent在该类上调用时才加载.但是,当texture在构造函数中指定参数时,我必须事先加载该纹理.

问题4:我认为应该有更好的方法来做到这一点.我正在考虑创建一个纹理字典,其资产名称为字符串.你会建议什么?

Luk*_*don 3

我曾经将 Game1 的 spriteBatch 声明为静态

你不必让它静态。只需创建一个单例即可。内部Draw方法

SpriteBatch spriteBatch = ScreenManager.SpriteBatch; // singletion SpriteBatch
spriteBatch.Begin();
// Draw the background
spriteBatch.Draw(background, ...
foreach (var enemy in enemys)
{
     enemy.Draw(gameTime);
}
// etc.
spriteBatch.End(); // call here end 
base.Draw(gameTime); // and then call the base class
Run Code Online (Sandbox Code Playgroud)

我认为最好有一个 SpriteBatch 实例,并且只调用开始/关闭一次。它是否正确?

我建议你用一种方法打开和结束SpriteBatch。它将帮助您避免与SpriteBatch已开始绘图但未完成的冲突。

您是否要将您的元素添加到全局组件集合中?将可绘制对象添加到此集合中是一个坏主意。您无法控制绘制的顺序,组件是全局的。看到这个答案

在您的组件中实现 IUpdatable 和 IDrawable 并在您需要的代码中调用它们。摆脱静态的东西并使用依赖注入代替。

此外,每个组件都有自己的 IGameComponent.LoadContent 方法。我应该在那里加载我的内容吗?还是在父类加载内容更好,例如 Game1.LoadContent?

您应该在需要时加载资产,并且您对此负责。当用户刚开始游戏时,您不必加载所有 30 个级别,是吗?例如,当游戏启动时,您将加载开始屏幕和主菜单所需的所有资源。如果您只加载所需的内容,玩家会很高兴游戏启动得很快。然后玩家想要开始游戏。在这里,您可以在单独的线程上加载资源,以保持应用程序的响应能力。

我认为应该有更好的方法来做到这一点。我正在考虑创建一个纹理字典,并将其资源名称作为字符串。你有什么建议?

Content.Load已缓存,因此您不必执行此操作。