Isometric games have a unique problem that “lower” tiles (with higher Y values) can overlap those that are higher up. Likewise, a tile texture will most likely not be fully contained within the cell that it belongs to. Because of this, when we want to select an item in a cell, we can’t rely on the local_to_map
function that would typically be used for non-isometric 2D tiles.
Take the following. The object we want to click on is the green cube. If we were to simply use local_to_map
we might get one of the tiles that sits behind it, depending on where the object was clicked.
To solve this, we can setup collision shapes in the TileSet properties, perform a 2d point ray query at the cursor position, detect the area2ds that we “collided” with and return the coordinates at the highest Y position. This is actually quite simple to implement.
Add Tile Collision
Add a Collision Layer to the TileSet. The layer properties aren’t particularly important so the defaults are fine.
Query Collisions
In the _unhandled_input
(or whichever method you’re using to detect), use intersect_point
to detect the areas in the TileMap. The position of the point is the mouse position.
We’re interested in the rid
that’s returned in the collision data. In this case, it corresponds to the collision body. We can retrieve the cell coordinates using the get_coords_for_body_rid
method on the TileMap. With that information, the data from the cell can also be retrieved if required.
If multiple hits are detected, we want to filter them by the highest Y value, this will return the tile coord “closest” to the camera.
The code for this is below, this is in a class extending TileMap.
|
|