Borhink
Borhink

Reputation: 367

How to revert isometric to orthographic position?

I struggle to get the reverse from my function to get the world position from a grid cell:

public class WorldPosition : IMessageSerializable
{
    private Vector2Int _map;
    private Vector2Int _cell;
    private Vector2Int _world;

    // Getter setter
    // other codes...
    public Vector2Int World { get => _world; set { _world = value; UpdateMapAndCell(); } }
    // other codes...
    public Vector2 ToUnityPosition()
    {
        float unityX = (World.X * 0.5f - World.Y * 0.5f);
        float unityY = 0.25f + (World.X * 0.25f + World.Y * 0.25f);
        return new Vector2(unityX, unityY);
    }
}

For the unityY, the 0.25f at start is the offset to be centered in the cell. I don't know how to create the function public ToWorldPosition(Vector2 unityPosition); I tried for 3 hours straight now and starting to going crazy...

I need this to update the position of my player while he is traveling between two points.

enter image description here

We can see on the picture: blue line is X axis: to move to cell X+1 in my unity space it's +0.5x,+0.25y.
red line is Y axis: to move to cell Y+1 in my unity space it's -0.5x,+0.25y.
So to have our unity position we need to involve both X and Y from the grid (World vector).
For X: we add World.X * 0.5f and we substract World.Y * 0.5f as Y go in reverse direction (It's the basic +x -y of isometric transformation)
For Y : World.X * 0.25f + World.Y * 0.25f because both X and Y go up. The 0.25f at start is for the offset because my player is out of the map when at 0,0.

Upvotes: 1

Views: 103

Answers (2)

Borhink
Borhink

Reputation: 367

After researches, help from derHuge and this link:
https://gamedev.stackexchange.com/questions/30566/how-would-i-translate-screen-coordinates-to-isometric-coordinates
I wrote this code which works :

public class WorldPosition : IMessageSerializable
{
    private Vector2Int _map;
    private Vector2Int _cell;
    private Vector2Int _world;

    // Getter setter
    // other functions...
    public Vector2Int World { get => _world; set { _world = value; UpdateMapAndCell(); } }

    // other functions...
    public Vector2 WorldToUnityPosition(float cellSize = 1f)
    {
        var offset = cellSize;
        var unityX = (_world.X - _world.Y) * cellSize;
        var unityY = (_world.X + _world.Y + offset) * cellSize / 2f;
        return new Vector2(unityX, unityY);
    }
    public static WorldPosition UnityToWorldPosition(Vector2 unity, float cellSize = 1f)
    {
        unity.Y -= cellSize / 2f;
        var isoX = unity.Y / cellSize + unity.X / (2 * cellSize);
        var isoY = unity.Y / cellSize - unity.X / (2 * cellSize);
        return new WorldPosition(new Vector2(isoX, isoY));
    }
}

Upvotes: 0

derHugo
derHugo

Reputation: 90872

As a first step I would generalize your method a bit into

public static class IsometricExtensions
{
    public static Vector2 ToUnityPosition(this Vector2Int iso, float cellSize = 0.5f)
    {
        var unityX = (iso.x - iso.y) * cellSize;
        var unityY = (iso.x + iso.y + 1) * cellSize / 2f;
        return new Vector2(unityX, unityY);
    }
}

Now in order to reverse this you can basically invert the operations one by one

public static Vector2Int ToIsometricPosition(this Vector2 unity, float cellSize = 0.5f)
{
    // inverts the offset
    unity.y -= cellSize / 2f;
    // both directions influence iso X positively
    var isoX = unity.x + unity.y;
    // Y axis influences positive while X-axis negative
    var isoY = unity.y - unity.x;
    // finally a step of 1 in any direction in Unity space 
    // is a step of 2 (= 1 / 0.5) in iso grid space
    return Vector2Int.RoundToInt(new Vector2(isoX, isoY) / cellSize);
}

Upvotes: 0

Related Questions