简体   繁体   中英

XNA / Monogame How to detect when the mouse hovers over a button

I'm currently studying programming and am making a small game in monogame. However, my progress has run to a stop at the menu, I'm trying to work out how to detect if my mouse is above a button, but I'm not able to figure out how I can check this with the sprite?

class Menubutton
{
    public Texture2D texture;
    public Vector2 coords;
    bool isClicked = false;
    bool isHovered = false;

    public Menubutton(Texture2D textur, int X, int Y)
    {
        this.texture = textur;
        this.coords.X = X;
        this.coords.Y = Y;
    }

    public void Update(GameWindow window)
    {


    }

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

}

Something like this should do the trick:

public void Update(GameWindow window)
{
    var mouseState = Mouse.GetState();
    var mousePoint = new Point(mouseState.X, mouseState.Y);
    var rectangle = new Rectangle(mousePoint.X, mousePoint.Y, this.texture.Width, this.texture.Height);

    if (rectangle.Contains(mousePoint))
    {
        isHovered = true;
        isClicked = mouseState.LeftButton == ButtonState.Pressed;
    }
    else
    {
        isHovered = false;
        isClicked = false;
    }
}

Note that the definition of what the isClicked flag actually means could vary. In this simple implementation it just means that the mouse button is pressed while over the button, but technically that's not really a "click" so I'll leave it up to you to consider if you want something more sophisiticated than that.

I usually separate as much Input logic as I can in to a static InputManager class:

public static class InputManager
{
    // #region #endregion tags are a nice way of blockifying code in VS.
    #region Fields

    // Store current and previous states for comparison. 
    private static MouseState previousMouseState;
    private static MouseState currentMouseState;

    // Some keyboard states for later use.
    private static KeyboardState previousKeyboardState;
    private static KeyboardState currentKeyboardState;

    #endregion



    #region Update

    // Update the states so that they contain the right data.
    public static void Update()
    {
        previousMouseState = currentMouseState;
        currentMouseState = Mouse.GetState();

        previousKeyboardState = currentKeyboardState;
        currentKeyboardState = Keyboard.GetState();
    }

    #endregion



    #region Mouse Methods

    public static Rectangle GetMouseBounds(bool currentState)
    {
        // Return a 1x1 squre representing the mouse click's bounding box.
        if (currentState)
            return new Rectangle(currentMouseState.X, currentMouseState.Y, 1, 1);
        else
            return new Rectangle(previousMouseState.X, previousMouseState.Y, 1, 1);
    }

    public static bool GetIsMouseButtonUp(MouseButton btn, bool currentState)
    {
        // Simply returns whether the button state is released or not.

        if (currentState)
            switch (btn)
            {
                case MouseButton.Left:
                    return currentMouseState.LeftButton == ButtonState.Released;
                case MouseButton.Middle:
                    return currentMouseState.MiddleButton == ButtonState.Released;
                case MouseButton.Right:
                    return currentMouseState.RightButton == ButtonState.Released;
            }
        else
            switch (btn)
            {
                case MouseButton.Left:
                    return previousMouseState.LeftButton == ButtonState.Released;
                case MouseButton.Middle:
                    return previousMouseState.MiddleButton == ButtonState.Released;
                case MouseButton.Right:
                    return previousMouseState.RightButton == ButtonState.Released;
            }

        return false;
    }

    public static bool GetIsMouseButtonDown(MouseButton btn, bool currentState)
    {
        // This will just call the method above and negate.
        return !GetIsMouseButtonUp(btn, currentState);
    }

    #endregion



    #region Keyboard Methods

    // TODO: Keyboard input stuff goes here.

    #endregion
}

// A simple enum for any mouse buttons - could just pass mouseState.ButtonState instead 
public enum MouseButton
{
    Left,
    Middle,
    Right
}

Your MenuButton class might then look something like this:

public class MenuButton
{
    #region Properties

    // Some properties that might come is handy
    public Rectangle Bounds { get { return bounds; } }

    public MenuButtonState State { get { return currentState; } }

    // Redundant but handy
    public bool IsClicked { get { return currentState == MenuButtonState.Clicked; } }

    #endregion



    #region Fields

    private Texture2D texture;
    private Vector2 position;
    private Rectangle bounds;

    private MenuButtonState currentState;

    #endregion



    #region Constructor

    public MenuButton(Texture2D texture, Vector2 position)
    {
        this.texture = texture;
        this.position = position;
        // Cast position X and Y to ints for the rectangle's constructor.
        bounds = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);

        // MenuButton starts off as Released.
        currentState = MenuButtonState.Released;
    }

    #endregion



    #region Update

    public void Update()
    {
        // There are much better ways to impliment button interaction than this 
        // but here is a simple example:

        // If the mouse cursor is on our MenuButton...
        if (InputManager.GetMouseBounds(true).Intersects(bounds))
        {
            // And if the Left mouse button is down...
            if (InputManager.GetIsMouseButtonDown(MouseButton.Left, true))
            {
                // Then our MenuButton is down!
                currentState = MenuButtonState.Pressed;
            }
            // Else if the Left mouse button WAS down but isn't any more...
            else if (InputManager.GetIsMouseButtonDown(MouseButton.Left, false))
            {
                // Then our MenuButton has been clicked!
                currentState = MenuButtonState.Clicked;
            }
            // Otherwise...
            else
            {
                // The mouse cursor is simply hovering above our MenuButton!
                currentState = MenuButtonState.Hovered;
            }
        }
        else
        {
            // If the cursor does not intersect with the MenuButton then just set the state to released.
            currentState = MenuButtonState.Released;
        }
    }

    #endregion
}

public enum MenuButtonState
{
    Released,
    Hovered,
    Pressed,
    Clicked
}

Of course you'll have a Draw() function and possibly some others.

I have not tested the above code but mainly I hope it helps you get where you want. I've had a lot of fun trying to implement different ways of interacting with the button. For example being able to process clicks when the the button is held down, then the cursor moved away, and moved back to the button, and then released.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM