En este tema aprenderás cómo dotar a los enemigos de tu juego con comportamientos inteligentes y dinámicos utilizando Phaser. Cubriremos desde patrones simples de movimiento hasta la implementación de lógica básica de IA (Inteligencia Artificial) para que los enemigos reaccionen al jugador y al entorno.
- ¿Qué es la IA en Juegos?
La Inteligencia Artificial en juegos se refiere a la lógica que permite a los personajes controlados por el ordenador (NPCs o enemigos) tomar decisiones y actuar de manera autónoma. Los comportamientos pueden ser simples (patrullar, seguir al jugador) o complejos (planificar rutas, cooperar entre enemigos).
Conceptos clave:
- Patrullaje: Movimiento repetitivo entre puntos.
- Persecución: Seguir al jugador cuando está cerca.
- Evasión: Alejarse del jugador o de peligros.
- Ataque: Realizar acciones ofensivas bajo ciertas condiciones.
- Estados: Cambiar de comportamiento según la situación (por ejemplo, patrullar → perseguir → atacar).
- Estructura Básica de un Enemigo con IA
En Phaser, los enemigos suelen ser Sprites con física habilitada y lógica personalizada en el bucle de actualización (update
). La IA se implementa como una serie de condiciones y acciones dentro de este método.
Estructura típica:
class Enemy extends Phaser.Physics.Arcade.Sprite { constructor(scene, x, y, texture) { super(scene, x, y, texture); scene.add.existing(this); scene.physics.add.existing(this); // Estado inicial this.state = 'patrolling'; this.speed = 100; this.patrolPoints = [x, x + 200]; this.currentPatrolIndex = 0; } update(player) { switch (this.state) { case 'patrolling': this.patrol(); if (this.canSeePlayer(player)) { this.state = 'chasing'; } break; case 'chasing': this.chase(player); if (!this.canSeePlayer(player)) { this.state = 'patrolling'; } break; } } patrol() { // Lógica de patrullaje } chase(player) { // Lógica de persecución } canSeePlayer(player) { // Lógica para detectar al jugador } }
- Ejemplo Práctico: Patrullaje y Persecución
3.1. Patrullaje
El enemigo se mueve entre dos puntos. Cuando llega a un extremo, se da la vuelta.
patrol() { const targetX = this.patrolPoints[this.currentPatrolIndex]; if (Math.abs(this.x - targetX) < 5) { // Cambia de dirección this.currentPatrolIndex = 1 - this.currentPatrolIndex; } this.setVelocityX(targetX > this.x ? this.speed : -this.speed); }
Explicación:
patrolPoints
define los extremos del patrullaje.- El enemigo se mueve hacia el punto objetivo.
- Al llegar, invierte la dirección.
3.2. Persecución
El enemigo sigue al jugador si está dentro de un rango de visión.
chase(player) { if (player.x > this.x) { this.setVelocityX(this.speed); } else { this.setVelocityX(-this.speed); } }
Explicación:
- Compara la posición del jugador con la del enemigo.
- Ajusta la velocidad para moverse hacia el jugador.
3.3. Detección del Jugador
canSeePlayer(player) { const distance = Phaser.Math.Distance.Between(this.x, this.y, player.x, player.y); return distance < 150; // Rango de visión }
Explicación:
- Calcula la distancia entre el enemigo y el jugador.
- Si está dentro del rango, retorna
true
.
- Tabla Comparativa: Patrones de Comportamiento
Patrón | Descripción | Dificultad de Implementación |
---|---|---|
Patrullaje | Movimiento entre puntos fijos | Baja |
Persecución | Seguir al jugador si está cerca | Media |
Evasión | Alejarse del jugador o de peligros | Media |
Ataque | Realizar acciones ofensivas | Media/Alta |
Estados | Cambiar entre varios comportamientos | Media/Alta |
- Ejercicio Práctico
Enunciado
Crea un enemigo que patrulle entre dos puntos. Si el jugador se acerca a menos de 100 píxeles, el enemigo lo perseguirá. Si el jugador se aleja, el enemigo volverá a patrullar.
Código Base
class Enemy extends Phaser.Physics.Arcade.Sprite { constructor(scene, x, y, texture) { super(scene, x, y, texture); scene.add.existing(this); scene.physics.add.existing(this); this.state = 'patrolling'; this.speed = 80; this.patrolPoints = [x, x + 150]; this.currentPatrolIndex = 0; } update(player) { switch (this.state) { case 'patrolling': this.patrol(); if (this.canSeePlayer(player)) { this.state = 'chasing'; } break; case 'chasing': this.chase(player); if (!this.canSeePlayer(player)) { this.state = 'patrolling'; } break; } } patrol() { const targetX = this.patrolPoints[this.currentPatrolIndex]; if (Math.abs(this.x - targetX) < 5) { this.currentPatrolIndex = 1 - this.currentPatrolIndex; } this.setVelocityX(targetX > this.x ? this.speed : -this.speed); } chase(player) { this.setVelocityX(player.x > this.x ? this.speed : -this.speed); } canSeePlayer(player) { return Phaser.Math.Distance.Between(this.x, this.y, player.x, player.y) < 100; } }
Solución y Explicación
- El enemigo alterna entre patrullar y perseguir según la distancia al jugador.
- El método
update
se llama en cada frame y decide el comportamiento. patrol
ychase
controlan el movimiento.canSeePlayer
determina si el jugador está lo suficientemente cerca.
Errores Comunes y Consejos
- Olvidar llamar a
update
del enemigo en la escena: Asegúrate de llamar aenemy.update(player)
en el métodoupdate
de tu escena. - No habilitar la física: Usa
scene.physics.add.existing(this)
en el constructor. - No ajustar la velocidad a cero cuando el enemigo está quieto: Si el enemigo debe detenerse, usa
this.setVelocityX(0)
.
- Ampliando la IA: Estados y Transiciones
Puedes agregar más estados, como "atacando" o "huyendo", y transiciones más complejas. Por ejemplo:
update(player) { switch (this.state) { case 'patrolling': this.patrol(); if (this.canSeePlayer(player)) { this.state = 'chasing'; } break; case 'chasing': this.chase(player); if (this.isCloseToPlayer(player)) { this.state = 'attacking'; } else if (!this.canSeePlayer(player)) { this.state = 'patrolling'; } break; case 'attacking': this.attack(player); if (!this.isCloseToPlayer(player)) { this.state = 'chasing'; } break; } }
- Resumen
- La IA en Phaser se basa en lógica condicional dentro del método
update
de los enemigos. - Los patrones básicos incluyen patrullaje, persecución y ataque.
- Utiliza estados para organizar y escalar la complejidad de los comportamientos.
- Practica implementando y combinando estos patrones para crear enemigos más interesantes y desafiantes.
¡Ahora estás listo para dotar a tus enemigos de comportamientos inteligentes y dinámicos! En el siguiente tema aprenderás a trabajar con temporizadores y eventos retardados para enriquecer aún más la jugabilidad.
Phaser - Desarrollo de Juegos con JavaScript
Módulo 1: Introducción al Desarrollo de Juegos y Phaser
- ¿Qué es el Desarrollo de Juegos?
- Descripción general de Phaser
- Configurando tu Entorno de Desarrollo
- Tu Primer Proyecto con Phaser
Módulo 2: Fundamentos de Phaser
- Entendiendo el Bucle de Juego
- Configuración del Juego y Escenas
- Cargando y Mostrando Imágenes
- Trabajando con Texto
- Manejo de Entrada (Teclado y Ratón)
Módulo 3: Sprites y Animación
- ¿Qué son los Sprites?
- Añadiendo y Moviendo Sprites
- Fundamentos de Animación de Sprites
- Grupos de Sprites y Gestión
Módulo 4: Física e Interactividad en el Juego
- Introducción a la Física en Phaser
- Habilitando Física en Sprites
- Colisiones y Superposiciones
- Objetos Interactivos y Eventos
Módulo 5: Mundo del Juego y Cámara
- Creando Tilemaps y Mundos de Juego
- Desplazamiento y Control de Cámara
- Capas y Gestión de Profundidad
Módulo 6: Audio e Interfaz de Usuario
Módulo 7: Arquitectura del Juego y Gestión de Estados
- Organizando el Código del Juego
- Gestionando Múltiples Escenas
- Guardando y Cargando el Estado del Juego
Módulo 8: Características Avanzadas de Jugabilidad
- Efectos de Partículas
- Tweens y Animaciones
- Temporizadores y Eventos Retardados
- IA y Comportamiento de Enemigos