使用静态纹理2D';s在XNA的课堂上

本文关键字:XNA 课堂 静态 纹理 2D | 更新日期: 2023-09-27 18:29:48

在XNA中,加载内容是在init之后调用的,这很公平,但它给我加载纹理带来了一些问题。

在Init中,我将精灵的精灵纹理设置为静态纹理2D的精灵纹理。

在LoadContent中,我然后设置静态纹理2D的值。这是成功的。

但是,当使用Draw()方法时,spriteTexture值仍然为null,导致它失败。我该如何克服这一点?

有一种感觉,这与传递价值而不是参考有关。有什么帮助吗?

谢谢,Danny

代码:http://pastebin.com/C92ADY7s

使用静态纹理2D';s在XNA的课堂上

在调用构造函数之前,必须调用LoadContent方法。否则,不会加载纹理,并且spriteBatch被指定为null(spriteBatch=null;),因此不会指定引用,以后的纹理loding也没有效果。

构造函数将在LoadContent之前调用。此时,switch语句中的行都将把null指定给spriteTexture。

最简单的修复方法是保存requestedMenuButtonType的值,并将switch语句(或对包含switch语句的方法的调用)放入LoadContent(在加载图标后的某个点)。例如:

private static MenuButtonType savedMenuButtonType;
public MenuButton(int requestedX, int requestedY, int requestedWidth, int requestedHeight, MenuButtonType requestedMenuButtonType)
   : base(requestedX, requestedY, requestedWidth, requestedHeight)
   {
      ...
      savedMenuButtonType = requestedMenuButtonType;
      ...
   }
public static void LoadContent(ContentManager Content)
{
   ...
   //Main Menu Icons
   ...
   //About Menu Icons
   ...
   spriteTexture = GetRequestedSpriteTexture();
}
private static Texture2D GetRequestedSpriteTexture()
{
   switch (savedMenuButtonType)
   {
      case MenuButtonType.play:
         return playButtonIcon;
         break;
      ...
}

一个更好的解决方案可能是将Texture2D封装在某个Icon类中,该类有自己的LoadContent方法(为其特定的Texture2D调用LoadContent)。然后,当调用LoadContent时,它将加载Texture2D,而不会丢弃图标引用。

public class Icon
{
   private string mTextureName;
   private Texture2D mTexture;
   public Icon(string pTextureName)
   {
      mTextureName = pTextureName;
   }
   ...
   public void LoadContent(ContentManager Content)
   {
      mTexture = Content.Load<Texture2D>(mTextureName);
   }
   ...
}
public class MenuButton : SpriteObject
{
   private Icon spriteIcon;
   //Different Icons, static for loading
   private static Icon playButtonIcon = new Icon("Menu Items/Menu Buttons/PlayButtonIcon");
   ...
   public MenuButton(int requestedX, int requestedY, int requestedWidth, int requestedHeight, MenuButtonType requestedMenuButtonType)
      : base(requestedX, requestedY, requestedWidth, requestedHeight)
   {
      ...
      spriteIcon = playButtonIcon;
      ...
   }
   public void LoadContent(ContentManager Content)
   {
      ...
      playButtonIcon.LoadContent(Content);
      ...
   }        
}

如果你只是加载小/少的纹理(不耗时),jou可以在MenuButton构造函数中调用加载内容。

这是因为引用在C#中的工作方式。下面是一个使用字符串而不是纹理的简单示例:

String foo = null; // A null reference is assigned to the foo variable...
String bar = foo; // The null reference is *copied* to the bar variable. We now have 2 distinct references..
foo = "foo"; // The foo variable is *overwritten* with a new reference to the string...
bar != "foo"; // The bar variable is not affected at all, its own reference still points at null.

现在,如果你想在加载纹理之前引用它,你需要为实际的Texture2D成员提供一个间接级别,从而避免从一开始就复制空引用。。。

static public Icon
{
    public Texture2D Texture; // starts with null...
    static public Icon PlayButton = new Icon(); // Not a null reference, even though the texture hasn't been loaded yet...
}

public class MenuButton
{
    public MenuButton()
    {
        this.Icon = Icon.PlayButton; // Again, not a null reference...
    }
    public Icon Icon { get; set; }
    public void Draw()
    {
        SpriteBatch.Draw(this.Icon.Texture); // etc...
    }
}

现在,只要我们调用加载内容(Icon.MenuButton.Tructure=content.load("blah.png");),我们的绘图方法会起作用*:)

现在,当Icon.Texture属性被更改/覆盖时,MenuButton类不受影响,因为它只保存对Icon类实例的引用,而不会更改。

*实际上我很想在Icon类中添加一个draw方法。或者甚至是SpriteBatch的扩展方法,直接绘制图标引用。。。这将更符合"告诉不要问"的原则:)