0
votes

In XNA load content is called after init, which is fair enough, however its causing me some problems with loading textures.

In Init i set the spriteTexture of a sprite to that of a Static Texture2D.

In LoadContent i then set the value of the Static Texture2D. This works successfully.

However the spriteTexture value is still null when it comes to the Draw() method, causing it to fail. How can I overcome this?

have a feeling its to do with passing by value rather than reference. Any help?

Thanks, Danny

Code: http://pastebin.com/C92ADY7s

4

4 Answers

0
votes

The LoadContent method must be called before you call the constuctor. Otherwise the textures are not loaded and spriteBatch is assigned to null (spriteBatch=null;), so references is not assigned and later textures loding has no effect.

0
votes

The constructor will be called before LoadContent. At that time, the lines in your switch statement will all be assigning null to spriteTexture.

The simplest fix would be to save the value of requestedMenuButtonType and put the switch statement (or a call to a method containing the switch statement) into LoadContent (at a point after the icons have been loaded). Ex:

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;

      ...
}

A better solution might be to wrap the Texture2Ds in some Icon class, which has its own LoadContent method (which calls LoadContent for its particular Texture2D). Then when LoadContent is called, it would load the Texture2Ds without throwing away the Icon references.

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);
      ...
   }        
}
0
votes

If you're just loading small/few textures (not time consuming), jou could just call load content in MenuButton constructor.

0
votes

This happens because of the way references work in C#. Here's a simple example using strings instead of textures:

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.

Now if you would like to reference a texture before it has been loaded, you will need to provide a level of indirection to the actual Texture2D member, thus avoiding copying a null reference to begin with...

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...
    }
}

Now as long as we call load content (Icon.MenuButton.Texture = Content.Load("blah.png");), our draw method will work* :)

Now the MenuButton class is not affected when the Icon.Texture property is changed/overwritten/whatever, because it only holds a reference to the Icon class instance, which does not change.

* I would actually be tempted to add a draw method to the Icon class. Or even an extension method to SpriteBatch to draw an Icon reference directly... this would be more in line with the 'tell don't ask' principle :)