Question

Hey guys I really need some help here my spriteBatch keeps returning a NullReference Exception and I don't know what I am doing wrong!? (I am making a brickbreaker game) and whenever my bricks are created inside Game1.cs it works fine but when I move it to Wall.cs (which is where I want to display a pattern of bricks) the game just crashes and gives a NullReference exception. Heres my code:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace BrickBreaker
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        private Paddle paddle;
        private Ball ball;
        private Texture2D background;
        private static int screenWidth = 750;
        private static int screenHeight = 600;
        private int leftBorder = 20;
        private int rightBorder = 28;
        private int topBorder = 20;
        private readonly int normalBrickResist = 2;
        private readonly int normalBrickPoints = 10;
        private Wall wall;

        //DELETE this shit
        private Brick brick;

        /// <summary>
        /// Contructor for the Game1 class.
        /// </summary>
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }


        /// <summary>
        /// Read only property for the screen height.
        /// </summary>
        public static int ScreenHeight
        {
            get { return screenHeight; }
        }

        /// <summary>
        /// Read only property for the screen width.
        /// </summary>
        public static int ScreenWidth
        {
            get { return screenWidth; }
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize() will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            graphics.PreferredBackBufferHeight = screenHeight;
            graphics.PreferredBackBufferWidth = screenWidth;
            graphics.ApplyChanges();

            paddle = new Paddle(this);
            Components.Add(paddle);

            wall = new Wall(this);
            Components.Add(wall);

            ball = new Ball(this, paddle, leftBorder, rightBorder, topBorder, brick);
            Components.Add(ball);

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            background = Content.Load<Texture2D>("background");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            Vector2 position = new Vector2(0, 0);
            spriteBatch.Draw(background, position, Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }

        public void RemoveComponent(IGameComponent obj)
        {
            this.Components.Remove(obj);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace BrickBreaker
{

    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Wall : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private Brick brick;
        private Brick[,] brickLayout = new Brick[5, 8];
        private Game game;
        SpriteBatch spriteBatch;
        private Texture2D brickImg;

        public Wall(Game game)
            : base(game)
        {
            this.game = game;
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Draw(GameTime gameTime)
        {
            foreach (var item in brickLayout)
            {
                if (item != null)
                {
                    item.Draw(gameTime);
                }

            }

            base.Draw(gameTime);
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            foreach (Brick item in brickLayout)
            {
                item.Update(gameTime);
            }

            base.Update(gameTime);
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here
            foreach (var item in brickLayout)
            {
                if (item != null)
                {
                    item.Initialize();
                }
            }
            base.Initialize();
        }

        protected override void LoadContent()
        {

            int x = 0;
            int y = 0;
            Vector2 startPosition;
            for (int i = 0; i < brickLayout.GetLength(0); i++)
            {
                for (int j = 0; j < brickLayout.GetLength(1); j++)
                {
                    startPosition = new Vector2(x, y);
                    brickLayout[i, j] = new Brick(game, 20, 1, startPosition);
                    x += 20;
                }
                y += 20;
            }

            base.LoadContent();
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace BrickBreaker
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Brick : Microsoft.Xna.Framework.DrawableGameComponent
    {
        enum brickType
        {
            Regular1,
            Regular2,
            Regular3,
            Regular4,
            Regular5,
            PowerUp,
            Unbreakable
        }

        private Texture2D brick;
        private SpriteBatch spriteBatch;
        private Game game;
        private int brickValue;
        private Vector2 startPosition, position;
        private Rectangle collisionBox;
        private int brickWidth;
        private bool isBroken = false;
        private int resistance;

        public Brick(Game game, int brickValue, int resistance, Vector2 startPosition)
            : base(game)
        {
            this.brickValue = brickValue;
            this.game = game;
            this.resistance = resistance;
            this.startPosition = startPosition;
        }

        public Boolean IsBroken
        {
            get
            {
                return this.isBroken;
            }
            set
            {
                this.isBroken = value;
            }
        }

        /// <summary>
        /// Property for the paddle collision box.
        /// </summary>
        public Rectangle CollisionBox
        {
            get { return collisionBox; }
        }


        /// <summary>
        /// Read only property for the paddle width.
        /// </summary>
        public int BrickWidth
        {
            get { return brickWidth; }
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here

            base.Update(gameTime);
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Draw(GameTime gameTime)
        {

            if (isBroken == false)
            {
                spriteBatch.Begin();
                spriteBatch.Draw(brick, this.position, Color.White);
                spriteBatch.End();
            }


            base.Draw(gameTime);
        }

        /// <summary>
        /// Comment
        /// </summary>
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            brick = game.Content.Load<Texture2D>("brick");

            collisionBox = new Rectangle(0, 0, brick.Width, brick.Height);

            position = startPosition;
            collisionBox.X = (int)position.X;
            collisionBox.Y = (int)position.Y;

            base.LoadContent();
        }

        public void TakeHit()
        {
            resistance--;

            if (resistance == 0)
                IsBroken = true;

        }

    }
}

Edit: Fixed the old problem by adding this in wall.cs

   for (int i = 0; i < brickLayout.GetLength(0); i++)
    {
        for (int j = 0; j < brickLayout.GetLength(1); j++)
        {
            startPosition = new Vector2(x, y);
            brickLayout[i, j] = new Brick(game, 20, 1, startPosition);
            //Added this line:
            brickLayout[i, j].Initialize();
            x += 45;
        }
        x = 150;
        y += 25;
    }

BUT now the collision box isn't working at all.

Was it helpful?

Solution 2

It's giving NullReferenceException in the Brick class at the SpriteBatch.Begin() line in the Draw method.

OTHER TIPS

Look closer at your Brick class. In your wall class you're not initializing spriteBatch, and you're not calling Begin and End

Your LoadContent method needs this:

spriteBatch = new SpriteBatch(GraphicsDevice);

And you need to be sure to call this is your Draw method:

spriteBatch.Begin();

and

spriteBatch.End();

EDIT: You're never calling LoadContent on your brick class which is why spriteBatch never gets initialized. Try:

    protected override void LoadContent()
    {

        int x = 0;
        int y = 0;
        Vector2 startPosition;
        for (int i = 0; i < brickLayout.GetLength(0); i++)
        {
            for (int j = 0; j < brickLayout.GetLength(1); j++)
            {
                startPosition = new Vector2(x, y);
                brickLayout[i, j] = new Brick(game, 20, 1, startPosition);
                // This new line...
                brickLayout[i, j].LoadContent();
                x += 20;
            }
            y += 20;
        }

        base.LoadContent();
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top