ADVERTENCIA: Este tutorial, de todos modos, está orintado a aquellos con conocimientos intermedios o avanzados de AS. Por lo que recomiendo que antes de leer lo que sigue, aquellos que recién empiezan con Flash, se den una vuelta por la sección de tutoriales de esta página y revisen los conceptos básicos de programación en AS.
Ahora, para empezar con el tema, hay que definir qué entendemos por inteligencia. La definición que me viene a la mente es la capacidad de aprender de nuestros errores y modificar nuestro comportamiento en base a ellos (aplicado a la programación, sería modificar el código ya escrito). Claro que esto es demasiado complicado, lo que nosotros buscamos es el tipo de inteligencia artificial (en adelante IA) encontrada en los videojuegos.
Entonces, la IA en los videojuegos se define como la imitación del comportamiento de jugadores de "carne y hueso" y es en eso en lo que nos vamos a basar. Claro que para hacer una IA de calidad es necesario emplear inteligencia real, para crear un código lo más simple posible que sea capaz de complicarle la vida a los videojugadores y, además, que el usuario no descubra brechas por las que puede confundir a nuestros autómatas (brechas que no deberían existir).
En este tutorial, vamos a armar un ejemplo en el que habrá unos cuantos clips de película, 1 que actuará de oveja y el resto, que actuarán de lobos. La idea va a ser que la oveja intentará escapar de los lobos que intentarán cazarla.
Para los lobos, podría hacerse un código simple que haga que se muevan en la dirección de la oveja. Pero el problema radica en que la oveja se mueve un 50% más rápido que ellos, lo que hace que este sistema se muestre inútil.
Pero entonces, uno podría pensar que es imposible. Pues no lo es, simplemente, hay que usar más de un lobo (es decir, una jauría). Entonces, del mismo modo en que ocurre en la naturaleza, los lobos deberían comportarse inteligentemente y organizarse para cazarla, rodeándola y evitando que se escape.
Ahora, las reglas. La oveja tendrá 2 estados, tranquila y asustada. Mientras esté tranquila se moverá un 20% más lento que los lobos, cuando se asuste, correrá a más no poder y esa velociadad será un 50% mayor que la velocidad de los lobos. Además, cambiará la forma en la que escapa de estos feroces carnívoros (en esta entrega, veremos solo el código que empleará para cuando está tranquila).
Otra regla, sería que los lobos, no pueden depender de variables externas (excepto la que determina su velocidad) ni acceder de ninguna manera a las variables de los otros lobos y la oveja (excepto las de posición, claro). Entonces, los prototipos de los lobos, podrían tener (eso va a depender de cada programador) más de un estado, como acechando y cazando, por ejemplo. El problema es que ningún lobo podrá acceder al estado de otro lobo o al estado de la oveja (eso es porque, aún, no han evolucionado los lobos telépatas).
Bien, ahora, luego de la teoría, un poco de código.
Este se va a ser escrito 100% en el único fotograma de la película (aunque habrá más de una capa), reemplazando el código en los MCs por prototipos (los prototipos son funciones que emulan código escrito en los símbolos). Además, por comodidad, vamos a trabajar con 4 capas, una en la que declararemos las variables, una donde ubicaremos los prototipos, una en la que irán las funciones y, finalmente, las acciones principales.
Vamos a comenzar por algunas funciones.
Lo primero, es una función que calcule la distancia entre 2 clips. Nada raro, un par de cuentas y un return.
Código :
calcularDistancia = function (objeto1:String, objeto2:String) { // // Calculamos la distancia en X y en Y var distX = _root[objeto1]._x - _root[objeto2]._x; var distY = _root[objeto1]._y - _root[objeto2]._y; // // Calculamos la distancia var distancia = Math.sqrt ((distX * distX) + (distY * distY)); // return distancia; };
Luego, una función que usará la oveja para detectar cúal es el lobo que se halla más cerca usando la función [i]calcularDistancia[\i].
Código :
buscarLobos = function (oveja:String, numeroLobos:Number) { // var distMin = 1000; var lobo; // for (i = 1; i <= (numeroLobos + 7); i++) { // // Calcular la distancia para cada uno de los lobos var distancia = calcularDistancia (oveja, "lobo" + i); // // Si la distancia es la distancia más pequeña encontrada, la variable lobo nos devuelve el lobo más cercano a la oveja if (distancia < distMin) { lobo = "lobo" + i; distMin = distancia; } } return lobo; };
Bien, ahora, la función que calcula el ángulo en el que la oveja intentará escapar cunado no este asustada. Veremos que cuando se asuste, huirá de un modo más eficaz.
Código :
calcularAngulo = function (oveja:String, lobo:String) { // // Calculamos la distancia en X y Y entre la oveja y el lobo var deltaX = _root[oveja]._x - _root[lobo]._x; var deltaY = _root[oveja]._y - _root[lobo]._y; // // Calculamos el ángulo en base a esas distancias var angulo = -Math.atan2 (deltaX, deltaY) / (Math.PI / 180) + 180; // return angulo; };
La última función que vamos a ver por ahora, será la que nos crea los clips de película (crearlos en forma dinámica, nos permite removerlos, entre otras cosas).
Código :
crearObjetos = function (ovejas:Number, lobos:Number) { // Crear las ovejas if (ovejas != undefined) { for (i = 1; i <= ovejas; i++) { this.attachMovie ("Oveja", "oveja" + i, i); } } // Crear los lobos if (lobos != undefined) { for (i = 1; i <= lobos; i++) { this.attachMovie ("Lobo", "lobo" + i, i + ovejas); } } };
Bien, este es el principio, para no extenderme demasiado, voy a cortar ahora, simplemente, esperen las otras entregas, pero pueden empezar a jugar con este código. Para probarlo, yo cree 3 MCs, exportados para AS con los siguientes nombres:
Oveja
Lobo
Linea
La obeja y el lobo son simples círculos de mismo tamaño y distinto color con el punto de anclaje en el centro y la línea, es una línea vertical con punto de anclaje en su extremo inferior que mostrará el ángulo en el que escapará la oveja.
Para ver un ejemplo de lo que estas funciones hacen, he aquí el código en el que las estuve probando:
Código :
// crearObjetos (1, 2); // oveja1._y = 200; oveja1._x = 275; // lobo1._x = 540; lobo1._y = 10; lobo2._y = 290; lobo2._x = 300; // lobo2._xscale = 180; // this.attachMovie ("Linea", "linea", 1000); // onMouseMove = function () { oveja1._x = _xmouse; oveja1._y = _ymouse; linea._x = oveja1._x; linea._y = oveja1._y; linea._rotation = (calcularAngulo ("oveja1", buscarLobos ("oveja1", 2))); }; onMouseDown = function () { trace (buscarLobos ("oveja1", 2)); };
Como verán, con el mouse se mueve la oveja y al hacer click, se puede ver cómo esta detecta el lobo más cercano. El xscale, fue solo para identificar los lobos.
Bueno, eso es todo por ahora, esperen próximas entregas de Inteligencia Artificial para mayores análisis, más código y más ejemplos. Espero les sirva de algo.
Cambios relizados:
1) La parte 2 está aquí: http://www.cristalab.com/foros/viewtopic.php?p=221382#221382
2) Corregido un error, un Math.round sobraba y ocasionaba errores en la parte 2
3) Un error de tipeo, la oveja se mueve 20% más lento que los lobos cuando está tranquila, antes (por error) decía que 20% más rápido.