4
\$\begingroup\$

Inside of my main class file I am initializing a number of game components which are used to represent game scenes i.e. main menu and game. I am initilizing each component inside of XNAs LoadContent method without issue and set the default scene as the main menu. I then switch to the game scene.

My issue then occurs when I switch back to the main menu scene and then try to start a new game by switch from the menu to the game scene. When I switch from the game to the menu I dispose of the game scene using the GameComponent.Dispose() method provided by the XNA framework.

private void UnloadScene(GameScene scene)
{
     scene.Dispose();
}

As I have disposed of the game scene I attempt to re-initialize the game scene component with the following method.

private void LoadScene(GameScene scene)
{
     scene = new GameScene(this, graphics.GraphicsDevice);
     Components.Add(scene);
}

I then switch from the menu scene to the game scene using the following method. This method is called in my Update method after the user has selected new game on the main menu.

public void SwitchScene(SceneManager manager)
{
     sceneManager.HideScene();
     sceneManager = manager;
     manager.ShowScene();
}

This time when the game scene loads I am met with a cornflower blue background and no assets on screen. I have placed a breakpoint within the above method and seen that the game scene is given all of the required data yet nothing is being drawn.

However if I explicitly place the following code above the SwitchScene() method after the player has selected new game then the scene is drawn without issue.

scene = new GameScene(this, graphics.GraphicsDevice);
Components.Add(scene);

Below is what the code looks like with the second approach mentioned.

if (InputHandler.IsHoldingButton(0, Buttons.A, out throwAway))
{
     switch (menuScene.Index)
     {
          case 0:
              gameScene = new GameScene(this, graphics.GraphicsDevice);
              Components.Add(gameScene);

              SwitchScene(gameScene);
              break;

          case 1:
              this.Exit();
              break;
     }
}

Is this behaviour intentional, if so how would I attempt to produce the first approach correctly?

Below is a screenshot of the graphics device after the second attempt to load the game scene. Note the data in this image is identical to the graphics device when loading the game scene for the first time.

GraphicsDevice Params

Below is the code for the SceneManager class.

public class SceneManager : DrawableGameComponent
{
    private readonly List<GameComponent> components;

    public List<GameComponent> Components
    {
        get { return components; }
    }

    public SceneManager(Game game)
        : base(game)
    {
        components = new List<GameComponent>();

        // Indicates whether draw should be called
        Visible = false;

        // Indicates whether GameComponent.Update should be called
        // when Game.Update is called
        Enabled = false;
    }

    public virtual void ShowScene()
    {
        Visible = true;
        Enabled = true;
    }

    public virtual void HideScene()
    {
        Visible = false;
        Enabled = false;
    }

    public override void Update(GameTime gameTime)
    {
        for (int i = 0; i < components.Count; i++)
        {
            if (components[i].Enabled)
                components[i].Update(gameTime);
        }

        base.Update(gameTime);
    }

    public override void Draw(GameTime gameTime)
    {
        for (int i = 0; i < components.Count; i++)
        {
            GameComponent component = Components[i];

            if ((component is DrawableGameComponent) &&
                ((DrawableGameComponent)component).Visible)
            {
                ((DrawableGameComponent)component).Draw(gameTime);
            }
        }

        base.Draw(gameTime);
    }
}
\$\endgroup\$
7
  • \$\begingroup\$ It almost looks like your reference to the graphics device is invalid. What is the value of graphicsDevice in the first version, when you re-initialize the game scene? \$\endgroup\$
    – Roy T.
    Commented Oct 13, 2014 at 14:02
  • \$\begingroup\$ I have added a screenshot of the graphics device after the second attempt to load the game scene. The data in the image is identical to what the graphics device shows when loading the game scene for the first time. \$\endgroup\$
    – Nexuz
    Commented Oct 13, 2014 at 14:11
  • \$\begingroup\$ And in the second try is graphicsDevice equal to graphics.GraphicsDevice? (imo they should be, but it is so weird that giving the second reference makes it work!) \$\endgroup\$
    – Roy T.
    Commented Oct 13, 2014 at 14:14
  • \$\begingroup\$ Yes, both are identical. \$\endgroup\$
    – Nexuz
    Commented Oct 13, 2014 at 14:16
  • 1
    \$\begingroup\$ I've had a similar problem, and it was because I had to re-initialize the camera with the graphics device. If you are using a camera for rendering your drawings it might be something worth looking into. \$\endgroup\$
    – jgallant
    Commented Oct 13, 2014 at 15:52

1 Answer 1

0
\$\begingroup\$

I have managed to get my application working with the first approach I was attempting to use. It appears that the way I am disposing of the GameScene is the cause of the issue. It seems as though it is also disposing of the SceneManager functionality which the GameScene is derived from as I noticed that none of my update and draw calls in both SceneManager and GameScene were being executed when the application had switched to the game scene.

However this does not explain why the second approach works and the first does not when I am disposing the scene the same way for both approaches. If anyone has any further information on this I would be greatful.

Rather than calling Dispose() on the game scene when I return to the main menu I am now declaring the game scene null.

private void UnloadScene(SceneManager scene)
{
     // Old approach
     // scene.Dispose();

     // New approach
     scene = null;
}

I am then re-initializing it inside of the LoadScene() method like I attempted originally.

private void LoadScene(GameScene scene)
{
     scene = new GameScene(this, graphics.GraphicsDevice);
     Components.Add(scene);
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .