Si estas desarrollando un vídeojuego (en Godot Engine) y quieres añadir mejoras u otros elementos, es probable que termines preparando muchas escenas para los items, monedas y otros objetos particulares, que después tendrás que posicionar dentro de un nivel. Instanciar y posicionar una escena dentro de otra puede resultar engorroso, sobretodo si después cambias de opinión y quieres eliminar o cambiar la posición de un item… en este artículo aprenderán a usar el nodo TileMap con un script muy sencillo, que les facilitará la tarea de colocar items en sus niveles.
Preparar el TileMap

Después de añadir un nodo TileMap con el nombre del item o cosa que represente, añádanle un recurso tileset con la imagen del objeto. Para crear ese recurso sólo tienen que hacer clic derecho en algún lugar del Sistema de Archivos y después presionar sobre «Crear Recurso > TileSet».


Supongo que ya saben trabajar con ese tipo de recursos. Después de añadir una imagen, presionan el botón amarillo con la opción de «Tile único» y ajustan el tamaño con el rectángulo amarillo. Después de colocar el recurso Tileset dentro del nodo TileMap, hagan que las celdas tengan el tamaño de la imagen de su item. En mi caso el item tiene las dimensiones de 16×16 pixeles.


Script del TileMap
Ya con eso podemos dibujar en cualquier lugar del mapa una imagen estática de nuestro objeto, faltaría que esas imágenes se convirtieran en una nueva instancia de la escena correspondiente. Añadan un script normal al nodo TileMap y copien lo siguiente:
extends TileMap
var cherry = load("res://Items/Cherry/Cherry.tscn")
func _ready():
for c in get_used_cells_by_id(0):
var new_cherry = cherry.instance()
add_child(new_cherry)
new_cherry.global_position = map_to_world(c) + Vector2(0, 8)
set_cellv(c, -1)

- La variable cherry lleva el nombre de su item y guarda con load la dirección de la escena que tiene ese item en la carpeta de proyecto. Pueden obtener esa dirección si desde el Sistema de Archivos hacen clic derecho sobre una escena y buscan la opción «Copiar Dirección».
- La variable c del bucle for tomará la posición de todas las celdas ocupadas en el TileMap. La función get_used_cells_by_id(0) devolverá una lista (array) y el bucle se ejecutará según el tamaño de esa lista. Con cada valor de la variable c, una nueva instancia se guardará como hija del nodo TileMap.
- Cuando decimos map_to_world(c) estamos indicando que la nueva posición global de cada item pase de la posición local del mapa (que en ese momento se guarda en «c») a la posición global de nuestro juego. Fíjense en que durante todas las vueltas del bucle, la variable «c» siempre tendrá el valor de Vector2() con la ubicación de cada celda. Para que los items se alineen con el suelo, pueden sumar un Vector2(0, y aquí poner el resultado del tamaño vertical de su item dividido entre dos) por ejemplo: como mi item mide 16px de alto, sume un Vector2(0, 16/2) para que quede alineado. Ustedes pueden sumar o restar según los valores que necesiten.
- Con la última línea de set_cellv(c, -1) estaremos eliminando la imagen estática que creamos al principio en la posición que tenía la variable c durante esa pasada del bucle.
Todo listo, deberían tener un resultado así:
Si tienen alguna duda, pueden dejarla en los comentarios :).
César,
estoy siguiendo tus videos por Youtube y recién estoy visitando tu sitio, está muy bueno, ordenado y limpio, te felicito.
Como sugerencia, para cuando agregues código en lugar de screenshots, puedes buscar un plugin de code highlight, hay varios y harán que tus códigos en los artículos tengan una mejor apariencia, con código resaltado. Algunos de ellos son configurables completamente (puedes casi hacer un resalto de código para un lenguaje nuevo)… esa sería mi sugerencia/crítica constructiva del día.
Por lo demás, me encanta lo que estás haciendo, yo de a poco estoy jugando con Godot después de décadas de tener abandonado el tema de los juegos, otro día te cuento la historia.
Epale, muchas gracias por la sugerencia :). Voy a buscar un plugin para eso.
César, soy muy novato, pero tengo una duda, en este caso la animación de las cerezas en vez de hacerse con un sprite tradicional se hace con el bucle for en cada instancia creada? Si es así, podría ser ineficiente en mapas más grandes?
Gracias y tú canal es excelente.
Hola! No amigo, la cereza que estoy instanciando tiene su propia animación y no necesita un bucle for. El bucle de este tutorial sólo lo estoy usando para detectar todas las cerezas en las celdas usadas por el TileMap, para instanciar una nueva escena de cereza en esas posiciones. La escena de la cereza es la que contiene las animaciones y todo.