Todas las entradas de: César León

Nací en el mes de mayo. En 2014 empecé a estudiar sobre el desarrollo de vídeojuegos, un conflicto de mi vida fue descargar software privado sin pagar licencias. Godot formó un puente entre mi y el Software Libre, probé GNU/Linux y termine aceptando el sentimiento ético de la FSF. Feliz de desarrollar juegos Indie con Software Libre :').

Cómo automatizar la colocación de items en mapas con Godot Engine

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 :).

Juego de Estrategia… y turnos | DevLog 1

Después de una pausa por cuestiones de salud (toda la semana pasada estuve enfermo) vuelvo con el desarrollo de este proyecto (Juego de Estrategia basada en turnos con Godot). Les dejaré una lista con los avances que hasta el momento pude realizar.

  1. Nueva paleta de colores.
  2. Límite al movimiento de las unidades (ya no pasan sobre el agua o la zona montañosa).
  3. Los Scripts del generador de mundos y el controlador de la partida ya se encuentran comentados y estructurados según la guía de estilo para gdscript.
  4. La cámara ahora tiene una base para recibir «animaciones» durante la partida, con un nodo Tween.
  5. Solución a dos problemas relacionados con las unidades: el primero era que podían desaparecer del mapa y el segundo que sus casillas claras no aparecían cuando estaba cerca de un obstáculo.

No fueron muchos cambios importantes, espero que durante esta semana pueda avanzar en la interfaz de usuario. Necesito hacer algo bonito para el menú de selección de edificios, la información de recursos del jugador y otros detalles.

¡Encontré recursos gratuitos para la interfaz de usuario!

Un dato interesante es que los experimentos para medir el rendimiento del proyecto no bajaron de 59fps hasta que llegó el momento de mostrar las casillas viables. Cuando la unidad a la que se hace clic tiene más de 15/20 movimientos disponibles, hay una bajada de veinte o más fps. Generalmente ninguna unidad supera los diez movimientos, ya que se cuentan otras cosas como el coste de movimiento según la casilla, por lo que esta imperfección estará eclipsada.

Entonces cierro por hoy. Sepan que si bien el desarrollo del repositorio apunta a la interfaz de usuario esta semana, también dejaré espacio para abrir una nueva línea independiente sobre la generación de mundos aleatorios (procedural generation) en github. Avisaré cuando llegue el momento, ¡buena suerte compañeros!

¿Nuevo proyecto? Juego de Estrategia por Turnos

¿Cuándo será el día en que pueda publicar un artículo DevLog con relativa constancia?

Muchas semanas han pasado desde que les hablé de mi proyecto de “juego de plataformas”, tanto que ya se encuentra desarrollado y con su curso publicado en YouTube, aunque seguro ya eso lo sabían.

Escribiendo estas lineas me enorgullece anunciarles que he progresado en el desarrollo de un proyecto “BTS” juego de “estrategia basada en turnos”, que reemplazará a mi antiguo «curso» de prácticamente el mismo género, que dejé a medias por falta de dedicación y obsolescencia de los métodos que usé para desarrollarlo.

Sin embargo el proyecto de estrategia pasado, tenía el género “RTS”. Estos días, cuando intenté introducir la nueva versión, me aclararon que hay una diferencia entre “RTS” (Real Time Strategy) y “BTS” (Based turn Strategy), por lo que resolví el detalle y continué con el desarrollo, enfocando ahora todas las características para un juego de turnos.

Estoy emocionado porque después de días enteros estudiando código de referencia y tratando de entender muchas cosas, he podido avanzar un montón y conseguir un resultado estructurado, comentado y limpio, para compartirles.

Pasaré entonces con la lista de novedades, basándome en las “actualizaciones de estado” que compartí en Twitter la semana pasada. Después de eso, hablaré un poco sobre los próximos movimientos respecto al proyecto.

¡Procedural Generation!

¿Sabes qué es? Esta es de las cosas más interesantes que haya podido estudiar para este proyecto. Es algo a lo que seguro le sacaré el jugo después de estudiarlo a profundidad: la generación de mundos aleatorios. Fue lo primero que me propuse aprender a implementar y hasta ahora tiene un buen resultado, aunque puede pulirse.

Recurso AStar

En mi lista de actualizaciones, esto fue lo segundo. Intenté muchas formas de movimiento entre Tiles hexágonales tratando de usar Navigation2D. El mejor resultado fue el recurso AStar: un algoritmo que incluye Godot para formar puntos en diferentes partes y buscar las mejores rutas de uno a otro.

Experimentos con la interfaz de usuario y construcción de «aldeas»

Esto es lo más reciente: hice un nodo modelo para la construcción de edificios y empecé a experimentar con la interfaz de usuario. Además, en ese vídeo verán como sigue el estado del movimiento, ahora con una cantidad limitada. Los mundos se generan de una forma diferente, incluyendo zonas de agua.


Sólo estas tres características van a necesitar de mucho tiempo para explicarse como es debido en una serie de vídeos . No he calculado cuántos vídeos me harían falta para respaldar al recurso AStar o la generación de mundos aleatorios, pero serán varios (aún con vídeos «cortos»). En los próximos días abriré un repositorio de GitHub para los patreons de Indie Libre, así como el anuncio de la nueva campaña para este proyecto.

Creación de Proyecto e información sobre los recursos – Sunny Land con Godot – Cap I

Si estas aquí es porque te decidiste a iniciar un nuevo curso. Espero que aprendas cosas nuevas. Seguro que ya sabes crear proyectos, definir los Nodos y las Escenas en Godot, y muchas cosas más relacionadas con el editor… pasaré entonces a darte más detalles sobre los Recursos que se pueden crear dentro de Godot, pero primero configuraremos nuestro proyecto.

Dirijanse a los “Ajustes de Proyecto”, les enumeraré los cambios que realizaremos:

  1. Windows → El Ancho y Alto del proyecto será de 320 y 240 pixeles respectivamente.
  2. Windows → Bajando en las propiedades de la misma sección, sería bueno cambiar el Mode a 2D y el Aspect en Keep. Así los gráficos se ajustarán a cualquier cambio que se le realice a la pantalla.
  3. Escriban “Snap” en el buscador, y después activen la propiedad “Pixel Snap”. Con eso evitamos que los gráficos no se encuentren perfectamente alineados.

Creando Recursos

Ahora podemos empezar: según la documentación oficial del motor, tenemos que Los recursos son Contenedores de datos. Sirven cuando un Nodo puede disponer de sus datos y darles una función. El recurso que necesitaremos para trabajar con nuestros mapas de tiles, se conoce como TileSet. Para no desviarme del tema, y pasar directamente a construir los gráficos ncesarios, les dejaré con este enlace la documentación de Godot en Español en su tema de los recursos: https://docs.godotengine.org/es/latest/getting_started/step_by_step/resources.html.

Creamos una nueva carpeta desde el sistema de archivos de Godot y dentro de ella, cuando pulsemos el clic derecho, podremos “Crear un Recurso”. Nos mostrará un menú parecido al que sale cuando creamos nodos, simplemente escribimos “TileSet” y ya tendremos lo que necesitamos. Guardamos y abrimos con doble clic.

Se abrirá el editor de Tiles. Lo pueden usar para crear AutoTiles y Tiles separados. Para eso ustedes deben tener preparada una hoja de Sprites con los tiles que van a necesitar, alineados en función de que sea fácil entender cómo es que deben estar colocados cuando Godot les dé posiciones. La hoja que usaré yo, la tienen en la carpeta de Assets que pegamos dentro del proyecto.

La añadimos con el botón de “+” y ahora podremos elegir entre crear un recurso AutoTile (azul) o un Tile único (amarillo). Esa hoja de ahí tiene muchas opciones, pero sólo vamos a poder aplicar tiles automáticos con unas zonas determinadas, como la tierra y la madera. Por lo tanto, primero seleccionaré la opción de AutoTile. Se nos permitirá definir la “región” o la “zona” de nuestra hoja. Para hacer que el selector sea más exacto, presionemos el botón con el imán:

Se percatarán de que los Tiles son más pequeños que los cuadrados de ahí. Para reducir el tamaño, vamos al inspector y cambiamos el «Snap» a valores de 16×16. Cuando la tengamos así, podremos seleccionar exactamente la zona de los tiles.

Los tenemos y ya podemos avanzar a la sección de «Collision», allí podremos hacer que los tiles sean sólidos para nuestro personaje. Nos encontraremos con que los cuadrados siguen siendo más grandes que la imagen, dirijanse nuevamente al inspector y abran la sección «Selected Tile» , busquen la propiedad «Subtile_size» y en los valores de «X» y «Y» ponen 16×16, el tamaño de estos tiles.

Ahora sólo debemos hacer un clic sobre la herramienta de rectángulo (la segunda, de izquierda a derecha), y después en los tiles que queramos como cuerpos sólidos.

Cuando tengamos todas las colisiones que necesitamos, pasaremos a la sección «BitMask», para definir cómo reaccionarán los Tiles mientras se estén creando. Deben hacer clic en todo el espacio que ocupa cada tile, menos en los bordes. Como en esta imagen:

Estos tiles ya deberían funcionar correctamente, sin embargo, nos toca seguir añadiendo otras partes que faltan. Como ya saben formar AutoTiles, explicaré como se hacen imágenes separadas, para saltarme el trabajo de hacerlo con todas.

Muy bien, hacer esto es practicamente el mismo proceso. Van al apartado de “Region” y en lugar de Autotiles seleccionan “Single Tile”. Marcan los tiles que necesitan, le dan una colisión si hace falta, y nos vamos felices.

En el próximo capítulo les explicaré todo lo que necesiten saben sobre el nodo TileMap y diseñaremos un mapa para nuestro nivel principal.

Botones virtuales para juegos en dispositivos móviles – Godot Engine

¡Hola! en este tutorial veremos una pieza fundamental para juegos de teléfonos. Incluir teclas virtuales en Godot es súper sencillo. Este artículo es una adaptación de otro tutorial, así que necesitarán que su personaje ya se pueda mover con un teclado desde la computadora.

Mi código de movimiento, sería algo como esto: (noten que en la dirección de izquierda o derecha, se define con la entrada de la acción «ui_right» y «ui_left»)

Muy bien: entren en la escena principal del juego y dentro de un nodo CanvasLayer, añadan los botones que necesiten para mover a su personaje, con el nodo de tipo TouchScreenButton. Un aproximado, serían tres de esos nodos, uno para la izquierda, otro para la derecha y un último para la flecha de saltar. A cada uno le colocan una imagen correspondiente a su acción: el primero se llama izquierda, tiene la flecha izquierda, el derecho es derecha, tiene su flecha, y el último se llama salto, con la flecha que apunta hacia arriba.

Para decirle a Godot que presionar esos botones desencadena una acción, la clase TouchScreenButton tiene una propiedad llamada «Action» que al ser presionada, producirá una entrada con el nombre que digamos. A cada dirección se le asignará una acción diferente: a izquierda y derecha, ui_left y ui_right respectivamente, ya que son las acciones que buscamos para mover horizontalmente a nuestro jugador. Y al salto, le corresponde ui_up.

Lo último que falta configurar para estos nodos, es que en su propiedad “Visibility Mode” indiquemos “Tuch screen only” para que sólo se muestre cuando el juego se ejecute sobre un entorno donde exista una pantalla táctil. Y si quieren emular un toque de la pantalla con el puntero del mouse, vayan a los Ajustes de Proyecto y, escribiendo «touch» en el buscador, activen la emulación de los toques.

De esta forma terminamos. Ahora, tocar esos botones produce el mismo efecto que presionar el teclado.

Preparando actualizaciones, tutoriales y campaña 📋

Ayer empecé a preparar un apartado para la página con información sobre uno de mis repositorios, el juego de plataformas. Decidí crearla con el objetivo de promocionar una campaña que me permita recaudar los fondos necesarios para cubrir los gastos de producción, tanto para el repositorio como para el contenido donde enseñaré a desarrollar cada parte.

No soy un buen diseñador, pero pronto iré actualizando esta página: https://indielibre.com/platformer-game/ para mejorar su apariencia y anexar los tutoriales y contenidos, que he producido para el proyecto.

Además, para mejorar la página principal de mis repositorios de GitHub he seguido esta guía sobre escribir archivos markdown. La recomiendo: https://programminghistorian.org/es/lecciones/introduccion-a-markdown.

Decidí usar gráficos con licencias libres, ya que se encuentran recursos con mucha calidad en itch.io. Actualizaré el repositorio con estos nuevos Assets para que el aspecto sea mucho mejor. Opino que lo importante en proyectos de código abierto es el código en sí, sin embargo muchas personas pueden alejarse si desde encima notan algo feo.

Por último decir que estoy escribiendo más tutoriales, probablemente siga con el curso básico de Godot. Además de que tengo en la lista muchas cosas interesantes que he aprendido, suerte por allá.

🔨 Creación de recursos TileSet para los mapas 2D en Godot 3.1 🧩

En Godot 3.1 el editor de TileSets mejoró drásticamente, haciendo mucho más fácil la creación de los recursos que usaremos para nuestros mapas de dos dimensiones. Sean AutoTiles o por separado.

Pasaré a explicarles como funciona este, prácticamente, nuevo editor de Godot.

Crear y editar un nuevo recurso

Dirijan la mirada al apartado de “Sistema de Archivos”. Hagan clic derecho sobre el lugar donde quieran crear un nuevo recurso Tileset y presionen clic derecho > Crear Recurso. El navegador de recursos es similar al de Nodos, busquen “TileSet” y listo. Lo guardan donde quieran, y después le dan doble clic sobre el Sistema de Archivos, para que se abra el editor.

Perfecto; ahora podemos crear un AutoTile o varios Tiles separados (Incluso los dos juntos).

Creando AutoTiles

Para esto ustedes deben tener preparada una hoja de Sprites con los tiles que van a necesitar, colocados en función de que sea fácil entender cómo es que deben estar colocados cuando Godot les dé posiciones. Usaré esta hoja:

Presionando el botón de “+” podrán añadir la imagen que quieran, yo seleccioné la hoja de arriba.

Ahora tienen que seleccionar el tipo de recurso que quieren crear. Elegiré primero el AutoTile, y después crearemos “un sólo tile”.

Después de presionar sobre el Autotile, se nos permitirá seleccionar la “región” o la “zona” de nuestra hoja, que tiene los Tiles que necesitamos. Para hacer que el selector sea más exacto, presionemos el botón con el imán:

Sin embargo, los Tiles son más pequeños que los cuadrados de ahí. Para reducir el tamaño, vamos al inspector y cambiamos el «Snap» a valores de 16×16. Cuando la tengamos así, podremos seleccionar exactamente la zona de los tiles (el snap.x es el tamaño horizontal de tus tiles, y el snap.y es el vertical).

Ya tenemos los Tiles que queremos usar, ahora vamos a la sección de «Collision», allí podremos hacer que los tiles sean sólidos para nuestro personaje. Nos encontraremos con que los cuadrados siguen siendo más grandes que la imagen (por lo menos en mi caso). Lo que haré será dirigirme nuevamente al inspector y abrir la sección «Selected Tile» , buscaré la propiedad «Subtile_size» y ajustaré los valores de «X» y «Y» al tamaño de mis tiles.

Ahora sólo debemos hacer un clic sobre la herramienta de rectángulo (la segunda, de izquierda a derecha), y después en los tiles que queramos como cuerpos sólidos.

Cuando tengamos todas las colisiones que necesitamos, pasaremos a la sección «BitMask», para definir cómo reaccionarán los Tiles mientras se estén creando. Deben hacer clic en todo el espacio que ocupa cada tile, menos en los bordes. Como en esta imagen:

Si el cuadrado rojo es muy grande para sus tiles, vayan al inspector y en la sección «Selected Tiles» cambien la propiedad «Autotile Bitmask» de 2X2 a 3X3.

El AutoTile ya debería hacer su trabajo correctamente. Añadan el recurso a algún nodo Tilemap y vean el resultado:

Recuerden que deben cambiar el tamaño de las celdas por el de sus tiles.

Creando tiles únicos

Para esto pueden usar también una hoja de sprites. Yo seguiré con la misma de antes. En lugar de seleccionar «AutoTile», hacen clic en «Single Tile».

Básicamente es lo mismo que usar Autotiles, con la diferencia de que por cada nuevo «Single Tile», debes hacer clic en el botón amarillo para crearlos y seleccionar otra zona de la imagen.


Espero que este tutorial sea suficiente para ustedes. Dentro de poco compartiré un vídeo siguiendo los pasos de este artículo.

Godot Engine: ¿Cómo crear una Máquina de Estados? II

¡Buenas noches! O mañana. Hoy terminaremos de crear nuestra Máquina de Estados.. sí, quizás sea incluso más trabajo que en la primera parte.

Antes de continuar, quiero avisar que ya hay dos repositorios publicados: el primero fue, como dije en mi artículo pasado, la Máquina de Estados. Por último esta el proyecto de plataformas completo. Dejaré los respectivos enlaces:

Oh, casi lo olvido: la primera parte de este tutorial se encuentra aquí.

Scripts importantes, y los estados de la máquina.

Vuelvan sobre su jugador. Es hora de que añadan un nodo llamado “Node”, y lo nombren «StateMachinePlayer» o algo por el estilo. El nodo «Node» es de las mejores opciones, ya que no utiliza otras funciones de nodos que puedan retrasar el rendimiento de nuestra Máquina de Estados.

El nodo principal de la máquina, tendrá como hijos directos otros nodos del mismo tipo, con el nombre de su respectivo estado. Por ejemplo: (Walk, Idle, Jump). Después les colocaremos un Script que se encargue de cada comportamiento, pero eso después.

Ahora que tenemos los nodos, los dejaremos ahí. Es necesario que hagamos un Script que se pueda usar en cualquier otro personaje que posea una Máquina de Estados. Un Script que sea la máquina de estados en sí. Con eso, simplemente tendremos que usar un “controlador” dentro de cada nodo que tenga la máquina de estados. Si no lo hacemos así, tenderemos a escribir más código del necesario, al momento de añadir una Máquina de Estados a cualquier otro personaje del mismo proyecto.

Ese Script lo crearemos de la siguiente forma:

Les mostraré lo que deben colocar dentro, y explicaré cada parte:

El diccionario “states_map” se encarga de guardar la dirección de todos los nodos que sean “estados” de la máquina. Ahora la dejamos vacía, pero en el “controlador” que se encuentra dentro de cada personaje, cuando llegue el momento, le daremos un valor. Por otro lado, “current_state” recibe el estado actual, y la “_active” es para el encendido y apagado de la máquina.

Para las funciones sí enumeraré una lista, vamos por ello:

  1. _ready(): Esta es muy simple. Todos los estados de la máquina van a disponer de una señal llamada “finished”. Es necesario que estén conectados a nuestra función de “change_state”, para que cada vez que termine un estado (“finished”) la máquina reciba la llamada y cambie al nuevo estado. Nota: los “hijos” son los nodos que creamos arriba, pronto les asignaremos un script con la señal “finished”.
  2. _input(event) and _physics_process(delta): Llegando a esta parte se darán cuenta de que usamos “current_state”. Sepan que esa variable guarda un nodo (cuando no es null). Ese nodo es uno de los estados, y todos los estados cuentan con una función llamada “handle_input(event)” y “update(delta)”. Sí… son un reemplazo de la función _input() y _ physics_process. No usamos las funciones “originales” dentro de los estados, porque crearía conflictos al manejar diferentes modos del parámetro “Event” y el tiempo “Delta”. Así como lo tenemos ahora, estamos usando un único valor que sale desde la Máquina de Estados.
  3. change_state(state_name): En esta función cambiamos los estados. Lo primero que se hace es comprobar que la máquina esta activa. Después, el estado actual se actualiza por la búsqueda que se realice en nuestro diccionario de mapas. Por ejemplo, sabiendo como funcionan los diccionarios en GDScript, para buscar el nodo “Idle”, tenemos que colocar la clave con la que guardamos ese estado. Esa clave es el “state_name” y cada vez que se emite la señal “finished”, se pasa un valor con el nombre del nuevo estado de la máquina. Tal que así: “emit_signal(‘finished’,”Idle”)”. Para finalizar, lo último es activar la función “enter” del estado actual. Seguro lo adivinas: “enter” es el reemplazo de los estados para “ready”.
  4. set_active: Otra papaya. Simplemente se encarga de activar o desactivar las funciones cuando llamemos a la función “set_active(true or false)”.

Perfecto, o casi perfecto. Puede que falten cosas por mejorar, pero ahí vamos aprendiendo. Por ahora nuestro código para la Máquina de Estados esta listo. Así como tenemos un script principal para la máquina, necesitamos uno para los estados. Cada estado independiente podrá heredar las funciones principales sin necesidad de repetir código.

Crearemos el script de la misma manera que el primero. Miren ahora, este es el código que tengo yo:

Muy corto. Primero creamos la señal “finished”. Recuerden que la invocamos en todos los estados, dentro del script de la máquina. Cuando usamos unos paréntesis para la señal, estaremos indicando que es necesario mandar un valor, cada vez que emitimos la señal. Nosotros generalmente haremos esto: “emit_signal(“finished”, “State_Idle”)”.

De resto, se darán cuenta que son las funciones que llamamos en el otro script. En el nodo principal no tienen importancia, sólo las colocamos para que estén creadas por defecto cada vez que añadamos un estado en nuestra máquina.

Controlador de la máquina dentro del jugador

Ya estamos terminando con nuestro trabajo. Vamos a crear el script del “controlador” de la máquina, en el nodo “StateMachinePlayer” que creamos al principio de este artículo. Aquí el código:

Fíjense que en donde dice “extends” he borrado la palabra “Node” y lo he reemplazado por la ruta que tiene el script de la Máquina de Estados principal dentro del proyecto. Eso hará que el código del otro script, forme parte del controlador, sin tener que escribirlo.

Ya que tenemos esto, pasemos a la función _ready(). Aprovechando que sólo se ejecuta una vez, pasaremos el nombre de cada estado (la clave), y su respectiva dirección dentro del jugador. Como son hijos del controlador, sólo hay que usar el signo “$” y escribir el nombre del estado, que generalmente es el mismo que la clave. Por último en esa función, usamos la función change_state(“Idle”) para decir que el primer estado en que se encontrará el jugador será el “Idle”.

Repetiremos una vez más la función change_state(state_name), y en su primera línea colocaremos un “.” y repetiremos el nombre. Con el “.” estamos accediendo a la función “change_state” que se encuentra arriba del script del controlador, osea en el script principal de la máquina, que se extiende sobre el controlador… haciendo eso, podremos procesar el estado con el código principal, que escribimos hace un rato. Nota: las últimas dos líneas no tienen importancia, son otra cosa.

Los estados independientes

Para esta parte necesitamos aplicar algo de lógica. Primero: el estado inicial es “Idle”. Por lo tanto, a partir de él deben salir otros estados: como el salto, el movimiento y el ataque. Sólo vamos a poder ejecutar un sólo estado a la vez. Un ejemplo sería que, cuando entremos en el estado del movimiento, sólo podremos salir cuando, dentro de su mismo código, demos instrucciones para que pasemos a otro estado, por ejemplo, el salto.

Empecemos pues, añadiendo el script del estado “Idle”:

¿Recuerdan cuando les dije que añadieran una animación para cada estado? Ya en la función _ready podemos decir (aunque esto es opcional y ustedes pueden hacer lo que quieran) que la animación “Idle” se reproduzca. Cuando usamos la palabra “owner”, estamos accediendo al nodo principal de la escena. En este caso el nodo principal es el KinematicBody2D del jugador, y uno de sus hijos, es el “Anim” que creamos en el artículo pasado.

Dentro de la función handle_input indicaremos que cuando se presione la flecha de arriba, compruebe que el “owner” osea el script del jugador, se encuentre en el piso. Si es así, puedes decir que el “estado a finalizado” y puedes “pasar al salto” (emit_signal(“finished”,”Jump”)). Desde ese momento, ya el script del Idle deja de ejecutarse, porque ahora el nuevo estado que estará ejecutándose será el salto.

Lo mismo pasaría si presionamos “Espace” y realizamos un ataque. Estaríamos cancelando el estado “Idle”, para pasar al “Attack”.

En la función update(delta) que se ejecuta en cada segundo, comprobaremos que la dirección del jugador no ha cambiado. De ser así significaría que queremos movernos, y emitimos la señal que llama al estado de movimiento.

Para los que quieran refrescar la memoria con respecto al código del “owner” o jugador, miren esta imagen del artículo pasado:

Esto, amigos míos, es todo lo que necesitan saber. Sólo falta que añadan el código de los otros estados y aprendan a salir de ellos para volver al “Idle”.

Continuemos, por ejemplo, con el código del “move_state”. Recuerden que casi todos los estados inician igual, y se extienden con la ruta del script de estados principal. Pasemos ahora al código que les quiero mostrar:

Todo igual ¿no?. Cuando el jugador tenga la dirección en 0 es porque ya esta quieto, y puede volver al estado “Idle”. Cuando saltas, cambias, etc. No veo complicaciones mayores. Igual si alguien tiene otra duda que no pueda resolver descargando el repositorio de la Máquina de Estados desde el enlace que dejé al inicio del capítulo, puede escribir un comentario. Con gusto lo ayudaré y actualizaré el artículo si es necesario.

Si te ha gustado el contenido, podrías ayudarme a seguir produciendo con una donación a PayPal o Patreon: https://www.paypal.me/joseleon1971?locale.x=es_XC&fbclid=IwAR2fl6Hg5ImDIBBv34BirPpfa7vL3QzZyEKN6E3LJibPYldSl9HO9yDGU-k

https://www.patreon.com/indielibre

Las donaciones me ayudan a estar conectado en Internet, en mi país es costoso. Cualquier cantidad, es aceptable :’).

Godot Engine: ¿Cómo crear una Máquina de Estados? I

¡Hola compañeros! Hace ya muchas noches de insomnio que empecé con el nuevo proyecto de plataformas. Quiero anunciar que ya se encuentra casi terminado, pero hoy me gustaría mostrarles algo diferente…

He dividido cada funcionalidad del juego en un paquete, como un Asset independiente, para que ustedes puedan tomar la parte que más les interese y puedan adaptarla a sus proyectos con facilidad. El primer Asset de estos que publicaré, será la Máquina de Estados que pueden usar para los personajes jugables, ya que la implementada en los NPC será diferente, incluyendo cosas relacionadas con la IA (Inteligencia Artificial)…

Esta noche les enseñaré a elaborar una máquina de estados en Godot Engine, así estarán preparados para el momento de descargar el Asset o, simplemente, sabrán los pasos para desarrollar su propia máquina. Sin embargo, puede que esto sea algo extenso, dividiré el tutorial en dos partes.

La escena del Jugador y los Nodos necesarios

¿Ya tienen identificado a su jugador? ¿Todas las animaciones de las que dispondrá? De ser así, podemos empezar a añadir los nodos que formarán parte de la Máquina de Estados. Miren este árbol de nodos, es mi jugador:

Ustedes deben decidir que tipo de nodo será la raíz de su jugador, el mio es un KinematicBody2D, por lo tanto también hago uso de un CollisionShape2D. Para controlar las imágenes del personaje uso unas hojas de sprites, divididas de la siguiente forma, que coloco en el nodo Sprite (llamado: Images):

Para animar las hojas de Sprites es necesario que también añadan un nodo AnimationPlayer, como ven en la imagen de arriba. El nodo de “BodyPivot” es un Position2D y después de crearlo, dentro de él añado el Sprite, ya que al momento de elegir la dirección del personaje (izquierda o derecha) parece más ordenado alterar un Position2D que el Sprite (Sin embargo, pueden prescindir del Position2D y usar únicamente el Sprite).

Antes de empezar con la máquina de estados…

Supongamos que todavía no crearemos la máquina de estados. Primero “prepararemos el terreno”: vayan al AnimationPlayer y empiecen a añadir una animación para cada “Estado” de la máquina.

Esta es mi animación de “Idle”. Algo que tienen en común todas las otras animaciones, es que tienen que cambiar la Textura (Asignando la hoja indicada para el estado Idle), los Hframes (El numero de frames horizontales) y la propiedad Frame (Esta cambiara cada microsegundo, y representa la imagen actual). Cuando ya cada Frame de la hoja ocupe un microsegundo, marquen el tiempo final y coloquen que esa será la duración total de la animación. Además activen las flechas que están a la derecha del tiempo total, (como yo, que las tengo en azul) para que la animación se repita. Sólo la tienen que desactivar en animaciones de un disparo, como la de Ataque.

Ahora les dejaré una imagen con todas las animaciones que voy a usar para mi máquina de estados:

Si no sabes usar el AnimationPlayer, puedes ver este tutorial de aquí, donde enseño sobre la animación de personajes usando hojas de sprites (Estoy por actualizar el Tutorial).

Llegamos al último paso antes de crear la máquina de estados. Vamos a añadir un Script para nuestro nodo principal. Aquí el mío:

Como ahora sólo tenemos a un personaje que salta, se mueve y ataca, no necesitamos muchas líneas. Sin embargo explicaré cada sección de mi Script:

  1. Variables: ahí se definen las variables que se encargaran de representar la física y las aceleraciones, tanto para el salto como para el movimiento. Estos últimos se expresan en “float” (números con decimales), o también en números enteros. La velocidad (velocity) es la variable que representa los cálculos del M.R.U (Física: Movimiento Rectilíneo Uniforme), es Vector2 porque necesita un valor para el eje horizontal y otro para el vertical.
  2. _physics_process(delta): como sabrán, esta función se ejecuta en cada frame del juego (hay como 30 frames por segundo). Dentro de ella llamo a una función que he creado para aplicar una gravedad constante todo el tiempo. Es más fácil aplicar desde el jugador la gravedad, que crear la misma función en los estados que necesiten hacer uso de ella.
  3. _input(event): esta función se ejecuta cada vez que el jugador presiona una tecla o, en caso de los teléfonos, toca la pantalla. Recibe un parámetro llamado event, que representa el botón exacto que fue presionado o el gesto que se realizó en la pantalla. Dentro de esta función estoy comprobando que flecha fue presionada, entre la izquierda y la derecha (como esta el código ahora, cuando se presiona la “izquierda” la variable vale -1, y cuando se presiona “derecha” vale 1). Según el resultado, la dirección de la imagen cambiará (Nunca debe valer 0, por eso uso esa condición en el if. De lo contrario, la imagen desaparecería). Nota: cuando cambias por números negativos la escala de un nodo, este se voltea. Osea que en mi código lo que hago es voltear la imagen. Ustedes pueden lograr un resultado similar si usan el método “flip_h = true” de los nodos Sprite2D.
  4. apply_gravity(delta): cada vez que inicia esta función se le suma al valor anterior de la variable que controla la velocidad vertical (velocity.y) el producto de multiplicar la gravedad por el tiempo físico (delta). Esto se sumará hasta que el jugador toque el suelo (if is_on_floor()), donde la velocidad vertical vuelve a ser 0. La función move_and_slide() se usa para mover al jugador según una fórmula física que haga uso de la Velocidad. Pero también hay una alternativa que permite usar unicamente el resultado de la Distancia… Sin embargo esos son otros temas, y creo que ya sabían bien que es el move_and_slide(). Cuando el get_slide_count() no sea 0, significará que el jugador esta colisionando con algo. Entonces comprobaremos que este chocando por debajo del cuerpo para decir que la velocidad vertical vuelva a 0. Si no hacen eso, notaran que cuando chocan debajo de un bloque, el jugador se queda en el aire un tiempo.

Muy bien. Después de esto ya el siguiente paso sería añadir los nodos de la máquina, junto con el código que necesitan para funcionar. Por hoy hemos finalizado la primera etapa. ¿Qué les ha parecido? Me estaban reprochando hacer siempre un enfoque básico, redundando en muchos temas… ahora quiero ver que tal queda este “nivel” de dificultad, donde doy por hecho que ya saben de algunas cosas para seguir el artículo.

Avanzando con el desarrollo de un juego de plataformas

¡Buenas noches compañer@s! Ayer se empezó el desarrollo del nuevo proyecto de plataformas que planeo publicar en Itch.io, GitHub y Godot Assets Library, como Software Libre. El desarrollo del mismo es radicalmente diferente a mi «juego» de plataformas pasado: tratando de suprimir la mayoría de problemas lógicos mientras se trabaja con mejores mecanismos para proyectos generales.

Sin más, dejaré las publicaciones que forman una especie de «camino», durante el desarrollo de los Assets y el proyecto:

¿Por qué hago un artículo para hablar sobre una fase tan temprana?… supongo que en esto se basa el DevLog, y aunque esto sea mi primer paso, la máquina de estados es un tema muy interesante e importante. Además, aprovecho para hablar un poco más sobre esos Assets que puse arriba:

PD: Este artículo se escribió cuatro días atrás, pero perdí la electricidad desde ese momento y vuelvo hoy para publicarlo.

¿Qué es ese paquete de Assets?

Muy bien, desde el principio: seguro algunos ya saben que estoy muy emocionado con practicar Pixel Art y hacer mis propios gráficos. Ese pasatiempo se complementó perfectamente con mi entusiasmo dentro de la programación de juegos, y desde entonces he buscando la forma de dibujar, programar y escribir, para ser feliz y útil dentro de mi trabajo. Ese «pack» es la primera fase del proyecto que he ideado para este mes (y parte del siguiente).

¿Cuáles son esas fases?

La primera fase corresponde al dibujo/Pixel Art: se elaboran todos los recursos importantes que podrán usarse para formar juegos más adelante.

Después, la segunda fase es la programación de una «plantilla» o «demo», que haga uso de los Assets para desarrollar un prototipo jugable que pueda ser difundido por todos como material educativo; permitiendo su lectura, cambio y distribución por parte de cualquier usuario (Software Libre).

Por último, seguro una de las cosas mas interesantes, es tomar ese demo desarrollado y explicar, paso por paso, sobre el desarrollo del mismo… sí, esto toma el nombre de «Curso» y «Tutoriales».

¿Qué generará ingresos?

Estuve dándole vueltas a la publicación de contenido pago, pero no creo que sea necesario. Es probable que pueda alcanzar al público anglosajón y reciba donaciones que me permitan continuar con el desarrollo de nuevos proyectos. Teniendo en cuenta que los Assets y proyectos de código abierto son algo que les beneficia, sin importar que sea hispano.

¿Cuáles son las mecánicas que se introducirán?

Unos días atrás pregunté por algunos temas que puedan resultar de interés para ustedes. Tengo entendido que debería abarcar la inteligencia artificial de enemigos y «jefes», además de introducir mecánicas para el uso de inventario, o recolección de objetos (Para este punto estoy desarrollando un Asset aparte, un inventario que podrán añadir en cualquier proyecto 😉 ). También me hablaron sobre las cuerdas y el balanceo, como de los ataques con espadas o cuerpo a cuerpo… todo eso lo tengo en cuenta. Todo se introducirá poco a poco, y algunas cosas que me parecen importantes, como por ejemplo el inventario, serán desarrolladas con la intención de que, a futuro, puedan ser útiles en cualquier tipo de proyecto, desarrollándolas con un punto de vista general.

SI tienes una idea para introducir, puedes decírmelo en los comentarios. Cuando termine una buena parte y me parezca un buen resultado, abriré el repositorio para que puedan ir descargando el código, sin embargo, las imágenes y el curso pueden salir después… o quizás antes, vamos a ver como me trata el tiempo.