2
\$\begingroup\$

What are the math for tile detection on a 2D isometric layered diamond shaped map ?

Here is an image of a layer (this is an image from an old folder, I didn't write the display yet for my current project, so it's incomplete but you get the idea) :

A layer A layer

I have them staggered on top of each other. Tile detection could works with a loop but it would take too much time. The basic math for floor tiles doesn't work.

A layer is composed of a tiles(array) :

A tile_size * tile_size image representing a 3D square.


A long time ago I asked this question with an account I'v lost unfortunatly and I had one answer :

  • Create an hollow ground

But I never understood what that was and when I type "tile detection hollow ground" on google, I got nothing.

I also found several solution I do not understand the concept :

  • Ray scan on neightbours (I know the theory for ray scanning, but neightbours ??? All of that sounds very difficult for me)

  • using color mask for a pixel perfect detection (no time to implement such a method)

So, was left the math. And here I'm stuck. I'm looking at my formula 'isometric to screen' conversion(for display), hoping a miracle ha ha :

int x = (i - j) * TILE_SIZE_HALF,
    y = (i + j) * TILE_SIZE_QUARTER - (layer_id * TILE_SIZE_HALF);
//This one is totally working

Anyway, is there even a formula able to solve tile detection for such a map ? Am I missing something ?

What I'm looking for :

   //With given x & y (mouse coordinates on screen)

    int i = ?,
        j = ?,
        layerID = current_layer_index,
        //tile's index in tile array(layers are tile arrays) :
        tileIndex = calculated from I & J;
        //Where goes the offsets in these calculations ?

How am I gonna know which layer the tile is from ?

I decided to only edit the selected layer (current_selected_layer variable) and then check if the tile is empty. If yes, I'll select the "same tile" but the layer under the selected one and so on. Now the problem should be less complicated since it's like there is only one layer. What bother me are the map offsets.

EDIT : I didn't tought about the corner... This is not gonna work. If I don't find a solution, I'll maybe switch to classic 2D. Sounds very complicate to code tile selection with isometric map.

There is another problem I have no idea how to handle these :

(this is a layered map, the screen do not represent the final result)

The corners

End note: Pseudo code is welcome. Also, consider you have all informations about the map. Since I use a pseudo MVC code, I have access to all data everywhere (tile size, layers number, etc...). There is no restriction.

\$\endgroup\$
0
\$\begingroup\$

The isometric stuff is just a projection, based on that, you have to unproject your mouse coords.

the following code is in pseudo javascript:

var x = MOUSE_X,
    y = MOUSE_Y,
    retX = 0,
    retY = 0;

    retX = Math.round(x / TILE_WIDTH) * TILE_WIDTH;
    retY = (Math.round(y / (TILE_HEIGHT/2)) - 1) * TILE_HEIGHT/2;

    if ((Math.round(y / (TILE_HEIGHT/2)) - 1) % 2) {
       retX -= (TILE_WIDTH/ 2);
    }

In this case, mouse coords are unprojected from isometric ones, so you can, after this, request your tile by doing:

map[retx + MAP_WIDTH * rety] (1D Array)

map[retx][rety] (2D Array)

\$\endgroup\$
  • \$\begingroup\$ Thanks for your answer. It's a layered map, I don't understand where are the layers in your pseudo-code. The screen you saw, there are several of this on top of each other. \$\endgroup\$ – Sanchez Tanguy May 17 '17 at 14:25
  • \$\begingroup\$ This pseudo-code would work for one layered map with flat tiles (a classic one) but I don't think it's gonna work for mine. \$\endgroup\$ – Sanchez Tanguy May 17 '17 at 14:54
  • \$\begingroup\$ oh, i see, sorry, somehow i thought you wanted to know how to do it in 2D. In your case, the easiest (and most common) approach is intersecting a ray from your camera to the pointer with the terrain cells. Read this stackoverflow.com/questions/2093096/implementing-ray-picking \$\endgroup\$ – PRDeving May 17 '17 at 16:31
  • 1
    \$\begingroup\$ @SanchezTanguy Sure, why not? "Cameras" in games are just a fiction, a useful conceptual tool to encapsulate some algebra related to positioning content on the player's screen. They don't do anything magic that you can't reproduce in your own code. \$\endgroup\$ – DMGregory May 17 '17 at 19:16
  • 1
    \$\begingroup\$ I'm pretty sure the 1d array's lookup algorithm is retx + WIDTH * rety \$\endgroup\$ – Bálint May 17 '17 at 19:29
0
\$\begingroup\$

Not efficient, but accurate on complex structures, is drawing all cubes with a different color and no shade(r) onto a black background into a framebufferobject and later testing which color a given pixel has. You should draw the objects without blending and without texture into the buffer.

Another way is, you ray-trace until you reach a cube or a limit.

\$\endgroup\$
0
\$\begingroup\$

First, I'll deal with the simpler problem with the edge and corner of the map you showed above. For that, you will only be concerned with the top of the tile when a person selects it, so if they click on the outer edge along the side or corner of the tile, than they are out of bounds and clicking off the map. It doesn't matter than they click the side of a tile. I would reject such a click as out of bounds.

As for layer selection, this is something I struggled with as well, and still do a little, but I have come up with several ideas on this. One idea I had was to store the highest layer on your map. Then when you click, you check to see if there is a tile at that location on the highest layer, so basically, take your normal flat selection, and offset it by the height of the layer; so, if your layers are all 16 pixels higher for each layer, than you would do your normal detection, except you would adjust the Y location by -16 * LAYER. You check the highest layer where the mouse clicked, if there is no tile at that height at that location, than check the next layer down until you end up at the ground level.

That was one idea anyhow. The other idea was to use mouse maps to determine if the tile you selected was the right one, of if you're clicking a tile next to it that is at a higher level.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.