Keep your place in this quest

Log in or sign up for free to subscribe, follow lesson progress, and access more learning content.

A medida que tu juego avanza, eventualmente necesitarás objetos que se comporten de manera diferente dependiendo de lo que estén haciendo en ese momento. Un enemigo puede estar inactivo, patrullando, persiguiendo, atacando, aturdido o muerto. Una puerta puede estar cerrada, abriéndose, abierta o bloqueada. Una pelea de jefe puede atravesar varias fases.

Aquí es donde las Máquinas de Estados se vuelven útiles.

image.png

En la imagen de arriba, puedes ver el enemigo predeterminado que Crave crea para el nuevo proyecto, con su Máquina de Estados abierta en el lado derecho. Estamos dentro del estado "vagar" que tiene estados internos, como el "selector aleatorio" (el estado inicial, representado por el color verde), el "ir a aleatorio" y el "inactivo". Puedes ver las transiciones entre los estados representadas por las flechas, y que cada estado puede tener su propia lógica, ya sea en Python, como se muestra en la imagen, o en bloques de lógica.

Una máquina de estados te ayuda a organizar el comportamiento en estados claros en lugar de escribir un solo script grande lleno de condiciones no relacionadas.

En esta lección, aprenderás:

  • Qué es un Estado.
  • Qué es una Transición.
  • Por qué las máquinas de estados jerárquicas son útiles.
  • Cómo el Componente de Máquina de Estados de Cave se integra en una entidad.
  • Cómo funcionan On Enter, On Update y On Exit.
  • Cómo se puede usar Python y Bloques de Lógica dentro de estados y transiciones.

El objetivo es entender primero el modelo mental. Una vez que eso tenga sentido, el editor se vuelve mucho más fácil de usar.

¿Qué es un Estado?

Un estado describe lo que un objeto está haciendo actualmente.

image.png

Por ejemplo, un enemigo podría tener estos estados:

  • Inactivo
  • Patrullar
  • Perseguir
  • Atacar
  • Muerto

Solo uno de esos estados debería controlar al enemigo a la vez. Si el enemigo está en Patrullando, no debería estar ejecutando el comportamiento de ataque. Si está en Muerto, no debería seguir persiguiendo al jugador.

Esto hace que la jugabilidad sea más fácil de razonar porque cada estado tiene una tarea clara.

Estado Lo que podría hacer
Inactivo Permanecer quieto y esperar.
Patrullar Moverse entre puntos.
Perseguir Acercarse al jugador.
Atacar Reproducir una animación de ataque y causar daño.
Muerto Desactivar movimiento y reproducir una animación de muerte.

En lugar de preguntar "¿qué debería hacer el enemigo en este fotograma?" a partir de un gran script, puedes preguntar "¿en qué estado está actualmente el enemigo?"

¿Qué es una Transición?

Una transición es la regla que mueve la máquina de estados de un estado a otro.

image.png

Por ejemplo:

  • Inactivo a Patrullar cuando el enemigo debería empezar a moverse, después de un temporizador.
  • Patrullar a Perseguir cuando se detecta al jugador.
  • Perseguir a Atacar cuando el enemigo está lo suficientemente cerca.
  • Atacar a Perseguir cuando finaliza el ataque.
  • Cualquier estado a Muerto cuando la salud llega a cero.

La transición no es el comportamiento en sí. Es la decisión que dice: "ahora deberíamos cambiar de estado."

Esa separación es importante. El estado Atacar puede centrarse en atacar, mientras que la transición decide cuándo es el momento de entrar o salir de ese estado.

Por qué las Máquinas de Estados Jerárquicas Ayudan

Cave utiliza un enfoque de máquina de estados jerárquica. Esto significa que los estados pueden organizarse dentro de otros estados. Eso es útil porque muchos comportamientos comparten una idea común de padre.

Por ejemplo, un enemigo podría organizarse así:

Vivo
    Inactivo
    Patrullar
    Perseguir
    Atacar
Muerto

Los estados Inactivo, Patrullar, Perseguir y Atacar pertenecen al estado más amplio Vivo. Esto hace que la estructura sea más fácil de entender y puede ayudarte a evitar repetir la misma lógica en varios lugares.

Para un proyecto para principiantes, puedes comenzar con una máquina de estados simple y plana. Pero a medida que tu jugabilidad se vuelve más compleja, la jerarquía ayuda a mantener la lógica limpia.

El Componente de Máquina de Estados

Para usar una máquina de estados en una escena, una entidad necesita un Componente de Máquina de Estados.

El componente conecta la entidad a un activo de Máquina de Estados. El activo define los estados, transiciones y lógica, mientras que el componente ejecuta esa lógica en la entidad durante la jugabilidad.

Esto es similar a otros sistemas de Cave:

Activo Componente
Script de Python Componente de Python lo ejecuta.
Animación Componente de Animación la reproduce.
Máquina de Estados Componente de Máquina de Estados la ejecuta.

En la práctica, esto significa que tu entidad de enemigo puede tener un Componente de Máquina de Estados, y ese componente puede ejecutar una máquina de estados de IA de enemigo.

Un activo de máquina de estados puede tener propiedades, como puedes ver al ir a la pestaña de propiedades; esas propiedades pueden ser cambiadas localmente en el componente de máquina de estados, permitiéndote crear máquinas de estados modulares que tengan diferentes configuraciones en diferentes tipos de entidades.

Eventos de Estado

Cada estado puede reaccionar a tres momentos importantes:

Evento Cuándo se ejecuta Uso Común
On Enter Cuando comienza el estado. Reiniciar temporizadores, inicializar variables, reproducir una animación, elegir un objetivo.
On Update Mientras el estado está activo. Mover, verificar distancias, actualizar temporizadores.
On Exit Al salir del estado. Detener efectos, limpiar valores temporales.

Por ejemplo, un estado Atacar podría funcionar así:

  • On Enter: reproducir la animación de ataque.
  • On Update: esperar el momento del golpe o la respuesta de la animación.
  • On Exit: limpiar la bandera de ataque.

Esto hace que cada estado se sienta como un comportamiento autónomo pequeño.

Python Dentro de Estados

Las máquinas de estados pueden usar Python para lógica.

Dentro del código de Python de cada Estado, Cave proporciona variables útiles como entity y scene, para que el estado pueda controlar la entidad que posee el Componente de Máquina de Estados.

Por ejemplo, un estado podría reproducir un sonido al ser ingresado:

cave.playSound("Enemy Alert", volume=0.8)

O podría leer una propiedad de la entidad:

health = entity.properties.get("health", 100)

Esto mantiene la lógica del estado cerca del comportamiento al que pertenece.

Python Dentro de Transiciones

Las transiciones también pueden usar Python. Para la lógica de Python de transición, Cave utiliza una variable llamada result. Si result se convierte en True, la transición puede ocurrir. Por ejemplo, una transición al estado Muerto podría comprobar la salud de esta manera:

health = entity.properties.get("health", 100)
result = health <= 0

Una transición de Perseguir a Atacar podría comprobar la distancia si tu script de enemigo o propiedades proporcionan ese valor:

player = scene.get("Player")
playerPos = player.getTransform().getWorldPosition()
entityPos = entity.getTransform().getWorldPosition()

distanceToPlayer = (playerPos - entityPos).length()
result = distanceToPlayer < 2.0

Los datos exactos dependen de tu juego, pero la idea siempre es la misma: la transición decide si es el momento de pasar de un estado a otro.

** CONSEJO:** Durante una transición, todas las variables locales definidas en el estado del que proviene la transición están disponibles para ti. Por lo tanto, en el ejemplo anterior, donde calculamos la distancia entre la entidad y el jugador, podríamos almacenar la transformación del jugador y la transformación de la entidad en dos variables en el estado de entrada del estado del que proviene esta transición para ahorrar un poco de recursos, ya que entonces se almacena en caché y no necesitaríamos obtener estos datos cada fotograma.

Bloques de Lógica Dentro de Máquinas de Estados

Las máquinas de estados también pueden usar Bloques de Lógica.

Esto es útil cuando deseas construir comportamientos visualmente en lugar de escribir código en Python. Para muchas tareas de jugabilidad, los Bloques de Lógica son una manera muy accesible de conectar eventos, condiciones y acciones.

Funcionan de la misma manera que se explicó arriba para el código de Python dentro del estado o para una transición. Los Bloques de Lógica del Estado y los Bloques de Lógica de la Transición ya están inicializados con los bloques que necesitas para comenzar.

Puedes mezclar Python y Bloques de Lógica dependiendo de lo que te parezca más claro para el comportamiento que estás construyendo. Si un Estado o Transición tiene ambos, entonces ambos se ejecutarán y la transición ocurrirá si uno O el otro sucede.

Cuándo Usar una Máquina de Estados

Usa una máquina de estados cuando un objeto tiene modos de comportamiento claros.

Los buenos ejemplos incluyen:

  • IA de Enemigos.
  • Fases de Jefes.
  • Puertas y objetos interactivos.
  • Flujo de misión o tarea.
  • Progresión de escenas.
  • Estados de habilidades de personajes.

Es posible que no necesites una máquina de estados para objetos pequeños de acción única. Si un objeto de recogida solo reproduce un sonido y desaparece, un pequeño script en Python o configuración de Bloques de Lógica puede ser suficiente.

Lo Que Debes Recordar

Una máquina de estados organiza la jugabilidad en estados y transiciones.

Los estados describen lo que está ocurriendo en este momento. Las transiciones deciden cuándo cambiar a otra cosa. On Enter, On Update y On Exit ayudan a mantener cada estado enfocado y legible.

Para un comportamiento simple, un script puede ser suficiente. Para comportamientos con múltiples modos, una máquina de estados generalmente facilita la comprensión de la lógica y su expansión.