none
ArgumntNullException was unhandled - Please Help RRS feed

  • Question

  • Hi, I am doing a coding course and have run into a problem in one of the assignments. I have 3 textures (bear0, bear1, bear2) which I intend to call upon randomly, based on a random generation of 0-2. The value generated should tell the code to assign one of the textures with my variable, currentSprite. however, when I attempt to run my program, currentSprite is showing as having null value, and it breaks the program. If I replace currentSprite with bear0 in the draw function, the program works.

    I have highlighted the relevant code in bold, however I put all my code in as it could very well be anything at this point (I have spent hours trying to fix this). 

    My code (note that the program is not finished):

    using System;

    using Microsoft.Xna.Framework;

    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    namespace ProgrammingAssignment2
    {
        /// <summary>
        /// This is the main type for your game
        /// </summary>
        public class Game1 : Microsoft.Xna.Framework.Game
        {
            const int WindowWidth = 800;
            const int WindowHeight = 600;
            GraphicsDeviceManager graphics;
            SpriteBatch spriteBatch;
            // STUDENTS: declare variables for three sprites
            Texture2D bear0;
            Texture2D bear1;
            Texture2D bear2;
           
            // STUDENTS: declare variables for x and y speeds
            int bear0SpeedX = 0;
            int bear0SpeedY = 0;
            int bear1SpeedX = 0;
            int bear1SpeedY = 0;
            int bear2SpeedX = 0;
            int bear2SpeedY = 0;

            // used to handle generating random values
            Random rand = new Random();
            const int ChangeDelayTime = 1000;
            int elapsedTime = 0;
            // used to keep track of current sprite and location
            Texture2D currentSprite;
            Rectangle drawRectangle = new Rectangle();
            public Game1()
            {
                graphics = new GraphicsDeviceManager(this);
                Content.RootDirectory = "Content";
                graphics.PreferredBackBufferWidth = WindowWidth;
                graphics.PreferredBackBufferHeight = WindowHeight;
            }
            /// <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()
            {
                // TODO: Add your initialization logic here
                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()
            {
                // Create a new SpriteBatch, which can be used to draw textures.
                spriteBatch = new SpriteBatch(GraphicsDevice);
                // STUDENTS: load the sprite images here
                bear0 = Content.Load<Texture2D>("teddybear0");
                bear1 = Content.Load<Texture2D>("teddybear1");
                bear2 = Content.Load<Texture2D>("teddybear2");

                // STUDENTS: set the currentSprite variable to one of your sprite variables
            }
            /// <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();

                //bear0 = currentSprite;
                elapsedTime += gameTime.ElapsedGameTime.Milliseconds;
                if (elapsedTime > ChangeDelayTime)
                {
                    elapsedTime = 0;
                    // STUDENTS: uncomment the code below and make it generate a random number
                    // between 0 and 2 inclusive using the rand field I provided
                    int spriteNumber = rand.Next(0,3);
                    //sets current sprite
                    //STUDENTS: uncomment the lines below and change sprite0, sprite1, and sprite2
                    //      to the three different names of your sprite variables
                    if (spriteNumber == 0)
                    {
                        currentSprite = bear0;
              //          Console.WriteLine("bear0");
                    }
                    else if (spriteNumber == 1)
                    {
                        currentSprite = bear1;
              //          Console.WriteLine("bear1");
                    }
                    else if (spriteNumber == 2)
                    {
                        currentSprite = bear2;
              //          Console.WriteLine("bear2");
                    }
                    // STUDENTS: set the drawRectangle.Width and drawRectangle.Height to match the width and height of currentSprite
                    drawRectangle.Width = (currentSprite.Width);
                    drawRectangle.Height = (currentSprite.Height);
                    // STUDENTS: center the draw rectangle in the window. Note that the X and Y properties of the rectangle
                    // are for the upper left corner of the rectangle, not the center of the rectangle
                   
                            //TO DO: CENTER drawRectangle IN WINDOW
                   
                   
                   
                    // STUDENTS: write code below to generate random numbers  between -4 and 4 inclusive for the x and y speed
                    // using the rand field I provided
                    // CAUTION: Don't redeclare the x speed and y speed variables here!
                }
                // STUDENTS: move the drawRectangle by the x speed and the y speed

                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);
                // STUDENTS: draw current sprite here
                spriteBatch.Begin();
                //code works if 'currentSprite' is replaced with 'bear0'
                spriteBatch.Draw (currentSprite, drawRectangle, Color.White);
                spriteBatch.End();

                base.Draw(gameTime);
            }
        }
    }
    Monday, February 12, 2018 8:21 AM

All replies

  • My guess would be that the issue is this line:

     int spriteNumber = rand.Next(0,3);

    If you look at the documentation for Random.Next you will see it accepts a min value and a max value which you are setting to 0 and 3. So there is a 1 in 4 chance that spriteNumber will be set to 3, even though you only have textures 0, 1 and 2!

    PS: You may want to consider putting your textures into a Texture2D array rather than 3 separate variables. Then you can just pick out the value from the array and remove the need to do a big "if (spriteNumber==0) etc etc" test :)

    currentSprite = bear[spriteNumber];


    • Edited by RJP1973 Monday, February 12, 2018 9:02 AM
    Monday, February 12, 2018 9:02 AM
  • I will need to look into an array.

    Regarding the rand.Next, according to many forums I have looked at, the min value of 0 will be inclusive, and the max value (3) will be exclusive, meaning 0-2 will be generated.

    Thanks for the reply

    Monday, February 12, 2018 9:52 AM
  • I will need to look into an array.

    Regarding the rand.Next, according to many forums I have looked at, the min value of 0 will be inclusive, and the max value (3) will be exclusive, meaning 0-2 will be generated.

    Thanks for the reply

    You are correct. I am an idiot.

    2nd attempt:

    Have you checked that all your Load<Texture2D> methods have successfully worked and that you haven't ended up with a bearN variable set to null?

    Is it possible that the Draw() method is getting called before the first call to Update()? If this is the case you just need to initialise currentSprite to one your bear variables in LoadContent.

    • Edited by RJP1973 Monday, February 12, 2018 9:59 AM
    Monday, February 12, 2018 9:54 AM
  • You probably forget to follow the comment “// STUDENTS: set the currentSprite variable to one of your sprite variables”. Maybe assign any initial bear to currentSprite here. Then when Update is executed, it will select another bear.


    • Edited by Viorel_MVP Monday, February 12, 2018 6:22 PM
    • Proposed as answer by Fei HuModerator Tuesday, February 27, 2018 8:04 AM
    Monday, February 12, 2018 6:21 PM
  • I think problem is currentSprite is not initialize before calling Draw method. Variable bear0 is initialized in LoadContent but currentSprite doesn't. 
    Monday, February 12, 2018 8:02 PM