Godot Version
4.3
Question
I want to add spikes to my platformer game, and wish to use a tilemap node with custom data to check if the player is touching a spike.
Scene tree:
Player data:
Tilemap atlas
4.3
I want to add spikes to my platformer game, and wish to use a tilemap node with custom data to check if the player is touching a spike.
Scene tree:
Player data:
Tilemap atlas
Well all you’re missing is checking.
var has_spike = tilemap.get_cell_tile_data(0, cell_coords).get_custom_data("Spike")
Read more on it in docs, but basically:
tilemap
is your TileMap node, 0
is the layer number,cell_coords
is the Vector2i position you want to check
Yeah I spent about an hour reading the docs and searching online to no avail, how do I get cell coords for where the player is?
You calculate it
Let’s say your tilemap is at global position (100, 100)
and your player’s global position is (200, 150)
and the size of each tile is (16, 16)
Then the cell coords for your player will be something like
var map_pos = Vector2(100, 100) # tilemap.global_position
var player_pos = Vector2(200, 150) # player.global_position
var tile_size: int = 16
var player_relative_to_map = player_pos - map_pos
var cell_coords = Vector2i(player_relative_to_map) / tile_size
Seee the code at this link
Or try to use the tilemap helper methods for this, I think they need the local position (player_relative_to_map
)
Let me rephrase my question.
I’m new to godot, and don’t have a full understanding of the syntax/language. I wish to use a tilemap so that when the player touches the atlas coords 5, 2 they take damage. I would also like to do it using custom data
I’ve been reading the docs and searching around online and haven’t found answers to this question.
In regard to your reply, after doing some testing and tinkering, I receive error after error trying to make things work. But the main cause is that this line
var cell_coords = Vector2i(player_relative_to_map) / tile_size
can return any number because the line directly above doesn’t stop the player from being at x = 1000 and y = 20, which leads to cell_coords defaulting to 6, 17.
Sorry if this seemed a bit aggressive.
My code:
func _process(delta: float) -> void:
var player_pos = Vector2($Player.position.x, $Player.position.y)
var map_pos = Vector2(0,0)
var tile_size = 16
var player_relative_to_map = (player_pos - map_pos)
var cell_coords = Vector2i(player_relative_to_map) / tile_size
var has_spike = $TileMap.get_cell_tile_data(2, cell_coords).get_custom_data("Spike")
if has_spike == true:
print("Has Spike")
else:
print("No Spike ", cell_coords)
Player scene:
It didn’t seem aggressive at all.
TileMap provides the function local_to_map()
to aid you. No need to calculate tilemap dimensions. The key here is to make sure that the player position is in the correct coordinate space with global_position
and to_local()
.
Here’s the idea broken down:
# 1. Get $Player global position.
var global_pos = $Player.global_position
# 2. Convert player global position to be local to $TileMap
var local_pos = $TileMap.to_local(global_pos)
# 3. Convert the local $TileMap position to coordinates
var coords = $TileMap.local_to_map(local_pos)
# 4. Get tile data with coords
var data = $TileMap.get_cell_tile_data(2, coords)
# 5. Check if data is not null
if data:
# 6. Get custom data
var has_spike = data.get_custom_data("Spike")
# 7. Handle spike
if has_spike:
print("Has Spike!")
Hope this helps.
The code looks like it should work, but upon testing, godot returns hundreds of errors which read “E 0:00:01:0744 level.gd:14 @ _process(): Index p_layer = 1 is out of bounds ((int)layers.size() = 1).
<C++ Source> scene/2d/tile_map.cpp:531 @ get_cell_tile_data()
level.gd:14 @ _process()”
Alongside this, because the player can walk around the map, coords can be any value, such as 9, 17, while we only need to check if the player node is touching the tile with the custom data being true.
Great! I’ll leave that as an exercise for you to solve.
Happy programming