Search code examples
c#xnamonogamemouse-position

Assigning values to a 2D array , using mouse clicks on a screen at monogame


I am working on a level editor for my game, developed by C# , using Monogame. There is a 2D matrix which represents the map itself , each cell is a 64 pixel unit. When loading the background , coordinates are shown on top of the screen, see example below. At first, the 2D matrix is set to 0 at each cell, by default. What i need is , by clicking objects at the screen using the left mouse button , to set a different value to the cell which corresponds to it at the matrix. Thats how i define obstacles at the game , which later on will be defined as collisions for the player when hitting them. For example , to define a ceiling, i would need to click several objects at the top of the screen one by another , at the same row . As an example, for a 640X192 background image, the matrix it would look like the example below (Since width is width/64 , and height is height/64)

{
{1,1,1,1,1,1,1,1,1,1}
{0,0,0,0,0,0,0,0,0,0}
{0,0,0,0,0,0,0,0,0,0}
 }

See example here for the screen and the coordinates: https://i.sstatic.net/zbUHJ.jpg Thanks alot for any help !

   class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Texture2D gameBackround;
    SpriteFont font;
    int[,] map ;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
        graphics.PreferredBackBufferWidth = 1920;
        graphics.PreferredBackBufferHeight = 1080;
        graphics.GraphicsProfile = GraphicsProfile.HiDef;

    }




    protected override void LoadContent()
    {


        this.IsMouseVisible = true;
        gameBackround = Content.Load<Texture2D>("level_01_A");//this is the background

    map = new int[gameBackround.Width / 64, gameBackround.Height / 64];

        font = Content.Load<SpriteFont>("Fonts/Font");
        spriteBatch = new SpriteBatch(GraphicsDevice);
    }          

      protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        spriteBatch.Draw(gameBackround, new Rectangle(0, -700, 3840, 1984), Color.White);
        DrawGrid(map, spriteBatch, font);
        base.Draw(gameTime);
        spriteBatch.End();
    }

             public void DrawGrid(int[,] gameMap, SpriteBatch spriteBatch, SpriteFont f)
    {
        for (int x = 0; x < gameMap.GetLength(1); x++)
        {
            for (int y = 0; y < gameMap.GetLength(0); y++)
            {
                spriteBatch.DrawString(f, x + " / " + y, new Vector2(x * 64, y * 64), Color.White);
            }

        }

    }

Solution

  • You need to do the following:

    • Detect a click and get the position of the mouse cursor
    • Convert the positions's X and Y co-ordinates to indices for your 2D array
    • Index the array and amend the values as required

    First you need to get the mouse's state using Mouse.GetState.

    You can then detect mouse clicks like so:

    var mouseState = Mouse.GetState();
    
    if (mouseState.LeftButton == ButtonState.Pressed)
    {
        // do something here
    }
    

    mouseState has X and Y members, which gets you the mouse cursor's position relative to the top-left corner of the game window.

    You need to convert this position to array indices. To do this, divide the X and Y components by the size of the tiles - 64 in your case:

    var xIndex = mouseState.X / 64;
    var yIndex = mouseState.Y / 64;
    

    You can then amend your array as you see fit:

    map[xIndex, yIndex] = 1;
    

    You'll want to do some bounds checking also, to ensure the indices you calculate are actually in the array.

    Lower bounds check is trivial - just check if xIndex and yIndex are greater than zero.

    For upper bounds check, use the GetLength property to get the length of each dimension of your array. Then assert that xIndex and yIndex are less than those values:

    if (xIndex >= 0 && xIndex < map.GetLength(0) && yIndex >= 0 && yIndex < map.GetLength(1)) {
      map[xIndex][yIndex] = 1;
    }
    

    All together something like this in your Update method should work:

    var mouseState = Mouse.GetState();
    
    if (mouseState.LeftButton == ButtonState.Pressed)
    {
      var xIndex = mouseState.X / 64;
      var yIndex = mouseState.Y / 64;
    
      if (xIndex >= 0 && xIndex < map.GetLength(0) && yIndex >= 0 && yIndex < map.GetLength(1)) {
        map[xIndex][yIndex] = 1;
      }
    }
    

    Hope that helps