CommunityProgramación y desarrollogithub.com

ziva-sh/godot-tilemaplayer

Corrige código de TileMapLayer en Godot 4.3+ - set_cell(coords, source_id, atlas_coords), lectura de celdas y datos personalizados, borrado, conversión de coordenadas, terrenos, colisión de baldosas mediante capas físicas de TileSet, encontrar la baldosa que golpeó un cuerpo y migración desde el nodo TileMap obsoleto y su API por índice de capa. Úsalo al colocar, leer o borrar baldosas desde GDScript, construir un TileSet en código, generar niveles proceduralmente, manejar colisiones de baldosas o portar código de TileMap desde Godot 3 o Godot 4.0.

¿Qué es godot-tilemaplayer?

Este skill proporciona una guía completa y precisa para trabajar con el nodo TileMapLayer en Godot 4.3 y superiores, reemplazando al obsoleto TileMap. Explica la API de celdas, mostrando cómo colocar, leer y borrar baldosas usando set_cell, get_cell_source_id y erase_cell, y cómo convertir coordenadas entre global, local y mapa. También cubre el manejo de datos personalizados por baldosa, el uso de terrenos (autotiling) con set_cells_terrain_connect, y la detección de colisiones de baldosas mediante capas físicas del TileSet, incluyendo cómo encontrar la baldosa que un cuerpo golpeó. Se incluye un ejemplo completo de construcción de un TileSet en código y una tabla de migración desde la API antigua de TileMap. El skill advierte sobre errores comunes, como pasar posiciones de píxeles a set_cell o esperar colisiones sin una capa física configurada. Está diseñado para desarrolladores que trabajan con GDScript en Godot 4.3+ y necesitan un referente claro y actualizado para el manejo de tilemaps.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ziva-sh/godot-skills/tree/HEAD/skills/godot-tilemaplayer

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

TileMapLayer (Godot 4.3+)

Godot 4.3 añadió el nodo TileMapLayer y dejó obsoleto TileMap. Cada TileMapLayer es una capa, por lo que un nivel con suelo, paredes y decoración son tres nodos TileMapLayer hermanos que comparten un TileSet. No escribas código nuevo contra TileMap, y nunca uses la API de Godot 3 (set_cellv, world_to_map, set_cell(x, y, tile_id)).

La API de celdas

Una celda se identifica por coordenadas enteras de mapa (Vector2i). Una baldosa se identifica por tres valores:

  • source_id: el ID de una fuente en el TileSet (una textura de atlas o una colección de escenas). El primer atlas suele ser 0; comprueba en el editor de TileSet o el valor de retorno de TileSet.add_source().
  • atlas_coords: la columna y fila de la baldosa dentro de ese atlas, en baldosas, no en píxeles.
  • alternative_tile: 0 a menos que hayas creado alternativas volteadas o rotadas.
extends TileMapLayer

const SOURCE_ID := 0
const GRASS := Vector2i(0, 0)
const WALL := Vector2i(1, 0)


func _ready() -> void:
	for x in range(10):
		set_cell(Vector2i(x, 5), SOURCE_ID, GRASS)
	set_cell(Vector2i(3, 4), SOURCE_ID, WALL)

	var source_id := get_cell_source_id(Vector2i(3, 4))  # -1 cuando la celda está vacía
	var atlas := get_cell_atlas_coords(Vector2i(3, 4))  # Vector2i(-1, -1) cuando está vacía
	print(source_id, atlas)

	erase_cell(Vector2i(3, 4))
	print(get_used_cells().size(), " celdas, límites ", get_used_rect())


func cell_at_global(global_point: Vector2) -> Vector2i:
	return local_to_map(to_local(global_point))


func center_of_cell(coords: Vector2i) -> Vector2:
	# map_to_local devuelve el centro de la celda en el espacio local de esta capa.
	return to_global(map_to_local(coords))

Hechos importantes:

  • set_cell(coords) con los argumentos por defecto borra la celda (source_id por defecto es -1). Siempre pasa source_id y atlas_coords al colocar una baldosa.
  • Establecer atlas_coords que no existen en el atlas almacena la celda sin error (get_cell_source_id() devuelve la fuente), y get_cell_tile_data() más tarde registra The TileSetAtlasSource atlas has no tile at (x, y). y devuelve null.
  • local_to_map() y map_to_local() trabajan en el espacio local de la capa. Convierte con to_local() / to_global() cuando la capa se mueve o escala.
  • get_used_cells_by_id(source_id, atlas_coords) encuentra todas las celdas que usan una baldosa.
  • Los cambios se agrupan al final del frame. Llama a update_internals() si necesitas que la colisión o las baldosas de escena se actualicen inmediatamente.

Datos personalizados por baldosa

Añade una capa de datos personalizados en el TileSet (Inspector > TileSet > Custom Data Layers, por ejemplo damage de tipo int), pinta valores en el editor de TileSet, luego léelos:

extends TileMapLayer


func damage_at(coords: Vector2i) -> int:
	var data := get_cell_tile_data(coords)
	if data == null:
		return 0
	return data.get_custom_data("damage")

get_cell_tile_data() devuelve null para celdas vacías y para baldosas de colección de escenas, así que comprueba antes de llamar a métodos sobre él.

Terrenos (autotiling)

Las máscaras de bits de autotile de Godot 3 se convirtieron en conjuntos de terrenos. En el TileSet, añade un conjunto de terrenos y un terreno, luego pinta los bits de conexión de cada baldosa en el editor de TileSet. En código, pasa todas las celdas que quieras rellenar:

extends TileMapLayer

const TERRAIN_SET := 0
const DIRT := 0


func paint_room(rect: Rect2i) -> void:
	var cells: Array[Vector2i] = []
	for x in range(rect.position.x, rect.end.x):
		for y in range(rect.position.y, rect.end.y):
			cells.append(Vector2i(x, y))
	set_cells_terrain_connect(cells, TERRAIN_SET, DIRT)

set_cells_terrain_connect() elige baldosas para que los bordes se conecten; set_cells_terrain_path() es para caminos y ríos dibujados como un recorrido. Si el resultado muestra baldosas incorrectas o faltantes, los bits de conexión en el TileSet están incompletos; el código no puede solucionarlo.

Colisión

Las baldosas colisionan solo cuando el TileSet tiene una capa física (Inspector de TileSet > Physics Layers > Add Element) y la baldosa tiene un polígono de colisión en esa capa (editor de TileSet, selecciona la baldosa, Physics > Physics Layer 0; presiona F para un rectángulo de baldosa completa). La propiedad collision_enabled de la capa está activada por defecto. Las capas físicas también llevan collision_layer y collision_mask, establecidos en el TileSet, no en el nodo.

Para encontrar qué baldosa tocó un CharacterBody2D, usa el punto de colisión. get_coords_for_body_rid() devuelve las coordenadas de un cuadrante físico, no de una celda, a menos que physics_quadrant_size sea 1 (Godot 4.5+ fusiona hasta 16x16 celdas en un cuerpo por defecto):

extends CharacterBody2D

@export var level: TileMapLayer


func _physics_process(delta: float) -> void:
	velocity += get_gravity() * delta
	move_and_slide()
	for i in get_slide_collision_count():
		var collision := get_slide_collision(i)
		if collision.get_collider() == level:
			# Avanza ligeramente dentro de la baldosa, porque el punto de contacto está en su borde.
			var inside := collision.get_position() - collision.get_normal()
			var coords := level.local_to_map(level.to_local(inside))
			print("Tocando baldosa ", coords)

Construir un TileSet en código

Útil para niveles procedurales y para pruebas que no pueden usar el editor de TileSet. Los puntos del polígono de colisión son relativos al centro de la baldosa.

extends Node2D


func _ready() -> void:
	var tile_set := TileSet.new()
	tile_set.tile_size = Vector2i(16, 16)
	tile_set.add_physics_layer()

	var source := TileSetAtlasSource.new()
	source.texture = load("res://tiles.png") as Texture2D
	source.texture_region_size = Vector2i(16, 16)
	source.create_tile(Vector2i(0, 0))
	var source_id := tile_set.add_source(source)

	var data := source.get_tile_data(Vector2i(0, 0), 0)
	data.add_collision_polygon(0)
	data.set_collision_polygon_points(0, 0, PackedVector2Array([
		Vector2(-8, -8), Vector2(8, -8), Vector2(8, 8), Vector2(-8, 8),
	]))

	var layer := TileMapLayer.new()
	layer.tile_set = tile_set
	add_child(layer)
	layer.set_cell(Vector2i(0, 0), source_id, Vector2i(0, 0))

Migrar desde TileMap

En el editor: selecciona el TileMap, abre el panel inferior TileMap, haz clic en el icono de la caja de herramientas y elige "Extract TileMap layers as individual TileMapLayer nodes". Luego actualiza los scripts: cada método de TileMap que tomaba un índice de layer ahora es un método en el nodo de esa capa, sin el índice.

Código antiguoTileMapLayer
tile_map.set_cell(0, coords, source_id, atlas_coords)ground.set_cell(coords, source_id, atlas_coords)
tile_map.get_cell_source_id(1, coords)walls.get_cell_source_id(coords)
tile_map.get_used_cells(0)ground.get_used_cells()
tile_map.set_layer_enabled(2, false)decoration.enabled = false
tile_map.set_layer_z_index(1, 5)walls.z_index = 5
Godot 3 set_cellv(pos, id), world_to_map(p), map_to_world(c)set_cell(coords, source_id, atlas_coords), local_to_map(p), map_to_local(c)

Errores comunes

  • Pasar posiciones de píxeles a set_cell(). Convierte primero con local_to_map().
  • Llamar a set_cell(coords, tile_index) con un solo número: el segundo argumento es el source ID, y atlas_coords por defecto es Vector2i(-1, -1), lo que borra la celda.
  • Esperar colisiones de un TileSet que no tiene capa física, o de baldosas sin polígono pintado.
  • Usar get_coords_for_body_rid() con el physics_quadrant_size por defecto y obtener una coordenada de cuadrante.
  • Llamar a métodos sobre get_cell_tile_data() sin comprobar si es null.
  • Añadir un nodo TileMap para trabajo nuevo porque tutoriales antiguos lo hacen. Usa un TileMapLayer por capa.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

ziva-sh/godot-4-api-pitfalls

Fixes Godot 3 APIs and GDScript syntax that AI assistants write into Godot 4 projects, such as KinematicBody2D, move_and_slide(velocity), export, onready, setget, yield, string connect(), instance(), rand_range, the Tween node, File, change_scene, Spatial, rect_* properties, Pool*Array, OS time functions and the old TileMap API. Use when writing, reviewing or porting GDScript for Godot 4.x, when a script fails with "not declared", "not found in base", "was removed in Godot 4" or "is not present

ziva-sh/godot-control-layout

Builds Godot 4 Control UIs that resize instead of clipping or overlapping - containers versus anchors, anchor presets from code, size flags, custom_minimum_size, MarginContainer margins, Label wrapping, mouse_filter, CanvasLayer HUDs, Godot 4 theme override names (add_theme_color_override and friends) and the display/window/stretch settings for multiple resolutions. Use when creating or fixing menus, HUDs, dialogs and inventory screens, when UI elements are cut off, zero-sized, overlapping, igno

ziva-sh/godot-scene-organization

Structures Godot 4 projects so scenes stay reusable and references do not break - when to make a scene, a script or a Resource, instancing with @export PackedScene, preload and load, @onready and %UniqueName node access, _ready order, groups, autoloads, class_name, and resource UIDs with the .uid files added in Godot 4.4, including how to move or rename files safely. Use when creating new scenes or scripts, deciding how nodes find each other, adding global state or an event bus, moving or renami

ziva-sh/godot-signals

Godot 4 signal patterns and their failure modes - declaring typed signals, emit(), connect() and disconnect() with Callables, bind() and unbind(), lambdas, CONNECT_ONE_SHOT and CONNECT_DEFERRED, await on signals and timers, editor-made connections stored in .tscn files, and the call down, signal up rule. Use when wiring UI buttons, timers, Area2D or body events and custom game events, when replacing Godot 3 connect("signal", self, "method") or yield code, or when debugging "already connected", "

Skills relacionados