Get tile at exact world coordinate? (SOLVED)

I’m working on turn-based RPG without physics and faced the problem of collision check with walls.
How can I get the tile at exact position?
I mean not the tile coordinate in tilemap, but it’s real world coordinates.

In documentation mentioned only one example, where we can use real coordinates - changing specific tile with message:

local tile_num = 1 -- some tile
local pos = go.get_position()
msg.post("/level#tilemap", "set_tile", { layer_id = hash("floor"), position = vmath.vector3(pos.x, pos.y, 0), tile = tile_num})

What would be a right solution:

  • manually transform world coordinates to tile coordinates and use tilemap.get_tile()
  • or create and check for collision? (but I’m not using physics :confused:)
    ?

tilemap.set_tile() doesn’t use world space coordinates, but rather the horizontal and vertical index of the tile to set. Where did you see this example that you’re mentioning?

As for your specific question about collision check with walls:

Why aren’t you using physics? Why do you wish to resolve collisions with walls manually?

If you really want to manually transform world coordinates to tile map coordinates and check what’s in a tile, then all you need to do is divide the world space coordinate x,y component with the tile width and then use tilemap.get_tile() to check what’s in that tile. If you have a camera you also need to adjust for the camera offset when you use tilemap.get_tile().

Here:
Changing tiles from script
It was a big surprize for me that it’s the only place where real coords are using.

I would really like to use anything that will be more correct and “native”.
But how I can use physics? I’m not using “speed” or something like this, I’m just moving object to specified position:

It’s kind of weird that the “set_tile” message is not in the tilemap API doc, it only shows up in that part of the 2D graphics manual, but that’s another issue . . .

I think in your case it would be better to keep track of the player’s tilemap position so you can just use tilemap.get_tile(). Or, you can convert a world pos to tilemap pos with something like this:

function world_to_tile(x, y)
     return math.ceil(x / tilesize), math.ceil(y / tilesize)
end

(assuming your tilemap is at (0, 0), otherwise you’ll need to get its position and figure in the offset)

4 Likes

I don’t think that’s a world space coordinate in that example. It’s not at all unlikely that a tilemap is a couple of hundred tiles wide.

The set_tile message still exists but it’s deprecated and the expected function to use is tilemap.set_tile()

Ok, you should be able to do something like this:

local TILE_SIZE = 16
local player_pos = go.get_position()
local tile = tilemap.get_tile("level#tilemap",  hash("blockers"), math.ceil(player_pos.x / TILE_SIZE), math.ceil(player_pos.y / TILE_SIZE))
1 Like

The message “set_tile” does take a world space coordinate, the method “tilemap.set_tile()” takes tile map coordinates.

1 Like

Well, I’ll be damned. You’re right. I need to look into why this isn’t documented, and more importantly why we have both a tilemap.set_tile and a set_tile message that doesn’t work the same way…

1 Like

Initially the API:s were all message but it was decided to wrap those into function calls, or replace them with functions for convenience. The original messages still exist not to break backwards compatibility. In this particular case is the message api conceptually “backwards” with all tile lookup happening from screen space.

Oh, that’s not good. I’ll make sure to remove that reference! Thanks for spotting!

1 Like