获取鼠标在网格上的位置

Getting location of mouse on a grid

所以我一直在思考如何将我在 monogame/XNA 中的鼠标位置转换为我的网格位置。我想要实现的基本上是在单击它们时将网格中特定单元格上的矩形颜色更改为不同的颜色。

这是我第一次在网格系统上工作,我真的不知道如何做。

这是我构建网格的方式。这里基本上发生的是我首先用 0 填充网格中的每个单元格。根据我在 Game1 class 的更新方法中分配的值,矩形的颜色会发生变化。

谢谢!

 public int[,] gridCell;
    Texture2D texture;
    public Rectangle rect;
    int col;
    int row;
    const int gridSize = 32;



    //Initializes the constructor
    public Grid(int sizeCol, int sizeRow)
    {
        //texture = sprite;
        col = sizeCol;
        row = sizeRow;
        gridCell = new int[col, row];

        for(int i = 0; i<col;i++)
        {
           for(int j = 0; j<row;j++)
            {
                gridCell[i, j] = 0;
            }
        }
    }


    public void Draw(SpriteBatch spritebatch)
    {
        for (int i = 0; i <= col-1; i++)
        {
            for (int j = 0; j <= row-1; j++)
            {
                if (gridCell[i, j] == 0)
                {
                    spritebatch.FillRectangle(i * 32, j * 32, 31, 31, Color.CornflowerBlue, 0f);
                    spritebatch.DrawRectangle(new Vector2(i * 32, j * 32), new Vector2(32, 32), Color.Black, 1f);
                }

                else if( gridCell[i,j] == 1)
                {
                    spritebatch.FillRectangle(i * 32, j * 32, 31, 31, Color.Yellow, 0f);
                    spritebatch.DrawRectangle(new Vector2(i * 32, j * 32), new Vector2(32, 32), Color.Black, 1f);
                }
                else if (gridCell[i, j] == 2)
                {
                    spritebatch.FillRectangle(i * 32, j * 32, 31, 31, Color.Red, 0f);
                    spritebatch.DrawRectangle(new Vector2(i * 32, j * 32), new Vector2(32, 32), Color.Black, 1f);
                }
                else if (gridCell[i, j] == 3)
                {
                    spritebatch.FillRectangle(i * 32, j * 32, 31, 31, Color.Purple, 0f);
                    spritebatch.DrawRectangle(new Vector2(i * 32, j * 32), new Vector2(32, 32), Color.Black, 1f);
                }
                else if (gridCell[i, j] == 4)
                {
                    spritebatch.FillRectangle(i * 32, j * 32, 31, 31, Color.Blue, 0f);
                    spritebatch.DrawRectangle(new Vector2(i * 32, j * 32), new Vector2(32, 32), Color.Black, 1f);
                }
                else if (gridCell[i, j] == 5)
                {
                    spritebatch.FillRectangle(i * 32, j * 32, 31, 31, Color.Black, 0f);
                    spritebatch.DrawRectangle(new Vector2(i * 32, j * 32), new Vector2(32, 32), Color.Black, 1f);
                }
            }
        }
    }

好的,事情是这样的:假设您的网格的一个正方形是 8x8。鼠标的位置可以在 8 到 0 之间,你只需要 0/8/16/24/... 当你将鼠标位置除以 8(假设 Mposition 是 4x20)时,你会得到 0.5x2 .5,如果你乘以 8,你会再次得到 4x20,但是:如果你截断除法结果,你会得到 0x2,乘以 8 是 0x16,所以(0x16) 是鼠标所在方块的实际位置,0x2 是鼠标的矩阵位置。这是一个简单的函数,可以满足您的需求:

public Vector2 PositionByGrid (int gridSize)
    {
        Vector2 result = new Vector2(MouseState.GetState().X, MouseState.GetState().Y);
        result.X = (int)(result.X / gridSize) * gridSize;
        result.Y = (int)(result.Y / gridSize) * gridSize;
        return result;
    }

这个函数会return方块的位置。如果你想要矩阵中的位置,只需输入 result.X = (int)(result.X / gridSize); 而不是 result.X = (int)(result.X / gridSize) * gridSize;

编辑:
正如@Slubberdegullion 所建议的,如果您的网格不是正方形而是矩形(适用于矩阵的相同原理),这里是函数:

public Vector2 PositionByGrid (int gridWidth, int gridHeight)
    {
        Vector2 result = new Vector2(MouseState.GetState().X, MouseState.GetState().Y);
        result.X = (int)(result.X / gridWidth) * gridWidth;
        result.Y = (int)(result.Y / gridHeight) * gridHeight;
        return result;
    }



编辑 2: 这是一个建议
此外,您可以缩短 Draw 函数,使其看起来像这样(建议 2 中的解释):

public void Draw(SpriteBatch spritebatch)
{
    for (int i = 0; i <= col-1; i++)
    {
        for (int j = 0; j <= row-1; j++)
        {
            Color newColor;
            switch(gridCell[i, j])
            {
                case 0: newColor = Color.CornflowerBlue; break;
                case 1: newColor = Color.Yellow; break;
                case 2: newColor = Color.Red; break;
                case 3: newColor = Color.Purple; break;
                case 4: newColor = Color.Blue; break;
                case 5: newColor = Color.Black; break;
                default: newColor = Color.White; break;
            }
            spritebatch.FillRectangle(i * 32, j * 32, 31, 31, newColor, 0f);
            spritebatch.DrawRectangle(new Vector2(i * 32, j * 32), new Vector2(32, 32), Color.Black, 1f);

        }
    }
}

这确实会使用更多的 RAM(等于向游戏中添加 4 个新的整数变量,因为颜色基本上是 Vector4,但使用 int 而不是 float)和 CPU 时间,但是对于您的游戏完整性和可读性而言,成本非常低。
建议 2:从你的代码中我相信你是一个初学者,话虽如此,我觉得我有义务告诉你不要在代码中重复相同的(组)代码行。相反,创建一个函数/执行我对 Draw 函数所做的操作等。按照您的方式,如果您到了必须更改 1 项的地步,则必须在 X 处进行更改。如果你必须再次更改它,或者再更改几次怎么办?通过在一个函数中保留重复代码,当需要时,您只需更改该函数中的一件事。

在构建网格时为网格生成一个碰撞矩形数组。

Rectangle[,] gridRects = new Rectangle[row, col];

for (int i = 0; i < row; i++)
{
    for (int j = 0; j < col; j++)
    {
        gridRects[i,j] = new Rectangle(i * gridSize, j * gridSize, gridSize, gridSize);
    }
}

然后在 Update 中对每一帧检查碰撞

MouseState ms = Mouse.GetState();

for (int i = 0; i < row; i++)
{
    for (int j = 0; j < col; j++)
    {
        if (gridRects.Contains(ms.X, ms.Y))
        {
            // Mouse is on gridCell[i,j]
        }
    }
}