Search code examples
c#xnaspritebatch

C# ArgumentNullException was unhandled (SpriteBatch.Draw)


I am actually a new student in XNA, finding this library very interesting, but I still lack some knowledge to go further as I felt on a issue I can't fix on my own :(

The spriteBatch.Draw() method says my texture is null, however I have loaded it in a Resources.cs class and passed the texture in MainMenu.cs, so I don't really know where the problem resides, if anybody could help me about that I would be very thankful !

Resources.cs

    class Resources
{
    public static Texture2D pixel;
    public static Texture2D startButton, loadButton, quitButton;

    public static SpriteFont consoleFont;

    public static void LoadContent(ContentManager Content)
    {
        pixel = Content.Load<Texture2D>("Pixel");
        consoleFont = Content.Load<SpriteFont>("Console");

        // UI Ressources :
        startButton = Content.Load<Texture2D>("UI/StartButton");
        loadButton = Content.Load<Texture2D>("UI/LoadButton");
        quitButton = Content.Load<Texture2D>("UI/QuitButton");
    }
}

MainMenu.cs

    class MainMenu
{
    // Fields
    List<Button> buttons = new List<Button>();

    // Constructors
    public MainMenu()
    {
        this.buttons.Add(new Button(new Vector2(480, 132), 256, 48, Resources.startButton));
        this.buttons.Add(new Button(new Vector2(480, 212), 256, 48, Resources.loadButton));
        this.buttons.Add(new Button(new Vector2(480, 292), 256, 48, Resources.quitButton));
    }

    // Methods

    // Update
    public void Update()
    {
    }

    // Draw
    public void Draw(SpriteBatch spriteBatch)
    {
        foreach (Button button in buttons)
        {
            button.Draw(spriteBatch);
        }
    }
}

Button.cs

    class Button : UIElement
{
    int width, height;
    Texture2D texture;

    public Button()
    {
    }

    public Button(Vector2 b_position, int b_width, int b_height, Texture2D b_texture)
    {
        this.position = b_position;
        this.width = b_width;
        this.height = b_height;
        this.texture = b_texture;
    }

    public void Update()
    {
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture, position, Color.White);
    }
}

Solution

  • Simple realy
    You just have to know the calling order of functions of Game1. First, Game1 constructor is called. That's where you've put mainMenu = new MainMenu();. After that go Initialize, Load and so on. You have to move mainMenu = new MainMenu(); from Game1 constructor to Load function, after the Resources.LoadContent(Content);, so the resources can be loaded before they are used in MainMenu. Your Game1.cs code should look like this:

    public class GameMain : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
    
        MainMenu mainMenu;
    
        public GameMain()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
    
            this.IsMouseVisible = true;
        }
    
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
    
            base.Initialize();
        }
    
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
    
            // TODO: use this.Content to load your game content here
            Resources.LoadContent(Content);
            mainMenu = new MainMenu();
        }
    
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }
    
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();
    
            // TODO: Add your update logic here
            base.Update(gameTime);
        }
    
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
    
            // TODO: Add your drawing code here
            spriteBatch.Begin();
            mainMenu.Draw(spriteBatch);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }