Lyise
Lyise

Reputation: 1110

Translating screen location to isometric tile location with scaling

I'm attempting to translate the mouse's location on the screen to a specific tile on the map. Using the function below, I believe I'm along the right lines however I can't get it to scale correctly when I zoom. Any ideas why?

Here's the function that I'm using:

    Vector2 TranslationVectorFromScreen(Vector2 toTranslate)
    {
        Vector2 output = new Vector2();

        toTranslate -= offset; // Offset is the map's offset if the view has been changed

        toTranslate.X /= tileBy2; // tileBy2 is half of the each tile's (sprite) size
        toTranslate.Y /= tileBy4; // tileBy2 is a quarter of the each tile's (sprite) size

        output.X = (toTranslate.X + toTranslate.Y) / 2;
        output.Y = (toTranslate.X - toTranslate.Y) / 2;

        return output;
    }

According to my debug information, the X and Y are incrementing when I move the mouse along the tile lines, however their values are all wrong because the scale is not being factored in. I've tried including the scale in the function above, but wherever I add it, it just seems to make matters worse. For reference, the scale is stored as a float where 1.0f means there is no scaling (just in case this is relevant).

Here's a screenshot in case that helps shed any light:

enter image description here

Edit:

By changing the function to the below, the number still seem to increment at the same points (i.e. go up by 1 or down by 1 along the relevant axis per tile), however the results still seem to scale too much. For example, if the results are 100, 100, when I zoom in, these might change to 50, 50 even if the mouse is over the same tile.

New function:

    Vector2 TranslationVectorFromScreen(Vector2 toTranslate)
    {
        Vector2 output = new Vector2();

        toTranslate -= offset;

        toTranslate.X /= (tileBy2 * scale); // here are the changes
        toTranslate.Y /= (tileBy4 * scale); // 

        output.X = (toTranslate.X + toTranslate.Y) / 2;
        output.Y = (toTranslate.X - toTranslate.Y) / 2;

        return output;
    }

Upvotes: 0

Views: 215

Answers (1)

Lyise
Lyise

Reputation: 1110

After a bit of messing around with the code, I appear to have found a solution. I'll leave it here in case it's of use for anyone else:

    Vector2 TranslationVectorFromScreen(Vector2 toTranslate)
    {
        Vector2 output = new Vector2();
        Vector2 tempOffset = offset; // copy of the main screen offset as we are going to modify this

        toTranslate.X -= GraphicsDevice.Viewport.Width / 2;
        toTranslate.Y -= GraphicsDevice.Viewport.Height / 2;
        tempOffset.X /= tileBy2;
        tempOffset.Y /= tileBy4;

        toTranslate.X /= tileBy2 * scale;
        toTranslate.Y /= tileBy4 * scale;

        toTranslate -= tempOffset;

        output.X = (toTranslate.X + toTranslate.Y) / 2;
        output.Y = (toTranslate.X - toTranslate.Y) / 2;

        output += new Vector2(-1.5f, 1.5f); // Normaliser - not too sure why this is needed

        output.X = (int)output.X; // rip out the data that we might not need
        output.Y = (int)output.Y; // 

        return output;
    }

I'm not entirely sure why the normaliser needs to be there, but I've played around with the scales and the size of the map in total and this doesn't appear to affect what this value needs to be.

Finally, here's a screenshot to illustrate it working in the top left:

enter image description here

Upvotes: 1

Related Questions