Search code examples
c#xna

Close XNA game window on rectangle click


I'm new to XNA and I'm trying to create a simple game menu and I'm using rectangles as menu items. I have the main class which is called Game1.cs and a different class for a rectangle, that is supposed to close the game on click, which is called _exitGame.cs. So far I've got this-

In the main class I initialize a class variable:

_exitGame exitGame;

I load the texture and the rectangle:

exitGame = new _exitGame(Content.Load<Texture2D>("exitGame"), new Rectangle(50, 250,300,50));

I've created a update code for the class:

exitGame.Update(gameTime);

And I draw the rectangle:

exitGame.Draw(spriteBatch);

In my _exitGame class I have this:

class _exitGame
    {
        Texture2D texture;
        Rectangle rectangle;

        public _exitGame(Texture2D newTexture, Rectangle newRectangle)
        {
            texture = newTexture;
            rectangle = newRectangle;

        }
        public void LoadContent()
        {

        }
        public void Update(GameTime gametime)
        {
            var mouseState = Mouse.GetState();
            var mousePosition = new Point(mouseState.X, mouseState.Y);
            var recWidth = rectangle.Width;
            var recHeight = rectangle.Height;
            if (rectangle.Contains(mousePosition))
            {
                rectangle.Width = 310;
                rectangle.Height = 60;
            }
            else
            {
                rectangle.Width = 300; 
                rectangle.Height = 50;
            }

        }
        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture, rectangle , Color.White);
        }
    }

So right now what I have is a rectangle that changes its size on mouse hover. Earlier I used code this.Close(); to close the game on keyboard button click but since I can't use it in this situation I'm a bit confused how to achieve this functionality. Any tips on how to do that?


Solution

  • Closing an XNA game can be achieved by calling Exit() method in your Game class.

    In your case, you could raise an event in your _exitGame class

    class _exitGame
    {
        public event EventHandler ExitRequested = delegate {};
    
        Texture2D texture;
        Rectangle rectangle;
    
        public _exitGame(Texture2D newTexture, Rectangle newRectangle)
        {
            texture = newTexture;
            rectangle = newRectangle;
    
        }
        public void LoadContent()
        {
    
        }
        public void Update(GameTime gametime)
        {
            var mouseState = Mouse.GetState();
            var mousePosition = new Point(mouseState.X, mouseState.Y);
            var recWidth = rectangle.Width;
            var recHeight = rectangle.Height;
            if (rectangle.Contains(mousePosition))
            {
                rectangle.Width = 310;
                rectangle.Height = 60;
                if (mouseState.LeftButton == ButtonState.Pressed)
                {
                    ExitRequested(this, EventArgs.Empty);
                }
            }
            else
            {
                rectangle.Width = 300; 
                rectangle.Height = 50;
            }
    
        }
        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture, rectangle , Color.White);
        }
    }
    

    and subscribe to that event in your Game class

    exitGame = new _exitGame(Content.Load<Texture2D>("exitGame"), new Rectangle(50, 250,300,50));
    exitGame.ExitRequested += (s, e) => Exit();
    

    A couple of notes:

    • In order not to always perform nullity check when raising an event, it is often convenient to use an empty delegate public event EventHandler ExitRequested = delegate {};
    • mouseState.LeftButton == ButtonState.Pressed expression will return true as long as left mouse button is down and not only on first click. It is fine as long as you use it to exit game, but for other scenarios where the update cycle will continue running, you should store the mouse state for previous update cycle and additionally check if mouse state was NOT pressed in previous cycle and pressed in current to catch a click event.