简体   繁体   English

向右或向左滚动(Monogame)并从网格中选择单位时获取鼠标位置

[英]Getting mouse position when scrolling right or left (Monogame), and choosing a unit from grid

I am creating a level editor for my game using Monogame. 我正在使用Monogame为我的游戏创建一个关卡编辑器。 At the level editor , the grid is printed on the screen . 在级别编辑器中,网格被打印在屏幕上。 The grid corresponds to a 2d array which represents the game map. 网格对应于代表游戏地图的2d数组。 When selecting a square at the grid , it changes the border's color according to the item selected at the menu. 在网格上选择一个正方形时,它将根据菜单上选择的项目更改边框的颜色。

For example, if i picked the second item from the left at the top of the menu, it will color the border of a selected square to green. 例如,如果我从菜单顶部的左侧选择了第二个项目,则它将所选正方形的边框颜色变为绿色。

My problem is , when i scroll to the right and select a square , i struggle to make a correct detection of where i clicked. 我的问题是,当我向右滚动并选择一个正方形时,我很难正确检测到我单击的位置。

See an example of the problem here: https://imgur.com/a/x07tDo3 // After scrolling right , i struggle to get the correct position 在此处查看问题的示例: https : //imgur.com/a/x07tDo3 //向右滚动后,我很难找到正确的位置

Any idea? 任何想法?

Here is my code, using an offset for scrolling , and the background itself is 64 pixel per unit. 这是我的代码,使用偏移量滚动,背景本身每单位64像素。 I have tried using camera from monogame.extended to solve the problem, but couldnt find a way to help it. 我曾尝试使用monogame.extended中的相机来解决问题,但找不到解决方法。 Thanks alot! 非常感谢!

            Point offset = new Point();
            Texture2D onePixelTex;
            int scrollSpeed = 7;
            int[,] map;
            int selectedTileStatus = 0;
            Color[] tileStatusColor = new Color[] { Color.Red, 
            Color.Green, Color.Blue };

              if (mouseState.LeftButton == ButtonState.Pressed)
        {
          //  var _worldPosition = _camera.ScreenToWorld(new Vector2(mouseState.X, mouseState.Y));
        //    Vector2 worldPosition = Vector2.Transform(new Vector2(ms.X,ms.Y), Matrix.Invert(_camera.GetViewMatrix()));

            var xIndex = ms.X / 64 ;
            var yIndex = ms.Y/ 64;
            Console.WriteLine(xIndex + " " + yIndex);
            bool handled = false;
            //for the menu to be selected
            for (int i = 0; i < tileRects.Length; i++)
            {
                if (tileRects[i].Contains(ms.X, ms.Y))
                {
                    selectedTileStatus = i;// choose 0 1 2 at menu. then use value to set at the matrix.
                    handled = true;
                }
            }

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

        }
         public void DrawGrid(int[,] gameMap, SpriteBatch spriteBatch, SpriteFont f)
    {
        for (int x = 0; x < gameMap.GetLength(0); x++)
        {
            for (int y = 0; y < gameMap.GetLength(1); y++)
            {

                Color color = tileStatusColor[map[x, y]];

                if (isGridActive)
                {
                    DrawBorder(new Rectangle(x * 64 + offset.X, y * 64, 64, 64), 2, color); // can draw any rectangle here 
                }
            }

        }

    }

       private void DrawBorder(Rectangle rect, int thicknessOfBorder, Color borderColor)
    {
        var pixel = onePixelTex;

        // Draw top line
        spriteBatch.Draw(pixel, new Rectangle(rect.X, rect.Y, rect.Width, thicknessOfBorder), borderColor);

        // Draw left line
        spriteBatch.Draw(pixel, new Rectangle(rect.X, rect.Y, thicknessOfBorder, rect.Height), borderColor);

        // Draw right line
        spriteBatch.Draw(pixel,
            new Rectangle(
                (rect.X + rect.Width - thicknessOfBorder),
                rect.Y,
                thicknessOfBorder,
                rect.Height),
            borderColor);
        // Draw bottom line
        spriteBatch.Draw(pixel,
            new Rectangle(
                rect.X,
                rect.Y + rect.Height - thicknessOfBorder,
                rect.Width,
                thicknessOfBorder),
            borderColor);
    }
    protected override void LoadContent()
    {
        this.IsMouseVisible = true;
        backGround1 = Content.Load<Texture2D>("layer/level_01_A");
        backGround2 = Content.Load<Texture2D>("layer/level_01_B");
        backGround3 = Content.Load<Texture2D>("layer/level_01_C");
        backGround4 = Content.Load<Texture2D>("layer/level_01_D");
        backGround5 = Content.Load<Texture2D>("layer/level_01_E");
        int totalWidth = backGround1.Width + backGround2.Width + backGround3.Width + backGround4.Width + backGround5.Width;
        map = new int[totalWidth / 64 , backGround1.Height / 64];
        font = Content.Load<SpriteFont>("Fonts/Font");
        spriteBatch = new SpriteBatch(GraphicsDevice);
        onePixelTex = new Texture2D(GraphicsDevice, 1, 1);
        onePixelTex.SetData(new Color[] { Color.White });
        // TODO: use this.Content to load your game content here
    }
      protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);
        spriteBatch.Begin();
        //offset is needed for scrolling
        spriteBatch.Draw(backGround1, new Rectangle(0 + offset.X, -700, 3840, 1984), Color.White);
        spriteBatch.Draw(backGround2, new Rectangle(3840 + offset.X, -700, 3840, 1984), Color.White);
        spriteBatch.Draw(backGround3, new Rectangle((3840 * 2 )+ offset.X, -700, 3840, 1984), Color.White);
        spriteBatch.Draw(backGround4, new Rectangle(3840*3 + offset.X, -700, 3840, 1984), Color.White);
        spriteBatch.Draw(backGround5, new Rectangle(3840*4 + offset.X, -700, 3840, 1984), Color.White);
        DrawGrid(map, spriteBatch, font);
        spriteBatch.End();
        base.Draw(gameTime);
    }

If the variable named ms is your mouse position, then you will need to translate this against your camera offset. 如果名为ms的变量是您的鼠标位置,那么您将需要针对您的相机偏移量对其进行转换。

        var xIndex = (ms.X - offset.X) / 64;
        var yIndex = (ms.Y - offset.Y) / 64;

If you don't need the functionality of a full camera class with rotation and scaling, this should work but I would recommend changing some lines in your draw function. 如果您不需要具有旋转和缩放功能的完整相机类的功能,则应该可以使用,但是我建议您更改绘图功能中的某些线条。 You can still use a matrix with your spritebatch which should help with keeping everything working and allow you to write less code when adding things that are going to move with the camera. 您仍然可以在spritebatch中使用矩阵,这将有助于保持一切正常运行,并在添加将随相机移动的内容时减少编写代码。

Matrix transformMatrix = Matrix.CreateTranslation(new Vector3(offset.X, offset.Y, 0.0f));
spritebatch.Begin(sortMode, blendState, samplerState, depthStencilState,
                  rasterizerState, effect, transformMatrix);

I haven't tested this yet but this should work and allow for you to remove the "+ offset.X" in your draw calls. 我尚未对此进行测试,但是它应该可以工作,并且允许您在绘图调用中删除“ + offset.X”。 I'm pretty sure that translation is correct but I'll double check it once I get home and update this if it's not. 我很确定翻译是正确的,但是回到家后我会仔细检查,如果不正确,请进行更新。

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

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