Interacting with specific tiles in a from a tileset?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By dejvid_bejlej
:warning: Old Version Published before Godot 3 was released.

I’m working on a player movement in platformer games, I have a Player (kinematic body) that can move to the sides, jump and grab/climb walls when holding a “grab” key.
He’s on a TileMap, right now he can climb on every tile(wall).
I’m trying to make it possible to grab and climb only on speciffic tiles (like ladders), and I’m wondering if it’s possible to “set it up” in a tileset.

To clarify what I’m trying to do:

  • make a TileSet that contains few tiles, one of them is Ladder tile
  • the ladder tile is set up in a way that lets player check if he’s colliding with it (I think Area2D doesn’t work, I thought about using raycast2D)
  • create a TileMap with that TileSet
  • Put that TileMap in a Level scene where player could detect if he’s colliding with Ladder tile, and if he is, he can clib it

I could probably do it by placing Areas2D in a level scene in places where climbing should be possible, but the amount of work (and nodes) necessary to do it would be very inconvenient

I also thought about getting a tile ID when interacting with tilemap but as far as I know, that requires preloading a map, so if I have many of them (maps), that’s kind of inconvenient.

Any ideas?

:bust_in_silhouette: Reply From: eons

You can get the tile id of a tilemap cell in world_to_map position (TlleMap), then do what you want with that information.

That may imply to check all the time or cells and mess things up if you change the tilemap, may be better to read the tilemap on load and add areas where cells using specific tiles are located (can be based on tile metadata instead of id/name too).

Thanks! I figured it out!
Now I have w really weird problem, it’s related so I won’t make a new thread, but please take look at it, it’s really frustrating.

I’m detecting tile ID using raycasts and it works, except for on the left side of the player. From what I found out, collision position is “rounding” to the next (to the right) map tile, which makes me get ID of the tile I’m being “in”, instead of the one on the left (everything works fine for detection on the right and down).

Here’s few screenshots to show the problem:
img1 - character, collision polygon, raycasts
img2 and 3 - detection on the right works fine
img4 - on the left, I detect an empty tile
img5 - detection works for a moment mid-jump (going up)
img6 - I “fixed” the problem by creating two more raycasts more on the left.
I check if the casts close the player colide, then I get_collision_point()) of the ones more on the left. It’s not elegant, but seems to work.
img7 - well, it does work, unless I enter the tile from above
img8 - entering from the side works

In player script:

if c_castL1.is_colliding():
	emit_signal("left_rays", c_castL1.get_collision_point())

if c_castL2.is_colliding():
	emit_signal("left_rays", c_castL2.get_collision_point())

“c_cast_L1” means “climb raycast left” (since I use them to detect ladders that I can climb on)

In main script:

var left_tile

func _ready():
	player.connect("left_rays", self, "_left_rays_collide")

func _left_rays_collide(pos):
	left_tile = (map1.get_cellv(map1.world_to_map(pos)))
	print(left_tile)

Any ideas how to go around that problem? I was thinking, maybe there’s a way to get a tile id minus one tile to the right.

Thanks again for your response!

dejvid_bejlej | 2017-11-11 02:24

Well, turns out it was rather easy to fix haha
My tile size is 30, so I do that:

(map1.get_cellv(map1.world_to_map(pos - Vector2(16,0))

Can’t belive it worked :smiley:

dejvid_bejlej | 2017-11-11 03:02

Yes, you can add half cell size * normalized direction (relative to the object/ray origin) to move the contact point to (near) the center of the cell.

eons | 2017-11-11 18:41