2012-04-03 4 views
4

Я пробовал все, что я нашел в Интернете, чтобы получить положение мыши относительно камеры, но ничего не получится. Плитка выбора всегда отходит далеко от мыши. Кроме того, как бы я только изменить плитки я щелкая на и не каждую плитку с той же текстуройXNA Поиск положения мыши с 2D-камерой

Класс камеры

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); 
    } 

Game1 Draw

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); 
    } 

enter image description here

+0

Код выглядит правильно, поэтому я не знаю, смогу ли я помочь. Но я скажу, что вы должны использовать MouseState MS вместо запроса состояния снова в методе Update. –

+0

Спасибо, это была ошибка, которую я не заметил – Corey

+0

Не совсем родственный, но ваш код был бы более логичным и исправляемым, если бы ваша камера не была реализацией игры. Скорее ваша камера должна быть «GameComponent», которую вы активируете в Game1 (добавьте в список компонентов), а затем используйте статически. То же самое для всех менеджеров. Фактически, в большинстве моих проектов Game1 является ПУСТОЙ, все делается во внешних (часто одноэлементных) менеджерах. –

ответ

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; 
+0

Да, второй метод - это то, что у меня есть сейчас, и оно не работает. Я пробовал первый способ, и он все еще не работает – Corey

+0

@Corey Можете ли вы точно описать, что происходит? Выбор находится далеко от курсора, но что с ним не так? Это вращение неправильным образом или не соответствует шкале? Трудно диагностировать вашу проблему, не видя ее в действии. – annonymously

+0

Хорошо. Я отредактировал фотографию в нижней части моего вопроса, чтобы объяснить ее лучше. Надеюсь, это полезно, если не сообщите мне, что я могу сделать, чтобы лучше объяснить. – Corey

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. Обратите внимание, что значительно быстрее получить, какую плиту мышь лежит, а не спрашивать каждую отдельную плитку, если она имеет «внутреннюю» мышь.

+0

++ Инвертирование преобразования, которое вы использовали для вашей камеры, является ключом к этому. Вы снова используете одно и то же преобразование в обратном направлении, поэтому его сложно испортить. –