Thursday, March 28, 2019

xna - How to get mouse position relative to the map?


I'm creating a game in XNA similar to Minecraft - Minecraft 2D


It looks like this



game


Here's how it works:




  • All blocks are generated once with fixed x,y coordinates and just re-drawn.


        //generate world
    for (int i = 0; i < 25; i++)
    {
    blocks.Add(new Block("top", i * 32, 32 * 7, Color.White));
    for (int j = 8; j < 20; j++)

    {
    blocks.Add(new Block("dirt", i * 32, 32 * j, Color.White));
    }
    }


  • When user clicks on a block, I just browse through all blocks and check whether block exists.


    if ((mouseCoordinate.X - (mouseCoordinate.X % 32)) == block.x && (mouseCoordinate.Y - (mouseCoordinate.Y % 32)) == block.y) {
    //destroy block
    }



  • Currently, without any camera movements, everything works. When I move my camera just about 32px to the right, for example, it's all broken. I can't do previous step anymore.



  • What I need: I need to get mouse position relative to the map, not to the game window. How can I get mouse position relative to the map? Basically, I want mouse position 0,0 on the point I have circled here


00


How do I calculate it?


EDIT: here's my camera class (yes, Matrix)


using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Reflection;
namespace MojePrvniHra

{
public class Camera2d
{
protected float _zoom; // Camera Zoom
public Matrix _transform; // Matrix Transform
public Vector2 _pos; // Camera Position
protected float _rotation; // Camera Rotation

public Camera2d()
{

_zoom = 1.0f;
_rotation = 0.0f;
_pos = Vector2.Zero;
}// Sets and gets zoom
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; }
}

// Auxiliary function to move the camera
public void Move(Vector2 amount)
{
_pos += amount;

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

public Matrix get_transformation(GraphicsDevice graphicsDevice)
{

_transform =
Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) *
Matrix.CreateRotationZ(_rotation) *
Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) *
Matrix.CreateTranslation(new Vector3(graphicsDevice.Viewport.Width * 0.5f, graphicsDevice.Viewport.Height * 0.5f, 0));
return _transform;
}

}
}


and here's how I start my spriteBatch


       spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend,
null,
null,
null,
null,
cam.get_transformation(graphics.GraphicsDevice));

Answer




Solution


Is your camera simulated using a view matrix? If so, all you need to do is:


Vector2 worldPosition = Vector2.Transform(mousePosition, Matrix.Invert(viewMatrix));

And if you're not using a view matrix... you should :-)


Explanation


The view matrix transforms coordinates from world space into view space. The inverse of this matrix does the opposite - it transforms coordinates from view space back into world space.


Since your mouse coordinates are defined in view space, all you need to do is transform them with the inverse view matrix to convert them into world space.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...