|
|
|
 |
Reply From: |
njamster |
As you’ve not been very specific with your question, I’ll assume you already have set up some TileMap and added a CollisionShape2D to at least one tile. Furthermore I’ll assume that your player character is a KinematicBody2D.
Movement using move_and_collide
var tilemap = get_node("<RelativePathToTileMap>")
var collision = move_and_collide(velocity * delta)
if collision:
var cell = tilemap.world_to_map(collision.position - collision.normal)
var tile_id = tilemap.get_cellv(cell)
Movement using move_and_slide
var tilemap = get_node("<RelativePathToTileMap>")
velocity = move_and_slide(velocity, Vector2.UP)
for i in range(get_slide_count()):
var collision = get_slide_collision(i)
var cell = tilemap.world_to_map(collision.position - collision.normal)
var tile_id = tilemap.get_cellv(cell)
I can’t get this approach to always work. Using
var cell = tilemap.world_to_map(collision.position - collision.normal)
var tile_id = tilemap.get_cellv(cell)
I will get tile_id of -1 if the collision happens on the right side of the tile, and the proper tile_id if it happens on the left side.
I created a tiny Godot project that illustrates what I am seeing:
https://github.com/city41/GodotTileMapCollisionTest
If anyone can help me understand what I’m doing wrong, I’d be grateful!
When a collision between a KinematicBody2D and TileMap occur, I want to grab the tile id properly for all collisions.
Matt Greer | 2020-09-12 01:09
Seems like the reported collision.position
is the rightmost point on the tile the KinematicBody2D collided with, in your example: (128, 65)
. However, if you use those coordinates for a cell-lookup with world_to_map
, this will result in cell (2, 1)
not (1, 1)
because cell 0 includes pixels 0 to 63 and cell 1 only includes pixels 64 to 127, so pixel 128 is already considered part of the third cell. Luckily the fix is simple: just subtract one pixel from the collision.position
before the lookup:
var cell = tilemap.world_to_map(collision.position - collision.normal - Vector2(1, 0))
var tile_id = tilemap.get_cellv(cell)
Btw: If you click the three dots in the lower right corner of an answer, you can choose “Ask related question”. This will increase your chances of getting an answer, as it appears as an unanswered, recently asked question on this site whereas asking in a comment will usually get lost when the original author of the answer (in this case: me) isn’t active anymore or chose to be not informed of new comments via e-mail.
njamster | 2020-09-13 21:47
Seems to work as expected but I’m also getting a deallocated value (the second index) when colliding on the left side… If I subtract it by Vector2(1, 0)
nothing changes, if I subtract it by Vector2(0, 1)
it corrects the value on the left collision but breaks the right one. Any idea how I should proceed?
Edit:
So, I’ve been able to make it work by manually checking the values of the coll.normal and subtracting the cell position as needed:
var cell = tilemap.world_to_map(coll.position)
if coll.normal.x == 1: cell -= Vector2(1, 1)
if coll.normal.y == -1: cell -= Vector2(1, 0)
if coll.normal.y == 1: cell -= Vector2(0, 1)
I’m sure there is a one-line version of this, but I have no idea how to do it, anyway, ty!