0
\$\begingroup\$

I'm currently attempting to learn the Monogame system. I have little prior experience in C# (about two weeks of XNA, four years ago) but am reasonably familiar with VB.NET.

Essentially, when calling Game.Exit(), I get the following error: An unhandled exception of type 'System.NullReferenceException' occurred in MonoGame.Framework.dll

My main class is this:

using System;

namespace MonoTest
{
#if WINDOWS || LINUX
    /// <summary>
    /// The main class.
    /// </summary>
    public static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            using (var game = new Game1())
                game.Run();
        }
    }
#endif
}

And the class in which the error occurs is:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace MonoTest
{
    /// <summary>
    /// This is the main type for your game.
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        // IMAGES
        private Texture2D background;
        private Texture2D shuttle;
        private Texture2D earth;
        private SpriteFont luna24;
        private int score;

        private AnimatedSprite walker;

        private Texture2D arrow;
        private float angle = 0;
        private int bgTint = 0;

        //Keyboard information
        KeyboardState state;
        KeyboardState oldState; //state from the previous update
        //Mouse information
        MouseState mState;
        MouseState oldMState;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <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
            this.IsMouseVisible = true; //Exactly what it sounds like.
            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);
            background = Content.Load<Texture2D>("bg/stars");
            shuttle = Content.Load<Texture2D>("entities/shuttle");
            earth = Content.Load<Texture2D>("entities/earth");
            luna24 = Content.Load<SpriteFont>("Luna24");

            Texture2D walkerTex = Content.Load<Texture2D>("atlases/SmileyWalk");
            walker = new AnimatedSprite(walkerTex, 4, 4);
            arrow = Content.Load<Texture2D>("entities/arrow");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// game-specific 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)
        {
            state = Keyboard.GetState(); //get current state of the keyboard
            mState = Mouse.GetState();
            //have an oldState value to compare against to check for presses and ignore holds

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
            score++;
            walker.Update();

            if (state.IsKeyDown(Keys.A))
            {
                angle += 0.01f; //rotate the arrow
            }
            if (state.IsKeyDown(Keys.Escape))
            {
                Quit();
                //// Monogame's default initialization process seems to run the game without an instance, but that's impossible.
                //// Can't think of another explanation.

            }
            //if (oldState.IsKeyUp(Keys.A) && state.IsKeyDown(Keys.A))
            //{
            //    bgTint += 1;
            //        if (bgTint > 3)
            //        {
            //            bgTint = 0;
            //        }
            //}
            //// Above is sample of code to check that a button was pressed *this cycle*.

            // If a given button does not exist, it will always appear as released.
            if (mState.LeftButton == ButtonState.Pressed && oldMState.LeftButton == ButtonState.Released)
            {
                bgTint += 1;
                if (bgTint > 3)
                {
                    bgTint = 0;
                }
                Mouse.SetPosition(400, 240);
            }

            base.Update(gameTime);
            oldState = state; //call this at the end of each update loop
            oldMState = mState;
        }

        /// <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);
            Vector2 arrowOrigin = new Vector2(20, 100);

            Vector2 arrowLoc = new Vector2(400, 240);
            Rectangle arrowSource = new Rectangle(0, 0, arrow.Width, arrow.Height);

            spriteBatch.Begin();
            switch (bgTint)
            {
                case 0:
                spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.White);
                break;
                case 1:
                spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.Blue);
                break;
                case 2:
                spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.Green);
                break;
                case 3:
                spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.Red);
                break;
                default:
                spriteBatch.Draw(background, new Rectangle(0, 0, 800, 480), Color.White);
                break;
            }
            spriteBatch.DrawString(luna24, "Score: " + score, new Vector2(10, 10), Color.Blue);
            spriteBatch.Draw(arrow, arrowLoc, arrowSource, Color.White, angle, arrowOrigin, 1.0f, SpriteEffects.None, 1);

            spriteBatch.End();
            walker.Draw(spriteBatch, new Vector2(mState.X, mState.Y));


            base.Draw(gameTime);
        }

        private void Quit()
        {
            if (this != null)
            {
                Exit(); //this line produces the error
            }
        }
    }
}

As may be apparent, this was created using the standard Monogame project template. The code that seems to be causing the issue is the Quit() method.

    private void Quit()
    {
        if (this != null)
        {
            Exit(); //this line produces the error
        }
    }

Quit() is called in Update() when the escape key is pressed. My understanding is that the NullReferenceException would seem to imply that the object Exit() is being called on has not been initialized, but as everything else in the class works as expected I can't see how this could be the case. The stacktrace is below.

   at MonoGame.Framework.WinFormsGamePlatform.Exit()
   at Microsoft.Xna.Framework.Game.Exit()
   at MonoTest.Game1.Quit() in c:\Users\natha\AppData\Local\Temporary Projects\MonoTest\Game1.cs:line 176
   at MonoTest.Game1.Update(GameTime gameTime) in c:\Users\natha\AppData\Local\Temporary Projects\MonoTest\Game1.cs:line 103
   at Microsoft.Xna.Framework.Game.DoUpdate(GameTime gameTime)
   at Microsoft.Xna.Framework.Game.Tick()
   at MonoGame.Framework.WinFormsGameWindow.RunLoop()
   at MonoGame.Framework.WinFormsGamePlatform.RunLoop()
   at Microsoft.Xna.Framework.Game.Run(GameRunBehavior runBehavior)
   at Microsoft.Xna.Framework.Game.Run()
   at MonoTest.Program.Main() in c:\Users\natha\AppData\Local\Temporary Projects\MonoTest\Program.cs:line 18
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

A temporary resolution has been found. I was able to resolve the issue by replacing the Exit() call on the current object with System.Environment.Exit(). However, this still leaves the issue of why the exception occurred.

\$\endgroup\$
2
\$\begingroup\$

I'm no monogame expert, but, you call Exit two times. One in

if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

and one into Quit called here:

 if (state.IsKeyDown(Keys.Escape))
            {
                Quit();

I suppose the second time is called some resurce used inside exit is at null.

\$\endgroup\$
  • \$\begingroup\$ This was entirely correct-- the first call was part of the template and I'd completely forgotten it was there. \$\endgroup\$ – Passage Dec 25 '15 at 20:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.