[SOLVED] How to find tile under cursor in a multilevel 2d isometric terrain?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By akoutsoulelos

Hello everybody,

I’m seeking more of an advise here than a direct help.

I’m trying to create a 2d isometric terrain with multiple levels (faking height), like the one in OpenTTD. To accomplish that, I use multiple Tilemaps (one for each height level, with the appropriate y offset), which gives the desired result.

The main problem I have, is finding the tile under the cursor, which is important for various actions (e.g. terraform, place buildings etc.). The tricky part is that terrain tiles have slopes and they do not fit exactly in the isometric grid, so the classic method the Tilemap provides is not enough and needs adjustments.
So what I have tried so far is:

  • first method, I looped (top to bottom) through the tilemaps, checked if the tile is occupied or not and did some corrections (due to slopes) accordingly - but there was always a gap that was not correctly handled and I was not willing to write a long tree of coord ifs.
  • second method, I checked on which tile the cursor is over on the first level, checked on my heightmap for the corresponding level and tried to deal with the slope, but with the same result; there was always a gap.
  • last method, I’m using Area2D with CollisionPolygon2D; when I place a tile on any Tilemap, I create an Area2D with a CollisionPolygon2D, that has the same shape as the sloped tile and is placed on the right coords to match the global place of the tile.

So, now everything works right, but with the cost of high CPU usage, that of course reflects to the FPS.
I can narrow the collision polygons enabled to the ones that are displayed each time in the viewport, but that is going to work only when zoomed, as when zoomed out the collision pollygons will be a lot. And I have not yet implemented any code to find the corner of each tile (needed for the terrafroming).

So, before continuing with that approach, I would like your advise: is this approach a good solution or is there something else I would try to find the tile (and each nearest corner) under the cursor?

Thanks in advance.

Just a suggestion
Choosing the one closest to the mouse cursor.

ramazan | 2022-02-05 14:28

Well, that’s were you start from; you first have to find the closest tile, but then it gets complicated due to the slopes.

Let me visualize it:
Sloped tile

As you can see the tile is located in B2, but it goes over its grid border. So the case is that visually the cursor hovers B2 sloped tile, but actually the cursor may be located under either B2, B1, A1 or A2 tile.
The thing gets even messier since there are 18 different slope tiles…

So the last solution was to create a CollisionPolygon with the visual shape of the slope tile, so I do not have to deal with Tilemap isometric grid, rather with the actual shape of the tile. But that is creating a hell of polygons and consumes CPU power for constant collision checks, just for tile hunting. The procedure is even further burdened by the fact that at each corner there are four vertices that may have to be checked.

That’s why I’m thinking now to create not CollisionPollygon2D over each tile, but rather vertices at each corner (thus reducing their amount four times) and create a custom routine to find the nearest vertex to the cursor.

akoutsoulelos | 2022-02-05 17:53

:bust_in_silhouette: Reply From: akoutsoulelos

Well, after some digging I found this article, which explains a lot about how to locate a tile in a 2D isometric terrain.

So, I just created mousemaps for my tiles, and after some trials I got exactly what I needed.

I’ve been working on this same problem for the last month or two and ran across the same article. (I’ve coincidentally been attempting the exact same project, only inspired by RCT2 more than Transport Tycoon.) Would you be willing to share some more details/code on how you implemented this in Godot? I’d really appreciate it. The method I set up when I attempted it chugged along at like 12 fps.

metaphysics_studios | 2022-03-03 22:56