Search code examples
c#mousemonogame

C# Monogame - handling mouse


I'm trying to understand what is the proper way of handling mouse input when there are multiple objects on the screen that can be clicked. I have a custom Mouse class and many "game objects" on the screen that can be clicked (say like buttons of a gui). In many simple tutorials I see people check for mouse-pressed or released inside the Update method of each game object instance present on the scene and then the particular clicked object invokes an event that it has been clicked. But having say 20 or 30 or more of these objects - each with a different function means that the "top layer" (the manager of these objects) has to subscribe to all the OnClick events of all the buttons and call the respective function. Is this the correct way? (I'm not asking for an opinion - I know that each can program it's own way) Is there a less cumbersome way of programming this?

The "solution" that I was thinking is putting the click event ivocation in the Mouse class. So the mouse will notify the game/state/ui-manager that a click occured, passing the mouse coordinates and buttin clicked in the eventArgs. Then (and not at each game loop as before) the "manager" would find the game-object that has been clicked over. This might work for click events but is it possible to implement the mouse hover functionality in this way too?

Thanks for your 2 cents.


Solution

  • I prefer to implement a static InputManager class to provide a common input across platforms and input devices.

    Here are snippets of that class relevant to your question:

    public static class InputManager
    {
       public static bool LeftClicked = false;
    
       private static MouseState ms = new MouseState(), oms;
    
       public static void Update()
       {
          oms = ms;
          ms = Mouse.GetState();
          LeftClicked = ms.LeftButton != ButtonState.Pressed && oms.LeftButton == ButtonState.Pressed; 
       // true On left release like Windows buttons
       }
       public static bool Hover(Rectangle r)
       {
          return r.Contains(new Vector2(ms.X,ms.Y));
       }
    }
    

    The first line of Update in game1.cs:

       InputManager.Update();
    

    In any of your game objects' Update method with a collision or draw rectangle named rect:

       if (InputManager.Hover(rect))
       {
          // do hover code here
          if(InputManager.LeftClicked)
          {
             //Do click action here
          }
       }
       else
       {
          //undo hover code here
       }
    

    The only time I used a native input event callback with MonoGame was in an Android App to register/process swipes that could occur faster than 16.66ms, 60 fps.(There were no Threading issues involved in that case)