Picking Cells On an Isometric Grid
Hi guys,
I'm currently making a game in flex and actionscript with a isometric view. The game is tile based and at certain points I need to know where the user has clicked on the grid, for pathfinding and the like.
I'm having some trouble getting the correct cell based on mouse position and think my logic must be flawed somewhere.
My first approach was to use parametric line intersections to work out where along the X and Y axis the click was. This produced results CLOSE to the answer but alway a few points off.
Then I found this article http://www.gamedev.net/reference/articles/article747.asp
and thought my problem was solved! But alas...no.
I cant figure out how to get the first the cell closest to the mouse position to then use the mask on to figure out the exact cell that was clicked.
Can anyone clarify things for me please?
Check your tiles in the reverse order you render them. Stop when you detect the mouse was over a tile or over the elevation part of a tile(if your world isn't flat). That should give you the correct tile.
If you know the mouse position in the world, you can directly compute the cell by converting a floating point position(x,y) to an integer grid cell coordinate(x,y). This how you do that, assuming:
- the grid is composed of equally sized square cells (cellSize)
- the grid is defined by two floats: Min and Max
- you want to convert the position Pos(x,y) into a grid Cell(x,y)
Cell.x = (Pos.X + Max) * 1.0/cellSize
Cell.y = (Pos.y + Max) * 1.0/cellSize
If you are using the cells to optimize collision, rendering, AI, picking, etc., to speed things up a bit you'll want to save 1.0/cellSize until your grid changes. Also, if all points in the space are greater than (0.0, 0.0) you can omit the "+ Max" from all calculations.
- the grid is composed of equally sized square cells (cellSize)
- the grid is defined by two floats: Min and Max
- you want to convert the position Pos(x,y) into a grid Cell(x,y)
Cell.x = (Pos.X + Max) * 1.0/cellSize
Cell.y = (Pos.y + Max) * 1.0/cellSize
If you are using the cells to optimize collision, rendering, AI, picking, etc., to speed things up a bit you'll want to save 1.0/cellSize until your grid changes. Also, if all points in the space are greater than (0.0, 0.0) you can omit the "+ Max" from all calculations.
Quote:Original post by EJH
You want to convert a floating point position(x,y) to an integer grid cell coordinate(x,y). This how you do that, assuming:
- the grid is composed of equally sized square cells (cellSize)
- the grid is defined by two floats: Min and a Max
- you want to convert the position Pos(x,y) into a grid Cell(x,y)
Cell.x = (Pos.X + Max) * 1.0/cellSize
Cell.y = (Pos.y + Max) * 1.0/cellSize
To speed things up a bit you'll want to save 1.0/cellSize until your grid changes. Also, if all points in the space are greater than (0.0, 0.0) you can omit the "+ Max" from all calculations.
Are min and max the limits of my grid? i.e in a 16x16 grid min would be 0 and Max would be 16?
And would that work on an isometric grid?
Quote:Original post by ScottH87Are min and max the limits of my grid? i.e in a 16x16 grid min would be 0 and Max would be 16?
No, Min and Max would be the corners in floating point coordinates. (should have clarified that). For example, if you had a 10*10 grid of cellSizes 1000.0 between Min(-5000.0, -5000.0) and Max(5000.0, 5000.0).
Here's some code from one of my grid implementations, if this helps at all (C#):
float sectorSize = 50000f;float min = -500000f;float max = 500000f;float conversionFactor = 1f / sectorSize;// convert position to grid cellVector2 position;int cellX = (int)((position.X + max) * conversionFactor);int cellZ = (int)((position.Z + max) * conversionFactor);
Quote:Original post by ScottH87And would that work on an isometric grid?
Yes. As with normal picking, cast a ray through the mouse pointer and intersect with the plane the grid is on. Convert that intersection position to a grid cell as above.
Quote:Original post by EJHQuote:Original post by ScottH87Are min and max the limits of my grid? i.e in a 16x16 grid min would be 0 and Max would be 16?
No, Min and Max would be the corners in floating point coordinates. (should have clarified that). For example, if you had a 10*10 grid of cellSizes 1000.0 between Min(-5000.0, -5000.0) and Max(5000.0, 5000.0).
Here's some code from one of my grid implementations, if this helps at all (C#):
*** Source Snippet Removed ***
I'm still not sure i understand. You say that this will only work for square cells. Do you mean isometrically square (diamond) or an actual square? Because an isometric square wouldnt fit in an actual square.
Quote:Original post by ScottH87I'm still not sure i understand. You say that this will only work for square cells. Do you mean isometrically square (diamond) or an actual square? Because an isometric square wouldnt fit in an actual square.
Yeah this is for a perfectly square grid. If your grid cells aren't square it won't work. =(
What is the final orientation of your entire map? Is it in the shape of a diamond (like Age of Empires), or a square (like Starcraft)? If it's a square I have some code at home that may help (i'm at work now).
Here is a brief overview of what I did (from what I remember, it's been a while since I worked on it).
Below is a set of tiles I pulled off the gamedev article and modified slightly as a reference. You need to think of your 'Mask Tiles' as the pink square grid. I'm also assuming that you are numbering your cells in the same way they are in the gamedev article you linked.
For my example I'll use:
TileWidth = 32;
TileHeight = 16;
MapX = 70;
MapY = 26;
Once you have the map coords, divide these by the width and height of your tiles and cast as integers (to truncate the decimal).
MaskX = MapX / TileWidth; // MaskX = 2
MaskY = MapY / TileHeight; // MaskY = 1
Now you need to get the x and y position that relate to the position inside the mouse map cell. Do this with the Modulo operator.
MouseMapX = MapX % TileWidth; // 6
MouseMapY = MapY % TileHeight; // 10
Now, we know that the map location we clicked on is inside the cell 2,1 (in the pink grid). Now, look at your mouse map at position 6,10. I believe this stays in the current 2,1 cell (doing this all off the top of my head).
Now we have to take the 2,1 cell and figure out which col,row that relates to on your map.
I think I did it as follows:
The columns are the same, so the map column is also 2.
To get rows, multiply the MaskY by 2.
So your final map cell location is 2, 2.
I'm pretty sure that is correct. I'll check it again when I get home. Let me know if it's confusing or if you see any mistakes.
Here is a brief overview of what I did (from what I remember, it's been a while since I worked on it).
Below is a set of tiles I pulled off the gamedev article and modified slightly as a reference. You need to think of your 'Mask Tiles' as the pink square grid. I'm also assuming that you are numbering your cells in the same way they are in the gamedev article you linked.
For my example I'll use:
TileWidth = 32;
TileHeight = 16;
MapX = 70;
MapY = 26;
Once you have the map coords, divide these by the width and height of your tiles and cast as integers (to truncate the decimal).
MaskX = MapX / TileWidth; // MaskX = 2
MaskY = MapY / TileHeight; // MaskY = 1
Now you need to get the x and y position that relate to the position inside the mouse map cell. Do this with the Modulo operator.
MouseMapX = MapX % TileWidth; // 6
MouseMapY = MapY % TileHeight; // 10
Now, we know that the map location we clicked on is inside the cell 2,1 (in the pink grid). Now, look at your mouse map at position 6,10. I believe this stays in the current 2,1 cell (doing this all off the top of my head).
Now we have to take the 2,1 cell and figure out which col,row that relates to on your map.
I think I did it as follows:
The columns are the same, so the map column is also 2.
To get rows, multiply the MaskY by 2.
So your final map cell location is 2, 2.
I'm pretty sure that is correct. I'll check it again when I get home. Let me know if it's confusing or if you see any mistakes.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement