I can't figure out the math. I have a staggered 2d isometric grid, got no problem into converting the grid cells into world coordinates, but now I can't figure out how to reverse the process.
Here is the CellToCoord method:
public static Vector2 CellToCoord(int x, int y) {
return new Vector2() {
x = x + ((y % 2) * 0.5f),
y = y * -0.25f
};
}
Pretty simple and display the grid exactly like i wanted it to be, I would like to get the tile from world coordinates now.
Edit:
Image, the world coordinates i get from the CellToCoord() method give me a world position which represent the center of the cell.
public static Point CoordToCell(Vector2 coord) {
// Divide the cell coordinate the value again (or multiply by -4)
// Then Math.Round() to eliminate any floating point inaccuracies
var cellY = (int)Math.Round(coord.y / -0.25f);
// Armed with the original Integer Y, we can undo the mutation of X (again, accounting for floating point inaccuracies)
var cellX = (int)Math.Round(coord.x - ((cellY % 2) * 0.5f));
return new Point() {
x = cellX,
y = cellY
};
}
This should reverse the process. I've used Point as a generic container for an integer X and Y coordinate, you can replace this as appropriate.
The biggest issue in my opinion is that the X mutation was originally based on the integer value of Y, from which you then stored a floating point value. I couldn't find a way to reverse this without the Math.Round()s to coerce the floating point results back into integer values reliably.
Update Calculating the cell coordinates containing a given world coordinate:
Looking at how your world coordinates are arranged, we can see that the centres of each cell are on the diagonal lines given by:
where i and j are integers. This diagram shows this for the x - 2y = i diagonals.
Using these, we can take the world coordinates of a given point, work out i and j, then round them to the nearest integer to get the centre of the cell as i and j.
We can then use i and j to work out the x and y of the cell centre, and use the function I posted before to convert these back into cell coordinates.
public static Point CoordToCell(Vector2 coord)
{
// Work out the diagonal i and j coordinates of the point.
// i and j are in a diagonal coordinate system that allows us
// to round them to get the centre of the cell.
var i = Math.Round( coord.x - coord.y * 2 );
var j = Math.Round( coord.x + coord.y * 2 );
// With the i and j coordinates of the centre of the cell,
// convert these back into the world coordinates of the centre
var centreX = ( i + j ) / 2;
var centreY = ( j - i ) / 4;
// Now convert these centre world coordinates back into the
// cell coordinates
int cellY = (int)Math.Round(centreY * -4f);
int cellX = (int)Math.Round(centreX - ((cellY % 2) * 0.5f));
return new Point() {
x = cellX,
y = cellY
};
}
I used the following coordinate points as test cases
{ x = 1.5f, y = -0.25f } => ( 1, 1 ) // Centre of 1, 1
{ x = 1.9f, y = -0.25f } => ( 1, 1 ) // Near the right of 1, 1
{ x = 1.5f, y = -0.374f } => ( 1, 1 ) // Near the bottom of 1, 1
{ x = 1.1f, y = -0.25f } => ( 1, 1 ) // Near the left of 1, 1
{ x = 1.5f, y = -0.126f } => ( 1, 1 ) // Near the top of 1, 1
{ x = 2.5f, y = -0.25f } => ( 2, 1 ) // Centre of 2, 1
{ x = 2f, y = -0.5f } => ( 2, 2 ) // Centre of 2, 2
Hope this helps