在我的2D XNA游戏中绘制精灵的有效方法是什么?更具体地说,我把这个问题分成4个问题。
我过去常常声明Game1的spriteBatch 静态,并在每个SpriteBatch.Begin
中调用.Close
和IDrawable.Draw
。这不太好用。给每个drawable它自己的SpriteBatch也不能很好地工作。
Q1 :我认为最好有一个 SpriteBatch实例,并且只能调用begin / close 一次。这是对的吗?
目前,我的Game1.Draw
看起来像这样:
spriteBatch.Begin();
base.Draw(gameTime); // draws elements of Game.Components
// ...
spriteBatch.End();
Q2 :这样,Begin
只会被调用一次。这是要走的路吗?你们是怎么解决这个问题的?
Q3 :此外,每个组件都有自己的IGameComponent.LoadContent
方法。我应该在那里加载我的内容吗?或者最好是在父类加载内容,例如Game1.LoadContent
?
我意识到我永远不应该加载相同的内容两次,所以我给了我的可绘制组件静态和非静态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;
}
}
这样,只有在该类上第一次调用LoadContent
时才会加载类的默认纹理。但是,当在构造函数中指定参数texture
时,我必须事先加载该纹理。
Q4 :我认为应该有更好的方法来做到这一点。我正在考虑创建一个纹理字典,其资产名称为字符串。你会建议什么?
答案 0 :(得分:3)
我曾经宣布过Game1的spriteBatch static
您不必将其静态化。只做一个单身人士。内部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
我认为最好有一个SpriteBatch实例,并且只能调用 开始/关闭一次。这是对的吗?
我建议你在一种方法中打开和结束SpriteBatch
。它可以帮助您避免与开始绘图但未完成的SpriteBatch
发生冲突。
您是否将元素添加到全局组件集合中?将drawable添加到此集合中是一个坏主意。您无法控制绘图的顺序,组件是全局的。 See this answer
在您的组件中实现IUpdatable和IDrawable,并在您需要的代码中调用它们。摆脱静态的东西,并使用Dependency Injection istead。
此外,每个组件都有自己的IGameComponent.LoadContent方法。我应该在那里加载我的内容吗?或者在父类中加载内容更好,例如Game1.LoadContent?
您应该在需要时加载资产,并由您负责。当用户刚刚开始游戏时,你不必加载所有30个关卡,对吗?例如,当您的游戏开始时,您将加载开始屏幕和主菜单所需的所有资源。如果你加载你需要的东西,玩家很高兴游戏开始很快。然后玩家想要开始玩游戏。在这里,您可以在单独的线程上加载资产,以保持应用程序的响应。
我认为应该有更好的方法来做到这一点。我正在考虑创建一个纹理字典,其资产名称为字符串。你会建议什么?
Content.Load
已缓存,因此您无需执行此操作。
答案 1 :(得分:1)
答案 2 :(得分:0)
Q4 :我认为应该有更好的方法来做到这一点。我正在考虑创建一个纹理字典,其资产名称为字符串。你会建议什么?
A4 :我通常在我的Dictionary<string, Texture2D> NameTextureDic
类中创建一个TextureLib
(它在运行时处理加载png图像),所以我可以得到任何这样的纹理:
var t2d = textureLib.NameTextureDic["tree-4"];