向右或向左滚动时获取鼠标位置(Monogame),并从网格中选择一个单位
Getting mouse position when scrolling right or left (Monogame), and choosing a unit from grid
我正在使用 Monogame 为我的游戏创建关卡编辑器。
在关卡编辑器中,网格打印在屏幕上。
网格对应于代表游戏地图的二维数组。
当 select 在网格中创建一个正方形时,它会根据在菜单中 select 编辑的项目更改边框的颜色。
例如,如果我选择了菜单顶部左侧的第二个项目,它会将 selected 正方形的边框着色为绿色。
我的问题是,当我向右滚动并select一个正方形时,我很难正确检测到我点击的位置。
在此处查看问题示例:
https://imgur.com/a/x07tDo3
// 向右滚动后,我很难找到正确的位置
有什么想法吗?
这是我的代码,使用滚动偏移量,背景本身是每单位 64 像素。
我曾尝试使用 monogame.extended 的相机来解决问题,但找不到解决问题的方法。
非常感谢!
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);
}
如果名为 ms 的变量是您的鼠标位置,那么您需要将其转换为您的相机偏移量。
var xIndex = (ms.X - offset.X) / 64;
var yIndex = (ms.Y - offset.Y) / 64;
如果您不需要带有旋转和缩放功能的完整相机 class 的功能,这应该可行,但我建议您更改绘制函数中的一些线条。你仍然可以在你的 spritebatch 中使用矩阵,这应该有助于保持一切正常工作,并允许你在添加将随相机移动的东西时编写更少的代码。
Matrix transformMatrix = Matrix.CreateTranslation(new Vector3(offset.X, offset.Y, 0.0f));
spritebatch.Begin(sortMode, blendState, samplerState, depthStencilState,
rasterizerState, effect, transformMatrix);
我还没有对此进行测试,但这应该可以工作,并且允许您删除绘制调用中的“+ offset.X”。我很确定翻译是正确的,但我会在回家后仔细检查,如果不正确,我会更新。
我正在使用 Monogame 为我的游戏创建关卡编辑器。 在关卡编辑器中,网格打印在屏幕上。 网格对应于代表游戏地图的二维数组。 当 select 在网格中创建一个正方形时,它会根据在菜单中 select 编辑的项目更改边框的颜色。
例如,如果我选择了菜单顶部左侧的第二个项目,它会将 selected 正方形的边框着色为绿色。
我的问题是,当我向右滚动并select一个正方形时,我很难正确检测到我点击的位置。
在此处查看问题示例: https://imgur.com/a/x07tDo3 // 向右滚动后,我很难找到正确的位置
有什么想法吗?
这是我的代码,使用滚动偏移量,背景本身是每单位 64 像素。 我曾尝试使用 monogame.extended 的相机来解决问题,但找不到解决问题的方法。 非常感谢!
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);
}
如果名为 ms 的变量是您的鼠标位置,那么您需要将其转换为您的相机偏移量。
var xIndex = (ms.X - offset.X) / 64;
var yIndex = (ms.Y - offset.Y) / 64;
如果您不需要带有旋转和缩放功能的完整相机 class 的功能,这应该可行,但我建议您更改绘制函数中的一些线条。你仍然可以在你的 spritebatch 中使用矩阵,这应该有助于保持一切正常工作,并允许你在添加将随相机移动的东西时编写更少的代码。
Matrix transformMatrix = Matrix.CreateTranslation(new Vector3(offset.X, offset.Y, 0.0f));
spritebatch.Begin(sortMode, blendState, samplerState, depthStencilState,
rasterizerState, effect, transformMatrix);
我还没有对此进行测试,但这应该可以工作,并且允许您删除绘制调用中的“+ offset.X”。我很确定翻译是正确的,但我会在回家后仔细检查,如果不正确,我会更新。