Hace un tiempo había intentado un acercamiento al tema usando vectores. Lamentablemente, el método era lento y no siempre encontraba un camino.
Entonces, me puse a trabajar en otro tipo de pathfinder. Uno que se basara en Waypoints.
Básicamente, los Waypoints son puntos que colocamos en un mapa que indican lugares a los que podemos ir. Estos Waypoints están conectados entre sí de forma tal que forman un grafo.
Por ejemplo, supongamos que tenemos el siguiente mapa:
Es obvio que no podemos ir directamente desde A a B en línea recta. La solución es crear 2 puntos de forma tal que pasando por éstos podamos llegar al objetivo:
Esos 2 puntos son los Waypoints, que de ahora en adelante, llamaremos nodos.
Ahora supongamos un mapa más complejo:
En éste mapa, podemos observar que desde cualquier nodo podemos movernos a cualquier otro (aunque no podamos directamente, siempre hay un camino). Además, no hay ningún punto (un punto no es un nodo) desde el que no se pueda ir en forma directa a, al menos, un nodo. Éso último es esencial y de eso va a depender que nuestro pathfinder funcione.
Ahora, queremos ir del nodo 1 al 6. Lo primero que hay que notar es que hay muchos caminos. Incluso, si decimos que podemos volver sobre nuestros pasos, éstos son infinitos (hay que tener en cuenta este detalle a la hora de programar el pathfinder). Igualmente, vemos que el ideal parece ser:
1 - 2 - 3 - 4 - 6
Pero si lo vemos nuevamente, nos damos cuenta que el camino puede ser más corto (con ésto me refiero al número de nodos y no a la distancia recorrida):
1 - 2 - 4 - 6
Ya que podemos saltar el nodo 3.
Entonces, cómo encontramos el camino? Es bastante simple, creamos un Array que llamaremos tree.
En el índice 0, ubicamos el nodo de inicio. El Array en el ejemplo es bidimensional, pero no es estrictamente necesario. Entonces, anotamos los nodos a los que se puede ir en línea recta, en el mapa anterior, sólo hay uno, el 2. Ese sería el índice 1 de nuestro Array.
Repetimos la operación anterior, nos fijamos qué nodos puede ver el 2 y los ubicamos en el siguiente índice. Ahora, repetimos, repetimos, repetimos. Siempre teniendo cuidado en no agregar 2 veces el mismo nodo, ni en el mismo índice ni en índices distintos.
Cuándo terminamos el loop? Bien, cuando hallamos encontrado el nodo destino. O cuando hallamos incluido todos los caminos hacía éste.
Vamos a analizar el primer caso. Si detenemos la búsqueda apenas encontremos el nodo destino, vamos a tener uno de los caminos con menor cantidad de nodos (si los nodos son equidistantes, tendríamos el camino más corto). Ésto tiene 2 ventajas, es rápido y al no encontrar siempre el camino idóneo, le agrega cierta torpeza a la IA.
El segundo caso requeriría analizar luego todos los caminos posibles. La ventaja de ésto es que incluso podríamos agregar que ciertos caminos sean menos transitables o cosas por el estilo (igual, si necesitan algo así, pueden considerar el algoritmo A* que se lee A-star)
Pero en éste caso, nos vamos a enfocar en la primer opción.
Es obvio que si llegamos al nodo destino, podemos hacer el camino inverso para llegar al nodo de partida. Entonces, tomamos el nodo de llegada y nos movemos hacia arriba en el tree hasta encontrar el nodo deseado.
Y listo, hemos conseguido un pathfinder relativamente simple (la función del ejemplo no está optimizada, encuentra los caminos en menos de 10ms, quizá, luego de optimizarla, logre bajarlo a 5). Simplemente hagan click en uno de los puntos y luego hagan click en el punto a donde quieren que se dirija.
Bajar el .fla
Tengo que aclarar que la idea de que un tree es un grafo en el que no podemos volver hacia atrás (idea en la que se basa el funcionamiento de éste ejemplo) la encontré en ésta página, aunque no tomé ni una línea de código de la misma. Además, querría agradecer a Zah, que me dio un método para hacer ésto que al final no pude usar porque no fui capaz de adaptarlo
¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.
Por Zguillez el 27 de Julio de 2007
Por Imer el 28 de Julio de 2007
Por eveevans el 28 de Julio de 2007
Nuevamente Felicidades Hernan
Gran Aporte
este me sera muy util
Por bicho_O el 28 de Julio de 2007
Por Carloz el 28 de Julio de 2007
Por jose bernal el 28 de Julio de 2007
Por Victor-Nael el 28 de Julio de 2007
Por eldervaz el 28 de Julio de 2007
Por Zah el 28 de Julio de 2007
Como apuntes, para detectar en qué botón hemos hecho click, te recomiendo hacerlo así, en vez de como lo tienes:
Código :
Así, utilizando un poco de ámbito de variables evitamos usar un hitTest innecesario y un return vacío en una función.
Pero como digo, muy buen trabajo ... a ver si encuentro tiempo para implementar el A*.
Por penholder el 29 de Julio de 2007
Por Zah el 29 de Julio de 2007
Viéndolo ahora por la mañana he visto por qué lo tienes así
Por HernanRivas el 30 de Julio de 2007
Por cierto, cómo hago con clases los prototipos? Porque me manda sintax error....
Por Freddie el 30 de Julio de 2007
HernanRivas :
¿Qué quieres hacer?
Por Zah el 30 de Julio de 2007
Freddie :
HernanRivas :
¿Qué quieres hacer?
Cosas como MovieClip.prototype.hazAlgo = function () {...}
Tienes dos opciones: una clase que extienda MovieClip, y en las opciones de vinculación del clip que te interese pones esa clase.
Otra es hacer que el clip sea una propiedad de la clase y es a ese clip a quien manipulan las funciones de la clase. Zguillez tiene muchísimos tips aplicando eso.
De todas formas, para una explicación más completa, si quieres, al foro.
Por el 30 de Julio de 2007
Generar un aumento progresivo con efecto de aceleración, sobre la transparencia de un clip
Sea el siguiente proto
Código :
el cual lo usamos de esta manera
Código :
Podemos traducirlo de la siguiente manera, de tal modo que tenga la misma funcionalidad de aplicación a cualquier clip
Código :
Dicha clase la usariamos de esta manera
Código :
Asi mismo como podemos aplicar el proto, a dos clips a la vez:
Código :
Con la clase, podemos hacerlo tambien, y sin necesidad de tener varias instancias de la misma
Código :
Esto es una forma muy básica de hacer dicha transición, de proto AS1 a Clase AS2; repito, es muy básica y ademas hay varias formas de hacerlo, dependiendo de la aplicación que vayas a implementar.
Desde luego ya estando en as2, podemos complicar las cosillas un poco, para hacerlas de la forma Asi es como debe ser®, y podemos meter al clip, como una propiedad (Como lo menciona el Sr Zah), o incluso disparar eventos (en este caso al terminar el fade) con la clase dispatchEvent.
Iba a poner un tip de esto, pero me parecio demasiado pequeño (Aunque considerando varios casos, pudiera ser que si cumpla con la extensión del tema)
Por HernanRivas el 31 de Julio de 2007
Por cierto, el comentario de Freddie, me hizo pensar.... sin clases hay algo que reemplace el MovieClip.prototype?
Por jack el 31 de Julio de 2007
eso esta bien chevere
Por [email protected] el 31 de Julio de 2007
Por hormy1 el 18 de Diciembre de 2007
Por MakerGames el 28 de Junio de 2010
Muchas gracias.
Por RevCat el 27 de Octubre de 2011