Menu drawing


I have been able to get a menu to draw now. It opens with the A button and closes with the X button from the GamePad.
I tried to have left on the Dpad select the magic icon but I right now the game is taking input over the menu screen so I will need to manage inputs for the game screens.
I also don't have any sort of state tracking for Gamepad or Keyboard so when I had A set to open and A to close, the A button would quickly flash the menu but close it again.

The way this was done was I created an interface:
public interface IScreen {
      void Update(GameTime gameTime);

      void Draw(GameTime gameTime);

      void Initialize();

      void LoadContent();

      void UnloadContent();

      bool IsClosed { get; set; }
      bool IsModal { get; }
   }

Then I created a MenuScreen class which inherits from that interface:
public class MenuScreen : IScreen
   {
      public MenuScreen(Game game) {
         _game = game;
      }
      private Game _game;
      private SpriteBatch _spriteBatch;
      private SpriteFont _titleFont;
      private bool _isClosed;
      private Texture2D _menuTexture;
      private Texture2D _menuLeftTexture;
      private Vector2 _menuPosition;

      /// <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 void Initialize()
      {
         // TODO: Add your initialization code here

        
      }

      /// <summary>
      /// Allows the game component to update itself.
      /// </summary>
      /// <param name="gameTime">Provides a snapshot of timing values.</param>
      public void Update(GameTime gameTime)
      {
         // TODO: Add your update code here
         if (GamePad.GetState(PlayerIndex.One).Buttons.A == ButtonState.Pressed)
            _isClosed = true;
         if (GamePad.GetState(PlayerIndex.One).DPad.Left == ButtonState.Pressed)
            DrawLeft(gameTime);
      }

      public void Draw(GameTime gameTime) {
         _spriteBatch.Begin();
         _spriteBatch.Draw(_menuTexture, _menuPosition, null, Color.White, 0f, Vector2.Zero, 2f, SpriteEffects.None, 0f);
         _spriteBatch.End();
      }

      public void DrawLeft(GameTime gameTime) {
         _spriteBatch.Begin();
         _spriteBatch.Draw(_menuLeftTexture, _menuPosition, null, Color.White, 0f, Vector2.Zero, 2f, SpriteEffects.None, 0f);
         _spriteBatch.End();
      }
      public void LoadContent() {
         _spriteBatch = new SpriteBatch(_game.GraphicsDevice);
         _menuPosition = new Vector2(375, 500);
         _titleFont = _game.Content.Load<SpriteFont>("Fonts\\MenuTitle");
         _menuTexture = _game.Content.Load<Texture2D>("Menu\\shfo2_battlemenu_default");
         _menuLeftTexture = _game.Content.Load<Texture2D>("Menu\\shfo2_battlemenu_magic");
      }
      public void UnloadContent() {
        
      }
      public bool IsClosed {
         get { return _isClosed; }
         set { _isClosed = value; }
      }
      public bool IsModal { get { return true; } }

   }


I also did a GameScreen class:

public class GameScreen : IScreen {
      public GameScreen(Game game) {
         _game = game;
      }


      private Game _game;
      private SpriteBatch _spriteBatch;
      private SpriteFont _titleFont;
      private string _text;
     

      public void Initialize() {
         // TODO: Add your initialization code here
      }

      public void Update (GameTime gameTime) {
         IScreen overlay = ( ( IScreenNotify )_game ).OverlayScreen;
         if (null != overlay) {
            if (overlay.IsModal) {
               _text = "Game (paused - modal overlay)";
               return;
            }
            _text = "Game (active - modeless overlay)";
         }
         else {
            _text = "Game (active)";
         }
         if (GamePad.GetState(PlayerIndex.One).Buttons.X == ButtonState.Pressed)
            ( ( IScreenNotify )_game ).SetOverlayType(typeof( MenuScreen ));
      }

      public void Draw (GameTime gameTime) {
         _spriteBatch.Begin();
         _spriteBatch.DrawString(_titleFont, _text, Vector2.Zero, Color.Black);
         _spriteBatch.End();
      }

      public void LoadContent() {
         _spriteBatch = new SpriteBatch(_game.GraphicsDevice);
         _titleFont = _game.Content.Load<SpriteFont>("Fonts\\MenuTitle");
      }

      public void UnloadContent() {
        
      }

      public bool IsClosed {
         get { return false; }
         set {}
      }

      public bool IsModal { get { return true; } }
   }

I also created an IScreenNotify inteface:

interface IScreenNotify {
      void SetOverlayType(Type screen);

      IScreen OverlayScreen { get; }
   }

Then on the main Game class implemented them:

private IScreen _overlayScreen;
private IScreen _gameScreen;
private readonly Dictionary<Type, IScreen> _screens = new Dictionary<Type,IScreen>();

In the initialize method of the Game class:

_gameScreen = new GameScreen(this);
_gameScreen.Initialize();
loadOverlay(typeof( MenuScreen ));

In the load content method of the Game class:

spriteBatch = new SpriteBatch(GraphicsDevice);
_gameScreen.LoadContent();

In the Update method of the Game class:

_gameScreen.Update(gameTime);

         if (null != _overlayScreen) {
            if (_overlayScreen.IsClosed) {
               _overlayScreen.IsClosed = false;
               _overlayScreen = null;
            }
            else {
               _overlayScreen.Update(gameTime);
            }
         }

Next in the Draw method of the Game class:

 _gameScreen.Draw(gameTime);
         if (_overlayScreen != null)
            _overlayScreen.Draw(gameTime);

Finally I had to create a few extra methods in the Game class:

 public void SetOverlayType(Type screen)
      {
         loadOverlay(screen);
      }

      public IScreen OverlayScreen
      {
         get { return _overlayScreen; }
      }
     
      private void loadOverlay(Type screen) {
         IScreen newScreen;
         if (!_screens.TryGetValue(screen, out newScreen)) {
            ConstructorInfo ci = screen.GetConstructor(new[] { typeof( Game ) });
            newScreen = ( IScreen )ci.Invoke(new object[] { this });
            newScreen.Initialize();
            newScreen.LoadContent();
            _screens.Add(screen, newScreen);
         }
         _overlayScreen = newScreen;
      }

Now is by no means believe this is the best way to do this but it was something I had tried out with a buddy while making another game and wanted  to try it here.

Until next day of Thor.




Comments

Popular Posts