Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate SCREEN to WORLD position in 2D game

Tags:

c#

2d

xna

I have this class, I use it for drawing sprites in my 2D game:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;

namespace Namespace
{

/// <summary>
/// Found this brilliant code at.
/// http://adambruenderman.wordpress.com/2011/04/05/create-a-2d-camera-in-xna-gs-4-0/
/// </summary>
public class CCamera2d
{

    private const float zoomUpperLimit = 1.3f;
    private const float zoomLowerLimit = .85f;
    private float _zoom;
    private Matrix _transform;
    private Vector2 _pos;
    private float _rotation;
    private int _viewportWidth;
    private int _viewportHeight;
    private int _worldWidth;
    private int _worldHeight;

    public CCamera2d(Viewport viewport, int worldWidth, int worldHeight, float initialZoom = zoomLowerLimit)
    {
        _zoom = initialZoom;
        _rotation = 0.0f;
        _pos = Vector2.Zero;
        _viewportWidth = viewport.Width;
        _viewportHeight = viewport.Height;
        _worldWidth = worldWidth;
        _worldHeight = worldHeight;
    }

    #region Properties

    public float Zoom
    {
        get { return _zoom; }

        set
        {
            _zoom = value;
            if (_zoom < zoomLowerLimit)
                _zoom = zoomLowerLimit;
            if (_zoom > zoomUpperLimit)
                _zoom = zoomUpperLimit;
        }
    }

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

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

    public Vector2 Pos
    {
        get { return _pos; }

        set
        {
            float leftBarrier = (float)_viewportWidth *
                   .5f / _zoom;
            float rightBarrier = _worldWidth -
                   (float)_viewportWidth * .5f / _zoom;
            float topBarrier = _worldHeight -
                   (float)_viewportHeight * .5f / _zoom;
            float bottomBarrier = (float)_viewportHeight *
                   .5f / _zoom;
            _pos = value;
            if (_pos.X < leftBarrier)
                _pos.X = leftBarrier;
            if (_pos.X > rightBarrier)
                _pos.X = rightBarrier;
            if (_pos.Y > topBarrier)
                _pos.Y = topBarrier;
            if (_pos.Y < bottomBarrier)
                _pos.Y = bottomBarrier;
        }
    }

    #endregion

    public Matrix GetTransformation()
    {
        _transform =
           Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) *
           Matrix.CreateRotationZ(Rotation) *
           Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) *
           Matrix.CreateTranslation(new Vector3(_viewportWidth * 0.5f,
               _viewportHeight * 0.5f, 0));
        return _transform;
    }
}
}

Now, I can't understand how to unproject a screen (mouse) position to world position. It would be great to have a function like this:

Vector2 ScreenToWorld(Vector2 onScreen, Matrix CameraTransformation)

For WorldToScreen I use (works fine) function:

public Vector2 WorldToScreen(Vector2 inWorld)
{
    return Vector2.Transform(inWorld, Camera.CurrentTransformation);
}
like image 271
Loryan55 Avatar asked Nov 13 '22 03:11

Loryan55


1 Answers

Inverted matrix:

    public Vector2 ScreenToWorld(Vector2 onScreen)
    {
        var matrix = Matrix.Invert(World.Camera.CurrentTransformation);
        return Vector2.Transform(onScreen, matrix);
    }
like image 192
Loryan55 Avatar answered Nov 14 '22 22:11

Loryan55