简体   繁体   English

XNA / Monogame如何检测鼠标何时悬停在按钮上

[英]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? 但是,我的进度已停在菜单上,我试图找出如何检测鼠标是否在按钮上方,但是我无法弄清楚如何使用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. 请注意, isClicked标志实际含义的定义可能有所不同。 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: 我通常将尽可能多的Input逻辑分离到一个静态InputManager类中:

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: 然后,您的MenuButton类可能看起来像这样:

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. 当然,您将拥有Draw()函数以及其他一些函数。

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. 例如,在按下按钮时能够处理单击,然后光标移开,移回按钮,然后释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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