Search code examples
c#xnamonogame

Slow update time with tiles and MouseState MonoGame


Very new developer here.

In my program I have a randomly generating world map using a simplex noise library. On top of this I am attempting to draw a tilemap of transparent 4x4 tiles that appear slightly translucent when the mouse is hovering over one.

I've got this working but it takes about 3 whole seconds for the highlighted tile to update to the mouse's current position. Is there anything I could do to solve this?

This is my code for the MouseState check in the tile class:

public override void Update(GameTime gameTime)
{
    _previousMouse = _currentMouse;
    _currentMouse = Mouse.GetState();

    var mouseRectangle = new Rectangle(_currentMouse.X, _currentMouse.Y, 1, 1);

    _isHovering = false;

    if (mouseRectangle.Intersects(Rectangle))
    {
        _isHovering = true;

        if (_currentMouse.LeftButton == ButtonState.Released && _previousMouse.LeftButton == ButtonState.Pressed)
        {
            Click?.Invoke(this, new EventArgs());
        }
    }
}

Sorry if this is formatted wrong or badly asked, first post so still getting to grips with everything :)


Solution

  • Invert the logic:

    Instead of checking thousands of tile objects against the mouse, apply the mouse to a single object.

    Assuming you have a list or array of tile objects:

    Add a new object to check for mouse hover and click:

    public class MouseDetect(Tile[] tiles) // replace with List<> as needed
    {
        int PrevHover = -1; // used to unHover
    
        // if (Area == Screen) make the next two lines `const`, so the compiler will remove all uses...
        int AreaX = 0; //Area x offset
        int AreaY = 0; //Area y offset
    
        int AreaW = 800; //Area width
        int AreaH = 480; //Area height
        const int Grid = 4; // assumes square
        const int GridW = AreaW / Grid;
    
    
    // I Will assume the `Delegate Click` in `Tile` is  public
        public void Update(MouseState ms, MouseState oms), //_currentMouse = ms and _previousMouse = oms;
        {
            int mouseIndex = (ms.X - AreaX) % Gridw + (ms.Y - AreaY) / GridW;
            tiles[PrevHover].Hover = false;
            PrevHover = mouseIndex;
            tiles[PrevHover].Hover = true;
    
            //Check Release
            if(tiles[PrevHover].Hover && ms.LeftButton == ms.ButtonState.Released && oms.LeftButton == ButtonState.Pressed)
             tiles[PrevHover].Click(tiles[PrevHover], new EventArgs());
        }
    }
    

    Remove the Update from the Tile class.


    Notes for anyone reading this later:

    Never call Mouse.GetState(); more than once per step.

    Predefined or framework names such as Rectangle should never be used as an identifier.

    i.e renamed and corrected to CollRectangle

    if (CollRectangle.Contains(ms.Position))