42. Enemigos "inteligentes": PicMan (2: varios enemigos). (*)

Una vez que tenemos un esqueleto básico de juego, podemos centrarnos en crear varios enemigos. Sobre estos enemigos, hay que hacer dos consideraciones:

  • Lo de que sean "inteligentes" supone básicamente que nosotros pensemos una lógica para sus movimientos. Por ejemplo, algo como "si está a menos de 100 píxeles del personaje, acercarse hacia él; si está a 100 píxeles o más, calcular la siguiente dirección al azar", de modo que finjamos que cuando estamos cerca del enemigo, éste nos divisa y nos persigue. La lógica de los enemigos del PacMan original la comentamos en el apartado anterior. En un juego diseñado por nosotros, no debemos perder de vista la jugabilidad: si los enemigos son "demasiado inteligentes", el juego puede resultar demasiado difícil. Generalmente, en un juego de este tipo, nos fijaremos en la distancia del enemigo al personaje y (quizá) en si hay obstáculos entre ellos, para que el enemigo "nos vea" o "nos detecte" de forma creíble cuando estamos cerca. Por supuesto, a este nivel del curso no vamos a hablar (al menos todavía) de que los enemigos aprendan de nuestro comportamiento, ni de comportamiento coordinado entre un grupo de enemigos, ni de búsqueda de caminos, ni de los otros muchos elementos relacionados con la "inteligencia" de los enemigos y que aparecerían en juegos más complejos.
  • Lo de que cada enemigo tenga su propia lógica de movimiento, distinta de la de los demás, supone que exista una función "mover" distinta para cada uno de ellos, que calcule hacia donde se moverá en el siguiente instante. En lenguajes como C, esas funciones "moverFantasmaRojo", "moverFantasmaRosa", "moverFantasmaAzul", "moverFantasmaNaranja" se irían llamando en orden desde "moverElementos". En lenguajes orientados a objetos, como C++, Java, C# o las últimas versiones de Pascal, hay una alternativa más elegante: la clase "Enemigo" tendrá un método "Mover", y los subtipos de enemigos serán "clases hijas", que hereden parte del comportamiento común a todos los enemigos, pero que también puedan redefinir los detalles que sean distintos para cada enemigo (como su imagen o su "Mover"). Esto, además de ser un diseño "más natural" y permitir repartir trabajo entre varios programadores con más facilidad, hace que el programa principal sea más legible, porque el "moverElementos", en vez de llamar a varias funciones distintas (una por cada tipo de enemigo, como hemos dicho antes), tendría simplemente un "para cada enemigo: enemigo[i].Mover"

El nuevo diagrama de clases, con una clase "Enemigo" de la que heredan su comportamiento cuatro subclases (una para cada tipo de enemigo) sería:


(Pronto disponible)