Creando una máquina de Estados Finito en Godot
Published: 2023-11-12 04:16:34

Dentro de las multiples técnicas para desarrollar la lógica de un personaje y la interacción entre las diferentes acciones que realiza en nuestro juego, encontramos un patrón muy interesante y es el de  las maquinas de estado finito. Pero primero definamos que es una maquina de estádo finito.

## Máquinas de estádo Finito
Las máquinas de estádo finito también llamado Automata finito, es una abstracción computacional que describe el comportamiento de un sistema reactivo mediante un número determinado de Estados y un número determinado de Transiciones entre dicho Estados.

Las Transiciones de un estado a otro se generan en respuesta a eventos de entrada externos e internos; a su vez estas transiciones y/o subsecuentes estados pueden generar otros eventos de salida. Esta dependencia de las acciones (respuesta) del sistema a los eventos de entrada hace que las Máquinas de Estádo Finito (MEF) sean una herramienta adecuada para el diseño de Sistemas Reactivos y la Programación Conducida por Eventos (Event Driven Programming), cual es el caso de la mayoría de los sistemas embebidos basados en microcontroladores o microprocesadores.

En nuestro caso especifico, aplicamos este patrón en el desarrollo de videojuegos, para definir las diferentes acciones (y animaciones) de un personaje.

Pero para entender mejor este concepto, definamos un personaje en Godot y definamos también 3 acciones básicas:
- Idle: Es la acción estática de nuestro personaje, va a tener una animación de "respirar".
- Move: Es la acción de mover nuestro personaje, y la animación va a corresponder a una serie de frames que simulan el efecto de correr.
- Jump: Acción de saltar, nuestra animación va a constar de 2 o mas frames que simulan la acción de salto.

## Definiendo el Proyecto
Primero, vamos a descargar una serie de assets gratuitos para poder hacer nuestra práctica, los pueden [encontrar acá](https://pixelfrog-assets.itch.io/pixel-adventure-1).

- Luego vamos a crear un nuevo proyecto, y en la ventana de nodo, vamos a agregar un nodo de tipo character body 2D.

![1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kd9pewpzdnk9u506241l.png)
- Despues adicionamos tres subnodos mas: 
  - Sprite2D, el cual va a contener nuestros sprites.
  - AnimationPlayer: El cual va a contener nuestras animaciones.
  - CollisionShape2D: El que va a definir nuestro marco de colisión.

![2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r5q6hcg2r9rqwuzrvmqs.png)
- Luego creamos una carpeta Assets en la raíz del proyecto y arrastramos todos los archivos que hemos descargado.

![3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8w75aah7qj0yr9hjn8am.png)

- El siguiente paso es renombrar nuestro nodo principal por "Player" y vamos a adicionar un nuevo script. 

![Adicionando Script](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a5n4qzgyy573t0t1mupc.png)

- Ahora, creamos un nuevo nodo (no el 2D, el que viene solito) para definir nuestra máquina de estados y lo renombramos como "state machine"

![maquina de estados](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qe6xbiwm2hhj17l58tv.png)

- Adicionamos los estádos como nodos hijo.

![nodos hijo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8qp842p4qjhk0zgt3xfd.png)

- Procedemos a crear un script genéral, es decir, este script no va a depender de un nodo, lo cual nos va a permitir rehusarlo si así lo requerimos.

![script](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rou7s3jtnfwsyh1i2ygq.png)

![script2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ukyl26uqc8pgo345xlyh.png)

- En este archivo lo que haremos será crear una clase padre de la cual los estados independientes van a heredar su funcionalidad, en las funciones que vamos a definir, vamos a recibir los llamados a las funciones nativas del [ciclo de vida de Godot](https://docs.godotengine.org/en/stable/classes/class_node.html) 

![functions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c13t4v737et65hk4oi33.png)

- Ahora vamos a crear una nueva clase llamada StateMachine, hay que recordar que al usar la definición class_name podremos referenciar nuestras clases desde otras clases.
En esta clase vamos a tener un poco mas de complejidad, lo primero es definir un Signal que se llama changeState, aca puedes ver que es un [Signal en Godot](https://docs.godotengine.org/en/stable/classes/class_signal.html#:~:text=Signal%20is%20a%20built%2Din,without%20directly%20referencing%20one%20another.) Este Signal nos va a permitir escuchar el cambio de estádo.
Luego definimos una variable initialState de tipo NodePath(), esto  lo definimos usando @export lo que en Godot significa que podemos anclar archivos o elementos desde el editor, es lo mismo que hacemos en Unity al exponer una variable en el editor, esta variable va a estar ligada a los estados que ya definimos en nuestros nodos.
Luego, creamos una variable state de tipo State (recuerden la clase que habiamos creado previamente) y va a recibir nuestra variable initialState, la cual contiene el nodo (donde estan definidos los estádos en el editor).

![StateMachine](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n8031dywbzk7rs0zj7yr.png)

Hasta acá vamos con la primera parte del tutorial, se que es un tema un poco denso especialmente si somos novatos, pero es cuestión de analizar y replicar hasta poder interiorizar. 

En el siguiente post vamos a sobreescribir las funciones que necesitamos en el StateMachine, y también, las funciones de cada estádo.