La planificación del movimiento te ayuda a mover una instancia de un punto a otro esquivando otras instancias que pudiera encontrarse por el camino (por ejempo, paredes). Resulta imposible dar funciones generales que funcionen en cualquier situación. Así mismo, las operaciones necesarias para calcular un camino libre de colisiones consumen bastantes recursos, así que debes usar estas funciones con criterio. Ten todo esto en cuenta cuando uses las siguientes funciones.
Game Maker dispone de diferentes formas de planificar el movimiento. La más simple consiste en hacer que una instancia de un paso hacia la posición final, intentando ir en línea recta pero tomando otra dirección si esto último resulta imposible. Estas funciones deben usarse en el evento step de la instancia y se corresponden a las acciones ya comentadas:
mp_linear_step(x,y,stepsize,checkall)
Esta función hace que la instancia de un paso hacia la posición (x,y). La
longitud del paso se indica con el parámetro
stepsize.
Si la instancia ya ha llegado a esa posición no se moverá. Si
checkall
es true la instancia se parará cuando choque con una instancia de cualquier
objeto. Si es false, sólo se parará al chocar con un objeto sólido. Esta función
no propone un camino alternativo, simplemente se parará si encuentra un
obstáculo.
La función
devuelve si se ha alcanzado el destino.
mp_linear_step_object(x,y,stepsize,obj)
Igual que la anterior, pero esta vez sólo se tienen en cuenta las instancias del
objeto
obj.
obj
puede ser un objeto o una id de una instancia particular.
mp_potential_step(x,y,stepsize,checkall)
Igual que las anteriores, pero en este caso la instancia intentará esquivar los
obstáculos que encuentre. Cuando la instancia se choque con un obstáculo
cambiará su dirección para tratar de esquivar el objeto, moviéndose alrededor de
él. Puede que no siempre se consiga llegar a la meta, pero la función siempre
intentará acercar lo más posible a la instancia. Devuelve true si se llega a la
meta.
mp_potential_step_object(x,y,stepsize,obj)
)
Igual que la anterior, pero esta vez sólo se tienen en cuenta las instancias del
objeto
obj.
obj
puede ser un objeto o una id de una instancia particular.
mp_potential_settings(maxrot,rotstep,ahead,onspot)
La función anterior hace su trabajo usando un número de parámetros que pueden
ser cambiados con esta función. El método funciona como sigue: primero la
instancia intenta moverse en línea recta hacia la meta. Para ello, mira un
número de pasos adelante para ver si hay algún obstáculo. Este número de pasos
corresponde al valor
ahead
(por defecto 3). Reduciendo este valor la instancia comenzará a cambiar su
dirección más tarde si encuentra un obstáculo. Aumentándolo cambiará antes de
dirección. Si detectamos una colisión, la función mira a la derecha y a la
izquierda para encontrar un camino libre. Esto se realiza en pasos de tamaño
rotstep (por
defecto 10). Reduciéndolo conseguimos que la instancia tenga más posibilidades
para moverse pero la función será más lenta. El parámetro
maxrot
(por defecto
30) indica cuánto puede cambiar como máximo la dirección en un paso. Así que
aunque pueda moverse en línea recta hacia la meta no lo hará si debe girar más
de lo indicado por este parámetro. Aumentándolo conseguimos que la instancia
pueda girar más en cada paso, haciendo que sea más fácil encontrar un camino
aunque éste será menos uniforme. Disminuyendo su valor el camino será más suave
pero la instancia realizará giros más largos, haciendo que a veces no pueda
llegar exactamente a la meta. Cuando la instancia no se puede mover en ninguna
dirección el comportamiento dependerá del valor de
onspot.
Si
onspot es true
la instancia rotará en su posición la cantidad indicada por
maxrot.
Si es false se parará (esto es útil para coches, por ejemplo, pero reduce las
posibilidades de encontrar un camino hacia la meta).
Observa que el acercamiento potencial sólo usa información local. Así que sólo encontrará un camino si la información es suficiente para determinar la dirección correcta. Por ejemplo, normalmente no podrá encontrar el camino para escapar de un laberinto.
El segundo tipo de funciones calcula un camino libre colisiones. Una vez que el camino se ha calculado puedes asignárselo a la instancia para que se mueva hacia la meta como si fuera un path normal que tú hubieras creado. El cálculo del camino tarda un poco pero una vez hecho la ejecución del path es muy rápida. Por supuesto, esto es válido si la situación no cambia (por ejemplo, si los obstáculos se mueven). Entonces necesitarás volver a calcular el path. De nuevo, estas funciones pueden fallar en algunas circunstancias. Estas funciones sólo están disponibles en la versión registrada de Game Maker.
Las dos primeras funciones usan el acercamiento por movimiento lineal y potencial que se usan en las funciones anteriores.
mp_linear_path(path,xg,yg,stepsize,checkall) Calcula un path en línea recta para la instancia desde su posición hasta (xg,yg) usando el paso especificado en stepsize. Usa pasos como en la función mp_linear_step(). El path indicado debe existir con anterioridad a la llamada de la función y será sobreescrito por el nuevo path (consulta el capítulo sobre cómo crear y destruir paths). La función devuelve si se ha encontrado un path. Si no consigue encontrar un camino, la función devolverá un path hasta la posición donde la instancia quedó bloqueada.
mp_linear_path_object(path,xg,yg,stepsize,obj)
Igual que la anterior, pero esta vez sólo se tienen en cuenta las instancias del
objeto
obj.
obj
puede ser un objeto o una id de una instancia particular.
mp_potential_path(path,xg,yg,stepsize,factor,checkall)
Esta función calcula un camino para instancia desde su posición actual y
orientación hasta (xg,yg) usando el paso especificado en
stepsize
e intentando evitar colisionar con los obstáculos. Utiliza pasos potenciales
como la función
mp_potential_step()
y los parámetros se pueden configurar con
mp_potential_settings().
El path indicado debe existir con anterioridad a la llamada de la función y será
sobreescrito por el nuevo path (consulta el capítulo sobre cómo crear y destruir
paths). La función devolverá si se ha encontrado un camino. Para evitar que la
función continúe calculando para siempre debes especificar un
factor
mayor que 1. La función se detendrá y devolverá un mensaje de error si no puede
encontrar un camino que sea más corto que la distancia del origen a la meta
multiplicada por
factor.
Un
factor de 4 es
normalmente suficiente pero si crees que la instancia tendrá un camino largo
puedes aumentarlo. Si la función falla se crea el camino en dirección a la meta
pero la instancia no llegará la meta.
mp_potential_path_object(path,xg,yg,stepsize,factor,obj)
Igual que la anterior, pero esta vez sólo se tienen en cuenta las instancias del
objeto
obj.
obj
puede ser un objeto o una id de una instancia particular.
Las demás funciones usan un mecanismo mucho más complejo basado en rejillas (un algoritmo A*). Tiene más sexito a la hora de encontrar caminos y hacerlos más cortos, pero requiere más trabajo por tu parte. Además, también puede fallar en algunas ocasiones. El funcionamiento es como sigue: primero situamos una rejilla sobre la parte del cuarto afectada. Puedes usar si quieres usar una rejilla fina (más lento) o más espaciada. Después, determinamos las celdas de la rejilla ocupadas por objetos relevantes (usando colisión precisa o la caja de contorno) y marcamos estas celdas como prohibidas. Así que una celda estará prohibida si parte de un obstáculo la está ocupando. Finalmente especificamos la posición inicial y final, que deben estar en celdas libres de la rejilla y la función calcula el camino más corto entre ellas. El camino irá de centro a centro de las celdas libres. Así que las celdas deben ser lo suficientemente grandes como para que la instancia entre totalmente dentro de ellas. Ahora puedes asignar el path a una instancia y hacer que lo siga.
Este sistema es muy potente (se usa en muchos juegos profesionales) pero requiere que lo planifiques con cuidado. Debes determinar la zona del cuarto sobre la que situar la rejilla y el tamaño de las celdas con la mayor precisión posible. También debes decidir qué objetos deben tomarse en cuenta y si es necesaria la colisión precisa o no. Todos estos parámetros afectan de manera muy notable a la eficiencia del método.
En particular, el tamaño de las celdas es crucial. Recuerda que las celdas deben lo suficientemente grandes como para que la instancia que se mueve entre totalmente dentro de ellas (ten cuidado con la posición del origen de la instancia y recuerda que puedes mover el path para hacer que el centro del objeto coincida con el centro de la celda). Por otro lado, cuanto menores sean las celdas más caminos diferentes podrás encontrar. Si haces las celdas demasiado grandes puede que unos pocos objetos ocupen todas las celdas cerrando todos los caminos posibles.
Las funciones para el método de rejilla son:
mp_grid_create(left,top,hcells,vcells,cellwidth,cellheight) Esta función crea la rejilla. Devuelve un índice que debe ser usado en las demás funciones. Puedes crear y mantener varias rejillas al mismo tiempo. left y top indican la posición de la esquina superior izquierda de la rejilla y hcells y vcells indican el número de celdas horizontales y verticales respectivamente. Finalmente, cellwidth y cellheight indican la anchura y altura de las celdas.
mp_grid_destroy(id)
Destruye la rejilla indicada y libera la memoria usada. No olvides llamar a esta
función cuando no necesites usar más la rejilla.
mp_grid_clear_all(id)
Marca todas las celdas como libres.
mp_grid_clear_cell(id,h,v)
Marca la celda indicada como libre (la primera celda es la 0,0).
mp_grid_clear_rectangle(id,left,top,right,bottom)
Marca como libres todas las celdas que intersectan el rectángulo definido en
coordenadas absolutas del cuarto.
mp_grid_add_cell(id,h,v)
Marca ls celdas indicadas como prohibidas.
mp_grid_add_rectangle(id,left,top,right,bottom)
Marca todas las celdas que intersectan el rectángulo como prohibidas.
mp_grid_add_instances(id,obj,prec)
Marca todas las celdas que intersectan una instancia del objeto indicado como
prohibidas. También puedes especificar una id de una instancia concreta, o la
palabra clave
all
para indicar todas las instancias.
prec
indica si hay que usar colisión precisa (sólo funcionará si en el sprite de la
instancia está activada la misma opción).
mp_grid_path(id,path,xstart,ystart,xgoal,ygoal,allowdiag)
Calcula el path a través de la rejilla. El path indicado debe existir con
anterioridad a la llamada de la función y será sobreescrito por el nuevo path
(consulta el capítulo sobre cómo crear y destruir paths).
xstart e
ystart indican
el comienzo del path y
xgoal
e
ygoal
las coordenadas de la meta.
allowdiag
indica si se permiten movimientos diagonales entre celdas o sólo horizontales y
verticales. La función devuelve si consiguió calcular un path (observa que el
path es independiente de la instancia actual).
mp_grid_draw(id)
Esta función dibuja la rejilla marcando las celdas libres y prohibidas (muy útil
para buscar errores).