4

我已经尝试了我在网上找到的所有方法来获取鼠标相对于相机的位置,但没有任何效果。选择图块总是远离鼠标。另外,我将如何只更改我单击的图块而不是每个具有相同纹理的图块

相机类

public class Camera : Game1
{
    protected float _zoom;
    public Matrix _transform;
    public Vector2 _pos;
    protected float _rotation;

    public Camera()
    {
        _zoom = 1.0f;
        _rotation = 0.0f;
        _pos = Vector2.Zero;
    }

    public float Zoom
    {
        get { return _zoom; }
        set { _zoom = value; if (_zoom < 0.1f) _zoom = 0.1f; } // Negative zoom will flip image
    }

    public float Rotation
    {
        get { return _rotation; }
        set { _rotation = value; }
    }


    public void Move(Vector2 amount)
    {
        _pos += amount;
    }

    public Vector2 Pos
    {
        get { return _pos; }
        set { _pos = value; }
    }

    public Matrix get_transformation()
    {
        _transform = 
                     Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) *
                     Matrix.CreateRotationZ(Rotation) *
                     Matrix.CreateScale(_zoom) *
                     Matrix.CreateTranslation(new Vector3(1024 * 0.5f, 768 * 0.5f, 0));
        return _transform;
    }

    public void Update()
    {
        Input();
    }

    protected virtual void Input()
    {
        KeyboardState _keyState;
        _keyState = Keyboard.GetState();

        if (_keyState.IsKeyDown(Keys.A))
        {
            _pos.X -= 5f;
        }
        if (_keyState.IsKeyDown(Keys.D))
        {
            _pos.X += 5f;
        }
        if (_keyState.IsKeyDown(Keys.W))
        {
            _pos.Y -= 5f;
        }
        if (_keyState.IsKeyDown(Keys.S))
        {
            _pos.Y += 5f;
        }
    }
}

瓷砖类

class TileGeneration
{
    public Block[] tiles = new Block[3];
    public int width, height;
    public int[,] index;
    public Texture2D grass, dirt, selection;
    bool selected;
    MouseState MS;
    Vector2 mousePos;

    Camera camera;

    public TileGeneration()
    {

    }

    public void Load(ContentManager content, GraphicsDevice g)
    {
        grass = content.Load<Texture2D>(@"Tiles/grass");
        dirt = content.Load<Texture2D>(@"Tiles/dirt");
        selection = content.Load<Texture2D>(@"Tiles/selection");

        tiles[0] = new Block { Type = BlockType.Grass, Position = Vector2.Zero, texture = grass};
        tiles[1] = new Block { Type = BlockType.Dirt, Position = Vector2.Zero, texture = dirt};

        width = 50;
        height = 50;

        index = new int[width, height];

        camera = new Camera();

        Random rand = new Random();
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                index[x,y] = rand.Next(0,2);
            }
        }
    }

    public void Update()
    {
        MS = Mouse.GetState();
        Matrix inverseViewMatrix = Matrix.Invert(camera.get_transformation());
        Vector2 mousePosition = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
        Vector2 worldMousePosition = Vector2.Transform(mousePosition, inverseViewMatrix);
        mousePos = worldMousePosition;
        Console.WriteLine(mousePos);

        if (MS.LeftButton == ButtonState.Pressed)
        {
            Console.WriteLine("Selected");
            selected = true;
        }
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
              spriteBatch.Draw(tiles[index[x,y]].texture, new Rectangle(x * 64, y * 64, 64, 64), 
                    Color.White);
              if (selected && IsMouseInsideTile(x, y))
              {
                  if (tiles[index[x,y]].texture == grass)
                      tiles[index[x,y]].texture = dirt;
              }
              if(IsMouseInsideTile(x, y))
                  spriteBatch.Draw(selection, new Rectangle(x * 64, y * 64, 64, 64), Color.White);
            }
        }    
    }

    public bool IsMouseInsideTile(int x, int y)
    {
        return (mousePos.X >= x * 64 && mousePos.X <= (x + 1) * 64 &&
            mousePos.Y >= y * 64 && mousePos.Y <= (y + 1) * 64);
    }

游戏1平局

protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, null, 
            camera.get_transformation());

        tile.Draw(this.spriteBatch);
        player.Draw(this.spriteBatch);
        spriteBatch.End();

        base.Draw(gameTime);
    }

在此处输入图像描述

4

2 回答 2

3

可能有更好的方法,但是:

// absoluteMouseX will be the value from your MouseState, and camera will be an instance of your class
// You may need to convert your rotation to radians.

float relativeMouseX = absoluteMouseX + camera.Pos.X;

float relativeMouseY = absoluteMouseY + camera.Pos.Y;
于 2012-04-03T22:23:50.087 回答
1

我现在没有 XNA 来测试它,但我记得有这个问题。

我拥有的一段代码可能会有所帮助:

        Vector2 mouse = new Vector2(ms.X, ms.Y);
        Matrix transform = Matrix.Invert(camera.ViewMatrix);

        Vector2.Transform(ref mouse, ref transform, out mouse);

        selectedRow = (int)(mouse.Y / Tile.SIZE);
        if (selectedRow < 0) selectedRow = 0;
        else if (selectedRow >= rows) selectedRow = rows - 1;

        selectedCol = (int)(mouse.X / Tile.SIZE);
        if (selectedCol < 0) selectedCol = 0;
        else if (selectedCol >= cols) selectedCol = cols - 1;

两件事:
1. 注意行如何依赖于鼠标的 Y 组件,以及列如何依赖于 X 组件。
2. 请注意,直接获取鼠标放置在哪个图块上比询问每个图块是否“里面”有鼠标要快得多。

于 2012-04-05T18:48:15.303 回答