Drawing from a new class is not working?

It’s just saying “An unhandled exception of type ‘System.InvalidOperationException’ occurred in MonoGame.Framework.dll”
and I don’t know what to do and why it isn’t working

Was Begin called prior to this? Each SpriteBatch Begin call must be followed by an End. Does the stack trace indicate where the error is?

Could be one of a few different things.

If you check the source code for Spritebatch we can see what types of situations throw that error: https://github.com/labnation/MonoGame/blob/master/MonoGame.Framework/Graphics/SpriteBatch.cs

The only ways I see to raise that particular exception is when either: you’ve called Begin() on the spritebatch twice without a prior End() (they must come in pairs), or both a position and a vector2 are passed into the Draw method, which appears not to be the case.

Based on the situation, you’re passing in a Spritebatch from outside this class… so I’d check to make sure that whoever called the Draw() method in this class ended its spritebatch before this class gets it. The Spritebatch is a reference type, so it’s state is persistent in memory as it’s passed around.

Instead you could nest the call to this class with Begin() and End().

spritebatch.Begin();
selection.Draw(spritebatch, spritefont);
spritebatch.End();

That’s just a quick and dirty method, though. In the long run you may want a more dynamic and comprehensive approach for Spritebatch management across your game.

If none of that works, you might need to find more specific info. That operationException should have come with a message and a stack trace as Kimimaru mentioned.

I’d suspect the same - external Begin may have been called already.
Btw - I’m just curious about this line:

class selection : Game1

I’ve never seen inheriting : Game1 before and wondering if this could lead to other potential issues.

You can’t just inheirit game1 willy nilly because it is instantiated in the Main function in program cs.
using (var game = new Game6()) game.Run();
Notice game.Run();

You could just use a drawable game component.

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

namespace GameComponentTest
{
    // links 
    // https://stackoverflow.com/questions/11372818/xna-game-components
    // https://www.codemag.com/article/1411081
    // Heres at least one decent link for a tutoria on this. http://blog.nuclex-games.com/tutorials/xna/components-and-services/
    // I dont use them but nothing wrong with using them.

    public class Player : DrawableGameComponent
    {
        SpriteBatch spriteBatch;
        Texture2D bigArrowTex2d;

        public Player(Game game) : base(game)
        {
        }
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            bigArrowTex2d = Game.Content.Load<Texture2D>("big arrow");
        }
        protected override void UnloadContent() { }

        int x = 300;
        public override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Game.Exit();

            if (x-- < -200)
                x = 800;

            base.Update(gameTime);
        }
        public override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(bigArrowTex2d, new Rectangle(x, 50, 200, 400), Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }

    }

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

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
        }
        
        protected override void Initialize()
        {
            player = new Player(this);
            Components.Add(player);
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
        }

        protected override void UnloadContent() { }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            base.Draw(gameTime);
        }
    }
}

However … I do regularly inherit game 1 myself.
.
.
If you’re trying to make a base class with the intent to have defaults to derive from.
This is how i do it primarily for prototyping or working on lots of different things at once.
.
.

public class BasicBaseGame : Game  // note this is really Game1
{...
  public BasicBaseGame()
  {
     Global.graphics = new GraphicsDeviceManager(this);
     Global.device = Global.graphics.GraphicsDevice;
     // ect ect... in load for content the spritebatch ect...
  }

  // you still need the constructor initializer load unload update and draw here.
}

public class Game6 : BasicBaseGame
{...
   public Game6() : base(){
   }

   // while the methods are derived you could override or add stuff onto the base called methods.
   // however that isn't really necessary if you also use a global class for states and defaults.
   // base.Initialize load ect will call the base methods.

   ...
   LoadContent()
   {
        Globals.content.Load<Texture2D>("myimage");
   }
}

Also be aware with a derived class the base constructor will execute first in this case.

// Output.

BasicGame : Game …BasicGame()
Game6 Constructing
Game6 Initialize
Game Initialize …BasicGame()
Game6 LoadContent()
Game LoadContent() …BasicGame()
Globals …SetUpLoad() // load defaults based on global states set from the derived class methods.
/// Global class has update draw ect as well that is called from the base class not the derived.
/// That allows for defaults stuff to be executed by turning it on in the derived game6 in this case.

/// in my case i have a default project set up as described here.
/// i make a new project and add a reference to the previous project to this then derive from project1’s BasicGame and i get all the functionally by default by typing this. or Globals.

public static class Globals
{... 
    // content spritebatch graphics, device so forth is also what i do.
    // i keep default settings in here as well so in a new project i can just call presets.
    public static Game game;
    public static GraphicsDeviceManager graphics;
    public static GraphicsDevice device;
    public static Texture2D dotTexture;
    public static SpriteBatch spriteBatch;
    public static SpriteFont currentFont;
    public static Microsoft.Xna.Framework.Content.ContentManager content;
    //
    public static bool DefaultUseOthographic = true;
    public static string DefaultFontName { get; set; }
    public static bool DefaultStatesSwitch { get; set; } = false;
    public static bool DefaultCameraSwitch { get; set; } = false;
    public static bool DefaultCameraMouseRightClickCentering { get; set; } = false;
    public static bool DefaultGrid3dSwitch { get; set; } = false;
    public static bool DefaultOreintationArrow3dSwitch { get; set; } = false;   
    public static bool DefaultQuickDrawSpriteBatch { get; set; } = true;
    public static bool DefaultUi { get; set; } = false;
    public static bool DefaultAllowCallbackOnKeyboardEvents { get; set; } = false;
    public static bool DefaultUseFixedTimeStep { get; set; } = false;
    public static float DefaultTimeStep { get; set; } = 120f;
    public static bool DefaultSyncronizeVerticalRetrace { get; set; } = false;
    public static bool DefaultDisplayMouse { get; set; } = false;
    public static bool DefaultAllowUserWindowResizing { get; set; } = false;
    public static bool DefaultDisplayFrameRate { get; set; } = true;
    public static bool DefaultDisplayGarbageCollections { get; set; } = true;

    public static MgFrameRate frameRate;

    // i also keep default update draw in here that is called from the base class.
    // as well as other things like callbacks ect anything that only should update or draw once per frame.
}
1 Like