Pathfinding con línea de vista

1
  • 0 favourites

Tagged

Contributors

Stats

4,975 visits, 5,563 views

Tools

License

This tutorial is licensed under CC BY 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

Introducción

¡Hola a todos!

Te voy a enseñar cómo combinar el comportamiento "Pathfinding" con un motor de "line of sight" para crear enemigos que tienen un poco de IA; Los enemigos van a pasear cuando no estén alertas, y una vez que tienen la línea de visión del jugador, le perseguirán. Si la línea de visión se rompe durante el tiempo suficiente, van a volver a su estado errante. Este tutorial se hace para un juego isométrico, pero también puede aplicarse a juegos top down.

Puedes ver el proyecto de ejemplo .capx aquí

La creación de nuestros activos

Ok, vamos a necesitar un par de cosas antes de que podamos comenzar cualquier scripting visual. Lo que vamos a necesitar es:

* Unos sprites de enemigos

 * Un sprite de jugador

 * Un sprite de línea de vista (line of sight)

 * Algunos sprites de entorno (paredes, piso, puerta)

 * Un sprite búsqueda de caminos "ayudante" que evita los problemas de recorte cuando los sprites enemigos se están moviendo.

 * Dos iconos de estado; uno para representar cuando se alertó a los enemigos, y otro para representar cuando el enemigo tiene línea de visión con el jugador.

Puedes crear la forma y el tamaño que desees, pero para facilitar la creación, he creado la mía en el editor de imágenes de Construct 2. A continuación se muestra un ejemplo de los sprites de entorno que he creado. Me quedé con una cuadrícula de 32x32 para este ejemplo.

De izquierda a derecha se encuentran: piso, zona intransitable (espacio dentro de las murallas), panel de pared, puerta.

Y aquí están en uso:

Para los iconos de estado, me he mantenido simple:

Para los sprites de jugadores y enemigos de este ejemplo, los he hecho de 24px de ancho y 48px de alto (los he puesto al lado de la baldosa para que te hagas una idea de qué tan grande debe ser el sprite):

Ahora, el sprite enemigo necesitará unos pocos puntos de la imagen para el anclaje de los iconos de estado y la línea de visión. El origen para el sprite enemigo debe ajustarse alrededor de 2/3 hacia abajo el sprite (para este sprite es en Y:32). Esto evitará que el sprite se cierna poco realista sobre las paredes / áreas intransitable. Los puntos de imagen alertPoint y losPoint son para el anclaje de los iconos de estado. El punto de imagen eyes es donde la línea de vista del sprite se ancla; Lo he puesto lo más cercano de donde los ojos del enemigo los tendría en la vida real.

Para la línea de vista del sprite, todo lo que tiene que hacer es crear un sprite de tamaño 1x1 que estaremos estirando desde el sprite del enemigo al sprite del jugador en tiempo de ejecución. Asegúrate de establecer el origen del sprite de línea de la vista al lado left del sprite, de lo contrario va a experimentar un comportamiento extraño de la línea (no se extenderá entre el enemigo y el jugador correctamente):

No olvides de nombrar los sprites descriptivamente ya que esto ayuda mucho cuando estás ejecutando y buscando errores.

Momento para ponerse en movimiento

Correcto, tenemos nuestros sprites creados. Ellos parecen impresionantes, pero no hacen nada.

El jugador

En primer lugar, darle a tu sprite de jugador el comportamiento '8 Direction', y establece los valores a los que se muestran aquí:

A continuación, dar a los script zona intransitable y puerta el comportamiento 'sólido'. Esto es puramente para hacer a estos objetos infranqueable para el jugador. Los sprites enemigos utilizan un método diferente para decirles donde pueden y no pueden caminar. La razón de esto es que vamos a incluir un obstáculo adicional que no es sólido (nuestro ayudante pathfinding):

Si ejecuta el layout ahora, puedes usar las teclas para mover el personaje del jugador. ¡Fabuloso!. Pero cuando choca con la puerta, nada sucede, así que vamos a conseguir esto ahora.

Anda a la hoja de acontecimientos para el layout y haz lo siguiente:

¡Hurra!, ahora cuando chocas con una puerta, ésta desaparecerá y el jugador puede continuar

El Enemigo

Aquí es donde se pone un poco complicado, pero vamos un paso a la vez, así que no te preocupes.

Dale al sprite del enemigo el comportamiento de 'Pathfinding' y dale la siguiente configuración:

Después de que hayas hecho esto, hace del sprite enemigo un contenedor con los siguientes sprites añadidos dentro de él:

Con esta configuración, primero programaremos el de vagar del enemigo. Esto es fácil de hacer, ya que todo lo que realmente implica es un comportamiento pathfinding del enemigo siguiendo un punto al azar en el diseño, viendo si se puede mover allí; si se puede, entonces se moverá a ese punto, si no se busca otro punto al que se puede mover. Como requisito previo a lo que vamos a hacer después, dar al sprite de enemigo las siguientes variables de instancia (explicaré esto más adelante en el tutorial):

Volver atrás a la hoja de evento y crear los siguientes eventos:

Esto le dice el sprite del enemigo que no puede atravesar, de lo contrario sería una imagen fantasma en las paredes y puertas.

Este conjunto de eventos le dice al sprite enemigo lo que hay que hacer cuando no es alertado (es decir: errante).

Si ejecuta hora el layout, tu enemigo vagará sin rumbo, evitando obstáculos y completamente ignorando al jugador. Si usted ha puesto habitaciones en el diseño, y el jugador ha abierto la puerta de algunos de ellos, el enemigo no se moverá en las habitaciones recientemente abiertas. Esto es debido a que el enemigo necesita reconstruir su mapa de obstáculo. Debe ejecutar esta llamada reconstrucción cada vez que se abre una puerta:

Ahora, los enemigos obtendrán un mapa obstáculo actualizado cada vez que se abre una puerta, y se moverá un poco más libres en torno al medio ambiente.

Esta parte es completamente opcional, pero yo recomendaría que por lo menos tomaras en cuenta el principio de la misma, ya que ha demostrado ser una solución digna al problema de sprites enemigo cortando esquinas y sprites obstáculos que no deben solaparse. Mediante el uso de sprites auxiliares invisibles, puedes ajustar fácilmente las rutas específicas que el sprite enemigo puede tomar. Esta actúa para evitar la superposición de los sprites obstáculos:

Mis sprites de ayuda están en verde, y se pueden activar visible/invisible pulsando H en el ejemplo .CAPX

La línea de visión

¡Ahora las cosas jugosas!

Lo esencial

Para nuestro motor de la línea de vista, conectamos una línea de sprite del enemigo y luego estira este elemento hacia el punto X e Y del sprite del jugador. Cuando el sprite no está chocando con los obstáculos del entorno, entonces el booleano hasLineOfSight del enemigo será verdadero y él perseguirá a nuestro jugador. Cuando el enemigo pierde la línea de visión con el jugador, se inicia un tiempo de reutilización, y una vez que la duración del tiempo de reutilización ha pasado, el enemigo detendrá la búsqueda y volverá a deambular. La razón por la que he incluido un tiempo de reutilización es evitar que el enemigo inmediatamente pare tan pronto cuando pierde de vista el jugador; sino que proseguirá durante unos segundos más antes de darse por vencido.

Vamos a hacer esto! Para la primera sección (la creación de la línea de vista de sprites) crear los siguientes eventos:

El primer evento eliminará nuestra instancia principal de la línea de sprite de vista. consejo: Construct 2 requiere por lo menos una instancia de cualquier cosa para recrearlo. Así que asegúrate de que tienes un sprite de cada elemento en el diseño (utilice los márgenes para ocultarlos).

El segundo bloque de eventos logra este resultado al ejecutar el layout:

¡Fantástico! Ahora tenemos una línea de visión unida a nuestro enemigo, y traza una línea recta entre el jugador y el enemigo.

Configuración de los estados

Siguiente paso, queremos definir lo que sucede cuando el enemigo no tiene línea de visión con el jugador:

En este caso, si la línea de vista del sprite es la superposición de cualquiera de los obstáculos, entonces el booleano hasLineOfSight del enemigo se establece en false y el enemigo no está renovando su estado "alerta". Una vez que la línea de vista del sprite no es la superposición de cualquiera de los obstáculos, el boolean hasLineOfSight del enemigo se establece en true, la variable alertCooldown se establece en 5 (lo que significa que seguirá buscando por 5 segundos después de que se pierde la línea de visión), y el booleano alertado se establece en true.

Estos estados booleanos son necesarias, ya que nos permiten controlar las acciones del enemigo en función de si tiene línea de visión o no, y qué hacer cuando se es o no alertado. Con esto en mente, ahora vamos a decirle al enemigo lo que debe hacer cuando su booleano 'alertado' está en verdadero:

Por el bien de limpieza, combina los dos bloques de eventos "Enemy is Alerted; Every 1 Second".

Una vez hecho esto, cuando se ejecuta el layout ahora tus enemigos perseguirán al jugador cuando tienen línea de visión, y perderán el interés cuando pierden la línea de visión durante más de 5 segundos.

Iconos de estado

Por último, podemos crear iconos de estado que nos muestren el estado en que está un enemigo:

This will dynamically show/hide the icons depending on what boolean states the enemy is in:

Esto dinámicamente mostrará/ocultará los iconos en función del estado booleano del enemigo:

Este es un enemigo alertado y que tiene línea de visión.

Este enemigo es alertado, pero no tiene línea de visión.

Pensamientos de cierre

Espero que este tutorial sea de utilidad, me tomó unos días conseguir que todo funcionara como yo quería.

Con los estados booleanos, podemos hacer fácilmente que el enemigo ataque cuando se tiene línea de visión (como en el ejemplo. CAPX que he incluido en este tutorial.)

Si te encuentras con cualquier inconsistencia en el tutorial, o necesita que explique algo con mayor detalle, lo comento aquí o me tiras un MP y yo estaré encantado de ayudarte!

Wrangler

  • 0 Comments

  • Order by
Want to leave a comment? Login or Register an account!