¡Construye una metroidvania en Godot! | Thomas Yanuziello | Skillshare

Velocidad de reproducción


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

¡Construye una metroidvania en Godot!

teacher avatar Thomas Yanuziello, Indie Game Developer

Ve esta clase y miles más

Obtenga acceso ilimitado a todas las clases
Clases enseñadas por líderes de la industria y profesionales activos
Los temas incluyen ilustración, diseño, fotografía y más

Ve esta clase y miles más

Obtenga acceso ilimitado a todas las clases
Clases enseñadas por líderes de la industria y profesionales activos
Los temas incluyen ilustración, diseño, fotografía y más

Lecciones en esta clase

    • 1.

      Avance 0-0

      2:01

    • 2.

      0-1 Descarga

      2:34

    • 3.

      Editor 0-2

      4:42

    • 4.

      0-3 escenas

      6:48

    • 5.

      0-4 Física

      4:51

    • 6.

      De 0 a 5 guiones

      5:43

    • 7.

      Juego 0-6

      5:44

    • 8.

      1-1 Cuerpo del personaje

      5:15

    • 9.

      Mapa de entrada 1-2

      8:47

    • 10.

      Movimientos 1-3

      7:15

    • 11.

      1-4 Saltos

      7:23

    • 12.

      1-5 Caída

      7:25

    • 13.

      1-6 Running

      4:40

    • 14.

      1-7 Coyote

      8:41

    • 15.

      Sprite 2-1

      7:36

    • 16.

      2-2 Reproductor de animación

      9:56

    • 17.

      Árbol de animación 2-3

      10:02

    • 18.

      2-4 efectos de sonido

      8:58

    • 19.

      2-5 Animated Sprite

      7:54

    • 20.

      2-6 Instantiar

      11:27

    • 21.

      Bus de audio 2-7

      6:13

    • 22.

      Mapa de mosaicos 3-1

      8:05

    • 23.

      3-2 terrenos

      8:15

    • 24.

      3-3 cámaras

      6:46

    • 25.

      3-4 Un vistazo al futuro

      9:24

    • 26.

      3-5 Mira hacia arriba

      10:41

    • 27.

      3-6 Límites

      11:05

    • 28.

      3-7 Parallax

      10:06

    • 29.

      4-1 Contenidos

      6:58

    • 30.

      4 a 2 habitaciones

      8:29

    • 31.

      4-3 Parallax

      10:06

    • 32.

      4-4 Transición

      7:38

    • 33.

      4-5 ventana gráfica

      7:05

    • 34.

      4-6 Visibilidad

      7:49

    • 35.

      Mapa 4-7

      7:46

    • 36.

      HUD 5-1

      9:38

    • 37.

      Calibre 5-2

      10:27

    • 38.

      5-3 Icono

      8:00

    • 39.

      Contador de 5-4

      8:40

    • 40.

      Caja de 5 a 5 heridos

      10:57

    • 41.

      5-6 Datos

      6:10

    • 42.

      Archivos de 5 a 7

      8:27

    • 43.

      6-1 doble salto

      10:37

    • 44.

      6-2 Diapositiva de pared

      10:16

    • 45.

      6-3 Salto de pared

      10:28

    • 46.

      6-4 Guiones

      10:45

    • 47.

      6-5 horas de enfriamiento

      11:34

    • 48.

      6-6 sombreros

      13:32

    • 49.

      6-7 Proyectil

      18:21

    • 50.

      Ritmo 7-1

      12:03

    • 51.

      7-2 paredes invisibles

      6:41

    • 52.

      7-3 Detección de bordes

      9:24

    • 53.

      7-4 Vuelo

      11:48

    • 54.

      Arrastrar de 7 a 5

      14:44

    • 55.

      Vista de 7-6

      12:48

    • 56.

      7-7 Agresión

      14:25

    • 57.

      Combinación 8-1

      12:21

    • 58.

      8-2 hits

      11:35

    • 59.

      8-3 jugos

      12:51

    • 60.

      8-4 Agitar

      7:39

    • 61.

      8-5 Muerte

      13:28

    • 62.

      8-6 Director 1

      15:37

    • 63.

      8-7 Jefe 2

      10:13

    • 64.

      8-8 Jefe 3

      13:48

    • 65.

      9-1 Punto de ahorro

      11:55

    • 66.

      9-2 Metroidvania

      10:45

    • 67.

      9-3 Atajo

      13:19

    • 68.

      Mapa de 9-4

      11:19

    • 69.

      Música de 9-5

      8:14

    • 70.

      Jefe final de 9 a 6

      9:54

    • 71.

      9-7 final

      5:42

  • --
  • Nivel principiante
  • Nivel intermedio
  • Nivel avanzado
  • Todos los niveles

Generado por la comunidad

El nivel se determina según la opinión de la mayoría de los estudiantes que han dejado reseñas en esta clase. La recomendación del profesor o de la profesora se muestra hasta que se recopilen al menos 5 reseñas de estudiantes.

6

Estudiantes

--

Proyectos

Acerca de esta clase

Aprende a crear un juego de Metroidvania en Godot desde cero.  Dales a tus jugadores habilidades desbloqueables que puedan utilizar para acceder gradualmente y explorar más del mundo de tu juego, un mapa que muestre su ubicación y guarda puntos para hacer un seguimiento de su progreso.

En este curso, aprenderás a:
Usar el motor de juegos Godot para crear juegos
Escribir guiones en GDScript
Principios de diseño de programación orientada a objetos
Descompone un proyecto complejo en componentes individuales

Construir un juego completo de metroidvania por tu cuenta puede parecer una tarea desalentadora, pero este curso te enseñará a dividirlo en piezas pequeñas que son mucho más fáciles de manejar, al mismo tiempo que te enseñará la estructura de diseño que une todas las piezas.

Este curso es para estudiantes de todos los niveles.
Si eres principiante, te recomiendo que sigas el curso exactamente como se muestra.  Cada línea de código será escrita en pantalla y se demostrará cada paso del proceso.
Los estudiantes de nivel intermedio pueden probar a usar otros recursos o adaptar parte de la mecánica del juego para darle su propio toque a lo que se proporciona.
Los estudiantes avanzados deben poder usar sus propios recursos para diseñar y construir su propio juego de Metroidvania utilizando este proyecto, una plantilla para estructura e inspiración generales.

Todos los recursos creativos utilizados en los videos se proporcionarán para que puedas seguirlos, pero puedes usar otros recursos creativos o hacer los tuyos propios si lo prefieres.

Conoce a tu profesor(a)

Teacher Profile Image

Thomas Yanuziello

Indie Game Developer

Profesor(a)

Habilidades relacionadas

Desarrollo Más Desarrollo
Level: All Levels

Valoración de la clase

¿Se cumplieron las expectativas?
    ¡Superadas!
  • 0%
  • Sí
  • 0%
  • Un poco
  • 0%
  • No realmente
  • 0%

¿Por qué unirse a Skillshare?

Mira las galardonadas Skillshare Originals

Cada clase tiene lecciones cortas y proyectos prácticos

Tu membresía apoya a los profesores de Skillshare

Aprende desde cualquier lugar

Ve clases sobre la marcha con la aplicación de Skillshare. Progresa en línea o descarga las clases para verlas en el avión, el metro o donde sea que aprendas mejor.

Transcripciones

1. Avance 0-0: Bienvenido a mi curso sobre cómo construir ametroivnia en el motor de juego Gadot Mi nombre es Thomas Ionizlo y seré tu instructor. Tengo una licenciatura en informática y llevo más de cinco años enseñando el desarrollo de juegos a través de múltiples plataformas. He incluido un conjunto completo de activos, incluyendo sprites, efectos de sonido y música que puedes usar para seguir o puedes usar tus propios activos si lo prefieres Este curso te ayudará a familiarizarte con el motor GdoGame Es un flujo de trabajo muy eficiente para crear juegos y su lenguaje nativo de scripting script GD Aprenderás a construir y editar escenas usando los diversos nodos de Gado y alterar su comportamiento con scripts. Mientras escribes estos scripts, aprenderás a aplicar principios de programación orientados a objetos para mantener tu código conciso, escalable y reutilizable para otros proyectos. Lo más importante es que aprenderás a estructurar un proyecto complejo de esta magnitud dividiéndolo en sus componentes individuales. Comenzaremos construyendo y animando un personaje de plataformas de dos D. Luego construye un entorno para que el personaje explore y mueva la cámara del juego. A continuación, permitiremos que el personaje haga la transición entre diferentes salas y dibuje el mundo en un mapa para ayudar al jugador a explorar tu mundo. Después de guardar y cargar el progreso del jugador, dibujaremos una pantalla frontal. Luego agrega nuestras habilidades desbloqueables, incluyendo un doble salto, un salto de pared, un guión y disparar un Por último, agregaremos algunos enemigos para el combate, una pelea de jefes y haremos un seguimiento del progreso del jugador a lo largo del juego. Ya sea que seas nuevo en el desarrollo de juegos, nuevo en el motor de juego Gadot o simplemente nuevo en Metroid venias, este curso te enseñará todo lo que necesitas saber para construir un juego completo desde cero Si necesitas ayuda, nuestro servidor de discordia está lleno de otros estudiantes y desarrolladores de juegos en ciernes que pueden responder a cualquiera de tus Haz clic en el enlace de mi perfil para unirte. Puedes previsualizar las dos primeras secciones del curso de forma gratuita, y tengo otro curso que cubre los conceptos básicos de la programación de GD Script completamente gratis, también. Una vez que estés listo, podemos empezar a aprender a construir una metrovnia en 2. 0-1 Descarga: Hola amigos. Para poder seguir este curso necesitarás el motor Godot Abre cualquier navegador web y dirígete a godot.org y descarga la última versión, que a partir de la grabación de este video es 4.5 0.1 El motor es de uso gratuito, pero opcionalmente puedes optar donar para apoyar el desarrollo si quieres. Una vez completada la descarga, deberás extraer los archivos de la carpeta con cremallera luego almacenarlos en un lugar seguro de tu computadora Para ejecutar el editor, todo lo que tienes que hacer es ejecutar el archivo más grande que no termina en la consola. No hay instaladores ni lanzadores de los que preocuparse. La primera vez que abras Godot, tu lista de proyectos estará vacía, y te preguntará si quieres explorar algunos de los proyectos de ejemplo que están disponibles Vamos a ignorar esto y crear nuestro primer proyecto, que abre una nueva ventana. Aquí podemos decidir dónde guardar el proyecto. La ubicación predeterminada está en la carpeta de documentos, pero es una buena idea crear una subcarpeta separada para contener tus proyectos de Godot A continuación, podemos darle un nombre a nuestro proyecto. No te preocupes por esto demasiado ahora mismo. Siempre puedes cambiarlo después. También se creará una nueva subcarpeta con el mismo nombre para contener todos los archivos relacionados con este proyecto pueden seleccionar tres renderizadores diferentes, cada uno optimizado para diferentes propósitos Te recomiendo comenzar todos tus proyectos usando el renderizador de compatibilidad para comenzar ya que es lo mejor para compilaciones web y solo cambiar tu renderer más tarde si necesitas un mejor soporte para efectos visuales de mejor calidad control de versiones con Gi Hub se admite automáticamente y recomiendo encarecidamente aprender a usarlo. Al crear este proyecto, se abrirá automáticamente para que podamos editarlo. Aunque voy a cerrar el editor y volver a abrirlo. Nuestro proyecto ahora está incluido en la lista de proyectos, y podemos abrirlo haciendo doble clic sobre él o seleccionándolo de la lista y haciendo clic en el botón Editar. Ahora tenemos acceso al Godot y podemos comenzar a editar nuestro primer proyecto En el siguiente video, exploraremos el diseño de la ventana del editor. Te veré en el siguiente video. 3. Editor 0-2: Hola, amigos. Antes de comenzar a editar nuestro proyecto, tendremos que familiarizarnos con el diseño de la ventana Godot Editor La mayor parte de la ventana se llena con una vista en tres D de la escena actual. Este proyecto será en dos D, no tres D. Podemos cambiar la vista entre tres D y dos D usando los botones en la parte superior de la ventana. En dos D, tenemos el eje X dibujado en rojo, el eje Y dibujado en verde, y un rectángulo azul que muestra la ventana gráfica, o lo que realmente se dibujará en pantalla al ejecutar el juego Tenga en cuenta que la ventana gráfica está por debajo del eje X con Y es igual a cero representando la parte superior de la pantalla El eje Y está invertido, por lo que los valores positivos para Y se moverán hacia abajo en el eje Y, no hacia arriba. En la parte superior izquierda, tenemos una pestaña para la estructura de la escena actual, que actualmente está vacía y nos pide crear un nodo raíz para esta escena. Ya que nuestro juego será dos D, hagamos una escena de dos D. La pestaña de escenas ahora muestra nuestro nodo raíz de escenas, un nodo dos D. Exploraremos más sobre escenas y nodos en el siguiente video. Este dock también contiene la pestaña Importar, que nos permitirá cambiar la configuración de importación para los archivos importados que usaremos en nuestro proyecto como gráficos y audio. Estos archivos se almacenarán y organizarán dentro del sistema de archivos del proyecto, que podemos ver en la parte inferior izquierda. Actualmente, nuestro proyecto solo tiene un archivo en él, que es el ícono de Gadot En la pestaña del sistema de archivos, podemos mantener nuestros archivos de proyecto organizados creando carpetas y buscando a través de ellas usando el filtro. Volviendo a la pestaña de escena, si tenemos una nota seleccionada, entonces sus propiedades se presentarán en la pestaña Inspector de la derecha. Podemos ampliar las categorías de estas propiedades y editar sus valores aquí. Este dock también contiene la pestaña nodo, que proporciona una lista de señales que este nodo puede emitir, así como de qué grupos forma parte. La pestaña de historial contiene una lista de todos los cambios que hemos realizado dentro de la escena actual o para todo el proyecto. Puedes ver todos los cambios que hicimos, además también edité el Editor Fontie El muelle inferior está actualmente colapsado, pero podemos hacer clic en el botón de salida para expandirlo. La salida también nos mostrará los cambios que hagamos el proyecto y también mostrará la salida de texto de nuestro juego, lo cual es muy útil para depurar Podemos generar mensajes manualmente aquí, pero el editor también emitirá advertencias y errores aquí también. El depurador tiene una variedad de herramientas útiles para ayudarnos a descubrir qué es lo que está ralentizando o estrellando También hay pestañas específicamente para audio, animación, shaders y aquí se agregarán más pestañas a medida que sean necesarias Podemos contraer este muelle haciendo clic en la pestaña seleccionada actualmente. Al hacer clic en los tres puntos, estos muelles se pueden reorganizar para adaptarse a sus necesidades, sin embargo, cree que funcionará mejor para adaptarse a su flujo de trabajo para adaptarse a su Las pestañas individuales también se pueden arrastrar entre documentos. Cuando encuentre un diseño que funcione bien para usted, puede guardarlo desde el menú del editor. También puede cambiar una variedad de configuraciones del editor para personalizar el editor para que se ajuste a sus necesidades. Cuando finalmente tenemos un juego que ejecutar, podemos hacerlo desde los botones de la esquina superior derecha. Ya sea jugando el juego desde el principio o solo corriendo la escena actual, pausa o deteniendo el juego En el siguiente video, aprenderemos a construir una escena. Te veré en el siguiente video. 4. 0-3 escenas: Hola, amigos. Ahora que estamos familiarizados con el layout del editor, comencemos a editar nuestra primera escena. Comenzaremos haciendo clic en dos escenas D, haciendo del nodo raíz de nuestra escena un nodo dos D. Un nodo dos D en realidad no representa nada en nuestro juego. Es sólo una transformación bidimensional. Una transformación es una combinación de una posición, rotación y escala. Godot también incluye un componente sesgado en dos transformaciones D. Si realmente queremos dibujar algo, necesitaremos agregar otro nodo a nuestra escena. Ya sea haciendo clic derecho en el nodo raíz y seleccionando Agregar hijo o haciendo clic en el botón Más, podemos agregar un nodo hijo a nuestra escena. Hay muchos tipos diferentes de nodos que sirven para diferentes propósitos. La forma más común de dibujar algo en dos juegos D es usar un sprite Entonces agregaremos un nodo Sprite dos D a nuestra escena. Los tipos de nodo heredan de otros tipos de nodos. Entonces un nodo sprite dos D también es un nodo dos D y un elemento canvas, y un nodo básico, y tiene todas las mismas propiedades heredadas de estos tipos, además de algunas más propias El nodo D de Sprite dos se agrega como hijo del nodo raíz, indicado por la sangría Las escenas se organizan en una jerarquía, comenzando con un nodo raíz singular luego ramificándose en cualquier número de nodos secundarios Estos nodos secundarios también pueden tener sus propios nodos secundarios que forman el árbol de escenas. Podemos colapsar ramas del árbol o todo el árbol haciendo clic en la flecha al lado de ellas, y nuevamente para expandirlas. El nodo sprite todavía no está dibujando nada porque no se le ha dicho qué dibujar Seleccionándolo, para que podamos ver sus propiedades en el inspector, donde efectivamente tiene propiedades heredadas del nodo, elemento Canvas, y nodo D. Bajo la sección Sprite two D, también tiene una propiedad texture, que actualmente está vacía Podemos cargar un archivo de textura o arrastrar el icono GAD desde la pestaña del sistema de archivos al campo de textura para poblarlo Y ahora el nodo Sprite dos D está dibujando la textura del icono de GADO como un sprite en nuestro juego Duplicemos este nodo Sprite dos D en el árbol de escenas haciendo clic derecho y seleccionando duplicar o seleccionando el nodo y presionando Control o Comando D. El duplicado tiene todas las mismas propiedades que el nodo original y se renombra agregando un número creciente a su hermanos en el árbol de escena no se les permite tener el mismo nombre. Podemos mover cualquiera de nuestros sprites en la vista de escena simplemente arrastrándolos. Esto actualizará automáticamente su propiedad transformada de dos posiciones D en el inspector. También podemos rotar el sprite, escalarlo y sesgarlo si queremos A continuación, arrastremos este nodo Sprite Tu Di al otro, asignándolo para que sea un nodo hijo del otro nodo Sprite Tu Di, indicado por otro nivel Ahora, si seleccionamos el nodo padre Sprite tu Di y editamos sus propiedades de transformación, estos cambios son heredados por el hijo Las propiedades de transformación propias del hijo se definen en relación con la del padre. Esta estructura jerárquica de escenas y herencia de propiedades nos permite construir escenas complejas con múltiples componentes diferentes Podemos agregar cualquier número de nodos diferentes a la escena de diferentes tipos, como un reproductor de flujo de audio dos nodos D, y una partícula GPU dos nodos D. Ahora bien, esta escena de dos D puede dibujar algo, emitir sonidos y partículas, y todos estos componentes heredarán a su posición de transformación desde el nodo raíz Para facilitar las cosas, la transformación de un nodo raíz siempre debe tener todos los valores predeterminados y tener solo nodos hijos con sus transformaciones editadas. Podemos renombrar nodos, lo que resulta particularmente útil para el nodo raíz de una escena describa lo que es. Vamos a llamarlo algo así como robot. Entonces podremos guardar esta escena como un archivo de escena en nuestro proyecto, y automáticamente se llamará igual que el nodo raíz. Entonces crea una nueva escena de dos D e imagina esto para representar una habitación que contiene al robot. Nuestra escena de robot se puede agregar a la escena como un solo nodo. Incluso podemos tener múltiples robots si queremos. Desde el contexto de esta escena más grande, ahora podemos editar las propiedades de transformación de un robot para moverlo, rotar, escalar, sesgar, etcétera Cambiemos el nombre de esta escena Room y guárdala. Si volvemos a la escena del robot y editamos los nodos hijos del robot, estos cambios se aplicarán a todas las instancias del robot en otras escenas. La escena de la habitación no necesita preocuparse por cómo se construye el robot, solo donde está dentro de la habitación. Construir escenas a partir de componentes individuales nos permite mantener los detalles de objetos individuales contenidos y ocultos lejos de alcances más grandes También nos permite producir fácilmente múltiples copias de la misma cosa, pero con una sola fuente para ese objeto que necesita ser editado. Construir un juego completo consistirá en construir muchas escenas más pequeñas que representen objetos individuales del juego, personajes y ubicaciones, y luego combinar múltiples de estas escenas para crear una escena más grande mientras el juego se ejecuta. En el siguiente video, exploraremos cómo el motor proporciona útiles tipos de nodos integrados para simular la física Te veré en el siguiente video. 5. 0-4 Física: Hola, amigos. Ahora que entendemos cómo se construyen las escenas, repasaremos cómo los motores de juego proporcionan una funcionalidad integrada para facilitar mucho el desarrollo de juegos. Podemos deshacernos de los robots y eliminar esa escena del proyecto. Empecemos por agregar un cuerpo rígido a nuestra escena. En el contexto de la física, un cuerpo es cualquier objeto que pueda chocar con otros objetos y que tenga masa Un cuerpo rígido representa un objeto sólido. Se verá afectada por fuerzas externas como la gravedad, colisionará con otros objetos sólidos, pero no se deformará ni se Mantendrá su forma. Este cuerpo rígido necesita una forma, que es otro nodo que debe agregarse como hijo directo del cuerpo rígido. Este nodo de forma no sabe qué forma es hasta que le damos un recurso de forma en el inspector. Desde el menú desplegable, podemos seleccionar algunas opciones diferentes. Voy a hacer una forma de rectángulo. Ahora este cuerpo rígido tiene forma, pero en realidad no se está dibujando nada. Entonces le agregaremos un nodo Sprite two D y haremos que dibuje la textura del icono de Godot El sprite y la forma de colisión no coinciden. Entonces seleccionando el nodo de forma de colisión, podemos ajustarlo para que se ajuste mejor al sprite haciendo clic y arrastrando los puntos rojos o editando sus propiedades en el inspector Al mantener presionada la tecla Alt con el nodo de cuerpo rígido seleccionado, colocémoslo para que esté en algún lugar alrededor de la mitad superior de la pantalla. Luego presione el botón Ejecutar escena actual o presione F six como atajo. El motor del juego aplica automáticamente fuerzas al cuerpo rígido para simular física del mundo real como la gravedad. La escala de masa y gravedad se puede ajustar rápidamente en el inspector para ajustar el comportamiento del cuerpo rígido Incluso podemos darle un material físico para agregar fricción o rebote, ajustarlo al centro de masa y muchas otras opciones. Por ahora, hagamos que esta sencilla caja choque con un piso. Los objetos muy robustos que no queremos mover generalmente se construyen a partir de un cuerpo estático en lugar de un cuerpo rígido. Un cuerpo estático aún puede chocar con otros cuerpos, pero no se moverá como resultado de esa colisión y no se verá afectado por fuerzas como la gravedad Un cuerpo estático también necesita una forma de colisión. Desde el menú desplegable, seleccionaré el límite mundial. A diferencia de otras formas, un límite mundial se extiende hasta el infinito. En dos D, esto se representa como una línea. La flecha en las dos vistas D apunta lejos del límite. Por defecto, creará un piso. Mover la posición del nodo de cuerpo estático hacia abajo hasta la parte inferior de la ventana gráfica impedirá que el cuerpo rígido caiga más allá de este límite mundial Duplicemos el cuerpo rígido y veamos cómo se comporta al chocar con otro Podemos hacer click en un nodo y cambiar su tipo. Entonces cambiemos este cuerpo rígido en un cuerpo estático. Después, colóquelo y gírelo para que el cuerpo rígido choque con él en el aire. Recuerda cambiar el nombre de los nodos después cambiar su tipo para que sepas de qué tipo son. Pero también se puede decir por el icono al lado de su nombre, también. Si tuviéramos que programar manualmente todo esto nosotros mismos, tomaría mucho trabajo dibujar estos sprites, calcular cómo se ven afectados por las fuerzas, averiguar cuándo chocan entre sí y determinar cómo eso afecta su comportamiento Junto con la física, los motores de juego nos ayudan automatizando gran parte de la funcionalidad común en la mayoría de los juegos para acelerar drásticamente y simplificar En el siguiente video, aprenderemos a adjuntar scripts a los nodos para editar su comportamiento. Te veré en el siguiente video. 6. De 0 a 5 guiones: Hola, amigos. Si bien el motor del juego nos brinda mucha funcionalidad incorporada , también podemos agregar la nuestra propia adjuntando scripts a los nodos. Seleccionando cualquier nodo en el árbol de escenas, usaré el cuerpo estático que es una caja flotante. Podemos hacer clic con el botón derecho y seleccionar script adjunto o presionar el botón del script adjunto. Esto abre una nueva ventana. El script heredará automáticamente del tipo de nodo al que se está adjuntando, y podremos iniciar nuestro script desde una plantilla si queremos También especificaremos un nombre para el guión, que debe reflejar su propósito. Voy a nombrar mi script spin, así como la carpeta en la que está guardado. Al hacer clic en el botón Crear se cambiará automáticamente la vista a la vista de script, para que podamos comenzar a editar el script. La plantilla nos inicia con dos funciones, listo y proceso. Cualquier texto que siga al símbolo de Octothorp es un comentario. No es utilizado por el motor y sólo existe para nuestro beneficio para ayudarnos a entender mejor el guión. Como describen estos comentarios, la función ready se llamará automáticamente cuando este nodo ingrese al árbol de escenas por primera vez, lo que es un poco engañoso. Pero por ahora, significará cuando empiece el juego por primera vez. Proceso, por otro lado, se llamará a cada fotograma mientras se esté ejecutando el juego, que con la configuración predeterminada del proyecto será de 60 veces por segundo. Una declaración de función comienza con la palabra clave funk, seguida del nombre de la función Estos nombres de funciones comienzan con un guión bajo, que es la forma en que Gudo marca las funciones como privadas, lo que significa que solo están destinadas a ser utilizadas dentro del contexto de este script El nombre de la función va seguido de paréntesis, cuales contendrán parámetros para la función si los hay La función de proceso tiene un parámetro, Delta, que es el número de segundos que han pasado desde el fotograma anterior. Por lo que esta mayoría de las veces será una 60ª, pero a veces aumentará si procesar un fotograma lleva más tiempo de lo esperado los parámetros le sigue un guión mayor que una flecha, luego el tipo de retorno de la función, que en ambos casos son nulos, lo que significa que no devuelven ningún valor Declarar los tipos de devolución es opcional, y estos se pueden eliminar si lo prefiere El contenido de una función tiene sangría en una pestaña, sin necesidad de llaves Ambas funciones contienen solo la palabra clave pass, lo que básicamente significa no hacer nada. Pero podemos sustituir esta instrucción por algo diferente. Para ver cómo funciona esto, cambiemos el cuerpo de la función ready para hacer algo. La función print emitirá todo lo que queramos al panel de salida cuando se ejecute el juego. Podemos llamar a funciones especificando su nombre seguido de paréntesis Luego dentro de los paréntesis, podemos proporcionar argumentos coincidan con las funciones declaradas parámetros Dentro de comillas, podemos escribir lo que queramos, como listo para girar. Todo lo que ponemos entre comillas se conoce como cadena, abreviatura de cadena de caracteres. En la función de proceso, hagamos lo mismo, pero esta vez, imprima el valor de Delta. También hagamos lo que se pretendía hacer este script y modifiquemos el valor de esta rotación de nodos, aumentándola por Delta usando el operador más iguales. El operador plus equals tomará el valor de Delta y lo sumará al valor de rotación. Después asigne también el resultado a la rotación. Corriendo la escena, podemos ver que la caja está dando vueltas. Deteniendo el juego, podemos ver en la salida que el mensaje listo se imprimió primero, solo una vez, seguido de muchos números, la mayoría de los cuales son uno 60. ¿Cómo funciona esto? Tanto ready como process son funciones de nodo, es decir, cada nodo nuestro árbol de escenas ya tiene estas funciones, pero no están haciendo nada. Nuestro script está anulando las definiciones de estas funciones para un nodo en particular al que se adjunta este script Podemos ver en nuestro script cuando una función está anulando una definición de función cuando tiene una flecha azul delante de ella Cuando ejecutemos el juego, el motor reconstruirá el árbol de escenas para esta escena, comenzando desde la raíz, agregando un nodo a la vez de arriba a abajo La función ready para cada nodo se llamará después de que se agregue al árbol de escenas, pero también después de que se hayan agregado todos sus hijos y sus funciones ready hayan sido llamadas primero. Esto significa que los padres pueden confiar en que sus hijos sean agregados al árbol de escena antes de que se los considere listos. Después de que todo el árbol de escenas esté listo, entonces comenzarán los fotogramas del proceso. El proceso se llamará en cada nodo del árbol de escena de arriba a abajo en orden secuencial. A diferencia de ready, los padres no dejarán que sus hijos procesen primero. Ahora que tenemos una comprensión básica de cómo funciona Godot, en el siguiente video, comenzaremos configurar el proyecto para hacer nuestro juego Te veré en el siguiente video. 7. Juego 0-6: Hola, amigos. Antes de comenzar nuestro proyecto de juego, tendremos que preparar algunas cosas. Primero, podemos eliminar todo o iniciar un nuevo proyecto para que tengamos un borrón y cuenta nueva. Voy a quitar todo excepto la colisión de piso. Después renombrar esta escena y su nodo raíz a juego. La escena del juego será una escena centralizada donde se lleva a cabo toda la jugabilidad principal. El nodo raíz del juego tendrá dos ramas hijas principales, un nodo de entorno mundial y un nodo de capa de lienzo. Estos representan una clara distinción entre lo que existe en el mundo del juego, como el nivel en el que el jugador está jugando actualmente, todos los elementos de los personajes, etcétera, y lo que existe fuera de ese mundo puramente para beneficio del jugador, información que se muestra en una pantalla frontal o interfaz de usuario El nodo de Medio Ambiente mundial tendrá varios hijos. Uno o más nodos para los niveles actuales que se cargan, por ahora solo vamos a representar eso como un tutti de cuerpo estático Un nodo tutti de cuerpo de personaje se usa con mayor frecuencia para el personaje del jugador y un nodo Tutti de cámara que suele seguir al jugador Voy a restablecer la posición de la colisión de piso de nuevo al origen de la escena. Con un nodo de cámara en la escena, el rectángulo azul ya no representa qué parte del mundo se dibuja en pantalla, en cambio, el puerto de visión de la cámara se muestra en Magenta, actualmente centrado en el origen. Por lo que el piso estará en el centro de la vista de esta cámara. La capa de lienzo tendrá hijos para cosas como mostrar la información del jugador en pantalla, menús, etcétera Todos estos estarán representados con nodos de control. Los nodos Canvas y control seguirán utilizando el rectángulo azul como ventana gráfica para organizar sus posiciones en la pantalla Cómo funciona esto mientras el jugador está jugando el juego es que la cámara verá el mundo y dibujará lo que ve, todos los hijos del mundo Environment Node. Después de que la cámara haya renderizado una imagen rectangular de Toti del mundo, la capa Canvas dibujará a sus hijos por encima de eso, creando la típica pantalla de juego que estamos acostumbrados a ver Estas dos ramas también comparten otra clara distinción. Habrá que pausar al mundo, pero la capa del lienzo no lo hará Por lo que seleccionar el nodo de juego en el inspector bajo nodo, proceso de expansión, cambiará su modo de proceso a siempre. El nodo de entorno mundial se establecerá pausble y la capa Canvas permanecerá como la herencia predeterminada Heredará el modo de proceso de su padre, que es el nodo de juego, por lo que también lo será siempre Dado que el modo de proceso predeterminado es heredar, todos los hijos del entorno mundial heredarán siendo pasibles mientras que los hijos de la capa Canvas heredarán siempre el La primera vez que presionemos el botón Ejecutar proyecto en cualquier proyecto nuevo, nos pedirá que fijemos la escena principal. Podemos seleccionar la escena actual o seleccionar otra del proyecto. Con la escena del juego actualmente abierta, podemos configurarla como la escena principal por ahora y cambiarla después cuando tengamos una escena de título. Esto se puede cambiar en la configuración del proyecto bajo la configuración de ejecución. También es una buena idea establecer la configuración de su pantalla antes de comenzar. Así que selecciona ventana. Aquí podemos establecer el ancho y alto de la ventana gráfica medidos en píxeles Encuentro 12 80 por 720 para ser de buen tamaño para la mayoría de los juegos, y es compatible con la mayoría de las plataformas. Bajo stretch, cambiar el modo de estiramiento de elementos desactivados a Canvas asegurará que dos nodos D se estiren o encojan para que se ajusten a la ventana del juego. Como voy a estar usando pixel art, voy a cambiar el modo de escala de fraccionario a entero Por lo que los píxeles solo duplicarán o la mitad de tamaño, evitando píxeles de tamaño mixto. Bajo texturas de renderizado, también cambiaré el filtro de textura predeterminado de lineal a más cercano. Esto dibujará mis activos de pixel art exactamente como están, evitando que sean borrosos Después de cerrar la configuración del proyecto, es posible que deba activar una actualización simplemente haciendo zoom o panoramizando la ventana gráfica para forzar que el rectángulo azul de la ventana gráfica o la cámara se redimensionen o la cámara Ahora estamos listos para comenzar a dividir el proyecto en sus componentes individuales y abordarlos uno a la vez. En la siguiente sección, crearemos un personaje básico de plataformas Tutti que el jugador pueda controlar Te veré en el siguiente video. 8. 1-1 Cuerpo del personaje: Hola, amigos. En esta sección, vamos a construir un personaje de plataformas de dos D que el jugador pueda controlar Si tu escena de juego no tiene ya un cuerpo de personaje dos Dnode, deberías agregar uno ahora El cuerpo del personaje dos D no es un cuerpo en el sentido de una persona, sino un cuerpo físico, como el cuerpo rígido o el cuerpo estático. A diferencia de los cuerpos rígidos, un cuerpo de personaje no tiene automáticamente la gravedad aplicada a él sino que reaccionará ante colisiones, a diferencia de un cuerpo estático Entonces el nodo del cuerpo del personaje también necesita una forma de colisión como hijo de él con un recurso de forma para decirle qué forma es. La mayoría de los juegos usan una cápsula para representar a un personaje, pero también se usan rectángulos y círculos Por ahora, usaré un rectángulo con dimensiones de 128 por 128. Siempre podemos cambiar o cambiar el tamaño a la forma de colisión después de tener un dibujo del personaje para basarlo más tarde Además de una forma de colisión, también necesitaremos un nodo de sprite para dibujar el personaje Es importante no usar un nodo Sprite Animado ya que este no es su propósito previsto Los nodos Sprite animados son solo para dibujar sprites animados simples Tan pronto como tengas que sincronizar cualquier otro nodo con tus animaciones como sonidos, partículas o funciones, necesitarás más flexibilidad de la que el nodo Animated Sprite puede proporcionar Por ahora, solo usaré el icono de Godot como textura del personaje, que es de 128 por 128 Pixel cuadrado que coincide con la forma de colisión Cambiemos el nombre del nodo Toti del cuerpo del personaje al nombre del personaje Si bien es posible que no tengamos ninguna intención de tener múltiples copias de este personaje, sigue siendo una buena idea componer su estructura en una escena separada, aislada de la escena del juego. Podemos lograr esto haciendo clic derecho en el nodo, luego seleccionando guardar rama como escena. Vamos a crear una nueva subcarpeta para escenas, otra dentro de esa para personajes, luego guardarla como nombre de este personaje En la escena del juego, este personaje ahora se representa como un solo nodo con un icono de tablilla, diciéndonos que se trata Todos sus nodos hijos están ocultos, ahora contenidos dentro de la escena del personaje. Podemos abrir la escena del personaje haciendo clic en el icono de la tablilla. En la escena del personaje, es una buena práctica considerar el origen del personaje está en el punto central entre el punto central entre sus pies como si el eje X fuera el piso. Esto asegura que todos los caracteres tendrán su punto de origen en común independientemente de su tamaño. Así que vamos a mover los nodos Sprite y la forma de colisión hacia arriba a lo largo del eje Y. Además de la forma de colisión y los nodos Sprite, nuestro personaje necesitará un jugador de animación para reproducir las animaciones de Sprite También un Árbol de Animación para controlar qué animación se está reproduciendo en un momento dado. Un reproductor de flujo de audio dos nodos D nos permitirá reproducir efectos de sonido también. También podemos querer un emisor de partículas GPU para crear efectos de partículas para cosas como pasos y saltos Cada uno de estos nodos será cubierto en su propio video para explicarlos con más detalle. Por ahora, es importante entender cómo una escena puede representar cualquier cosa en el juego con su propia escena teniendo muchos nodos hijos que se utilizan para construirla. El nodo raíz de esta escena suele tener un script adjunto al mismo. Dependiendo de cómo prefiera organizar sus archivos, posible que desee mantener este script en la misma carpeta que la escena a la que se adjunta o en una carpeta separada específicamente para los scripts. Debe nombrar sus guiones después de su propósito previsto en un nombre lo más vago posible Este guión no será específico para mi personaje infantil, sino que debería escribirse de tal manera que pueda aplicarse a cualquier personaje, al menos por ahora El propósito del script será no solo controlar el propio nodo del cuerpo del personaje, sino también realizar las operaciones de todos los nodos hijos para operar en armonía según sea necesario para crear nuestro personaje. Este guión adjunto al nodo raíz de nuestra escena de personajes también es accesible desde la escena del juego y servirá para dos propósitos adicionales. Se ofuscará el procesamiento de los componentes individuales de la escena del personaje a la vez que proporciona una interfaz limpia y concisa para interacción con otros guiones y objetos en la escena del juego Esto se explorará con mayor detalle a lo largo del resto de esta sección. Ahora que tenemos lista una estructura básica de personajes, necesitaremos recibir aportes del jugador para controlarlos. Te veré en el siguiente video. 9. Mapa de entrada 1-2: Hola, amigos. En este video, vamos a recibir entrada del jugador y enviársela al personaje. Desde que creé el script para mi cuerpo de personaje Tu Di node a partir de una plantilla, ya tiene algún código que recibirá entrada y moverá el carácter hacia la izquierda o hacia la derecha. Si ejecutamos la escena del juego, al presionar las teclas de flecha izquierda y derecha se moverá al personaje, pero no se siente muy bien y no se implementa muy bien. El comentario proporcionado incluso nos dice que al menos deberíamos reemplazar acciones izquierda y derecha de la interfaz con nuestras propias acciones de juego personalizadas. Para ello, abriremos la configuración del proyecto, luego cambiaremos a la pestaña Mapa de entrada. En el campo que dice agregar nueva acción, vamos a escribir el nombre de nuestra acción, empezando por mover a la izquierda. Esto no debe contener ningún espacio y generalmente se escribe en minúsculas serpiente, todas minúsculas separadas con Presiona la tecla Enter o haz clic en el botón Agregar para agregar la acción de entrada, luego haz otra para moverte a la derecha. Y también necesitaremos uno para Jump más adelante. A la derecha de cada una de estas acciones, haga clic en el botón más para agregar un evento a esta acción de entrada. Este será el botón que se presiona para activarlo. El campo de escucha detectará automáticamente los eventos de entrada, o puede buscar a través de los eventos de entrada disponibles. Para moverme a la izquierda, usaré la tecla de flecha izquierda, moviéndome a la derecha con la tecla de flecha derecha, y saltar será la tecla z. Podemos agregar múltiples eventos diferentes a cada acción, lo que significa que podemos agregar soporte de controlador fácilmente agregando eventos adicionales para el controlador. Usaré pad direccional izquierda y derecha para mover al personaje, así como stick izquierdo a izquierda y derecha, y también el botón de la cara inferior para saltar. Cuando hayas terminado, cierra la configuración del proyecto. En este video, solo vamos a cambiar esta única línea donde estamos recuperando entrada, y lo más importante, moverla a un script separado Es una buena práctica que todos tus guiones tengan un solo propósito. Este guión solo se utilizará para controlar a un personaje, no para recibir entrada del jugador. Añadiendo un nuevo nodo al árbol de escenas, éste puede ser simplemente un nodo normal ya que no va a estar haciendo otra cosa que ejecutar nuestro script. Vamos a llamarlo Jugador. Después adjuntarle un nuevo guión. Hay múltiples formas de recibir entrada. El más común es anular la función de entrada. Las anulaciones de función deben coincidir exactamente con la función que se está anulando Entonces el nombre debe tener exactamente la misma ortografía, los mismos tipos de parámetros y el mismo tipo de retorno. La función de entrada tiene un parámetro, un evento de entrada, al que podemos nombrar lo que queramos. Pero prefiero usar sus nombres predeterminados, y no devuelve nada. La función de entrada se llamará durante cualquier fotograma cuando ocurra algún evento de acción de entrada, ya sea presionar un botón, inclinar un stick analógico o mover el mouse Dentro de esta función de entrada, podemos acceder al evento input por su nombre y acceder a su contenido con un punto. Queremos llamar a una función del evento de entrada llamada Is action pressed. Al llamar a una función, el nombre de la función debe ir seguido de paréntesis Dentro de los paréntesis, proporcionamos argumentos a la función que coinciden con sus parámetros En este caso, una cadena, el nombre de la acción de entrada que estamos comprobando. Entonces escribiremos salto entre comillas, teniendo cuidado de hacer coincidir el caso exacto y ortografía de la acción de entrada que creamos en la configuración del proyecto. Esta función devuelve un booleano, ya sea true si se presionó el botón o false si no lo fue Al poner esta función después de la palabra clave if, luego seguida de dos puntos, podemos crear un nuevo nivel de sangría para nuestro script Cualquier cosa que pongamos aquí dentro solo se ejecutará si el resultado de la declaración I es verdadero, así que solo si se presionó el botón. Por ahora, solo imprimiremos la palabra salto. Ejecutando el juego, si presionamos alguno de los eventos de entrada que especificamos como la acción de entrada de salto, veremos que jump está impreso en el panel de salida. No necesitamos la función ready, así que vamos a eliminar eso. Para cosas como el movimiento, especialmente cuando se usan controladores con sticks analógicos, puede ser útil verificar esta entrada dentro de la función de proceso. Al igual que estaba haciendo el script de caracteres, necesitaremos usar el singleton de entrada Esta clase singleton tiene una función llamada get axis. La función del eje G requiere dos parámetros, una acción negativa y una acción positiva. La izquierda siempre se considera la negativa y la derecha positiva, coincidiendo con el eje X en nuestro mundo dos D. Entonces escribiremos los nombres de nuestras acciones de entrada que creamos en la configuración del proyecto entre comillas, moveremos a la izquierda y moveremos a la derecha. Esta función devolverá un número decimal entre uno negativo y uno positivo, representando hasta qué punto se inclina el stick izquierdo en cualquier dirección, o simplemente uno negativo o uno positivo si usa teclas o botones Dado que un valor de cero, lo que significa que no se está dando ninguna entrada, sigue siendo una entrada válida siempre vamos a querer enviar esta información al jugador cada cuadro. Entonces no hay necesidad de una declaración if aquí. Vamos a imprimir el valor que se devuelve aquí para que podamos verlo. ejecutar el juego, el número cero se está imprimiendo repetidamente. Presionando las teclas de flecha izquierda o derecha, las teclas del pad de dirección en mi controlador o inclinando el stick analógico izquierdo cambia el valor entre uno negativo y uno positivo Si alguna vez deseas más información sobre alguna de estas clases o funciones, puedes acceder a su documentación manteniendo pulsada la tecla de control o comando y haciendo clic en ellas. abrir el script de caracteres desde antes, tenemos una variable llamada direction que se declara dentro de la función de proceso. Comentemos esto y movamos esta variable al alcance global de nuestro script declarándolo en la parte superior del guión en su lugar Volviendo al guión del jugador donde recibimos entrada de movimiento para pasar esta información de un guión a otro, necesitaremos una referencia al otro guión. En el script del jugador, vamos a crear una variable que contiene una referencia a un cuerpo de personaje para dende Al agregar una etiqueta de exportación al frente de la declaración de la variable, la variable será accesible desde el inspector, y podemos asignar su valor como nuestro carácter. Entonces, en lugar de imprimir el valor del punto de entrada get axis, lo enviaremos al personaje asignándolo a la variable de dirección del personaje Cuando ejecutemos el juego, el nodo jugador estará comprobando cada fotograma para ver el estado de nuestras entradas de movimiento a la izquierda y a la derecha. Después asigne eso a la variable de dirección del personaje. La función de proceso de scripts de caracteres verificará la variable de dirección, cada fotograma y la usará para mover el carácter hacia la izquierda y hacia la derecha. Ahora tenemos a nuestro jugador dando entrada para mover a nuestro personaje. Te veré en el siguiente video. 10. Movimientos 1-3: Hola, amigos. En este video, vamos a mejorar el movimiento de los personajes aplicando la física. En el script de caracteres, podemos ver que la plantilla por defecto está comprobando si el valor de direction es cero. Cero se trata como falso y cualquier otro valor es verdadero. Entonces, si se le da algún valor de dirección que no sea cero, la velocidad X del personaje se establece en dirección multiplicada por la velocidad. O si la dirección es cero, entonces está moviendo el valor de la velocidad X del personaje hacia cero por velocidad. El resultado de esto es que la velocidad del personaje es cero o velocidad, excepto en el caso de inclinar el stick analógico Esto no es muy realista y no se siente muy bien. Estos valores de velocidad y velocidad de salto también se definen como constantes, que, a diferencia de las variables, nunca se les permite cambiar Esto es problemático, y deberíamos cambiarlo si alguna vez queremos que los personajes se muevan a diferentes velocidades en nuestro juego. Nos ocuparemos de saltar más tarde. Otra cosa a tener en cuenta es que estos valores se miden en píxeles, por lo que variarán en función del tamaño de tu personaje. Por ahora, reemplacemos nuestra constante de velocidad una variable de velocidad de movimiento de tipo flotador. Pondré el mío a 256 píxeles por segundo. Es una buena idea separar variables y funciones en lo que se pretende que sea público versus privado precediendo nombres privados con un guión bajo Cualquier cosa privada está pensada para que solo se pueda acceder desde dentro de este script en sí, a diferencia de la variable direction, que se está accediendo y cambiando desde el script del reproductor, por lo que es pública. En el proceso de física, reemplazaremos la constante de velocidad con nuestra variable de velocidad de movimiento. Y ahora todo funciona exactamente como lo hacía antes, excepto que la velocidad es un poco más lenta. Si agregamos una etiqueta de exportación al frente de esta declaración de variable, podremos cambiar el valor de la misma en el inspector. Esta es una excelente manera de probar y ajustar el valor para que se sienta bien Ya que podemos ejecutar nuestro juego, ver si se siente bien, luego cambiarlo y volver a probar. Otro beneficio es que si tenemos múltiples caracteres usando este mismo script, cada uno puede tener su propio valor para esta variable. Pero los personajes no suelen pasar de quedarse quietos a moverse a su máxima velocidad instantáneamente En cambio, tienen cierta cantidad de aceleración aplicada a lo largo del tiempo antes de alcanzar su velocidad máxima. Esto se puede lograr declarando otra variable llamada aceleración, también a flote y se medirá en píxeles por segundo al cuadrado Si lo hace más fácil, puedes considerar que su valor un múltiplo de tu velocidad. Si mi aceleración es el doble de mi velocidad, entonces alcanzaré la velocidad máxima en medio segundo. O si es la mitad de mi velocidad, entonces tardará 2 segundos en alcanzar la velocidad máxima. Para aplicar la aceleración en el proceso físico, todo lo que tenemos que hacer es mover el valor de nuestra velocidad X actual hacia la velocidad multiplicada por la dirección a una velocidad de aceleración. Pero esto sucederá de una vez en un solo fotograma. Para ajustar la velocidad a lo largo del tiempo, tenemos que hacer lo que la plantilla está haciendo aquí donde aplica gravedad y multiplicar por Delta. Dado que Delta es la cantidad de segundos que han pasado desde el fotograma anterior, generalmente uno 60 de segundo, esto provocará que la tasa de aceleración se aplique a lo largo del tiempo en lugar de todas a la vez El movimiento hacia la función toma lo que está en el primer parámetro, lo mueve hacia el valor del segundo parámetro por la cantidad del tercer parámetro y devuelve el resultado. No modifica el valor del primer parámetro, así que tenemos que asignarlo para sobrescribir el valor anterior de nuestra velocidad X. La función de movimiento y deslizamiento se define en el cuerpo del personaje dos clases D y realizará todos los cálculos difíciles para nosotros, considerando la velocidad del personaje, fuerzas externas como la gravedad, colisiones con otros cuerpos físicos, y luego decidir dónde debe estar el personaje cada fotograma Ejecutando el juego ahora, tenemos una aceleración gradual que se está aplicando antes de alcanzar nuestra velocidad máxima, y también podemos ajustar el valor de nuestra aceleración en el inspector para que se sienta de la manera que queremos. Podemos eliminar estos comentarios. La misma lógica se puede aplicar a la desaceleración simplemente agregando otra variable Este valor suele ser mucho mayor que la aceleración. El código en el proceso de física ya está utilizando mover hacia. Sólo tenemos que sustituir la velocidad por tiempos de desaceleración Delta Sin embargo, hay otro momento en el que es posible que queramos aplicar desaceleración que no sea cuando el jugador no está dando ninguna entrada, que es cuando quiere dar la vuelta e ir por el otro lado Podemos ampliar nuestra declaración I para considerar este caso. Después de verificar si la dirección no es cero, si nuestra velocidad X es cero, el personaje está parado, entonces todavía queremos acelerar. Pero también, si el pecado de dirección es el mismo que el seno de la velocidad X, entonces el jugador está tratando de seguir moviéndose en la misma dirección en la que ya se están moviendo y queremos seguir acelerando a la velocidad. La función seno convertirá cualquier número en uno negativo, cero o uno positivo, haciendo más simple comparar si estos dos valores son ambos positivos o ambos negativos. Podemos combinar condiciones junto con o. Entonces, si alguno de estos valores es verdadero, entonces toda la afirmación es verdadera. Si ambos son falsos, entonces queremos dar la vuelta, lo que significa aplicar desaceleración lugar de aceleración, resultando en un cambio mucho más rápido que lo haría aplicando aceleración si el valor de desaceleración Probando esto, mover nuestro personaje hacia la izquierda y hacia la derecha debería parecer mucho más realista ahora, y podemos ajustar fácilmente los valores de nuestra velocidad, aceleración y desaceleración en el inspector Te veré en el siguiente video. 11. 1-4 Saltos: Hola, amigos. En este video, vamos a mejorar cómo se implementa el salto. Antes de comenzar a saltar, moveré la cámara hacia arriba a lo largo del eje Y para que el piso esté en la parte inferior de la pantalla, no en la mitad. El script de plantilla para nuestro personaje ya tiene un botón de salto usando UI excepto, que es la barra espaciadora, configurando la velocidad Y del personaje para saltar velocidad. Pero ya agregamos nuestro propio botón de salto en un video anterior. A diferencia de la gravedad o la aceleración, que se multiplican por Delta y se aplican al personaje sobre múltiples fotogramas, esta velocidad de salto se aplica al personaje de una vez inmediatamente. Ejecutando el juego, podemos presionar la barra espaciadora para saltar, pero hay múltiples problemas. El salto es siempre de la misma altura, y tenemos el script de caracteres comprobando la entrada. Primero eliminemos esto del proceso de física del personaje y en su lugar lo pongamos en una función pública. Lo llamaremos salto. Después en el guión del jugador, al presionar el botón de salto, en lugar de imprimir salto, podemos decirle al personaje que salte en su lugar. Accediendo al contenido del personaje con un punto seguido del nombre de la función, y la función no tiene parámetros, por lo que no hay nada entre paréntesis Pero ahora estamos permitiendo que el personaje salte cada vez que se presiona el botón, aunque no estén en el suelo. Tenemos que verificar si el personaje está en el piso primero antes de permitirle saltar. Esto es en la función de piso se define en el cuerpo de carácter dos clase D. Ahora el personaje sólo puede saltar si está en el suelo, pero el salto es siempre de la misma altura. En la mayoría de los juegos, el personaje saltará más alto manteniendo presionado el botón que si solo se presiona. A veces podemos medir cuánto tiempo se mantiene el botón de salto antes de soltarlo, luego pasar esa información a través de la llamada a la función de salto para ajustar la fuerza de salto. Pero sobre todo en dos juegos de plataformas D, generalmente esperamos que los saltos ocurran de inmediato cuando presionamos el botón, lo que significa que no podemos esperar a que el botón se mantenga presionado o se suelte Entonces, en cambio, es más común asumir que el salto será la altura completa del salto y luego cortarlo si el jugador suelta el botón antes de tiempo. la misma manera que reaccionamos ante un botón que se presionaba en el guión del jugador, podemos reaccionar a que se libere también. Usando la palabra clave if, esto solo se verificará si las condiciones anteriores si eran falsas, eliminando la redundancia de verificar si el botón fue presionado y liberado al mismo tiempo Si se suelta el botón de salto, podemos llamar a una función diferente para cancelar el salto cortándolo corto. De vuelta en el script de caracteres, necesitamos declarar la función de salto cancelada, que no requiere parámetros y no devuelve ningún valor. Una forma sencilla de hacer esto sería establecer la velocidad Y del personaje en cero, pero esto puede parecer bastante antinatural llegando a una parada completa en el aire Entonces, en cambio, dividiré la velocidad Y por dos. Pero solo queremos que esto suceda si la velocidad del personaje es actualmente menor que cero, es decir, se están moviendo hacia arriba y solo si su velocidad es menor que cero porque saltaron. Si hubiera alguna otra razón por la que el personaje se movía hacia arriba, pero no saltaron, no querríamos que cancelaran un salto y redujeran su velocidad. Podemos controlar esto declarando una nueva variable. Lo llamaremos Is jumping de tipo Boolean, que naturalmente por defecto será Si establecemos esta variable en true cuando el personaje salta, entonces podemos verificar si el personaje está saltando antes de permitirle cancelar el salto. En el caso de que no cancelen el salto, necesitamos establecer la variable is jumping de nuevo a false automáticamente. Entonces en el proceso de física, comprobando si el personaje está saltando y si su velocidad y es mayor o igual a cero, es decir, el personaje está cayendo o al menos no se mueve hacia arriba, entonces podemos establecer está saltando de nuevo a falso porque es demasiado tarde para que el personaje suelte el botón para cancelar este salto. Esto funciona muy bien, pero ahora tal vez queramos ajustar qué tan alto puede saltar el personaje. El script de la plantilla declara la velocidad de salto como una constante. Al igual que hicimos con la velocidad de movimiento, podemos cambiar esto para que sea una variable. Pero saber cuánta velocidad se requiere para alcanzar una altura específica no es muy intuitivo, y desde una perspectiva de diseño, a menudo es mejor poder controlar exactamente qué tan alto puede saltar un personaje. Así que vamos a declarar otra variable llamada altura de salto como un entero. Esto se medirá en píxeles. Voy a poner el mío en 256, que es el doble de la altura del personaje. Usando la etiqueta on ready, podemos usar algunas matemáticas para calcular la fuerza de salto requerida para alcanzar esta altura exacta. La etiqueta on ready ejecutará esta línea del script cuando el nodo esté listo antes de la función ready. No soy físico, así que no podría explicar por qué funciona esta ecuación, pero sí Simplemente tome la raíz cuadrada de la gravedad multiplicada por la fuerza de salto por dos. Entonces también multiplique todo esto por uno negativo ya que negativo a lo largo del eje y es hacia arriba. Para ello, necesitamos conocer la fuerza de gravedad se está aplicando al carácter como un número decimal, a flote Entonces declarando otra variable usando la etiqueta on ready, esta debe estar por encima de la variable de fuerza de salto, por lo que se establecerá primero Podemos obtener la fuerza de gravedad desde la configuración del proyecto. Sólo tenemos que especificar la ruta a la configuración que queremos en una cadena. Finalmente, cuando el personaje salta, estableceremos su velocidad Y a esta fuerza de salto calculada. Ahora el jugador puede controlar qué tan alto quiere saltar. Y podemos editar fácilmente altura máxima de salto de un personaje desde el inspector. Te veré en el siguiente video. 12. 1-5 Caída: Hola, amigos. En este video, ajustaremos cómo se siente y controla el personaje en el aire. Nuestro personaje puede saltar más alto ahora, pero se siente muy flotante, y el personaje puede controlar su movimiento en el aire tan fácilmente como podría hacerlo en el suelo Quizás quieras esto para tu juego, pero muchas veces el jugador tiene menos control sobre el personaje mientras está en el aire. En el script de caracteres, podemos eliminar estas constantes antiguas ya que ya no se utilizan en ningún Ya que nuestro guión está haciendo múltiples cosas, moviendo el personaje a izquierda y derecha y saltando, sería una buena idea mantenerlo organizado. Mantendré mis variables de velocidad de movimiento, aceleración, desaceleración y dirección agrupadas y haré lo mismo con variables relacionadas con el salto Incluso podemos crear categorías para nuestras variables usando la etiqueta de categoría de exportación y especificar el nombre de la categoría como una cadena. Tengamos una categoría separada para las variables relacionadas con la locomoción y otra para el salto Esto agrega encabezados al inspector, por lo que nuestras variables exportadas se organizarán en estas categorías. Nuestra categoría de salto solo tiene una variable, pero agregaremos algunas más, comenzando con un multiplicador de gravedad. Esto va a ser un flotador y le voy a dar un valor por defecto de uno. Luego multiplique nuestra gravedad por el multiplicador de gravedad después de recuperarla de la configuración del proyecto Dado que este número se utiliza para calcular la fuerza de salto requerida para alcanzar nuestra altura de salto deseada, la altura de salto del personaje no cambiará, y la fuerza se incrementará automáticamente para compensar. Al abrir los ajustes del proyecto, mirando debajo de Física dos D, la gravedad predeterminada se establece en 980 píxeles por segundo al cuadrado Podemos modificar la fuerza de gravedad aquí para todo el proyecto y afectaremos a todos nuestros cuerpos físicos. Es posible que queramos que algunas cosas se sientan más pesadas o ligeras que otras, y una manera fácil de hacerlo es multiplicar su propia gravedad individual por un número diferente. Aumentar el multiplicador de gravedad de nuestro personaje hará que su salto sea más rápido y hará que el personaje se sienta más pesado. Bajar el multiplicador de gravedad los hará sentir más ligeros y flotantes A continuación, podemos reducir la cantidad de control el jugador tiene sobre el personaje usando más multiplicadores, comúnmente conocidos como control de aire y frenos de aire control de aire se usa cuando el jugador está dando entrada de movimiento en el aire y frenos de aire cuando no están dando entrada en el aire medio Pondré ambos en 0.5, lo que significa que la aceleración y desaceleración del personaje se reducirán a la mitad Abajo en el proceso de física, podemos organizar mejor todo lo que está sucediendo dividiéndolo en diferentes funciones, una que se llama solo cuando el personaje está en el piso y otra cuando no lo están. Pasaremos el valor de Delta a ambas funciones. Al definir una función de física terrestre separada, ahora podemos enfocarnos en aplicar solo la física adecuada para cuando el personaje está en el suelo. Entonces crea otra función para la física del aire y usa esta función para controlar al personaje manera diferente a cuando están en el suelo. Aquí es donde aplicaremos la fuerza de la gravedad. Luego copia también los controles para el personaje que se mueve y no se mueve de la física del suelo. vuelta es menos importante en el aire ya que no hay terreno para proporcionar fricción, por lo que no tendría sentido dar la vuelta Todo lo que tenemos que hacer es multiplicar la aceleración natural del personaje por el multiplicador de control de aire y su desaceleración por el multiplicador de frenos de aire Otro método es que se podría considerar el control de aire y los frenos de aire como valores alternativos que sustituyan a la aceleración y desaceleración en lugar de utilizarlos como multiplicadores También es posible que desee considerar agregar una velocidad terminal, dependiendo de la cantidad de caídas que esté haciendo el personaje para largas distancias y si el jugador necesita tener un mejor control en tales situaciones. Una velocidad terminal es la velocidad máxima que un objeto podrá recorrer por el aire, ya que la fuerza de resistencia del aire eventualmente igualará la fuerza de la gravedad y se cancelará entre sí. Como todavía no tenemos un entorno adecuado para probar esto, todo lo que realmente podemos hacer es establecer la altura del salto del personaje en algo muy alto, tal vez incluso alejar la cámara para que podamos ver más arriba. Pero podemos ver que el personaje se moverá muy rápido al seguir largas distancias, y es muy difícil para el jugador controlar con alguna precisión. Así que vamos a exportar otra variable para nuestra velocidad terminal. En la atmósfera terrestre, un humano paracaidista alcanzará una velocidad terminal a unos 54 metros/segundo Si 100 píxeles es de 1 metro, entonces eso es 5,400 píxeles por segundo Para aplicar este límite en la función de física del aire, simplemente podemos usar la función Min para devolver ya sea la velocidad Y actual del personaje o la velocidad terminal, la que sea menor Luego asigne el valor devuelto a la velocidad Y del personaje. Ahora podemos limitar fácilmente qué tan rápido se permite que el personaje caiga en el inspector, dándole al jugador más control cuando está siguiendo largas distancias. Voy a poner el mío en 4,096 por ahora. Te veré en el siguiente video. 13. 1-6 Running: Hola, amigos. En este video, agregaremos un botón de ejecución que el jugador puede mantener pulsado para cambiar su velocidad de movimiento. Primero, restableceré el Zoom de la cámara y la colocaré donde estaba antes. La velocidad de movimiento del personaje al jugar con el teclado es siempre la misma, pero podemos ajustar la velocidad de movimiento inclinando solo parcialmente el stick analógico En algunos juegos, esto es suficiente para permitir que el jugador camine o corra. Pero en otros, hay un botón de carrera designado para que el jugador mantenga pulsado para moverse más rápido. Al abrir la configuración del proyecto, podemos agregar un botón Ejecutar a nuestro Mapa de entrada. Usaré la tecla Mayús o el botón de la cara derecha en mi controlador. En el script del reproductor, usaremos las mismas funciones que hicimos con el salto para verificar si se está presionando o soltando el botón de ejecución. Cuando se presiona el botón de correr, podemos decirle al personaje que corra, y cuando se suelta, decirle que caminen. Mientras estamos aquí, podemos lidiar con esta advertencia de que la función de proceso en realidad no está usando el valor de Delta. Para anular una función existente, los parámetros deben coincidir exactamente, por lo que no podemos eliminar Delta por completo. En cambio, el motor Godot preferiría que marquemos este parámetro como no utilizado precediendo su nombre con un guión bajo Alternativamente, podemos abrir el panel de advertencias y hacer clic en Ignorar para decirle al motor que ignore esta advertencia. Ahora el guión del personaje necesitará estas funciones públicas, correr y caminar. Comenzaremos agregando dos variables exportadas más en la categoría de locomoción, una velocidad de caminata y una velocidad de carrera Entonces la velocidad de movimiento puede tener su etiqueta cambiada de exportación a on ready y su valor asignado a la velocidad de caminata por defecto. Dando una declaración a las funciones de caminar y correr , no aceptar parámetros y no devolver valores, solo necesitamos establecer el valor de velocidad de movimiento para velocidad de carrera o velocidad de caminata. Entonces el proceso de física manejará el resto usando el valor actual de la velocidad de movimiento. Eso es todo lo que se necesita para cambiar la velocidad de movimiento de nuestro personaje mientras mantienes pulsado un botón. Podríamos revertir esto fácilmente para que el personaje se ejecute por defecto, pero mantén presionado un botón para caminar simplemente cambiando el valor predeterminado de velocidad de movimiento a velocidad de carrera y haciendo que el script del jugador llame a las funciones opuestas. Como esta lección fue tan corta, también me prepararé para el siguiente video agregando un bloque para que el personaje salte usando un nodo de cuerpo estático. A Te veré en el siguiente video. 14. 1-7 Coyote: Hola, amigos. En este video, vamos a ayudar al jugador agregando funciones de accesibilidad que harán que nuestro personaje se sienta más indulgente para controlar Comenzaré restableciendo la altura del salto del personaje a un número razonable En la mayoría de los dos juegos de plataformas D, el juego permitirá al jugador presionar el botón de salto por un corto tiempo después su personaje haya salido de una repisa y también cuando está cayendo y casi aterrizando En ambos casos, la función is on floor devolverá false, pero haría que el juego se sintiera mejor para el jugador si aún se le permite realizar un salto. Para agregar estas características, comencemos cambiando el tipo de retorno de la función de salto de nada a un booleano Entonces volveremos verdadero si el salto fue exitoso o falso si no lo fue. De esa manera, el guión del jugador puede reaccionar ante el botón de salto que se presiona demasiado pronto y volver a intentar el salto después de que el personaje aterrice en el suelo Cambiando al guión del jugador, en lugar de simplemente llamar a la función de salto de punto de carácter, podemos reaccionar a su valor de retorno poniéndolo dentro de una declaración if. Si jump devuelve true, no necesitamos hacer nada, pero si devuelve false, podemos suponer que el jugador quiere saltar cuando sea posible si eso sucede relativamente pronto. Entonces si no salta, si jump devolvió false, entonces almacenaremos en búfer esta entrada de salto por una breve ventana de tiempo. La forma más fácil de realizar un seguimiento del tiempo es usar un nodo temporizador. Podemos agregar esto como un hijo del nodo jugador, o como el nodo jugador no tiene un tipo específico para el que lo estemos usando, podemos cambiar su tipo para que sea el propio temporizador. Al observar sus propiedades en el inspector, podemos establecer la duración del temporizador, que será la ventana de tiempo durante la cual la entrada se almacenará en búfer y establecer su propiedad one shot en true. Esto significa que una vez iniciado, el temporizador solo contará atrás hasta 01 tiempo. El comportamiento predeterminado sería contar hasta cero repetidamente. A continuación, declaremos una nueva variable. Le nombraremos entrada en búfer de tipo callable. Callable es una clase que contiene una llamada a función completa con argumentos Entonces, si nuestro salto falla, queremos establecer nuestra entrada en búfer para que sea salto de punto de carácter sin paréntesis, ya que no estamos llamando a la función ahora, sino almacenándola en una variable Y también arranca el temporizador. Desde que cambiamos el tipo de este nodo a un temporizador, tendremos que cambiar el tipo de nodo que este script extiende en la parte superior del script para poder acceder a funciones de la clase timer. Entonces en la función de proceso, si este temporizador se está ejecutando, si no se detiene, entonces llame a la entrada búfer. Si la entrada en búfer devuelve true, entonces tuvo éxito, y podemos detener el tiempo. Si la entrada en búfer devolvió false, entonces no puede suceder todavía este fotograma, y querremos volver a intentarlo el siguiente fotograma hasta que se acabe el temporizador o tenga éxito Para fines de prueba, también usemos algunas declaraciones de impresión para imprimir cuando el salto está en búfer, cuando falla la entrada en búfer y cuando tiene éxito Ejecutando el juego, si presionamos el botón de salto temprano, la entrada de salto se almacena en búfer. Falla algunas veces luego tiene éxito cuando el personaje golpea el suelo Si presionamos el botón de salto cuando el personaje está muy arriba en el aire, entonces la entrada se almacena en búfer, pero falla hasta que se agota el temporizador y nunca tiene éxito Una vez que estemos satisfechos con el rendimiento de nuestro almacenamiento en búfer de entrada, podemos eliminar o comentar estas declaraciones impresas A continuación, queremos permitir que el personaje salte si recientemente han salido de una repisa, comúnmente conocida como tiempo de coyote, refiriéndose al coyote Wiley En la escena del personaje, podemos agregar un nodo temporizador y cambiarle el nombre coyote Al igual que el temporizador de búfer de entrada, será un temporizador de un disparo, y podemos ajustar la duración del temporizador. Con la escena del personaje abierta en el guión del personaje, podemos tomar una referencia a cualquier nodo hijo manteniendo presionada la tecla de control o comando, luego haciendo clic y arrastrando el nodo al script Esto crea automáticamente una variable con el mismo nombre y usa la etiqueta on ready para establecer su valor usando la notación de ruta de nodo que comienza con el signo $1. El uso de esta notación de ruta de nodo de signo de dólar requiere que este nodo debe existir con la ruta de nodo exacta relativa al nodo al que está adjunto este script. De lo contrario, provocará un error. Sin embargo, este tiempo de coyote es una característica que generalmente solo es aplicable al personaje del jugador Puede que no queramos tener este nodo en cada escena de personajes. Entonces podemos usar la función get node o null pasando la misma ruta de nodo como un argumento de cadena. Esta función devolverá una referencia al nodo que sigue esta ruta de nodo o nulo si no existe sin causar ningún error. En la función de salto, nuestra verificación para ver si es posible un salto ahora será si el personaje está en el piso o si el personaje tiene un temporizador coyote y el temporizador coyote no está parado En operaciones lógicas, y se evaluará antes o a menos que incluya corchetes. En lo que respecta a la declaración A, se verificará el lado izquierdo antes que el lado derecho. Entonces, si el temporizador coyote no existe, la declaración A se considerará falsa Por lo que no se verificará el lado derecho de si el temporizador coyote está funcionando o no Ahora todo lo que tenemos que hacer es iniciar el temporizador coyote. Para ello, necesitamos saber cuándo el personaje sale de una repisa Consideraré que esto está incluido en la categoría de salto, y declararemos dos nuevas variables. Está en piso para almacenar el valor devuelto de la función I on floor para este marco. Esto nos permitirá realizar esta comprobación una vez por cuadro y almacenar los resultados para que podamos usarlo varias veces, ahorrando la necesidad de llamar a la función varias veces por cuadro y estaba en piso, lo que mantendrá el valor de is en piso del cuadro anterior. Durante el proceso de física, estableceremos el valor de was on floor a is on floor, luego está en floor al valor devuelto de la función is on floor. Cualquier otra llamada a la función is on floor puede usar nuestra variable en su lugar para ser más eficientes. Entonces si el personaje estaba en el suelo en el cuadro anterior y no está en el piso de este cuadro y su velocidad y es mayor o igual a cero, es decir, no saltaron, la única conclusión lógica es que este personaje ha salido de una repisa o el piso en el que estaban parados ha desaparecido, y este es el momento exacto cuando debería comenzar el temporizador coyote. Para fines de prueba, agreguemos declaraciones impresas para que sepamos cuándo comienza el temporizador de coyote y cuándo se realiza con éxito un salto de coyote Esto requerirá una sentencia if redundante, pero la eliminaremos más tarde. Bien. Ejecutando el juego para probarlo. Podemos bajarnos de una repisa y ver que arranca el temporizador de coyote Si presionamos el botón de salto mientras el temporizador coyote está funcionando, entonces el personaje aún puede realizar un salto Ahora tenemos una plataforma Toti sólida y controlador de personajes En la siguiente sección, dibujaremos y animaremos al personaje Te veré en la siguiente sección. 15. Sprite 2-1: Hola, amigos. En esta sección, vamos a tomar nuestro sencillo icono de Gadot y pulirlo para convertirlo en un personaje completamente animado Para eso, vamos a necesitar activos, imágenes y archivos de audio. Los que estoy usando se incluirán si quieres usarlos, pero recomiendo a los estudiantes intermedios usen tus propios activos u otros activos gratuitos. Antes de comenzar a importar activos, es una buena idea crear una carpeta separada para mantenerlos. También podemos crear diferentes subcarpetas para diferentes tipos de activos como hojas de sprites y efectos de sonido Haga clic en la carpeta en la que desea que estén sus activos importados, luego simplemente haga clic y arrastre los activos a la ventana de Gadot El proceso de importación ocurrirá automáticamente, y se ordenarán en la carpeta enfocada. Si no están en la carpeta correcta, siempre puedes arrastrarlos pestaña del sistema de archivos para reorganizarlos también. Pero esto desencadenará una reimportación, por lo que es mejor importarlos a la carpeta correcta para empezar, especialmente para archivos más grandes Abre tu escena de personaje si no está abierta ya. Usar estos activos para dibujar el personaje podría ser tan simple como reemplazar el icono de Gadot con tu archivo de imagen importado si tus activos tienen solo un sprite por Los activos que estoy usando están organizados en una hoja de sprites, por lo que hay múltiples sprites en una sola textura, que no es lo que quiero dibujar Usando el menú desplegable, podemos seleccionar otros tipos de texturas, y la que se usa para usar una hoja de sprites se llama textura de atlas Al hacer clic en la textura del atlas para expandirla, podemos editarla aquí mismo desde el inspector. Asignar la hoja de sprites como atlas. Luego podremos editar la región del atlas, que será dibujada por la textura del atlas. Al seleccionar una región de la hoja de sprites para usar, podemos usar la función de corte automático para seleccionar un solo sprite o ajuste de píxeles para hacer clic y arrastrar una Dado que estos sprites son todos de tamaño uniforme y espaciados, usaré esta región de 32 por 36 píxeles Al cambiar el sprite, el ancho y la altura no cambiarán Sólo las posiciones X e Y se incrementarán por valores uniformes Esto hace que sea mucho más fácil animar al personaje. Antes de comprometerse a usar un conjunto de activos para animar un personaje, podría valer la pena editar su hoja de sprites para tener este espaciado uniforme para ahorrar tiempo y esfuerzo Voy a mover el sprite hacia abajo para que descanse sobre el eje X. Su posición Y es ahora la mitad de la altura de la región de sprites. Ahora que tenemos una representación visual precisa de nuestro personaje, podemos adaptarnos mejor a la forma de colisión. Podemos reordenar los nodos secundarios para dibujar la forma de colisión sobre el sprite del personaje para facilitar las cosas Usaré forma de cápsula y la haré lo suficientemente grande como para incluir la cabeza pero no las orejas y el cuerpo, pero no necesariamente los brazos, la cola o el arma. Esto se utilizará para colisionar con el entorno, por lo que cualquier cosa fuera de la forma de colisión se superpondrá con las paredes, el techo o el suelo Asegúrate de que tu forma de colisión y sprite permanezcan centrados alrededor del eje Y y se asienten cómodamente en el eje X como si fuera el piso Si el tamaño de tu personaje cambia significativamente, probablemente querrás cambiar los valores de sus variables para cosas como velocidad de movimiento y la altura del salto. También podemos escribir ecuaciones matemáticas en estos campos, y el motor determinará el resultado por nosotros. Pero voy a reordenar la forma de colisión a estar detrás del sprite Con el carácter centrado a lo largo del eje Y, para hacer que el personaje quede a la izquierda o a la derecha, todo lo que necesitamos hacer es cambiar el valor de la variable flip horizontal en el nodo Sprite two D. Cambiando al script de caracteres, tomaremos una referencia al nodo Sprite two D y lo almacenaremos en una variable manteniendo presionada la tecla control o comando y arrastrándolo al Después declararemos una función pública llamada cara izquierda, aceptando sin parámetros y no devolviendo ningún valor. Si bien la intención actual es usar solo esta función de forma privada dentro de este guión, probablemente puedas imaginar que decirle a un personaje que se enfrente a una dirección podría ser útil en un contexto público. Para mirar a la izquierda, todo lo que tenemos que hacer es establecer el valor de la propiedad sprites flip H en true También podríamos escribir otra función llamada face right, pero la función solo estaría estableciendo el valor de esta variable de nuevo en false. A veces es más fácil escribir nuestras funciones para ser más flexibles. En lugar de tener tanto una función face left como face right, podemos darle a la función face left un parámetro que le permita hacer ambas cosas. Simplemente lo nombraré a la izquierda y le daré un valor predeterminado de true. Darle un valor predeterminado a un parámetro lo convierte en opcional. Entonces esta función llamada cara izquierda, se puede llamar sin aportar ningún argumento, y vamos a suponer que quieren enfrentar a la izquierda. Entonces podemos establecer el valor de flip H al valor de left. Para que el personaje se vea bien, todo lo que tenemos que hacer es llamar a la cara izquierda pero proporcionar falso como argumento en lugar de llamar a una función completamente diferente. En el proceso de física, si la dirección de un personaje es negativa, entonces quieren enfrentar a la izquierda. Y si es positivo, entonces quieren enfrentar no a la izquierda, que es la derecha. Si la dirección es cero, entonces permanecerán mirando la misma dirección en la que estaban en el cuadro anterior. Para obtener una mejor visión de mi personaje pequeño, acercaré la cámara por un factor de cuatro y reposicionaré para que el piso quede en la parte inferior de la pantalla O. Cuando golpeamos play, el personaje está siendo dibujado y su sprite volteado para mirar en la dirección correcta, pero aún no están siendo animados Me gustaría que mi personaje fuera más rápido, así que voy a incrementar sus valores en la escena del personaje. Te veré en el siguiente video. 16. 2-2 Reproductor de animación: Hola, amigos. En este video, vamos a agregar animaciones a nuestro personaje. Si tu personaje no tiene un nodo de reproductor de animación, deberías agregar uno ahora. Con el nodo del reproductor de animación seleccionado, la pestaña de animación debería expandirse automáticamente. Si no está abierto, puede abrirlo haciendo clic en el botón Animación. El panel de animación está actualmente vacío ya que aún no hay animaciones. Al hacer clic en el botón Animación, seleccionaremos Nuevo para crear una nueva animación y ponerle el nombre inactivo. Con una animación seleccionada, ahora hay una línea de tiempo medida en segundos. Si lo prefieres, puedes cambiar los segundos a fotogramas por segundo, y la línea de tiempo se mostrará en fotogramas en su lugar. Los fotogramas están muy juntos, así que acercaré el zoom para mostrar fotogramas más separados entre sí. También podemos cambiar la velocidad de fotogramas. Pondré el mío a 12 cuadros por segundo. También ayuda a aplicar el ajuste al cursor de la línea de tiempo con esta palanca Ahora, cuando recorremos la línea de tiempo de animación, se ajusta automáticamente al fotograma más cercano Desde este panel, podemos agregar pistas a la animación haciendo clic en el botón más. El más común es una pista de propiedad, que nos permite editar cualquier propiedad de cualquier nodo en el árbol de escenas a lo largo del tiempo. El nodo que queremos animar es el nodo Sprite Ti, específicamente, es propiedad de textura Esto agrega una pista a la línea de tiempo de animación, y en esta pista, podemos agregar fotogramas clave para editar la propiedad a un nuevo valor en ese momento Al hacer clic derecho sobre la pista, podemos seleccionar Insertar clave para agregar un fotograma clave a esta pista Por defecto, el valor de este fotograma clave será su valor actual, que es la misma textura lo configuramos en el video anterior Esto es lo suficientemente bueno para archivos sprite individuales, ya que aquí solo podemos cambiar la textura Pero como estoy usando una hoja de sprites, en realidad no quiero cambiar la textura Solo quiero cambiar la región de la textura que se está utilizando. Hay un par de formas de hacer esto. Una es hacer clic en la pista de propiedad y editar su nombre de propiedad, agregando dos puntos y la palabra región después de la textura. Esto le dice a la animación que quiero editar la propiedad region de la textura, no la textura misma. Volveré a restablecer la animación para que esté vacía por ahora. Asegúrate de tener seleccionado el nodo del reproductor de animación en el árbol de escenas y, a continuación, selecciona el nodo Sprite two D. Ampliando la propiedad de textura del atlas, podemos ver sus propiedades en un panel anidado Al pasar el mouse sobre el nombre de la propiedad de la región, la ventana emergente nos mostrará el nombre de la propiedad Esto es útil para garantizar que tienes el caso exacto y la ortografía cuando intentas acceder a él a través del código o a través del nombre de la pista de animación como acabamos de hacer. Pero el segundo método para agregar pistas de propiedad a una animación, que es mucho más fácil es usar el botón clave a la derecha de la propiedad. Este botón solo estará aquí si el nodo reproductor de animación fue seleccionado previamente en el árbol de escenas. Una animación está abierta actualmente y luego se selecciona otro nodo en el árbol de escenas. Al hacer clic en este botón de tecla, se agregará un fotograma clave a la animación actual en la posición del cursor de la línea de La primera vez que agregamos un fotograma clave para una propiedad que actualmente no tiene pista en la animación, Godot nos preguntará si queremos hacer una pista para ello Y también, si queremos agregar esta pista a la animación de reinicio, diremos que sí a ambos. Esto agrega la pista a la animación, además de que también agrega el primer fotograma clave al mismo tiempo Al hacer clic en el nombre de la animación inactiva para expandir el menú desplegable, también creó la animación de reinicio, que es como GoDo almacenará los valores predeterminados de las propiedades Esto ayuda a evitar problemas con la ejecución de animaciones en el editor y cambiar permanentemente los valores de las propiedades sin querer Godot restablecerá todas las propiedades a los valores predeterminados especificados en esta animación de reinicio Para que esto sea más suave, intente agregar siempre pistas de propiedad a las animaciones cuando estén en su estado predeterminado. Ahora estamos listos para iniciar el proceso de animación real. Debe tener una pista de textura para cambiar sprites individuales o una pista de región de textura para cambiar sprites dentro de una hoja de sprites Sus activos también pueden usar diferentes hojas de sprites para diferentes animaciones Si este es el caso, también necesitará una pista tanto para la textura del atlas como para la región de textura. Todo lo que tenemos que hacer es fregar hacia adelante en la línea de tiempo un fotograma, luego editar el valor de la textura o la región de textura y hacer clic en el botón de tecla para agregar otro fotograma clave y repetir Como sé que todos mis sprites son del mismo tamaño y están espaciados uniformemente, puedo hacerlo aún más fácil simplemente insertando nuevos fotogramas clave que editando manualmente la propiedad X, aumentándola en 32 cada Si probamos esta animación, el motor asumirá que queremos interponer los valores de estas propiedades entre fotogramas clave Dado que la velocidad de fotogramas del juego general es de 60 fotogramas por segundo, pero esta animación es de 12 fotogramas por segundo. El motor crea cuatro fotogramas adicionales entre cada fotograma clave para crear una transición más suave Obviamente, esto no es lo que queremos con una animación de sprites, por lo que tendremos que cambiar el modo de actualización de esta pista de continuo a discreto Ahora la propiedad solo cambiará cuando la animación llegue a un fotograma clave y cambiará el valor inmediatamente La animación es demasiado larga, por lo que tendremos que establecer el número de fotogramas de la animación para que termine después del último fotograma clave Esta animación también tendrá que hacer un bucle, así que haga clic en el botón de bucle de animación para que el icono de bucle sea azul Si haces clic en él una vez más, se establecerá en Ping Pong, que es un tipo diferente de bucle Para las animaciones de personajes, generalmente queremos un bucle hacia adelante Es una buena idea establecer también las pistas de animación de reinicio en discretas en caso de que decidas usarlo para restablecer un personaje a través de un guión. Esta animación ociosa ya está completa, y podemos seguir haciendo el resto de las animaciones que necesitamos para nuestra plataforma y personaje. Al hacer clic en el botón de animación, podemos agregar una nueva animación y comenzar desde cero, o podemos duplicar esta animación inactiva y usarla como plantilla. Como sé que mis sprites están espaciados uniformemente, solo necesito editar las propiedades Y de mis fotogramas clave para cambiar de fotogramas inactivos a fotogramas caminados Podemos copiar y pegar claves para facilitar las cosas. Una línea que conecta dos claves significa que los valores no están cambiando entre ellas. Al hacer la animación de ejecución, simplemente duplicaré la velocidad de fotogramas. Podemos hacer clic y arrastrar las teclas para moverlas a lo largo de la línea de tiempo. También voy a necesitar hacer animaciones de saltos y caídas. Dependiendo de los activos que estés usando, es posible que necesites hacer diferentes animaciones. Por ejemplo, es posible que necesite un arranque en salto, salto inactivo, inactivo o animaciones de aterrizaje. Asegúrate de saber qué animaciones necesitan bucle y cuáles no. Ahora el personaje tiene todas las animaciones, pero están atrapadas en la animación ociosa. Así que tendremos que decirle al personaje cuándo cambiar a otras animaciones. Te veré en el siguiente video. 17. Árbol de animación 2-3: Hola, amigos. En este video, controlaremos qué animación se está reproduciendo en el reproductor de animación usando un árbol de animación. Si la escena de tu personaje no tiene un nodo de árbol de animación, deberías agregar uno ahora. El propósito del árbol de animación es controlar al jugador de animación, decidiendo qué animación debe reproducirse en un momento dado. Entonces, con el nodo del árbol de animación seleccionado en el árbol de escenas buscando en el inspector, estableceremos su propiedad de reproductor de animación nuestro nodo reproductor de animación. La propiedad raíz del árbol es un recurso que se utilizará para determinar qué animación será reproducida por el nodo del reproductor de animación. Al hacer clic en el menú desplegable, tenemos algunas opciones diferentes para esto, mayoría de las cuales son más aplicables al usar tres animaciones D o óseas, que a menudo combinan múltiples animaciones juntas. Dado que este es un simple sprite de dos D, usaremos una máquina de estado Al hacer clic en nuestra nueva máquina de estado, abriremos el panel del árbol de animación en la parte inferior de la ventana del editor con una máquina de estado abierta para su edición. Nuestra máquina de estado actualmente tiene un nodo de inicio y un nodo final. Estos no son los mismos que los nodos en el árbol de escenas, sino que son nodos en el contexto de una gráfica de nodos. Podemos hacer click en el espacio vacío para agregar más nodos. Agreguemos la animación inactiva como nodo. Podemos hacer clic y arrastrar estos nodos alrededor para organizarlos como queramos. Sus posiciones dentro de este espacio son irrelevantes. Cambiando nuestro modo de edición de seleccionar y mover nodos para conectar nodos, podemos hacer clic y arrastrar de un nodo a otro, creando una flecha que los conecta en una dirección. Esta es una transición del nodo de inicio al nodo inactivo. Entonces, cuando se inicia la máquina de estado, pasará inmediatamente al nodo inactivo, que le dice al reproductor de animación que reproduzca la animación inactiva. Cambiando de nuevo el modo de edición para seleccionar y mover nodos, agreguemos las animaciones walk and run, también. Y volviendo a conectar nodos una vez más, crear una transición de inactivo a caminar y caminar a correr. Cuando se inicia esta máquina de estado, pasará inmediatamente desde el nodo de inicio al nodo de ejecución. Por lo que queremos agregar condiciones a estas transiciones para restringir cuándo se permite que ocurra esta transición. Seleccionando la transición de inactivo a caminar, expanda la sección de avance. Bajo la expresión de avance se encuentra un área de texto. Aquí podemos especificar cualquier expresión lógica que queramos controlar cuando se permita que se produzca esta transición, siempre y cuando el resultado sea un booleano, verdadero o falso En este caso, queremos reproducir la animación de caminata si la velocidad X del personaje es otra cosa que no sea cero. Por lo que esto acomodará caminar tanto a la izquierda como a la derecha. Esta expresión se verificará en el nodo que especificamos en las propiedades del nodo del árbol de animación, el nodo base de expresión avanzada. Configurando esto para que sea el nodo raíz de la escena, el cuerpo del personaje dos nodo D, podemos hacer que la máquina de estado de animación reaccione automáticamente a la velocidad del personaje para cambiar la animación. Volviendo a la máquina de estados, pasando de caminar a correr, vamos a querer verificar si el valor absoluto de la velocidad X del personaje es mayor que la velocidad de caminata del personaje Es posible que desee especificar un umbral diferente, como requerir que el valor absoluto de la velocidad X sea igual a velocidad de carrera o mayor que el promedio de la velocidad de caminata y carrera, etcétera Ahora necesitamos agregar una transición de regreso a inactivo de caminar. Al crear bucles de transición entre dos o más nodos en una máquina de estado como esta, las condiciones de todas las transiciones no deben ser todas ciertas al mismo tiempo. Esto haría imposible que la máquina estatal decida qué estado debería estar activo actualmente, ya que simplemente circulará entre los estados indefinidamente Dado que la condición para pasar de ralentí a caminar es que la velocidad X sea cualquier otra cosa que no sea cero, entonces la transición de caminar a ralentí debería ser si la velocidad X es igual a cero Estas dos condiciones no pueden ser ciertas al mismo tiempo, por lo que la máquina de estado no puede quedar atascada en bucle entre estos dos estados Aplicando la misma lógica para la transición de carrera a caminata, las condiciones para esta transición deben ser lógicamente incompatibles con la transición de caminar a correr Entonces, si el valor absoluto de la velocidad X del personaje es menor o igual que la velocidad de caminar del personaje, esto nunca será cierto al mismo tiempo como mayor que. Cuando ejecutemos el juego, la máquina de estado comenzará desde el nodo de inicio y se moverá a lo largo de transiciones entre diferentes estados, representando cada estado una o más animaciones. En algunos casos, la máquina de estado puede hacer la transición al nodo final. En cuyo caso dejará de funcionar. Al animar nuestro personaje, nunca queremos que esta máquina de estado llegue al nodo final, por lo que no hay transición que conduzca a él Esto funciona para animar al personaje al ralentí, caminando y corriendo a la izquierda o a la derecha, pero también necesitamos agregar animaciones para saltar Si tuviéramos que agregar la animación de salto aquí, necesitaríamos agregar transiciones de todos nuestros estados existentes a la animación de salto, ya que el personaje puede saltar desde cualquiera de estos estados. Esto se enredará y desordenado y difícil de manejar, sobre todo si tu personaje tiene múltiples animaciones de salto diferentes Lo que podemos hacer en cambio es crear una máquina de estado anidada. Empezaremos por guardar nuestra máquina de estado actual como recurso de proyecto. Llámalo locomoción. Después reemplace esta máquina de estado por una nueva. En nuestra nueva máquina de estado en blanco, derecha, haga clic en el espacio vacío y seleccione Cargar. Encuentre la máquina de estado Locomotion y agréguela a la nueva máquina de estado como un solo nodo, y cámbiele el nombre para que sepa que es la máquina de estado Locomotion Después agrega una transición de inicio a locomoción. Toda la máquina de estado Locomotion ahora existe como un solo nodo que podemos abrir haciendo clic en su botón Editar con un icono de lápiz Todavía tenemos las animaciones de marcha y ejecución inactivas en transición como antes, pero ahora está anidada dentro de una máquina de estado más grande Podemos regresar a la otra máquina estatal haciendo clic en el pan rallado. En esta máquina de estado, agregaremos cualquier animación relacionada con el salto y las conectaremos con transiciones. Así es como se ve un bucle infinito en una máquina de estado. Queremos que el personaje cambie de cualquier estado de locomoción para saltar si su velocidad Y es menor que cero, es decir, se están moviendo hacia arriba. Si su velocidad Y es mayor o igual a cero, han alcanzado el ápice de su salto, y voy a cambiar a la animación de caída. Después la transición de la caída de nuevo a la locomoción si el personaje está en el piso Podemos llamar a la función o usar nuestra variable privada que creamos anteriormente. Es posible que queramos saltarnos los saltos e ir directo a caer si el personaje se sale de una repisa Entonces agreguemos eso como otra transición bajo la condición de que el personaje ya no esté en el suelo. Esto crea un conflicto en nuestra máquina estatal cuando el personaje se encuentra en estado de locomoción y salta Su velocidad es a la vez menor que cero y no están en el piso. Entonces, ¿qué transición debería usar la máquina estatal? En casos como este, podemos dar prioridad a nuestras transiciones sobre otras bajando su propiedad prioritaria. Si el personaje salta, su velocidad Y es menor que cero, y no están en el suelo. Pero se le da prioridad a la transición al salto. Entonces esa es la transición la que se utilizará. Si el personaje sale de una repisa, su velocidad es mayor a cero, y no están en el suelo, por lo que no hay conflicto Nuestro personaje de plataformas en dos D ahora está animado, pero podemos hacerlo sentir mucho mejor agregando más pulido Te veré en el siguiente video. 18. 2-4 efectos de sonido: Hola, amigos. En este video, vamos a agregar efectos de sonido a nuestro personaje animado. Para ello, tendremos que importar algunos archivos de sonido a nuestro proyecto, ordenados en una carpeta apropiada. Incluiré algunos efectos de sonido que puedes usar para seguir junto con esta lección, pero recomiendo que los estudiantes intermedios usen sus propios activos o gratuitos. Primero, me desharé del nodo de cuerpo estático que es este rectángulo blanco ya que ya no lo estoy usando. Comienza agregando un nodo de transmisión de audio Player two D a tu escena de personaje si aún no tienes uno. El reproductor de flujo de audio dos nodos D difiere de un nodo reproductor de flujo de audio en que el volumen del efecto de sonido variará en función de su proximidad al oyente El oyente predeterminado es la cámara. Podemos poblar la propiedad de flujo de nuestro reproductor de flujo de audio con un efecto de sonido y hacer clic en el botón de reproducción para escucharlo Si echamos un vistazo a las animaciones de nuestro personaje, particularmente la animación de salto, podemos agregar una pista de reproducción de audio a la animación y seleccionar el reproductor de flujo de audio para denodar para ser el reproductor de esta pista Podemos entonces los efectos de sonido de fotogramas clave para jugar como parte de esta animación, pero esto viene con muchas limitaciones Si el efecto de sonido es más largo que la animación, se acortará. Si la animación está en un ciclo, se repetirá, y con efectos de sonido, el jugador escuchará muchas veces mientras juega el juego como este Es una buena idea agregarle algo de variedad y aleatorización para que el jugador no se canse de escucharlo Entonces, eliminemos esta pista de la animación y probemos un método diferente. Ya que conocemos el momento exacto en que el personaje salta del guión, sería más fácil reproducir el sonido de esa manera. Cambiemos el nombre del reproductor de flujo de audio a dNodet jump y tomemos una referencia para almacenarlo en una variable privada Cuando el personaje salta, lo único que tenemos que hacer es decirle que juegue. Manteniendo el efecto de sonido fuera de la animación, se reproducirá en su totalidad y sólo una vez. Podemos duplicar este reproductor de flujo de audio dos nodos D para agregar más efectos de sonido, también, como uno para un sonido de aterrizaje. Entonces en el guión, podemos tocarlo de la misma manera que el sonido del salto, pero no tenemos una función conveniente para cuando el personaje aterriza en el suelo todavía. En el proceso de física, tenemos una declaración if verifica si el personaje se ha salido de una repisa Revirtiendo esta lógica, podemos comprobar si el personaje ha aterrizado este fotograma, si no estaban en el piso último marco y están en el piso este marco. Entonces llamaremos a una nueva función privada. Vamos a llamarlo en aterrizado. Por ahora, esta función solo necesita reproducir el efecto de sonido de aterrizaje. Estos efectos de sonido se reproducirán cuando el personaje salte y aterrice, pero siempre serán los mismos, lo que se volverá molesto para el jugador después de algún tiempo. Podemos mejorar esto aleatorizando ligeramente la escala de tono del sonido cada vez que se reproduce Así que vamos a adjuntar un script a nuestro reproductor de flujo de audio dos dende y nombrarlo algo así como aleatorizador de efectos de sonido sin usar una plantilla y guardarlo en la carpeta correspondiente Este guión necesitará una función pública le diga que reproduzca un efecto de sonido aleatorio, no aceptando parámetros y no devolviendo ningún valor El resultado final de esto será llamar a la función de reproducción definida en el reproductor de flujo de audio para denodar clase Pero antes de reproducir el efecto de sonido, queremos editar el valor de la propiedad de escala de tono. Usando la función incorporada rand F range, podemos generar un float aleatorio entre un valor mínimo y máximo que especificamos. Siendo una la escala de tono predeterminada, aleatorizaré para que esté entre 0.5 y 1.5, que debería producir una amplia gama de sonidos similares Podemos adjuntar este mismo script al otro reproductor de flujo de audio a Dnode haciendo clic y arrastrando desde la pestaña del sistema de archivos al nodo en el árbol de escenas De vuelta en el guión del personaje, en lugar de llamar a la función de reproducción de audio Stream Player to D classes, llamaremos a nuestra función aleatoria de reproducción en su lugar. Esto podría ser suficiente para reducir la monotonía de nuestros sonidos de salto y aterrizaje, pero los pasos se escucharán constantemente mientras jugamos el juego Por lo tanto, es posible que desee tener múltiples efectos de sonido diferentes para algo así y que el reproductor de audiostream elija uno al azar Duplicemos un reproductor AudioStream dos nodos D para hacer otro para sonidos de paso, también con el mismo script aleatorizador aún adjunto En el script, exportaremos una variable para contener todos los diferentes efectos de sonido de pasos como una matriz de flujos de audio Esto se puede poblar rápidamente por grupo seleccionando todos los sonidos de paso en la carpeta assets y arrastrándolos a la matriz exportada en el inspector Entonces, al reproducir un efecto de sonido aleatorio, comprobaremos si el tamaño de esta matriz no es cero Si la matriz no está vacía, eso significa que debemos establecer el valor de stream para que sea un elemento aleatorio de esta matriz. Acceder a un miembro de la matriz con un número de índice entero como un entero aleatorio entre cero y el tamaño de la matriz menos uno. Esto simplemente elegirá un sonido aleatorio de nuestra variedad de sonidos. En el caso de nuestros otros sonidos aleatorios, ya que no están especificando ningún valor para la matriz, su tamaño es cero, y no intentará aleatorizar el efecto de sonido, solo ajustará su Ahora solo necesitamos tener el efecto de sonido desencadenado por las animaciones de caminar y correr. Al cambiar de la vista de guión a dos vistas D, primero seleccione el nodo Árbol de animación y luego el nodo Reproductor de animación para previsualizar temporalmente las animaciones sin el árbol de animación interfiera. Ya sea con las animaciones walk o run abiertas, podemos agregar una pista de método de llamada a la animación y llamar a un método en los pasos reproductor de flujo de audio para denodar Insertando una clave en la animación en esta pista, llamaremos al método play random. Un método en este contexto es sinónimo de una función. Podemos pasar por la animación para encontrar los fotogramas cuando los pies del personaje realmente hacen contacto con el suelo y establecer los fotogramas clave para que estén en estos fotogramas exactos. Después repite este proceso con la otra animación. Ahora tenemos un montón de pasos aleatorios, efectos de sonido de salto y aterrizaje, pero también podemos querer nubes de polvo Te veré en el siguiente video. 19. 2-5 Animated Sprite: Hola, amigos. En este video, vamos a crear partículas de polvo para nuestro personaje de plataformas Para eso, necesitaremos importar más hojas de sprites. Comenzando en la escena del personaje, agregaremos un Sprite Animado a de node y le daremos el nombre de algo así como Saltar polvo El Sprite Animated to dende difiere de un Sprite regular a de node en que no tiene una sola Cuenta con un recurso de marcos Sprite. Al hacer clic en el menú desplegable, podemos crear un nuevo recurso de marcos de Sprite para este nodo animado de dos D de Sprite Después haz click en el recurso para abrirlo. Esto abrirá una nueva pestaña en el panel inferior etiquetada como marcos Sprite En esta ventana, podemos crear una o más animaciones de fotogramas Sprite que este nodo podrá reproducir Estas animaciones solo pueden cambiar el Sprite mismo. No se pueden sincronizar con audio, llamadas de función u otras propiedades la manera que un nodo de Animation Player puede hacerlo. Dependiendo de los activos que estés usando, puedes agregar sprites desde archivos individuales o desde una sola hoja de Sprite Estoy usando Sprite Sheets, así que voy a hacer clic en los marcos del anuncio desde el botón Sprite Sheet Navegue por el sistema de archivos para encontrar sus activos deseados. Si usa una hoja de sprites, se le pedirá que seleccione qué marcos de la hoja de sprite desea usar A diferencia de una textura de atlas, estos marcos de sprites deben estar espaciados uniformemente Selecciona el número de fotogramas en cada fila y columna de la hoja de sprites, y se cortarán por ti A continuación, puede seleccionar cada uno de los marcos que desee utilizar haciendo clic en ellos. El número en la esquina de cada fotograma de sprite es el orden en el que se agregará a la animación Si no están en el orden correcto, puede anular la selección y volver a seleccionar los marcos de Sprite o importarlos fuera de orden y reordenarlos Al igual que con las animaciones de personajes siendo un fotograma más largo que el último fotograma, es una buena idea las animaciones de sprites como esta tengan un fotograma vacío al final Por lo que el último fotograma permanecerá dibujado en pantalla durante toda la duración de un fotograma antes de que la animación se considere terminada. Podemos establecer la velocidad de fotogramas de la animación. Voy a usar 12 fotogramas por segundo y si esta animación debe o no bucle, que voy a apagar. También hay una opción para reproducir esta animación de forma automática. Cada nodo Sprite Toti animado puede tener solo una animación de reproducción automática, y el nodo reproducirá esta animación cuando el nodo se agregue al árbol Cuando una nube de polvo es creada por el jugador saltando, queríamos reproducir esta animación. Así que hagamos esta animación de reproducción automática. Podemos previsualizar cómo se verá la animación haciendo clic en el botón de reproducción. Para ver mejor la animación, podemos ocultar temporalmente el sprite del personaje y la forma de colisión haciendo clic en el icono del ojo junto a ellos en el árbol de escenas Al igual que el personaje, esta animación necesita descansar limpiamente en el suelo del eje X. Entonces, en la sección offset en el inspector, podemos establecer su desplazamiento Y para que sea la mitad de su tamaño vertical. Con los activos que estoy usando, eso es 16 pixeles arriba. Esto mantiene los orígenes de los nodos a las 00 mientras se sigue dibujando el desplazamiento de Sprite Si el color de los sprites no es del todo correcto o quieres ajustar su transparencia, puedes hacerlo desde la sección de elemento de lienzo las propiedades de nodos en el inspector La propiedad modulate es un color con un valor predeterminado de blanco, que tiene valores de un rojo, uno verde, uno azul y uno Alpha Cada píxel en el sprite tendrá su propio color multiplicado por este color modular antes de ser Así podemos ajustar sus valores de rojo, verde, azul o Alfa. Voy a darle a mi nube de polvo la mitad de transparencia estableciendo su Modulate Alpha en 0.5 Podemos reordenar los sprites haciendo clic y arrastrándolos usando los botones de flecha, eliminar marcos, agregar marcos vacíos o importar más marcos si es necesario Una vez que estés contento con el aspecto de la animación, recuerda mostrar el sprite del personaje y la forma recuerda mostrar el sprite del personaje y la de colusión Encenderé el bucle para fines de demostración. Cuando ejecutamos el juego, el polvo sigue al personaje por ahí ya que es hijo de él. Pero lo que normalmente queremos para algo como esto es la nube de polvo genere en una ubicación específica y no se mueva Esta nube de polvo tendrá que ser un hermano del personaje, no un niño Al hacer clic derecho sobre el nodo Animated Sprite two D, podemos guardarlo como su propia escena Ponlo en una carpeta nueva para nubes de polvo. Eliminarlo de la escena del personaje. Entonces ábrelo para que podamos editarlo de forma aislada. Apaguemos el bucle de esta animación. Todavía queremos que se reproduzca de forma automática cuando se cree la nube de polvo, pero trataremos de eso en el siguiente video Por ahora, tenemos dos nubes de polvo más que crear. Uno para cuando el personaje aterriza y otro para cuando camina o corre. Así podemos duplicar nuestra escena de salto de polvo existente para facilitar las cosas. No va a marcar la diferencia, pero me gusta asegurarme de que el nombre del nodo raíz de mis escenas coincida con el nombre del archivo de la escena. Entonces solo cambia los sprites por los correctos en cada caso A Asegúrese de que todos estén correctamente desfasados para descansar limpiamente en el piso del eje X. Ahora tenemos tres nubes de polvo diferentes que queremos usar con nuestro personaje. Sólo tenemos que instanciarlos. Te veré en el siguiente video. 20. 2-6 Instantiar: Hola, amigos. En este video, instanciaremos las nubes de polvo en reacción a los movimientos de nuestro personaje animado Partiendo de la escena del juego, queremos que nuestras nubes de polvo existan en el mundo como hermanos de nuestro personaje, no como niños Adjuntemos un nuevo script al Nodo de Medio Ambiente mundial. Le pondré el nombre mundo y lo pondré en la carpeta de scripts. propósito principal de este guión por ahora será generar nuevas escenas como sus hijos Así que vamos a escribir una nueva función pública llamada spawn, que acepta una escena empaquetada como primer parámetro Yo solo lo llamaré algo vago como SN y también una posición donde se debe generar, que es un vector dos Entonces esta función devolverá el nodo que crea en caso de que queramos usarlo. Podemos convertir una escena empaquetada en un nodo llamando a su función Instanciate. Tendremos que almacenar este nodo en una variable para poder usarlo. Voy a llamarlo instancia. La creación de un nodo no lo agrega al árbol de escenas. Nosotros también tenemos que hacer eso. Pero para agregar cualquier nodo al árbol de escenas, el nodo necesitará un padre. Este nodo de entorno mundial será el padre, por lo que lo llamaremos add child function, dándole la instancia como argumento. Esto agregará el nodo al árbol de escenas, pero su posición será en el origen de la escena, coordenadas 00. Así que queremos establecer la posición del nodo recién instanciado para que sea la posición de generación Sin embargo, esto supone que el nodo recién instanciado tiene una propiedad position, lo que no es cierto para todos los Si bien esto no causaría un error todavía, podría ser que en el futuro, si usamos la función spawn para crear diferentes tipos de nodos Por lo que sería una buena idea verificar si esta instancia es un elemento canvas antes intentar acceder a su propiedad position. Podemos hacer que el parámetro de posición de generación sea opcional dándole un valor predeterminado de vector dos punto cero Finalmente, podemos devolver el nodo de instancia. Ahora necesitamos llamar a esta función como una reacción al personaje realizando ciertas acciones. La forma más fácil de hacerlo es usando señales. En el guión del personaje, podemos declarar señales en la parte superior del guión para cada una de las tres veces que queremos generar una nube de polvo cuando el personaje ha pisado, saltado o aterrizado Las señales se nombran convencionalmente en tiempo pasado, para decir que el suceso en cuestión ha ocurrido. Al igual que las funciones, las señales pueden tener parámetros. Para generar las nubes de polvo, necesitaremos saber la posición del personaje y en qué dirección están mirando, indicando si el sprite debe voltearse En la función de salto, podemos emitir la señal saltada, pasando la posición actual del personaje y si el sprite de caracteres es volteado horizontalmente como argumentos que coinciden con los parámetros de la señal Lo mismo se puede hacer cuando el personaje aterriza. Para los pasos, podemos declarar una nueva función privada. Nombrémoslo en el paso y emitamos la señal. Si quieres, también puedes decirle al sonido de paso que reproduzca dentro de esta función en lugar de incluirlo en las animaciones como una pista separada Pero para hacer eso, voy a necesitar una referencia al reproductor de audio paso para denotar en la parte superior de mi guión Seleccionar el nodo Animation Player y la animación de paseo. Podemos agregar una pista de método de llamada a la animación, llamando a un método en el nodo raíz de escenas. Luego inserte fotogramas clave para llamar a la función on step durante los fotogramas cuando los pies del personaje hacen contacto con el suelo Si activamos los efectos de sonido a través del script, ya no necesitamos hacer esto desde la animación y podemos eliminar esta pista Entonces también necesitaré repetir este proceso para mi animación de ejecución. Cambiando a la escena del juego, podemos conectar señales a scripts para reaccionar a ellos automáticamente. Seleccionando el carácter, cambiando la pestaña inspector a la pestaña de nodo, podemos ver nuestra lista de señales. Ya sea haciendo doble clic en una señal o haciendo clic derecho y eligiendo Conectar, se abre una nueva ventana. Desde esta ventana, podemos seleccionar el nodo al que queremos conectar la señal. En este caso, el nodo del entorno mundial. Después o bien ingresa el nombre de una función a llamar como reacción a la señal o escogiendo una de una lista. Ingresaré manualmente el nombre de una nueva función y la nombraré spawn Jump dust Al hacer clic en Conectar se cerrará la ventana y se mostrará el script World Environment Node con esta función agregada automáticamente. Esta función también tiene un icono verde que indica que está siendo llamado por una conexión de señal, y el nodo de caracteres en el árbol de escenas tiene un icono de señal para mostrarnos que está emitiendo una señal con una conexión. Esta conexión de señal también aparece en la pestaña nodo. Podemos exportar variables para contener nuestras tres escenas de nubes de polvo diferentes, que son de tipo escena llena. Después, rellena cada una de estas variables con las escenas apropiadas desde la pestaña del sistema de archivos Por ahora, vamos a llamar a la función spawn pasando Jump dust como argumento y también a la posición actual del personaje Godot no le gusta cuando nombramos los parámetros de nuestra función de la misma manera que las propiedades ya existentes de un nodo Pero podemos cambiar el nombre de este parámetro a algo más específico como la posición del personaje. Esto creará una instancia de una nube de polvo de salto automáticamente cada vez que el personaje El nodo Animated Sprite two D reproducirá de forma automática la animación Sprite que creamos, pero no queremos que este nodo de nube de polvo continúe existiendo después de que termine la animación Después de que el personaje haya estado saltando muchas veces, el árbol de escenas tendría un montón de Sprite Animado dos nodos D que no están haciendo nada Entonces tendremos que limpiarlos. La forma de eliminar nodos del árbol de escenas es llamar a su función libre. Pero no queremos hacer eso hasta después de que su animación haya terminado, que es una señal del nodo animado Sprite dos D. Como sabemos que el tipo de nodo de nuestras escenas de nubes de polvo es un Sprite Animado dos D, podemos almacenarlos en una variable privada de ese tipo y llamarlo polvo Podemos conectar señales a través del código tal como lo hicimos a través del inspector y conectar su señal de animación terminada a su función libre. Recuerda que al hacer referencia a una función en lugar de llamar a una función, no usamos paréntesis También podemos voltear la nube de polvo horizontalmente si el sprite del personaje se volteó cuando se omitió esta señal Repitiendo este proceso para las otras dos señales, podemos cambiar el tipo de nube de polvo que se genera. A ejecutar el juego, volveremos a la ventana Editor y daremos clic en el botón remoto en la pestaña de escena. Podemos ver el árbol de escenas del juego que actualmente se está ejecutando. Ampliando el árbol para que podamos ver los hijos del Nodo Mundial del Medio Ambiente. Podemos ver que los dos nodos D de Sprite Animado están siendo creados y destruidos a medida que saltamos, aterrizamos y caminamos El árbol de escena remoto no actualiza todos los fotogramas, por lo que algunas nubes de polvo pueden ser creadas y destruidas sin que se muestren en el árbol de escena remoto. Te veré en el siguiente video. 21. Bus de audio 2-7: Hola, amigos. En este video, agregaremos un efecto de sonido separado para la voz del personaje. Voy a necesitar importar algunos archivos de audio más para los esfuerzos del personaje. Los efectos de sonido de voz difieren de otros efectos de sonido en que solo queremos tocar uno a la vez, ya que nuestras cajas de voz solo pueden producir un sonido a la vez. Así que solo necesitaremos tener un nodo TD del reproductor de flujo de audio para todas las vocalizaciones de un personaje En la escena del personaje, vamos a duplicar cualquiera de los nodos TD del reproductor de flujo de audio existentes para crear uno nuevo para la voz del personaje. También es posible que desee colocar este nodo en algún lugar alrededor del cuello o la cabeza del personaje en lugar de a sus pies. Aunque esto no hará mucha diferencia notable en mi pequeño personaje. El aleatorizador de efectos de sonido ya no es aplicable a este nodo, lo que podemos eliminar el script haciendo clic en el botón de script separado Reemplazaremos esto por un nuevo guión. Vamos a llamarlo voz. En este script, podemos exportar cualquier número de efectos de sonido de voz estándar, comúnmente conocidos como esfuerzos o esfuerzos. Exportemos una variable para el sonido de esfuerzo de salto como un flujo de audio, que podemos poblar en el inspector Podemos previsualizar cómo sonará esto haciendo clic en el recurso. Luego agregaremos una función que tocará un sonido de esfuerzo de salto. Sin embargo, esta función no necesitará hacer nada si el reproductor de flujo de audio de voz para denotar está actualmente ocupado reproduciendo cualquier otro sonido Sólo si no está jugando, entonces configuraremos el stream para Saltar esfuerzo y jugarlo. Esto evitará que cualquier nueva solicitud de reproducir otro sonido de esfuerzo interrumpa el anterior También podemos usar las mismas técnicas que hicimos con nuestros efectos de sonido aquí, como aleatorizar la escala de tono o tener una matriz de flujos de audio y elegir uno al azar cada vez Y a diferencia de los efectos de sonido regulares, que siempre se espera que se reproduzcan cada vez, los esfuerzos no siempre son necesarios. Por lo que también podemos agregar en una oportunidad aleatoria de que el esfuerzo no juegue, aunque sea posible. Usando la función rand F, esto devolverá un número aleatorio 0-1 Podemos verificar si esto es menor que un porcentaje de probabilidad, digamos, 25%, expresado como 0.25. Añadiendo esto a la declaración condicional con un operador y, voz de este personaje no debe estar ocupada tocando ningún otro sonido y además debe pasar una probabilidad aleatoria del 25% antes de que se le permita tocar este esfuerzo Todo lo que tenemos que hacer para activar esto es conectar la señal de salto del personaje a las voces que tocan la función de esfuerzo de salto. Pero la señal de salto del personaje proporciona dos argumentos y las voces tocan función de esfuerzo de salto no acepta ningún parámetro, por lo que no se consideran compatibles. Si hacemos clic en los métodos compatibles solo toggle, todas las funciones se mostrarán aunque no coincidan, y podremos seleccionar la función play Jump effort. Para evitar que esto cause un error, ampliaremos la sección avanzada haciendo clic en el Toggle Avanzado. Aquí podemos enlazar nuevos argumentos o desvincular los argumentos existentes Simplemente desvincula los dos argumentos existentes de la señal saltada del personaje, y ahora la señal es compatible con la llamada a la función probarlo, escucharemos el sonido de esfuerzo reproducido aleatoriamente con un 25% de probabilidad, y nunca se interrumpirá. B. Otra cosa que podemos hacer para separar las voces de otros efectos de sonido es darles un Bus de Audio separado en el diseño del Bus de Audio. Haga clic en el botón Audio en la parte inferior del editor para abrir el diseño del Bus de Audio, que actualmente solo tiene un solo bus, el Bus Maestro. Pero si hacemos clic en Agregar bus, podemos agregar más buses al diseño de Audio Bus, uno para efectos de sonido y otro para voces. También es una buena idea tener otro para la música. Esto nos permite ordenar nuestro audio en diferentes categorías y controlar fácilmente toda la categoría a la vez en todo el juego. Podemos ajustar el volumen de todos los efectos de sonido, voces y música de forma independiente, y el volumen maestro afectará a todos ellos. También hay muchos efectos de audio diferentes que se pueden agregar a cada bus si queremos. En nuestra escena de personajes, tenemos múltiples reproductores de flujo de audio diferentes dos nodos D, y cada uno de estos necesita ser dicho a qué Bus de Audio pertenecen, siendo el predeterminado Bus Maestro. cada uno de los efectos de sonido se le puede decir que se reproduzca en el Bus de efectos de sonido, mientras que el reproductor de voz AudioStream de dos nodos D se puede decir que reproduzca en el Bus de voz Ahora podemos ajustar el volumen de nuestros efectos de sonido independientemente de las voces. M. M. Ahora tenemos un carácter de plataformas de dos D muy pulido A continuación, comenzaremos a construir entornos para movernos. Te veré en la siguiente sección. 22. Mapa de mosaicos 3-1: Hola, amigos. En esta sección, construiremos un entorno para que nuestro personaje se mueva y salte. Para ello, necesitaré importar activos para mi terreno, ordenados en una nueva carpeta para activos de sprites de terreno Al hacer doble clic sobre el activo, podemos previsualizarlo en el inspector. Podemos ver que este activo es una hoja de sprites al igual que el personaje Excepto en lugar de marcos de animación, esta hoja de sprites contiene diferentes sprites para dibujar el terreno en función de sus mosaicos circundantes Comenzando en la escena del juego, haremos que el nivel actual sea un cuerpo estático para denodar su propia escena Haré una nueva carpeta para escenas de sala. Y dependiendo del tamaño de tu juego, es posible que también quieras clasificar las habitaciones en regiones. Entonces haré otra carpeta para habitaciones en la región forestal y guardaré esta habitación como algo así como sala de inicio. Entonces abre esta nueva escena de sala. Ya no quiero que el nodo D del cuerpo estático dos sea el nodo raíz, ya que esta sala contendrá más que solo un piso. Entonces agregaré un nodo regular dos D a esta escena cuando era niño. Después haciendo clic derecho sobre este nodo, podemos seleccionar make scene root para reorganizar el árbol de escenas para que este nodo sea ahora el nodo raíz Ahora el piso es hijo del nodo raíz, y podríamos agregar más cuerpos estáticos a este nodo para las paredes, el techo, las plataformas y los obstáculos para construir nuestra habitación. Voy a cambiar el nombre del nodo raíz para que sea el mismo que el nombre de la escena. Al usar mosaicos de una hoja de sprites que tienen el mismo tamaño y espaciados, podemos usar otro nodo que proporciona Gadot llamado capa de mapa de teselas para dibujarlos Agregar un nodo de capa de mapa de teselas a la escena abre el panel de mapa de teselas en la parte inferior del editor, pero aún no podemos hacer nada aquí. Primero, necesitamos echar un vistazo a propiedades de nodos de capa de mapa de teselas en el inspector. El nodo de capa de mapa de teselas no puede dibujar nada hasta que tenga un conjunto de teselas. Al hacer clic en el menú desplegable, crearemos un nuevo conjunto de mosaicos. Luego haga clic en el conjunto de mosaicos para expandir sus propiedades. La primera opción es la forma de las baldosas en este conjunto de azulejos. Los mosaicos que estoy usando son cuadrados, pero también hay opciones para mosaicos isométricos, cuadrados de medio desplazamiento y hexágono. Estos suelen usarse para perspectivas de arriba hacia abajo, y este juego es un desplazador lateral, así que voy a estar usando fichas de forma cuadrada A continuación, tenemos que establecer el tamaño de las baldosas. Mi hoja de sprites importada tiene el tamaño de mosaico en su nombre, 32 por 32 píxeles Ignoraremos el resto de los ajustes por ahora y cambiaremos el panel inferior del editor de Tilemap a conjunto de mosaicos Ahora podemos agregar mosaicos al conjunto de mosaicos que acabamos de crear. Ya sea haciendo clic en el botón Más en la parte inferior, luego navegando por el sistema de archivos para encontrar sus activos o haciendo clic y arrastrando los activos desde la pestaña del sistema de archivos al área de fuentes de teselas Esto nos dará un aviso para que el motor divida automáticamente la hoja de sprites en mosaicos para nosotros. Si seleccionamos yes, y si establecemos el tamaño de mosaico correctamente, entonces los mosaicos en la hoja de sprites se cortarán automáticamente a ese tamaño para nosotros y se agregarán al conjunto de mosaicos Al hacer clic en el botón de borrador, podemos hacer clic en los mosaicos para eliminarlos del conjunto de mosaicos Al hacer clic y arrastrar, se borrarán todos los mosaicos que arrastramos Manteniendo el control o comando, luego haciendo clic y arrastrando, podremos eliminar todas las teselas del área seleccionada alternar la goma de borrar, podemos usar los mismos controles para agregar mosaicos al conjunto de mosaicos Si desea crear mosaicos sobredimensionados, puede hacerlo manteniendo presionada la tecla Mayús y, a continuación, haga clic y arrastre sobre varias teselas. Esto tratará múltiples mosaicos como si siempre estuvieran destinados a ser dibujados como un grupo más grande de mosaicos. Pero esta hoja de sprites no tiene fichas de gran tamaño, así que borraré esto y agregaré cada una de estas fichas al juego de mosaicos individualmente Ahora que nuestro conjunto de mosaicos contiene teselas, nuestra capa de mapa de teselas puede usar este conjunto de mosaicos para dibujar las teselas. Entonces cambiaremos del panel de conjunto de teselas al panel de mapa de teselas. Con la herramienta de pintura seleccionada, podemos seleccionar una fuente de mosaico del conjunto de mosaicos, luego una baldosa de la fuente de mosaico. En la vista de dos escenas D, el editor proporciona pautas naranjas de cómo se colocarán los mosaicos y ahora podemos pintar este azulejo donde queramos haciendo clic. Si desea cambiar el desplazamiento de las teselas, puede ajustar la posición de transformación de los nodos de la capa de tilemap posición de transformación de los nodos de la capa Al igual que en el conjunto de mosaicos, podemos usar la palanca de borrado para borrar mosaicos en lugar de pintarlos. La herramienta de selección se puede utilizar para seleccionar un mosaico de la vista T D en lugar del panel de conjunto de mosaicos Podemos dibujar mosaicos volteados horizontalmente, verticalmente o ambos y girarlos sentido horario o antihorario según sea necesario También podemos agrupar varias baldosas seleccionadas y pintarlas todas a la vez. alternar el lugar del mosaico aleatorio, esto elegirá de los mosaicos seleccionados al azar El aumento de la dispersión dejará algunas baldosas sin pintar mientras se arrastran También puedes dibujar líneas. Con múltiples mosaicos seleccionados, se repetirán a lo largo de la línea. Y la herramienta rectángulo puede llenar un área completa de la capa de mapa de teselas muy rápidamente. La herramienta de cubeta se puede utilizar para rellenar un área cerrada vacía de la capa de mapa de teselas. Las opciones aleatorias y de dispersión también se aplican a las herramientas de línea destrozada y cucharón La herramienta bucket también tiene un conmutador contiguo, que cuando está desactivado se puede usar para efectuar todas las teselas coincidentes en toda la capa del mapa de teselas. Con el nodo de capa de mapa de teselas dibujando nuestro terreno, ya no necesitamos el nodo tutti de cuerpo estático y podemos eliminarlo de la escena De vuelta a la escena del juego, podemos ver nuestra sala de inicio. El nodo no se renombra. Todavía dice nivel actual. Si ejecutamos el juego, el personaje no choca con el terreno y simplemente cae por él. Ahora tenemos una capa de mapa de teselas usando un conjunto de teselas para dibujar mosaicos, pero necesitamos hacer más trabajo para configurar nuestro conjunto de teselas. Te veré en el siguiente video. 23. 3-2 terrenos: Hola, amigos. En este video, usaremos más opciones de conjuntos de teselas para hacer que pintar mosaicos en una capa de mapa de teselas sea más rápido y fácil. Comenzando en la escena de la habitación, seleccione el nodo de capa de mapa de teselas y luego expanda el conjunto de mosaicos en el inspector. Al expandir la sección de la capa de física, actualmente está vacía, por lo que agregaremos una nueva capa de física. No necesitamos editar ninguna de las propiedades de la capa física. Solo necesita existir. Repasaremos las capas de colisión y el enmascaramiento de colisiones más adelante en el curso. Pero si quisieras, también podrías agregar un material físico para ajustar su fricción, rugosidad, rebote o absorbencia No quiero un material de física, así que lo borraré del menú desplegable. Con la capa física agregada a nuestro conjunto de mosaicos, podemos abrir la pestaña de conjunto de mosaicos en la parte inferior del editor para aplicar esta capa de física a nuestras teselas. Cambie de la configuración del atlas a las propiedades de pintura haciendo clic en este botón. Aquí podemos pintar muchas propiedades diferentes sobre nuestras baldosas, pero la que queremos pintar ahora mismo es la capa física cero. Debajo de la pintura, toda la loseta debe rellenarse con cuatro nodos blancos en todas las esquinas por defecto. Si no lo es, haga clic en los tres puntos y seleccione restablecer a la forma predeterminada o presione la tecla Fkey Ahora podemos pintar esta forma de colisión física en nuestras baldosas. Todos estos azulejos están diseñados para tener la misma forma cuadrada. Pero si estás usando diferentes activos, posible que necesites ajustar la forma de colisión para diferentes mosaicos. Podemos hacer clic y arrastrar estos puntos blancos para ajustar la forma de colisión, eliminarlos o agregar más según sea necesario para crear cualquier forma que queramos. Si necesitas una mejor vista para ser más precisos, puedes expandir este editor para llenar todo el panel. También hay opciones de ajuste de rejilla disponibles. Establecer el ajuste de cuadrícula al tamaño de píxel le permitirá crear una colisión perfecta de píxeles si lo desea A después de pintar formas de colisión en las fichas, ejecutar el juego de nuevo, tendremos al personaje colisionando con nuestras fichas Ahora tenemos colisión, pero dibujar terreno una baldosa a la vez es muy tedioso Podemos usar herramientas integradas en el editor para hacerlo más fácil. Ampliando la sección del terreno, podemos agregar un conjunto de terrenos a este conjunto de baldosas. El conjunto de terrenos necesita un terreno agregado a él también. Así que vamos a crear un elemento aquí, también. Podemos nombrar el terreno como queramos. Voy a nombrar mi bosque y darle un color. Este color no se dibujará en el juego solo en el editor como una forma de configurarlo. Ayuda a elegir un color que contrastará con los colores utilizados en la hoja de sprites para que destaque. Usaré el rosa para contrastar con mis baldosas verdes y marrones del terreno. A continuación, abra el panel de conjunto de mosaicos en la parte inferior del editor. Los terrenos son una forma de dibujar azulejos que están diseñados para conectarse entre sí como lo es esta hoja de sprites Cambiar a propiedades de pintura, y la propiedad que queremos pintar es la propiedad del terreno. Luego podemos seleccionar nuestro conjunto de terrenos que acabamos de crear el conjunto de terreno cero y el terreno en ese conjunto de terrenos, el terreno forestal. Para pintar la propiedad del terreno, primero, tenemos que seleccionar cada una de las baldosas que forman parte del terreno para que ya no estén oscuras. En esta hoja de sprites, eso son todas ellas. Al pasar el ratón sobre una baldosa que se ha agregado a este terreno, la baldosa se divide en nueve cuadrados cuadrado medio necesita ser rellenado para dibujar este azulejo como parte de nuestro terreno. Los otros cuadrados le dicen al editor que dibuje esta baldosa si hay otra baldosa de terreno adyacente a ésta en esa dirección. Comenzando con esta baldosa, esta está destinada a ser dibujada si no tiene otras baldosas de terreno adyacentes a ella. Entonces solo se pinta el cuadrado medio. El azulejo sobre el extremo izquierdo está destinado a ser dibujado si hay otra teja de terreno a la derecha de la misma, por lo que tendrá el cuadrado derecho pintado. El mosaico opuesto a la derecha sigue la misma lógica hacia la izquierda, y el mosaico medio se dibuja si hay terreno adyacente tanto a la izquierda como a la derecha. Las baldosas verticales son iguales, solo arriba y abajo. El bloque grande en la esquina superior izquierda combina estos dos, agrega esquinas, y además tiene el azulejo sólido en el medio con todos los cuadrados pintados. Esto será suficiente para dibujar bloques de terreno de forma convexa. abrir el panel de mapa de teselas, cambiar de mosaicos a terrenos, luego seleccionar el terreno que acabamos de crear Con la herramienta de pintura seleccionada, podemos pintar las teselas del terreno libremente en la capa del mapa de teselas, igual que antes. Pero ahora, si nuestras baldosas de terreno son adyacentes a otras baldosas de terreno y forman formas rectangulares, entonces se actualizarán automáticamente a la baldosa correcta del terreno. Borrar mosaicos también actualizará los mosaicos circundantes. Esto también funciona con las herramientas de naufragio de línea y cucharón. Si queremos crear esquinas cóncavas, tendremos que volver a la pintura del terreno. Al agregar cada una de las fichas restantes al terreno, rellenaremos los cuadrados que coincidan con si debería haber otra baldosa de terreno adyacente a esta en esa dirección. Si estás siguiendo junto con estos activos y no estás seguro de qué patrón se debe dibujar en cada mosaico, puedes pausar el video y copiar el mío Algunos activos de teselas proporcionarán una guía o referencia para ayudarlo con las reglas de adyacencia para mosaicos, o simplemente puede experimentar y ver qué se ve bien Intente dibujar algún terreno en una variedad de formas diferentes para ver si se tiene en cuenta cada combinación posible y dibujar apropiadamente. Las baldosas en la parte inferior también están pensadas para ser dibujadas con terreno adyacente en todas las direcciones. Cada mosaico en un mapa de teselas suele estar diseñado para tener un patrón único. Pero si tienes varias teselas con el mismo patrón, la herramienta terreno elegirá una al azar con el mismo patrón al dibujar. Podemos ajustar la probabilidad de esta aleatoriedad pintando otra propiedad de la lista desplegable probabilidad Simplemente ingrese una probabilidad. Usaré 0.01, que es 1% y pintaré esto sobre las baldosas en la parte inferior. Cada vez que la herramienta de terreno dibuja una baldosa con adyacencia en todas las direcciones, tendrá un 1% de probabilidad de dibujar cada una de estas teselas en la parte inferior o usar la baldosa en blanco por defecto Al pintar terreno desde el mapa de teselas, si la distribución aleatoria de estas teselas no se ve muy bien, puedes seguir dibujando fácilmente sobre él. El editor de terreno recalculará la distribución aleatoria cada vez Ahora podemos dibujar fácilmente salas para nuestro juego usando un nodo de capa de mapa de teselas, pero la cámara no se mueve, así que no podemos mover a nuestro personaje muy lejos. Te veré en el siguiente video. 24. 3-3 cámaras: Hola, amigos. En este video, haremos que la cámara siga al personaje para que puedan moverse más por el entorno. En la escena del juego, tenemos al personaje y cámara dos nodos D como hermanos. Obviamente, si asignamos la cámara como hijo del personaje, entonces seguirá al jugador alrededor. Sin embargo, esta no es una muy buena manera de hacerlo porque la mayoría de los juegos tendrán transiciones, escenas de corte u otras áreas del juego que se ajusten a la vista de la cámara independientemente del personaje del jugador En algunos juegos, el jugador tiene opción de elegir a qué personaje quiere jugar, y ese personaje debe estar cargado, por lo que no se puede determinar en la escena del juego que la cámara debe seguir a este personaje. Es mejor dejar la cámara como hermano y hacer que la cámara siga al personaje del jugador a través de un guión. Adjuntemos un guión a nuestra cámara para denodar. Podríamos llamarlo cámara o nombrarlo después del comportamiento, seguir al jugador o combinar los dos, seguimiento de cámara. Podríamos exportar el personaje del jugador como una variable como lo hicimos con el controlador de entrada, pero supongamos que a esta cámara se le dirá que siga a más de un personaje lo largo del juego y en su lugar defina una función pública llamada follow, que acepta un sujeto como parámetro Teóricamente, este tema podría ser cualquier cosa siempre cuando exista en el mundo dos D y tenga una posición Entonces le daremos un tipo de nodo dos D en lugar del tipo más específico de cuerpo de personaje dos D. De esa manera, se podría decir a esta cámara que siga un cuerpo rígido o cualquier otra cosa que queramos. Esta función no necesita devolver ningún valor. Todo lo que realmente necesita hacer es almacenar este tema en una variable privada. Después anulando la función de proceso, si esta cámara tiene un sujeto, entonces establecerá su posición para que sea la misma que la posición global del sujeto Dado que el sujeto puede ser parte de una escena más grande, no queremos usar su posición local relativa a su padre, sino su posición global dentro del alcance de toda la escena del juego. No estamos usando el parámetro Delta, así que procederé con un guión bajo Ahora necesitamos otro script para llamar a esta función desde un nodo que tenga acceso tanto a la cámara como a nuestro personaje, que será el nodo del juego. Adjuntando un script al nodo de juego, le pondremos a este el administrador del juego, y lo pondré en una nueva carpeta de scripts para scripts de manager. Será responsabilidad del manager del juego gestionar cuando el jugador esté jugando el juego o en una escena de corte o transitando entre escenas Por ahora, cuando el manager del juego esté listo anulando la función ready, le diremos a la cámara que siga al jugador y active el manejador de entrada Para ello, tendremos que almacenar cada uno de estos nodos en variables. Dado que la jerarquía de la escena del juego es bastante compleja en comparación con otras escenas, posible que necesitemos reorganizar los nodos, cambiando su parentesco en el proceso Cuando eso suceda, la ruta del nodo en nuestro script ya no será válida provocando errores. Podemos evitarlo haciendo clic derecho sobre los nodos nuestro árbol de escenas y seleccionando el acceso como nombre único. Esto agrega un signo de porcentaje a la derecha del nodo en el árbol de escenas. Esto nos permite reemplazar la ruta del nodo anotado del signo de dólar con el nombre único anotado del signo de porcentaje Si el nodo tiene un nombre único ya asignado, se aplicará automáticamente al mantener control o comando y arrastrarlo al script Ahora que tenemos todas estas referencias de nodo, cuando el manager del juego esté listo, podemos decirle a la cámara que siga al personaje del jugador y habilite el controlador de entrada Aún no hemos escrito una función enable para el controlador de entrada, así que cambiemos a ese script y escribamos creación de una variable privada está habilitada como booleana, que por defecto será false, y una función de habilitación pública que podemos establecer está habilitada Entonces antes de manejar cualquier entrada del reproductor, comprobaremos si el controlador de entrada está habilitado y regresaremos si no lo es saldrá de la función si está habilitado es falso, evitando que se ejecute alguno de los códigos restantes También necesitaremos una función de desactivación que establezca la variable is enabled de nuevo en false. Esto puede parecer excesivo, ya que podríamos simplemente hacer pública la variable is enabled. Pero usando esta estructura encapsulada, podemos hacer otra lógica dentro de estas funciones. Como cuando el controlador de entrada está deshabilitado, dígale al personaje que deje de moverse estableciendo la dirección a cero y también dígale que camine Al habilitar el manejador de entrada, dado que el movimiento se está comprobando en proceso, ya se detectará automáticamente Pero si el jugador comenzó a mantener presionado el botón Ejecutar antes de que se habilitara el controlador de entrada, la entrada habrá sido ignorada, pero el jugador seguirá esperando que su personaje corra Podemos verificar el estado del botón de ejecución al habilitar el controlador de entrada y decirle al personaje que se ejecute en consecuencia Si usamos la función de entrada para el movimiento, podríamos verificar el singleton de entrada para el estado del movimiento a la izquierda, eje derecho, y decirle al personaje que se mueva aquí también. Volviendo a la escena del juego, ya que la posición del personaje también está en el origen, esto es lo que dibujará la cámara cuando comience el juego. Este no es un muy buen encuadre del personaje o de la habitación Por lo general, el jugador necesita ver más de lo que está por encima de ellos o lo que le espera. Podemos darle a la cámara un desplazamiento de posición para moverla hacia arriba a lo largo del eje y y hacia la derecha a lo largo del eje X para lograrlo. Lo pondré 64 pixeles arriba y a la derecha y también cambiaré mi Zoom a dos. Entonces, cuando se establece la posición de la cámara para que coincida con la posición del personaje, cada fotograma, se compensará en esta cantidad después de eso, dando al jugador una vista ligeramente hacia arriba en la derecha del personaje. Ahora tenemos nuestra cámara siguiendo al personaje por ahí, pero la cámara solo mira a la derecha. Te veré en el siguiente video. 25. 3-4 Un vistazo al futuro: Hola, amigos. Y este video permitirá que la cámara mire por delante del personaje ya sea a la izquierda o a la derecha. Comenzando en el guión de caracteres, podemos facilitarnos las cosas proporcionando nombres de clase para algunos de nuestros scripts usando el nombre de clase de palabra clave en la parte superior del script. Nombremos a esta clase algo más genérico como carácter. Esto permitirá a Godot completar de forma automática los nombres de las variables y funciones al acceder a los miembros de esta clase en otros scripts Al igual que usamos señales para reaccionar a las acciones del personaje para producir nubes de polvo, necesitaremos hacer otra señal para cuando el personaje cambie la dirección a la que se enfrenta. Declarando una señal llamada dirección cambiada, tendremos que pasar a qué dirección se enfrenta el personaje ahora como parámetro Añadiendo otra variable a la sección de locomoción, necesitaremos saber qué dirección se encuentra el personaje actualmente para saber si ha cambiado su dirección de orientación Dado que una variable booleana naturalmente por defecto es false, voy a nombrar la variable está orientada hacia la izquierda, lo que cuando false implica que están En la función cara izquierda, podemos emitir nuestra nueva señal y pasar el valor de dirección como argumento. Oh, abajo en el proceso de física, al decirle al personaje que mire la dirección, esto sucederá cada vez el jugador dé entrada a cada fotograma. No queremos emitir esta señal en todos los fotogramas, solo en los fotogramas cuando cambian de dirección. Entonces agregaremos la condición de que el personaje esté orientado hacia la izquierda y la dirección sea mayor que cero, o el personaje no esté orientado hacia izquierda y la dirección sea menor que cero. Ahora estas funciones solo se llamarán durante el fotograma cuando el personaje realmente cambie su dirección de orientación, lo que emitirá la señal para que reaccionemos ante ella. Cambiando al script de la cámara, necesitaremos una función que coincida con la firma de la señal que acabamos de crear para conectarla. Vamos a llamarlo sobre el tema cambió de dirección, ya que el personaje será el sujeto, aceptando la dirección al que se enfrenta el personaje como flotador y no devolviendo ningún valor. Lo que queremos hacer es tener el desplazamiento X de la cámara para que coincida con el signo de dirección. Así que tendremos que almacenar el valor de offset en otra variable inalterado nombraremos offset predeterminado y lo estableceremos el valor de offset usando una etiqueta ready. Ahora podemos editar con seguridad el valor de offset sin olvidar cuál era el valor original. H. Cuando el sujeto cambie de dirección, estableceremos el valor de offset para que sea el desplazamiento predeterminado multiplicado por el signo de dirección. Entonces, si la dirección es positiva, entonces el desplazamiento de la cámara también será positivo, y de igual manera para negativo. Para conectar esta señal al decirle a la cámara que siga a un sujeto, si el sujeto no es nulo y el sujeto es un personaje, la clase que acabamos de nombrar, entonces podemos acceder de manera segura a la señal de dirección cambiada del personaje y conectarla a nuestra función. Un Godot no reconocerá los nuevos nombres de clase hasta después de que hayas guardado tus scripts Pero si llamamos a esta función de seguimiento sobre el mismo tema más de una vez por cualquier motivo, esto provocará un error ya que la señal ya está conectada. Primero, comprobemos si el sujeto que se le dice a la cámara siga es el mismo el sujeto al que ya están siguiendo. En este caso, no tenemos que hacer nada y podemos simplemente devolverlo a esta función. Ahora sabemos que el tema es algo distinto al sujeto actual. Comprobemos si el sujeto actual no es nulo y si es un carácter. Si ambos son verdaderos, entonces también deberíamos verificar si la señal de dirección cambiada del personaje se ha conectado a la función de dirección cambiada en sujeto. Y si esto es cierto, desconectaremos la señal, ya que la cámara ya no sigue al sujeto y no necesita reaccionar ante él. ejecutar el juego, esto colocará a la cámara por delante del personaje, pero sucederá instantáneamente, lo que es bastante discortante para el jugador. Lo que sería mejor es ajustar el valor de offset gradualmente a lo largo del tiempo, que es algo que podemos hacer fácilmente usando una preadolescentes, abreviatura de entre medias Entonces declararemos una nueva variable, llamaremos algo así como mirar hacia adelante tween A continuación, cuando el carácter cambia de dirección, asignando el valor de esta variable para crear tween Crear tween es una función de la clase de nodo, por lo que cualquier nodo puede usarlo. Cuando se crea la preadolescentes, accederemos a su función de propiedad Tween Esto acepta un objeto como primer argumento, que es este nodo en sí. Podemos especificar esto con la palabra clave self. Entonces la propiedad que queremos interponer como cadena, que es la propiedad offset, específicamente el componente X, que podemos especificar con los dos puntos El siguiente argumento es el valor final, que es el desplazamiento X predeterminado multiplicado por el signo de dirección que calculamos anteriormente. Y por último, la duración de la preadolescentes en segundos. Por ahora, lo pondré a 1 segundo. Dado que esta preadolescentes tardará 1 segundo, pero es muy posible que el personaje cambie de dirección varias veces durante ese 1 segundo, esto crearía múltiples preadolescentes todos tratando de editar el valor de offset al mismo tiempo Entonces antes de crear la preadolescentes, debemos verificar si ya existe primero, y si la mata De esta manera, no puede existir más de una de estas preadolescentes a la vez y estar tratando de editar el desplazamiento X. Ejecutando esto ahora, el desplazamiento X de la cámara se está tweening para mirar por delante del personaje más de 1 segundo, pero sigue siendo un poco discortante. Podemos ajustar cómo ocurre esta preadolescentes exportando algunas variables más Primero, vamos a exportar una duración para esta preadolescentes como flotante y darle un valor por defecto de 1 segundo Después sustituimos el de nuestra función con esta variable. A continuación, agregaremos un tipo de transición y un tipo de flexibilización. Juntas, estas tres variables nos permitirán crear una amplia variedad de diferentes preadolescentes ajustando la rapidez con la que cambia el valor al principio y al final de la preadolescentes. Dado que create tween devuelve una tween, podemos acceder a su función set trans y pasar nuestro tipo de transición como argumento en la misma línea La función set trans también devuelve la tween, por lo que podemos continuar esta línea y llamar a la función set Es inmediatamente después de eso, también. Pasando nuestra variable Es como argumento. Todo esto devolverá la preadolescentes con el conjunto de tipos de transición y facilidad y asignará el resultado a la variable Desde la escena del juego, seleccionando el nodo tutti de la cámara, echando un vistazo a sus propiedades en el inspector, podemos editar los valores de estas variables con los tipos de transición y flexibilización proporcionando listas desplegables convenientes También podemos hacer que la duración de la preadolescentes sea más corta o más larga Voy a hacer que el mío use un quad in out tween más de 2 segundos. Intente experimentar con las diferentes opciones para tener una idea de cómo funcionan El tipo de transición determina qué fórmula matemática se está utilizando para alterar el comportamiento, mientras que el tipo de flexibilización decide cómo afectará a la primera mitad o segunda mitad de la preadolescentes. Ahora tenemos la cámara desplazando suavemente hacia la izquierda o hacia derecha para mostrar lo que está por delante de la dirección hacia la que se enfrenta el personaje, pero a veces el jugador puede querer mirar hacia arriba y hacia abajo, también. Te veré en el siguiente video. 26. 3-5 Mira hacia arriba: Hola, amigos. En este video, permitiremos que el jugador le diga al personaje que mire hacia arriba y hacia abajo. Primero, necesitaremos agregar más eventos de entrada al mapa de entrada en la configuración del proyecto para buscar hacia arriba y hacia abajo. Voy a usar las teclas de flecha arriba y abajo. Los botones direccionales de arriba y abajo, y el stick derecho se inclinaron hacia arriba y hacia abajo. Entonces en el guión del jugador, a diferencia de la dirección de movimiento, que sólo está siendo utilizada por el personaje, la dirección de mirada será utilizada tanto por el personaje como por la cámara, lo que significa que necesitaremos una referencia a la cámara. Vale la pena almacenar la dirección de la mirada en una variable, por lo que solo necesitamos calcularla una vez por fotograma. Entonces en la función process, obtenemos su valor del singleton de entrada, la misma manera que lo hicimos con la dirección del movimiento usando la función get axis, cambiando los nombres de las acciones de entrada Recuerda que como arriba es negativo, será el primer argumento. Entonces podemos enviar esta dirección de mirada tanto al personaje como a la cámara. Para la cámara, voy a usar una llamada de función. Pero para el personaje, voy a dislocar el valor de una variable pública Para que el nombre de la variable de dirección de la clase de carácter sea un poco más claro, podría ser inteligente cambiarle el nombre para mover la dirección. Como esta función no existe en el script de la cámara, comentaré por ahora para evitar errores hasta que esté listo para escribirla. Sobre en el guión de caracteres, podemos abrir el diálogo de reemplazo con Control o Comando R y reemplazar dirección con dirección de movimiento que quede más claro para qué se utilizará. A continuación, agregue una nueva variable pública para la dirección de la mirada. La variable de dirección L no necesita ser utilizada en ninguna parte del script. Sólo será leída por el Árbol de Animación. Desde la escena de los personajes, seleccionando el Reproductor de Animación, necesitaré crear animaciones LU y L abajo. Duplicaré mi animación ociosa para facilitar las cosas. Entonces solo edita los valores Y de mis fotogramas clave para dibujar el personaje mirando hacia arriba o hacia abajo en consecuencia. Después en la máquina de estado Árbol de Animación editando la máquina de estado Locomotion, puedo agregar las animaciones de mirar hacia arriba y mirar hacia abajo Transición a ellos basada en el valor de la dirección de la mirada Y asegurándose de que su velocidad X siga siendo cero, lo contrario, deberían hacer la transición para caminar en su lugar. Y volver al ralentí en el caso que la dirección de la mirada sea igual a cero. O si han empezado a caminar, esto tendrá al personaje animando para mirar hacia arriba o hacia abajo a medida que presionamos las direcciones arriba y abajo, pero la cámara aún no se mueve. En la escena del juego, intenta alterar el desplazamiento Y de la cámara y decide hasta dónde te gustaría que se moviera la cámara cuando el personaje mira hacia arriba o hacia abajo. Usaré 128 píxeles y volveré a restablecer al valor predeterminado de 64 negativo. Volviendo al guión del reproductor, descomentaré la función de cámara ahora, luego cambiaré al guión de la cámara para declarar esta función Aceptaré una dirección como flotador y no devolveré ningún valor. El cuerpo de esta función será casi idéntico a la función de dirección en sujeto cambiado. Todo lo que tenemos que hacer es sustituir todas las instancias de una cabeza con arriba abajo. Después declararlas como nuevas variables. También necesitaremos otra variable exportada para la distancia máxima de mirada que decidimos anteriormente, que usaremos en lugar del desplazamiento predeterminado, y el desplazamiento X será compensado Y. Sin embargo, cuando soltamos las flechas arriba o abajo, queremos que la cámara vuelva al valor de desplazamiento predeterminado, no a cero. Entonces esto requerirá un poco de lógica extra. Otra forma de agregar sentencias if simples a tus scripts es usar una operación ternaria, que en GDScript usa las mismas palabras clave if que una sentencia if normal, comenzando por el caso predeterminado, que es el valor que ya hemos calculado, pero solo si direction no es cero, seguido Entonces, si la dirección es cero, entonces queremos usar nuestro desplazamiento Y predeterminado en su lugar. Esto funciona, pero en la mayoría de los juegos que tienen esta mecánica, el jugador tiene que mantener presionado el botón durante algún tiempo antes de que la cámara se mueva. Podemos lograr esto agregando un nodo temporizador al nodo jugador. Vamos a llamarlo. Mira, sostén. Podemos ajustar el tiempo de espera del inspector, pero 1 segundo está bien, y el temporizador tendrá que ser un disparo único. Conectando la señal de tiempo de espera de este temporizador al guión del jugador, Esto es cuando el guión de los jugadores le dirá la cámara que comience a mirar hacia la dirección En la parte superior del guión, tendremos que tomar una referencia al antiguo nodo temporizador, y también necesitaremos un booleano para que sepamos si el jugador está buscando actualmente o En la función de proceso, después de obtener el valor de dirección de la mirada de la entrada Singleton, si el jugador ya está mirando, entonces también si la dirección de la mirada es cero, reiniciaremos la cámara llamando a su función look y pasando cero como argumento Entonces set está buscando a false. La razón por la que no usé una declaración y es para que pueda usar un else si aquí y ahora asumir que está buscando es falso. Entonces también verifica si la dirección de la mirada no es cero. En este escenario, donde el jugador aún no está buscando, pero está dando entrada de dirección de mirada, entonces si se detiene el temporizador de espera , tendremos que iniciarlo. Añadiendo una más si el jugador no está mirando y no está dando ninguna entrada de dirección de mirada, entonces también si el temporizador de retención de mirada no se detiene, eso significa que tenemos que detenerlo y cancelar el look. Añadiendo declaraciones impresas para todos estos, podemos confirmar que cada uno es llamado solo una vez cuando sea apropiado. También tendremos que establecer la variable is looking true cuando el temporizador de espera de mirada se agota y la cámara comience a interconectarse. Ejecutando el juego, tocando las flechas arriba o abajo sin sostenerlo, el temporizador de espera se inicia pero se detiene y la cámara no se mueve, pero el personaje sigue animando mirando hacia arriba y hacia abajo mantener presionadas las teclas arriba o abajo, el temporizador se agota después 1 segundo y le dice a la cámara que mire hacia arriba o hacia abajo. Al soltar las teclas arriba o abajo, la cámara se restablece de nuevo a su posición de desplazamiento predeterminada. Voy a comentar estas declaraciones impresas y ajustar mi configuración de pregeneración en el inspector para cuadriplicar más de medio segundo El jugador ahora puede mantener presionadas las direcciones arriba y abajo para mirar hacia arriba y hacia abajo, pero es posible que queramos restringir hasta dónde puede moverse la cámara para evitar mostrar contenido fuera de la sala actual. Te veré en el siguiente video. 27. 3-6 Límites: Hola, amigos. En este video, restringiremos la cámara para que se mantenga dentro de los límites del entorno. Comenzando en la escena de la sala, podemos cambiar el nodo raíz para que sea un nodo D del área dos en lugar de solo un nodo D normal de dos. Esto es similar a un cuerpo de física en que tiene forma de colisión, pero no tiene masa ni reacciona a las fuerzas. En cambio, se puede pensar en ello como un detector de movimiento o calor. Representa una región del espacio y emitirá una señal cuando los cuerpos físicos entren o salgan de ella. Esto será útil más adelante para detectar cuando el personaje jugador entra en la sala. Pero por ahora, todo lo que necesitamos saber es qué forma es. Al agregar una forma de colisión para denotar como un niño, podemos darle un recurso de forma Usaremos forma de rectángulo. Luego podemos movernos y cambiar el tamaño de la forma para crear límites de habitación A adjuntando un script al nodo raíz de la escena, lo llamaremos Room y lo ordenaremos en la carpeta de scripts. Necesitaremos una referencia a la forma de colisión para dende. Voy a renombrarlo para dar forma a nodo. Entonces necesitamos funciones que puedan ser utilizadas para recuperar la esquina superior izquierda y la esquina inferior derecha de este rectángulo para que devuelvan dos coordenadas vectoriales. Podemos acceder a la forma de colisión dos denodes shape propiedad por su nombre Entonces también queremos llamar a una función sobre el recurso shape, Get wrecked La función G wrecked devuelve un naufragio dos, que si abrimos la documentación para esta clase, podemos ver que tiene una posición y un final La posición es la esquina superior izquierda y el final es la esquina inferior derecha. Pero estos son relativos a la posición de los nodos. Necesitaremos estas coordenadas en el espacio global, por lo que las agregaremos a la posición global de los nodos. La posición global de un nodo será relativa al origen del juego, no a la posición de los nodos padre. Entonces podemos devolver estos valores. Ahora, todo lo que tenemos que hacer es decirle la cámara que se mantenga dentro de estos límites. De la escena del manager del juego, por ahora, solo tomaremos una referencia a la sala de inicio y la almacenaremos en una variable llamada current room. Cuando la escena del juego esté lista, podemos obtener la esquina superior izquierda y la esquina inferior derecha de la sala actual, y las pasaremos a la cámara llamando a una función que establece sus límites. Cambiando al script de la cámara, declararemos esta función aceptando los dos vectores dos recuperados de la habitación actual y no devolviendo ningún valor En esta función, descubriremos qué tan cerca puede llegar la cámara a las esquinas superior izquierda e inferior derecha de esta habitación sin ver nada más allá de esos puntos. Para ello, necesitaremos crear estas variables como vectores de dos, y nos ayudará tener un booleano para saber si la cámara está enlazada actualmente o no También necesitaremos conocer el tamaño de la Viewport, que podemos recuperar automáticamente con la función Get Viewport, luego acceder a su propiedad size y almacenarla en una variable usando la etiqueta on ready La función Get Viewport se declara en la clase node y devuelve un vector dos, coincidiendo con el tamaño de la ventana que establecemos en la configuración del proyecto Este tamaño de la ventana gráfica no es necesariamente el mismo que la cantidad de píxeles que dibujará la cámara, ya que la cámara puede acercar o alejar. Tendremos que dividir el tamaño de la ventana gráfica por el Zoom de la cámara para obtener el tamaño real de píxeles del área que la cámara puede ver Pero un vector no se puede dividir por otro vector. Tenemos que usar un flotador. Usaré solo el Zoom X y asumiré que las cámaras Zoom siempre serán uniformes. Pero esto todavía no es lo suficientemente bueno porque la posición de la cámara está en el centro de su visión. La posición más cercana que la cámara pueda posicionarse a la esquina superior izquierda o inferior derecha de la habitación sin dibujar más allá estos puntos será en realidad la mitad del tamaño. Dividiendo este valor por dos, cambiaré el nombre de la variable para reflejar su nuevo valor. Al establecer los límites, la posición superior izquierda será la esquina superior izquierda de la habitación más la mitad del tamaño de la vista de la cámara. Mientras que la posición inferior derecha más será la esquina inferior derecha de la habitación menos la mitad del tamaño de la vista de la cámara, y podemos establecer el valor de is bound en true. H. En la función de proceso, después de decirle a la cámara que coincida con la posición del sujeto, entonces aplicaremos estas restricciones de límite usando la función Abrazadera F. La función clamp F toma un parámetro flotante como la posición de la cámara, luego un valor mínimo y un valor máximo, luego devuelve un valor que permanecerá dentro de esos límites. Luego sobrescribiremos la posición de la cámara con el resultado sujetado y repetiremos esto para la Y. Pero como nuestra cámara también tiene un desplazamiento, su posición no es una representación lo suficientemente precisa del centro de su También estamos editando el valor del offset en momentos impredecibles. Entonces no es algo que podamos factorizar en los cálculos de la parte superior izquierda e inferior derecha, ya que el valor probablemente cambiará a menudo. Así que tendremos que factorizar el desplazamiento en las funciones de sujeción restándolo de la parte superior izquierda e inferior derecha cada vez Si quieres que tu cámara se acerque y apague durante el juego sin dejar de respetar estos límites, también necesitarás factorizarlos en los cálculos dentro de la función de proceso Esto funciona, pero los preadolescentes de cámara parecen luchar contra los límites de los límites La preadolescentes mueve el desplazamiento de la cámara ligeramente fuera de los límites El fotograma se dibuja, luego el siguiente bucle de proceso empuja la posición de la cámara lejos del límite para compensar el nuevo desplazamiento. Esto sucede repetidamente hasta que la preadolescentes se detiene. Esto se debe a que las preadolescentes se ejecutan después del proceso al final del fotograma justo antes de dibujar todo en pantalla Para solucionar esto, podemos cambiar nuestras preadolescentes de usar la propiedad tween al método tween en su lugar Al llamar a un método, podemos aplicar los límites de límite al mismo tiempo que estamos cambiando el valor de offset. Los argumentos para el método tween, en lugar de una referencia a un objeto, necesita un método invocable Diremos set Y offset. Seguido del valor inicial, que es el valor actual del desplazamiento Y de la cámara, entonces los argumentos restantes son los mismos. Dos es el valor final al final de la preadolescentes y la duración de la preadolescentes. Podemos hacer lo mismo con la mirada hacia delante entre dos. Sólo tenemos que escribir este conjunto de función de desplazamiento X, aceptando un solo parámetro que coincida con el tipo de los argumentos from y dos. Después de cambiar el valor del desplazamiento X, podemos imponer el límite límite en la posición de la cámara para compensar inmediatamente y hacer lo mismo para el desplazamiento y. Ejecutando esto ahora, los preadolescentes compensados no alcanzarán su punto máximo más allá de los límites de la habitación Ahora tenemos la cámara limitada para mostrar solo lo que hay en la sala actual, pero el ambiente se ve muy plano. Te veré en el siguiente video. 28. 3-7 Parallax: Hola, amigos. En este video, arreglaremos el desplazamiento de paralaje del primer plano y fondo con Comenzando en la escena de la segunda sala, voy a copiar todos mis colores de modulación de los nodos Parallax Tut a sus nodos hijos Entonces puedo unparent a los sprites y eliminar los nodos Parallax Tut mientras sigo manteniendo Luego adjuntaré un nuevo script a cualquiera de estos sprites, lo nombraré Parallax y lo pondré en la carpeta de scripts Este mismo script se puede adjuntar a todos los sprites que quiero a Parallax Para crear un comportamiento personalizado, ayuda tomar algún tiempo para pensar qué es lo que estás tratando de lograr, qué referencias de nodo y otra información se requerirá. Tengo varios sprites diferentes. Quiero moverme en diferentes cantidades relación con la posición de la cámara, y sé que la cámara está actualmente encuadernada dentro de los límites de esta sala. Agregaré temporalmente una cámara dos nodos D a la escena y acercaré por un factor de dos para fingir que esta es la escena del juego. Si la cámara está exactamente en el centro de esta habitación, quería dibujar todo exactamente como está. Pero cuando la cámara se aleja del centro, moveré todos los sprites de paralaje una cantidad relativa con fondo moviéndose menos que la cámara y los elementos primer plano moviéndose en la dirección Para ello, cada sprite necesitará conocer la posición de la cámara relativa al centro de la habitación, así como su propia posición original En el script Parallax, declararé una variable exportada para contener el factor por el cual el sprite se mueve con relación a la cámara y le nombraré escala de desplazamiento como vector dos Esto funcionará de manera similar a la variable de escala de desplazamiento en el nodo Parallax two D. Cuando esta sala se carga en el árbol de escenas, podemos usar la etiqueta on ready para obtener su posición y almacenarla en una variable como la posición original. Obtener una referencia a la cámara actual es fácil gracias a la función nodo G Viewport Devolviendo el Viewport en el que existe este nodo, que también tiene la función Get camera to D para obtener la cámara También podemos almacenar esto en una variable, usando la etiqueta on ready. Anulando la función de proceso, no necesitamos Delta y podemos marcarla como no utilizada Simplemente configuraré la posición del sprite para que sea su posición original más la distancia de la cámara desde el punto medio de la habitación multiplicada por la escala de desplazamiento Ahora la cámara solo necesita una función pública que nos pueda decir su posición relativa al punto medio de la sala actual Cambiando al guión de la cámara, escribiré esta función, desplazada desde el punto medio, que será la posición de la cámara más su desplazamiento menos el punto medio de la habitación actual Declarando esto como una nueva variable, puedo calcularla como el promedio de la esquina superior izquierda e inferior derecha de la habitación al aceptarlas desde la función de límites establecidos Podríamos modificar esta función para aceptar el punto medio y tamaño del rectángulo en lugar de sus esquinas superior izquierda e inferior derecha, pero de todos modos no hará ninguna diferencia en eficiencia, así que no me molestaré Ahora podemos establecer la escala de desplazamiento para cada uno de los sprites de paralaje para darles a cada uno una distancia diferente de la cámara Todavía solo usaré paralaje horizontal, dando a mis colinas una escala de desplazamiento de un tercio a lo largo del eje X, y las colinas más atrás dos tercios Para el primer plano, necesitarán moverse en dirección opuesta a la de la cámara, tendrán una escala de desplazamiento de un tercio negativo y dos tercios negativos Esto será suficiente para crear la ilusión de profundidad para nuestras habitaciones. ejecutar el juego, podemos pasar a la segunda sala y ver que el efecto de paralaje se ve idéntico al de la sala de inicio, a pesar de ser realizado por un guión muy sencillo Dado que los sprites de primer plano se mueven en la dirección opuesta a la cámara, necesitarán repetir y envolver su posición para crear un bucle infinito, o simplemente podemos hacer que el sprite sea más grande que la Hacer mis arbustos 1.5 veces más largos que la habitación y la hierba duplicar la longitud de la habitación dejará suficiente extra a ambos lados para que los bordes nunca lleguen a la vista de la cámara A sería posible utilizar el nodo Parallax two D para dibujar el primer plano y el fondo usando Viewport separado y fondo usando Viewport separado dibujarlos en diferentes capas de lienzo o intentar dibujar siempre habitación actual en el origen de la escena del juego Estas soluciones llevarían a otras complicaciones y limitaciones en el futuro a la hora de dibujar el mapa del juego, por ejemplo. Me parece que escribir soluciones personalizadas como esta a veces es más fácil que usar los nodos proporcionados. La solución también mantiene todo para una habitación en un solo lugar, lo que simplifica el diseño y construcción de las habitaciones de una manera más intuitiva. Ya no necesito esta cámara nodo Tuti, así que la eliminaré. Eliminando las nubes del nodo Parallax touti, podemos alterar el script Parallax, también auto scroll las nubes también Ampliando el naufragio de la región, todo lo que necesitamos hacer para mover las nubes hacia la derecha es disminuir el valor de exposición con Adjuntando el script Parallax a este nodo, primero podemos establecer su escala de desplazamiento uno para que coincida con el movimiento de la cámara Esto hará que las nubes aparezcan una distancia infinita en comparación con las colinas Parallax Al exportar otro vector dos para la velocidad de desplazamiento automático, necesitaremos usar Delta en la función de proceso ahora y podemos eliminar el guión bajo Accediendo a la propiedad region rect y su posición, comenzando con la X, restaremos el valor AutoScrollX Entonces esto hará que la velocidad de desplazamiento automático píxeles por segundo. Después asigne el resultado a la región recs X posición. Pero si tuviéramos que ejecutar esto por mucho tiempo, este número se acercaría a los límites de un número de punto flotante y puede causar problemas. El valor de la posición X coincide con el tamaño, el resultado es en realidad el mismo. Sería mejor restablecer la posición X de nuevo a cero cuando esto suceda, que podamos recorrer esto por una cantidad infinita de tiempo. Usando la función AP F, podemos proporcionar un valor mínimo y máximo para limitarlo a estar solo entre cero y el tamaño rec. Esta función devolverá un resultado que debe estar entre estos dos valores, pero a diferencia del pinzamiento, el resto seguirá siendo incluido en el resultado. Y podemos hacer lo mismo si queremos usar el desplazamiento automático vertical a Voy a dar a las nubes un gran desplazamiento automático a lo largo de la X para demostración. Y cuando ejecutamos el juego, las nubes se desplazan auto hacia la derecha, dando vueltas infinitamente. Mamá. Mamá. Volveré a restablecer el valor de desplazamiento automático a una cantidad razonable. Ahora tenemos el desplazamiento de paralaje de primer plano y fondo Pero las transiciones entre habitaciones es muy repentina. Te veré en el siguiente video. 29. 4-1 Contenidos: Hola, amigos. En esta sección, permitiremos que el jugador se mueva entre varias salas en nuestro juego. Al abrir la escena de la sala de inicio, podemos ver que los componentes visuales de esta sala van fuera de los límites de la cámara. Si estuviéramos en una habitación contigua a esta, no nos gustaría ver a estos sprites dibujando cuando están destinados a estar en una habitación diferente Además, si imagináramos todo nuestro juego lleno de muchas salas diferentes, sería un enorme desperdicio de recursos tener todos sus componentes visuales cargados cuando solo estamos viendo uno a la vez. Entonces agregaremos otro nodo dos D a la escena. Denle el nombre contenido. Luego repare todos estos otros nodos al nodo de contenido, excepto la forma de colisión Al hacer clic derecho en el nodo de contenidos, lo guardaremos como escena propia. Voy a hacer una nueva carpeta en la carpeta de habitaciones del bosque para el contenido. Después nombra la escena Contenido de la sala de inicio. Después borra el contenido de esta escena. Cuando el personaje jugador entra en esta sala, todo lo que tenemos que hacer es cargar su contenido y agregarlo a la escena. Después borre los contenidos cuando se vayan. Podemos detectar cuando el personaje jugador entra en la habitación conectando su cuerpo ingresado señal, ya que el cuerpo del personaje nodo Tutti es un cuerpo físico Conectando esta señal al script de la sala, automáticamente agregará una función para nosotros en el cuerpo ingresado, aceptando el cuerpo como parámetro. No necesitamos el cuerpo, por lo que podemos proceder con un guión bajo para marcarlo como no utilizado En la parte superior del guión, será útil darle a este script un nombre de clase. Vamos a llamarlo Habitación. Después exportar los contenidos vistos como una escena repleta. Y llene esta variable haciendo clic y arrastrando la escena de contenido desde la pestaña del sistema de archivos al inspector También declararemos una variable content como un nodo dos D. Declarando una nueva función llamada load contents I content es nulo, entonces le asignaremos el valor de los contenidos vistos instanciados Después agrega el nodo de contenido a la escena como hijo. Cuando el personaje jugador entre a esta sala, llamaremos a la función de carga de contenido. Imprimamos temporalmente el valor del cuerpo para que podamos ver de qué se trata. También necesitaremos otra función para descargar los contenidos de la sala cuando ya no sean necesarios, aunque no podremos probarlo hasta el siguiente video Primero, comprobando si hay algún contenido a descargar. Si hay contenido, llame a su función Qu free y establezca la variable en null. Liberar un nodo del árbol de escenas no borra automáticamente el contenido de la variable Entonces, si tuviéramos que salir de una habitación, descargar su contenido, luego volver a entrar en esa misma habitación, esta declaración if, comprobando si el valor de los contenidos es nulo, diría, sí, en realidad hay algo en esta variable de contenidos Sin embargo, el nodo que se almacenó aquí fue previamente liberado del árbol de escenas, por lo que provocará un error Entonces, establecer la variable en null después eliminarla del árbol de escenas soluciona este problema. Al ejecutar el juego, nuestro personaje está dentro del área de colisión de la sala de inicio, por lo que activa la carga del contenido de la sala de inicio. Sin embargo, no queremos que otros cuerpos físicos activen la señal y carguen accidentalmente el contenido de la habitación Tenemos que asegurarnos de que el personaje del jugador será el único cuerpo que pueda hacer que esto suceda. Al cambiar a la escena del personaje del jugador, podemos seleccionar el nodo Tutti del cuerpo del personaje y expandir la sección de colisión en las propiedades heredadas del objeto de colisión Aquí tenemos una capa de colisión y una máscara de colisión, cada una con 32 botones numerados. Estas son máscaras de bits, que son solo números enteros utilizados de una manera particular. Dado que los números enteros se almacenan como 32 ceros binarios y unos, podemos usar cada bit individual como capa Cuando llega el momento de verificar si hay colisiones, aplicando operaciones lógicas simples entre máscara de colisión de un objeto con la capa de colisión del otro objeto, podemos determinar si deben colisionar o Solo si la máscara del primer objeto tiene uno en la misma posición de bit que la capa del segundo objeto desencadenará una colisión. De lo contrario, simplemente pasará como si no estuviera ahí. Cambiando la capa de colisión del personaje a cualquier otro número, ahora existirá en su propia capa de colisión única separada de todo lo demás en el juego. Como los números están en grupos de ocho, me gusta usar las primeras ocho capas para capas de colisión ambiental, las siguientes ocho para el personaje del jugador, las siguientes ocho para los enemigos, etcétera El cuerpo del personaje sigue enmascarando la capa uno, por lo que seguirá colisionando con el terreno durante su proceso de física cuando llamemos move y Slide Podemos nombrar estas capas en la configuración del proyecto bajo nombres de capa Física dos D. Nombraré a la capa uno como terreno y a la capa nueve como jugador. Estos nombres se mostrarán al pasar el mouse sobre los botones de capa en el inspector, junto con su bit y valor entero En la escena de la sala de inicio, podemos cambiar la máscara de colisión, por lo que esta área dos dende solo enmascarará la capa de colisión del personaje del jugador, solo el personaje del jugador activará colisiones con esta Ejecutando el juego de nuevo, nada va a cambiar, pero podemos estar seguros de que ningún otro cuerpo va a estar cargando el contenido de la sala. Ahora tenemos nuestra sala cargando dinámicamente su contenido cuando el personaje jugador entra en ella, pero todavía solo tenemos una habitación. Te veré en el siguiente video. 30. 4 a 2 habitaciones: Hola, amigos. En este video, agregaremos una segunda habitación para que el personaje se mueva. Comenzaremos duplicando la escena de la sala de inicio. Voy a nombrar a esta habitación de 1 segundo. Luego también duplique la escena de contenido de la sala de inicio y la abra para que pueda editarla, luego quitar los árboles y el dosel para que sea visualmente distinto de la sala de inicio. También podemos editar el terreno y los límites si queremos que las dos habitaciones sean aún más distintas. Al abrir la escena de la segunda sala, cambiaré el nombre del nodo raíz de la escena para que coincida con su nombre de archivo. No olvides asignar la segunda escena de contenido de habitaciones en la segunda escena de espacio de habitación para que cargue el contenido correcto cuando se ingrese. En la escena del juego, ya que mi mundo se dividirá en regiones, agregaré un nodo dos D y lo nombraré bosque. Entonces hacer de mis dos habitaciones hijos de la región forestal. Guarde la región forestal como su propia escena en la carpeta de habitaciones y abra la escena de la región forestal para editarla. En la escena de la región forestal, ahora podemos posicionar fácilmente estas dos habitaciones una al lado de la otra. Queremos posicionar las habitaciones una al lado de la otra para que podamos cambiar de habitación cuando el jugador salga de una habitación y entre a otra. Alternar el ajuste de cuadrícula, luego expandir las opciones de alineación y seleccionar Podemos establecer el paso de la cuadrícula al tamaño de mosaico de nuestros mosaicos de terreno -32 píxeles Esto hace que sea muy sencillo posicionar las habitaciones exactamente alineadas una al lado de la otra. La señal ingresada en el cuerpo de los nodos Tutti del área se emitirá tan pronto como la forma de colisión del personaje Tutti se superponga con la forma de colisión de la habitación Para mantener las cosas simples, tendremos que dejar un poco de espacio entre habitaciones lo suficientemente grande como para que el cuerpo del personaje no pueda superponerse con más de una habitación a la vez. De lo contrario, necesitaríamos agregar lógica extra para cuando el personaje entra en una habitación sin salir completamente de la anterior. Su cuerpo de personaje se solapa con las áreas de ambas habitaciones al mismo tiempo, pero luego se da la vuelta y vuelve a la primera habitación Es mucho más fácil si las habitaciones están espaciadas. Cuando el personaje entra en una nueva habitación, sabemos que ya han salido de la habitación anterior Esto también permitirá que el personaje se mueva completamente fuera los límites de la cámara antes activar la transición a la nueva habitación Dado que la forma de colisión de mi personaje tiene solo 12 píxeles ancho y la brecha entre las habitaciones es de 32 píxeles de ancho, sé con certeza que el personaje encajará entre estas dos habitaciones sin tocar ambas al mismo tiempo. Tener esta brecha significa que todas nuestras habitaciones también necesitarán extender su colisión en el piso lo suficiente fuera de los límites de la cámara de habitación para evitar que el personaje se caiga antes de que llegue a la habitación contigua Alejaré un poco la cámara y comentaré la línea de código que une la cámara a los límites de la habitación actual. Al ejecutar el juego, podemos ver que los contenidos de la sala de inicio se cargan de inmediato porque el personaje ya estaba dentro de esta sala. Pasando a donde estará la segunda sala, su contenido se carga tan pronto como el personaje jugador cruza el umbral. Pero también queremos descargar el contenido de la habitación anterior que acabamos de dejar Será responsabilidad del manager del juego manejar las transiciones, ya que involucrará a muchos componentes de la escena del juego trabajando juntos. Tendremos que enviar una señal desde la sala en la que se ingresó al manager del juego, que ni siquiera están en la misma escena en nuestro proyecto. También tendremos muchas salas diferentes en nuestro juego y sería un dolor tener que conectar manualmente esta señal para cada habitación individual una a la vez. Por lo que sería más fácil usar nuestros scripts para automatizarlo. Desde el guión de la sala, agregaremos una nueva señal en la parte superior del guión que podemos emitir para decir que el personaje del jugador ha entrado esta sala con la habitación que se ingresó como parámetro. Entonces, cuando se reciba la señal ingresada del cuerpo, emitiremos esta señal en lugar de cargar el contenido y pasaremos esta sala misma como argumento. Cuando esta sala esté lista, podemos acceder a la raíz de árboles de escena iniciando una muñeca o firmar la ruta de nodo anotado con una diagonal hacia adelante, luego la palabra raíz y otra diagonal hacia adelante Desde la escena Raíz del árbol, el primer nodo al que queremos acceder se llama juego tal como se nombra en la escena del juego. Esto nos da acceso al guión del manager del juego con un punto. Entonces podemos hacer referencia a una función que aún no hemos escrito. Vamos a llamarlo en el jugador ingresó a la habitación. Entonces podemos escribir esta función en el script del administrador de juegos con un parámetro de sala coincidente. Lo voy a nombrar habitación Entró para ser más claros en este contexto. Para descargar el contenido de la sala anterior, necesitaremos saber cuál era la habitación anterior, así que necesitaremos una variable para mantener la sala en la que se encuentra actualmente el personaje del jugador Voy a reemplazar este nivel actual habitación actual y lo dejaré vacío. Ya no necesito la etiqueta lista. Lo primero que debemos hacer es verificar si la habitación que se ingresa es la misma que la habitación en la que se encuentra actualmente el personaje del jugador. En cuyo caso, realmente no necesitamos hacer nada y podemos simplemente regresar de esta función. Ahora podemos suponer que la habitación actual y la habitación ingresada son habitaciones diferentes. Al comenzar el juego por primera vez, no hay habitación actual. Primero comprobaremos si la habitación actual no es nula. Si hay una habitación actual, debemos indicarle que descargue su contenido usando la función que escribimos en el video anterior Después asignando habitación actual para que sea la habitación ingresada, ahora podemos decirle a esta sala actual que cargue su contenido y finalmente ate la cámara a los límites de la habitación actual Pero voy a comentar esto para que podamos ver qué pasa con el zoom hacia fuera. Ahora cuando ejecutamos el juego, entrar a la segunda sala envía una señal al gestor del juego para descargar el contenido de la sala de inicio antes de cargar los contenidos de la segunda sala Ahora tenemos múltiples salas en nuestro juego, pero el desplazamiento de paralaje de primer plano y fondo no funciona para salas que no están centradas en el origen de Te veré en el siguiente video. 31. 4-3 Parallax: Hola, amigos. En este video, arreglaremos el desplazamiento de paralaje del primer plano y fondo con Comenzando en la escena de la segunda sala, voy a copiar todos mis colores de modulación de los nodos Parallax Tut a sus nodos hijos Entonces puedo unparent a los sprites y eliminar los nodos Parallax Tut mientras sigo manteniendo Luego adjuntaré un nuevo script a cualquiera de estos sprites, lo nombraré Parallax y lo pondré en la carpeta de scripts Este mismo script se puede adjuntar a todos los sprites que quiero a Parallax Para crear un comportamiento personalizado, ayuda tomar algún tiempo para pensar qué es lo que estás tratando de lograr, qué referencias de nodo y otra información se requerirá. Tengo un número de sprites diferentes. Quiero moverme en diferentes cantidades relación con la posición de la cámara, y sé que la cámara está actualmente encuadernada dentro de los límites de esta sala. Agregaré temporalmente una cámara dos nodos D a la escena y acercaré por un factor de dos para fingir que esta es la escena del juego. Si la cámara está exactamente en el centro de esta habitación, quería dibujar todo exactamente como está. Pero cuando la cámara se aleja del centro, moveré todos los sprites de paralaje una cantidad relativa con fondo moviéndose menos que la cámara y los elementos primer plano moviéndose en la dirección Para ello, cada sprite necesitará conocer la posición de la cámara relativa al centro de la habitación, así como su propia posición original En el script Parallax, declararé una variable exportada para contener el factor por el cual el sprite se mueve con relación a la cámara y le nombraré escala de desplazamiento como vector dos Esto funcionará de manera similar a la variable de escala de desplazamiento en el nodo Parallax two D. Cuando esta sala se carga en el árbol de escenas, podemos usar la etiqueta on ready para obtener su posición y almacenarla en una variable como la posición original. Conseguir una referencia a la cámara actual es fácil gracias a la función nodo G Viewport Devolviendo el Viewport en el que existe este nodo, que además cuenta con la función Get camera to D para obtener la cámara También podemos almacenar esto en una variable, usando la etiqueta on ready. Anulando la función de proceso, no necesitamos Delta y podemos marcarla como no utilizada Simplemente estableceré la posición del sprite para que sea su posición original más la distancia de la cámara desde el punto medio de la habitación multiplicada por la escala de desplazamiento Ahora la cámara solo necesita una función pública que pueda decirnos su posición relativa al punto medio de la sala actual Cambiando al guión de la cámara, escribiré esta función, desplazada desde el punto medio, que será la posición de la cámara más su desplazamiento menos el punto medio de la habitación actual Declarando esto como una nueva variable, puedo calcularla como el promedio de la esquina superior izquierda e inferior derecha de la habitación al aceptarlas desde la función de límites establecidos Podríamos modificar esta función para aceptar el punto medio y tamaño del rectángulo en lugar de sus esquinas superior izquierda e inferior derecha, pero de todos modos no hará ninguna diferencia en eficiencia, así que no me molestaré Ahora podemos establecer la escala de desplazamiento para cada uno de los sprites de paralaje para darles a cada uno una distancia diferente de la cámara Todavía solo usaré paralaje horizontal, dando a mis colinas una escala de desplazamiento de un tercio a lo largo del eje X, y las colinas más atrás dos tercios Para el primer plano, necesitarán moverse en dirección opuesta a la de la cámara, tendrán una escala de desplazamiento de un tercio negativo y dos tercios negativos Esto será suficiente para crear la ilusión de profundidad para nuestras habitaciones. ejecutar el juego, podemos pasar a la segunda sala y ver que el efecto de paralaje se ve idéntico al de la sala de inicio, a pesar de ser realizado por un guión muy sencillo Dado que los sprites de primer plano se mueven en la dirección opuesta a la cámara, necesitarán repetir y envolver su posición para crear un bucle infinito, o simplemente podemos hacer que el sprite sea más grande que la Hacer mis arbustos 1.5 veces más largos que la habitación y la hierba duplicar la longitud de la habitación dejará suficiente extra a ambos lados para que los bordes nunca lleguen a la vista de la cámara A sería posible utilizar el nodo Parallax two D para dibujar el primer plano y el fondo usando Viewport separado y fondo usando Viewport separado dibujarlos en diferentes capas de lienzo o intentar dibujar siempre habitación actual en el origen de la escena del juego Estas soluciones llevarían a otras complicaciones y limitaciones en el futuro a la hora de dibujar el mapa del juego, por ejemplo. Me parece que escribir soluciones personalizadas como esta a veces es más fácil que usar los nodos proporcionados. La solución también mantiene todo para una habitación en un solo lugar, lo que simplifica el diseño y construcción de las habitaciones de una manera más intuitiva. Ya no necesito esta cámara nodo Tuti, así que la eliminaré. Eliminando las nubes del nodo Parallax touti, podemos alterar el script Parallax, también auto scroll las nubes también Ampliando el naufragio de la región, todo lo que necesitamos hacer para mover las nubes hacia la derecha es disminuir el valor de exposición con Adjuntando el script Parallax a este nodo, primero podemos establecer su escala de desplazamiento uno para que coincida con el movimiento de la cámara Esto hará que las nubes aparezcan una distancia infinita en comparación con las colinas Parallax Al exportar otro vector dos para la velocidad de desplazamiento automático, necesitaremos usar Delta en la función de proceso ahora y podemos eliminar el guión bajo Accediendo a la propiedad region rect y su posición, comenzando con la X, restaremos el valor AutoScrollX Entonces esto hará que la velocidad de desplazamiento automático píxeles por segundo. Después asigne el resultado a la región recs X posición. Pero si tuviéramos que ejecutar esto por mucho tiempo, este número se acercaría a los límites de un número de punto flotante y puede causar problemas. El valor de la posición X coincide con el tamaño, el resultado es en realidad el mismo. Sería mejor restablecer la posición X de nuevo a cero cuando esto suceda, que podamos recorrer esto por una cantidad infinita de tiempo. Usando la función AP F, podemos proporcionar un valor mínimo y máximo para limitarlo a estar solo entre cero y el tamaño rec. Esta función devolverá un resultado que debe estar entre estos dos valores, pero a diferencia del pinzamiento, el resto seguirá siendo incluido en el resultado. Y podemos hacer lo mismo si queremos usar el desplazamiento automático vertical a Voy a dar a las nubes un gran desplazamiento automático a lo largo de la X para demostración. Y cuando ejecutamos el juego, las nubes se desplazan auto hacia la derecha, dando vueltas infinitamente. Mamá. Mamá. Volveré a restablecer el valor de desplazamiento automático a una cantidad razonable. Ahora tenemos el desplazamiento de paralaje de primer plano y fondo Pero las transiciones entre habitaciones es muy repentina. Te veré en el siguiente video. 32. 4-4 Transición: Hola, amigos. En este video, suavizaremos la transición entre habitaciones con un simple desvanecimiento a negro. En la escena del juego, la mayoría de los juegos comenzarán ya sea con una pantalla de carga o completamente negra, luego se desvanecerán cuando comience el juego. Al agregar un nodo a la capa de lienzo, podemos usar un nodo destrozado de color para dibujar colores simples fácilmente Ampliando la sección de diseño, cambiaremos los anclajes preestablecidos a naufragio completo Esto le dirá el color destrozado para llenar todo el lienzo Actualmente es blanco, pero el negro es más común, por lo que podemos cambiar el color a negro en la parte superior. Cuando comience el juego, todo lo que tenemos que hacer es cambiar gradualmente este color de negro a claro, revelando la ventana gráfica de la cámara detrás de él Con nuestras habitaciones pequeñas y sencillas, se cargan instantáneamente. La carga y descarga del contenido de la habitación no causa actualmente ningún retraso. Pero si imaginamos que nuestras habitaciones consistirán en muchos más sprites y sobre todo los efectos de muchos más sprites y sonido y música de fondo que se está cargando, esto hará que la carga de la habitación tarde más que un solo fotograma Podemos usar el mismo efecto hacia atrás para desvanecer a negro, hacer nuestra descarga y carga de la habitación, luego volver a desvanecerse cuando todo esté hecho. Este proyecto no va a ser tan grande que necesitemos una pantalla de carga real. Vamos a cambiar el nombre de este nodo fade y darle un nombre único. Tendremos que asegurarnos de que este nodo permanezca en la parte inferior del árbol de escenas para ser dibujado sobre todo lo demás o aumentar su índice Z. Tener este gran rectángulo negro en la escena del juego puede obstaculizar el trabajo en otras cosas. Podríamos querer tener este nodo oculto por defecto. Adjuntando un script a este nodo, lo nombraré fade y lo guardaré en la carpeta scripts. Anulando la función ready, lo primero que quiero hacer es establecer su propiedad visible en true, así cubre todo en negro Necesitaremos dos funciones públicas para ajustar el color a negro o claro. Para ajustar el valor de una propiedad a lo largo del tiempo, la forma más fácil es usar una preadolescente Entonces declararemos uno como variable. Si bien no espero permitir desvanezca más de una vez en rápida sucesión, sigue siendo una buena idea verificar si la preadolescente ya existe y matarla por si acaso Luego crea una nueva preadolescente. No hay necesidad de tipos elegantes de transición o flexibilización aquí, una preadolescente lineal funcionará bien Y será entre este nodo en sí, su propiedad de color y cambiando su color para que sea transparente a lo largo de un tiempo Por ahora, pondré 1 segundo. Hay un color transparente definido en la clase, pero si colocamos el mouse sobre él, podemos ver que tiene valores rojo, verde y azul de uno, valores rojo, verde y azul de uno, lo que significa que es blanco transparente, no negro transparente Esto no creará el efecto que quiero, así que definiré mi propio color transparente como una constante y lo nombraré claro. Usar todas las mayúsculas es convencional al nombrar constantes. Este será un color con cero valores rojo, verde, azul y Alfa. También podemos definir una constante para la duración de la premezcla y reemplazar el 1 segundo con esta constante Esto hace que sea un poco más fácil cambiar la duración sin tener que mirar a través del script y sin exportar una variable para algo que quieras mantener consistente para todo tu proyecto. Para la función feed to black, podríamos copiar y pegar todo este código, solo cambiando el argumento de valor final de la llamada a la función de propiedad tween, pero sería mejor evitar la redundancia Et en su lugar hacen de esta su propia función privada llamada tween color, aceptando el color final como un parámetro, luego pasa esto a la llamada a la función de propiedad tween como argumento Entonces tanto el destino al negro como a dos funciones claras pueden llamar a esta función, pasando diferentes argumentos. En el guión del administrador del juego, tomaremos una referencia al nodo fade en la parte superior. Cuando el personaje jugador entra en una habitación después de cargar el contenido de la sala, podemos decirle al desvanecimiento que se interponga su color para despejar Cuando comience el juego por primera vez, no habrá una sala actual para descargar, por lo que esta se desvanecerá de inmediato. Después de ingresar a la segunda habitación, querremos desvanecernos a negro antes de descargar el contenido de la habitación actual, luego proceder a cargar la segunda habitación y volver a desvanecerse Pero esta función no esperará a que termine la preadolescente antes de descargar el contenido de la habitación Lo hará de inmediato. Para pausar esta función mientras la tween se desvanece a negro, podemos usar la palabra clave wait Esperar será seguido con una señal. La señal que queremos esperar es la señal de tweens terminada en el script fade Así podemos devolver esta señal desde nuestra función de premezcla. Cambiar el tipo de retorno de nuestra función de void a signal. Pasar la misma señal de retorno a lo largo nuevo a través de las funciones de fundido a negro y para borrar. De vuelta en el guión del administrador del juego, el administrador del juego ahora puede acceder a esta señal en cualquier momento que llame a estas funciones. Podemos esperar fade a negro o esperar fade to clear, por lo que esta función se detendrá y esperará a que termine la preadolescente antes de continuar Generalmente no queremos que el jugador tenga control sobre el personaje mientras esto sucede. Así podemos llamar al jugador punto Desactivar en la parte superior de la función antes de iniciar la transición y volver a habilitar el nodo reproductor al final después de que se complete la transición. Olvidé actualizar esta variable de dirección para moverla de dirección cuando la cambié de nombre. Si bien estas habitaciones son bastante pequeñas y deberían estar descargando y cargando con bastante rapidez, todavía podríamos ver una instancia donde se descarga la habitación anterior y debido a ver una instancia donde se descarga la habitación anterior que no hay terreno para que el personaje se pare, caen por el piso antes cargue el contenido de la habitación siguiente para proporcionar un nuevo piso Por lo que también debemos desactivar y habilitar al personaje al mismo tiempo que hacemos el nodo jugador. Otra forma en que podemos habilitar y deshabilitar nodos es cambiando su propiedad de modo de proceso. Configurarlo en deshabilitado cuando se inicia la transición, luego hereda cuando se complete la transición Ahora el jugador no puede controlar al personaje, y el personaje no se verá afectado por gravedad mientras realiza la transición entre habitaciones A continuación, trabajaremos en dibujar nuestras habitaciones en un mapa. Te veré en el siguiente video. 33. 4-5 ventana gráfica: Hola, amigos. En este video, comenzaremos a trabajar en dibujar nuestras habitaciones en un mapa. Si bien es posible dibujar el mapa por separado del mundo del juego, es mucho más complicado mantener la consistencia entre el mundo y el mapa si tienes que actualizar ambos por separado cada vez que cambias algo. Posicionar iconos en el mapa, especialmente los iconos que pueden moverse como el personaje del jugador, puede convertirse en una tarea aún más difícil. Un método mucho más fácil de crear un mapa es simplemente tener una segunda cámara que vea el mundo desde una perspectiva Zoomed out, pero dibujar el mundo y sus contenidos de una manera más simple Así que agreguemos otra cámara a nuestra escena de juego y cambiemos el nombre de esta para que sea Cámara de mapa. Por defecto, solo se utilizará la primera cámara, y dibujará la ventana principal del juego Para dibujar el mapa, la cámara del mapa necesitará dibujar una ventana gráfica diferente, por lo que agregaremos una como nodo en el árbol de escenas, que es un nodo sub Viewport Renombrarlo a Map Viewport y darle un nombre único. En algunos de nuestros guiones, ya hemos utilizado la función G Viewport para obtener la Viewport principal del juego, que se está utilizando para dibujar los dos mundos D del juego El mundo dos D en este contexto no es lo mismo que el nodo mundial Medio Ambiente. Contiene todos los nodos TD que se encuentran actualmente en el centro, incluido el manager del juego. Si hijo de la cámara del mapa a la Vista de mapa, esta cámara ahora dibujará la Vista de mapa en lugar de la ventana gráfica principal del juego, pero no tiene ningún lugar en la pantalla para dibujarla Y así tendremos que agregar un nodo de textura destrozada a la capa de lienzo para darle a la cámara un lugar para dibujar la ventana gráfica Nombremos esto para que sea la textura de Map Viewport. Eliminaré todos estos nodos de control ficticios y me aseguraré de que el nodo destrozado de textura se dibuje antes el nodo de fundido poniéndolo más alto en la jerarquía de escena Al hacer clic en el menú desplegable de texturas, podemos seleccionar la textura de la ventana gráfica luego seleccionar el mapa Vista a dibujar como la textura para este wret de textura La textura rect se redimensionará automáticamente para que coincida con el tamaño de la ventana gráfica Actualmente solo está dibujando el color de fondo gris predeterminado porque la cámara del mapa y la ventana gráfica no pueden ver nada Por defecto, cada Viewport tendrá su propio mundo. Se puede pensar en estos mundos como mundos paralelos o planos de existencia. Pueden ocupar el mismo espacio al mismo tiempo pero existir independientemente entre sí. Pero queremos que esta Viewport dibuje el mismo mundo que nuestra principal Viewport En el script del administrador del juego, tomaremos una referencia al nodo Map Viewport Luego en la función ready, establezca la propiedad world two D de la Viewport Podemos acceder a la ventana principal llamando a los nodos del administrador de juegos obtener la función Viewport, luego acceder a su propiedad mundial dos D. Ahora, tanto el Viewport principal el Map Viewport dibujarán el mismo mundo Generalmente queremos que nuestros mapas vean mucho más del mundo, así que lo configuraré en un octavo Zoom. Si queremos cambiar las dimensiones de la textura del mapa, podemos establecer las dimensiones de píxeles de la ventana gráfica seleccionándola en el árbol de escenas Voy a hacer que sea la mitad de las dimensiones de mi juego 640 por 360 pixeles. En lugar de dibujar este color gris cuando no hay nada, prefiero que el fondo de mi Map Viewport sea transparente Voy a alternar sobre fondo transparente. Sin embargo, esto hace que el mapa sea difícil de leer, me gustaría tener esta textura de mapa contenida dentro un panel para que parezca separado del juego principal. Al agregar un contenedor de panel a la capa Canvas, repararé la textura del mapa para que sea hijo del nodo contenedor del panel, luego renombraré el contenedor del panel a Mapa y le daré un nombre único Con el tema predeterminado, el contenedor del panel dibujará un color negro transparente y como es un contenedor, automáticamente se redimensionará para contener a sus hijos Esto deja claro que la textura del mapa se está dibujando en el lienzo, no como parte del mundo, y podemos ajustar el aspecto del contenedor del panel más adelante a través del editor de temas. Usaré los anclajes de los contenedores del panel para anclarlo al centro de la pantalla Generalmente queremos que la cámara de mapa siga al personaje del jugador como lo hace la cámara principal, pero sin ninguna de las características de tweening u otras características A diferencia de la cámara principal, la cámara de mapas nunca necesitará hacer otra cosa, por lo que es seguro que siempre coincida con la posición del personaje del jugador exactamente. No hay forma de tener la cámara del mapa infantil al personaje del jugador, ya que debe seguir siendo un hijo del mapa Viewport para dibujar el Podríamos escribir otro guión para mover esta cámara, pero hay un nodo que podemos usar para facilitar las cosas, el remoto transforma dos D. Con la transformación remota dos D como hijo del personaje del jugador, podemos establecer su ruta remota a la cámara del mapa. Ahora las propiedades de transformación de la cámara, rotación de posición y escala se actualizarán automáticamente para que sean las mismas que el personaje del jugador. Podemos desactivar la rotación y la escala expandiendo la sección de actualización. Incluso si estuviéramos editando la rotación o escala del personaje del jugador, no quisiéramos que el mapa copiara estas propiedades. Mm. Ahora tenemos nuestro mundo de Juegos dibujado en el Canvas, pero queremos dibujar una versión simplificada del mundo en lugar de una copia exacta. Te veré en el siguiente video. 34. 4-6 Visibilidad: Hola, amigos. En este video, haremos que la cámara de mapas dibuje una versión simplificada del mundo. Comenzando en la sala de inicio, agreguemos temporalmente el contenido de la habitación. No quiero dibujar todos estos sprites en el mapa, solo un contorno de la forma y el terreno de la habitación Podemos usar cualquier nodo D para dibujar esto dependiendo del estilo que queramos. Usaré un nodo de capa de mapa de teselas. Dale un nuevo juego de mosaicos con mosaicos de 32 por 32 píxeles. Voy a importar un nuevo sprite, que es solo un simple cuadrado blanco de 32 por 32 píxeles Luego agrega esto al conjunto de mosaicos. Dibujando este cuadrado blanco en mi capa Tile Map, dibujaré un contorno de la habitación usando el terreno como piso en lugar del límite de la cámara y dejando puertas para conectarse a otras habitaciones Queremos que la cámara principal dibuje solo el contenido, mientras que la cámara de mapa dibujará esta nota de capa de Tile Map en su lugar. Si bien ambos están mirando la misma habitación, verán dos versiones diferentes de la misma. Ahora que tengo la forma de mi habitación, eliminaré el contenido de la escena. Dado que el nodo de capa Tile Map siempre será visto por la cámara del mapa, siempre permanecerá cargado en lugar de cargarse y descargarse como el contenido Ampliando la sección de visibilidad, puedo usar la propiedad de modular color para cambiar mis cuadrados blancos en colores si quiero Ya que esto es parte de la región forestal, dibujaré su mapa en verde. Para que la cámara de mapa dibuje esto pero no la cámara principal, voy a cambiar su capa de visibilidad 1-2. La capa de visibilidad predeterminada uno será todo lo que dibuje la cámara principal del juego, mientras que la capa dos será todo lo que quiera dibujar en el mapa. Al igual que con las capas de colisión, podemos nombrar estas capas de visibilidad en la configuración del proyecto bajo los nombres de capa dos D render. Voy a nombrar a la capa un mundo y a la capa dos Mapa. Estas capas de visibilidad dependen de las capas de visibilidad de sus padres. Si la ventana gráfica no puede ver el nodo de área de la sala de inicio, entonces no se molestará en verificar si puede ver el nodo secundario del nodo de capa de mapa de teselas El nodo padre de la sala de inicio necesitará tener su capa de visibilidad establecida tanto en uno como en dos, ya que tendrá hijos que pueden ser dibujados por ambas vistas. Avanzando por la jerarquía, la región forestal necesita tener su visibilidad establecida para usar ambas capas de visibilidad al igual que el nodo raíz de escenas del juego. El entorno mundial Node no tiene una propiedad de capa de visibilidad. Ahora seleccionando la Vista de mapa, podemos establecer su máscara de llamada Canvas para ver solo la capa dos y no la capa uno Esto funciona de manera similar a la propiedad de máscara de colisión para objetos de colisión. Solo si el bit para la máscara se establece en uno, ¿podrá ver algo cuya capa tenga el mismo bit configurado en uno? Pero no podemos acceder a la ventana principal desde el editor para cambiar su máscara de llamada Canvas a solo ver la capa uno y no la capa dos Por defecto, estará enmascarando cada capa. Así que tendremos que editarlo a través de script. En la función de script ready del administrador de juegos, podemos acceder a la ventana gráfica principal con la función G Viewport, luego establecer su propiedad de máscara de llamada Canvas Al pasar el cursor sobre la capa uno, podemos ver que su valor entero también es uno Solo podemos establecer el valor de las máscaras de llamada de Canvas en uno. Ahora solo verá la capa de visibilidad uno y no la capa dos o cualquier otra capa para el caso. Copiando el nodo de capa Tile Map en la sala de inicio, lo pegaré en la segunda habitación para dibujar también esta habitación en el mapa. Instanciaré el contenido de la habitación, luego editaré los mosaicos para reflejar con mayor precisión la forma de esta habitación y eliminaré el contenido cuando termine Recuerde establecer la capa de visibilidad de los nodos padre para que exista en ambas capas de visibilidad para que los hijos sean vistos por sus respectivas vistas. Ahora, ambas habitaciones son claramente visibles en el mapa con muy poco esfuerzo requerido ya que agregamos más habitaciones, solo necesitando agregar el mapa para cada habitación de su escena en una capa de visibilidad separada. Podemos agregar fácilmente otras cosas al Mapa dos agregando más sprites a ellos y poniéndolos en visibilidad Capa dos, como un icono de mapa de personajes de jugador Abriendo la escena de los personajes del jugador, agreguemos un Sprite para denodar y ponerle el nombre Icono de Mapa Voy a poblar la textura con una textura de atlas, usar la misma hoja de sprites y seleccionar una región para usar como icono de mapa Usaré la cabeza del personaje en algún lugar de la hoja de sprites donde la cola no esté en el camino Después de poblar la propiedad texture, estableceremos su capa de visibilidad en dos y no en una Entonces el nodo raíz de esta escena necesitará tener tanto la capa uno como la dos. Me ajustaré al desplazamiento del sprite, así que se sienta en el suelo como lo hace el personaje Sabiendo que el Zoom de la cámara es un octavo, escalaré este icono ocho veces haciéndole parecer muy grande en la escena. Como no quiero que este ícono cubra a mi personaje cada vez que trabajo en la escena, prefiero tenerlo oculto y esto será cierto de todo en mi juego a lo que quiera adjuntar un ícono de mapa. Voy a agregar un script a este nodo, ponerle el nombre Icono de mapa. Y solo voy a hacer que establezca la propiedad de visibilidad en true on ready. Ahora bien, este icono de mapa muy grande no necesita ser dibujado en el editor mientras estoy trabajando en mi personaje, pero se dibujará cuando ejecute el juego. Ahora tenemos nuestro mapa dibujando contornos de habitaciones y el personaje del jugador con un icono, pero es posible que queramos que el mapa encienda y desconecte con un botón. Te veré en el siguiente video. 35. Mapa 4-7: Hola, amigos. En este video, permitiremos que el jugador abra y cierre el mapa con un botón. Comenzando en la escena del juego, tendré el mapa oculto por defecto alternando la visibilidad del nodo contenedor que lo sostiene A continuación, adjunte un nuevo script al contenedor. Si bien actualmente estoy usando un contenedor de panel para esto, no necesitaré acceder a ninguna de las características del contenedor de panel en este script y puedo heredar del tipo de control más genérico Si quiero usar un tipo diferente nodo de control en el futuro, no necesitaré modificar mi script. Este script necesitará funciones públicas para abrir el mapa y cerrar el mapa. Para que las cosas sean simples, simplemente estableceré la visibilidad del nodo en true o false en consecuencia. También hay funciones show and hide definidas en la clase de elemento Canvas que hacen lo mismo. Si bien esto puede parecer inútil tener una función que solo llame a otra función, mantener sus implementaciones encapsuladas en funciones públicas como esta significa que podemos actualizarla fácilmente en el futuro Podemos agregar lógica extra en estas funciones para hacer que las cosas sucedan cuando se abre o cierra el mapa, o podríamos usar una preadolescente para mover el mapa fuera de la pantalla o hacer que crezca y se encoja en lugar de simplemente alternar su visibilidad Si quiero hacer estos cambios, solo necesito editar este script, en lugar de necesitar también editar el guión del reproductor o cualquier otro script que esté llamando a esas funciones. Como he decidido usar un botón de alternar para activar y desactivar el mapa, en lugar de llamar a las funciones de abrir o cerrar, prefiero tener una sola función de alternar que haga ambas cosas. Añadiendo una variable privada para saber si el mapa está abierto o no actualmente, haré que la función toggle cierre el mapa si está abierto o lo abra si está cerrado. Entonces las funciones abierta y cerrada pueden establecer el valor de I open en consecuencia. abrir la configuración del proyecto, la pestaña Mapa de entrada, necesitamos agregar una nueva acción de entrada para abrir y cerrar el mapa. Usaré la tecla de retroceso y el botón de selección en mi controlador La mayoría de los juegos con este tipo de mapa de juego permitirán al jugador desplazar la cámara también. Ya tengo mirar hacia arriba y mirar hacia abajo entradas. Solo voy a agregar mira a la izquierda y mira a la derecha. Usando las teclas de flecha izquierda y derecha o el stick derecho inclinado hacia la izquierda o hacia la derecha en mi controlador En el script del reproductor, podemos exportar una variable para mantener una referencia al nodo de mapa y poblarlo en el inspector Luego en la función de entrada, dígale al mapa que active o desactive si se presionó el botón de mapa. ejecutar el juego, el mapa comienza oculto, pero al presionar el botón del mapa, muestra el mapa y al presionarlo de nuevo, lo cierra. Para desplazar la cámara de mapas, solo tendremos que ajustar su valor de desplazamiento. Entonces le daremos al script del mapa una referencia a la cámara del mapa. Agregar una función pública llamada pan, aceptando un argumento vector dos para la dirección de desplazamiento panorámico de la cámara. Añadiremos al desplazamiento de la cámara esta dirección multiplicada por una velocidad de Pan, y podremos acceder a Delta aunque no estemos en una función de proceso llamando a las clases de nodo Get Process Delta t function. Al exportar esta variable de velocidad de pan, estableceré la mía en 1024. Esto puede parecer rápido, pero recuerde que la cámara del mapa está muy alejada, por lo que parecerá moverse a una octava parte de la velocidad Para que el script del jugador controle esta cámara cuando el mapa esté abierto, necesitará saber si el mapa está abierto, lugar de hacer pública la variable is open, permitiendo que cualquier otro script modifique su valor, podemos escribir una función que devuelva el valor de la variable. Cuando el mapa esté cerrado, restableceré el desplazamiento de la cámara de nuevo a cero, por lo que una vez más se centrará en el personaje del jugador. Cambiando al script del reproductor, agregaremos los controles para panoramizar el mapa en la función de proceso Pero sólo si el mapa está abierto. Si el mapa está abierto, le diremos al mapa que se desplace. Al igual que usamos el eje G para obtener el estado de dos direcciones opuestas como un flotador, podemos usar el vector G para obtener un vector dos desde cuatro direcciones. Sólo tenemos que darle los nombres de las cuatro acciones de entrada que coincidan con los ejes X e Y. Mira a la izquierda, mira a la derecha, mira hacia arriba y mira hacia abajo. El último argumento es una zona muerta, que es la longitud mínima del vector que se utilizará. Si el vector es demasiado corto, podemos ignorarlo, lo cual es útil para que los sticks analógicos ignoren la deriva. Si bien esto no causará ningún problema en un controlador ya que estoy usando el stick analógico derecho, los controles de mi PC están usando las teclas de flecha tanto para el movimiento como para mirar. Entonces, si el mapa está abierto, pondré el resto de los controles de mirada y movimiento en una cuadra para saltarlos. Si quieres permitir que el personaje del jugador se mueva y mire hacia arriba o hacia abajo mientras el mapa está abierto, tendrás que cambiar las acciones de entrada para que no se superpongan. Para evitar que el personaje continúe moviéndose después de abrir el mapa, estableceré su dirección de movimiento cero cuando se abra el mapa. El jugador ahora puede presionar un botón para acceder a un mapa del mundo, mostrando nuestras dos salas y la posición actual del jugador, y podemos desplazar la cámara del mapa si queremos. En la siguiente sección, comenzaremos a hacer un seguimiento de las estadísticas del jugador y las dibujaremos en la pantalla frontal. Te veré en la siguiente sección. 36. HUD 5-1: Hola, amigos. En este video, comenzaremos a mostrar información sobre el personaje del jugador en la pantalla frontal. Desde que inició este curso, Godot 4.6 fue liberado. Actualizar el proyecto a Godot 4.6 no causó ningún problema, así que continuaré con las lecciones en la versión actualizada No recomiendo actualizar a una versión más reciente de ningún motor de juego mientras estás trabajando en un proyecto a menos que tengas control de versiones para revertir si es necesario Voy a necesitar importar algunos sprites de interfaz de usuario a mi proyecto para dibujar las estadísticas de los personajes en la pantalla En la escena del juego, tenemos una capa de lienzo que se establece en la capa uno en el inspector. El Viewport principal que dibuja los dos mundos D del juego se considera capa cero Por lo que todo en el mundo dos D del juego se dibujará en la capa cero independientemente de su índice z. La capa de lienzo, la capa uno, dibujará sobre todo eso para dibujar cosas como menús y nuestros personajes se mostrarán como su salud y magia. Los nodos en la capa Canvas suelen ser nodos de control Goy, todos los cuales tienen iconos verdes para diferenciarlos de dos nodos D que son azules Comencemos por agregar un nodo de control como hijo de la capa Canvas, renombrarlo a HUD, reordenarlo para que esté en la parte superior de las capas de Canvas hijos y hagamos del mapa un hijo del Luego podemos agregar tantos iconos, medidores y texto como necesitemos a este nodo padre para crear nuestra pantalla frontal. Ayuda que un nodo de control básico actúe como padre de todo tu HUD por varias razones Algunas de las propiedades del nodo HUD padre serán heredadas por todos los nodos secundarios Dado que el nodo de capa de lienzo no es un nodo de control, no tiene las mismas propiedades, por lo que no puede proporcionar este beneficio. Si quieres dar a todos tus elementos de HUD una apariencia consistente, puedes agregar un tema al nodo padre y se aplicará a todos los nodos secundarios automáticamente También mantiene la transición de desvanecimiento en la parte inferior del árbol de escenas de forma natural, ya que solo agregarás niños por encima de él, por lo que no tendrás que preocuparte por reorganizar el árbol de escenas cada vez A diferencia de dos nodos D, que utilizan su propiedad de posición de transformación para definir dónde están relativos al origen de la escena, los nodos de control utilizan tanto una posición un tamaño para definir su ubicación dentro de un espacio definido. Por lo general, la ventana del juego, que se muestra como este rectángulo azul. Podemos ver que el nodo HUD tiene un tamaño de 40 por 40 píxeles y se encuentra en la posición 00, que es la esquina superior izquierda de la ventana Si bien podemos simplemente mover y cambiar el tamaño del nodo de control editando estos valores, estos cambios no escalarán bien ni funcionarán manera efectiva si cambiáramos tamaño de la ventana en la configuración del proyecto Entonces los nodos de control tienen estos anclajes verdes que podemos usar para establecer la posición y el tamaño de cada nodo de control en relación su padre con la capa de lienzo que representa toda la ventana Queremos que el Hud cubra toda la ventana para que podamos establecer su preajuste de anclaje en naufragio completo Esto coloca los anclajes en cada una de las cuatro esquinas de la ventana, luego actualiza automáticamente los valores de tamaño y posición para que coincidan Si hacemos visible el mapa, su posición no se ha actualizado, así que restableceré sus anclajes al centro Ahora podemos ver que ya que está anclado al centro de su padre, al mover o redimensionar el nodo HUD se moverá el mapa para permanecer centrado Para dibujar la salud y la magia del personaje, agregaré un nuevo nodo de control para mantener estos elementos agrupados y nombrarlo vitales. Dejaré esto anclado a la parte superior izquierda pero restableceré su tamaño a cero A continuación, agregaré un nodo de textura destrozada para dibujar una textura simple, un perfil del personaje y rellenar su propiedad de textura arrastrando el activo desde la pestaña del sistema de archivos Añadiendo otro nodo destrozado de textura, nombraré este ícono de salud y rellenaré su textura con una textura de atlas, seleccionando un sprite de mi hoja de sprites Voy a necesitar tener múltiples de estos para representar la salud total de mi personaje. Así que lo duplicaré un montón de veces y los colocaré más o menos en secuencia. Sería una buena idea mantener estos iconos agrupados bajo un único nodo padre. Entonces agregaré otro nodo de control llamado Health Counter y repararé todos los íconos de salud para que sean hijos de este nodo Posicionar manualmente cada uno de estos iconos es una especie de dolor. Por lo que Godot proporciona nodos de control llamados contenedores para que lo hagan por nosotros. Como quiero que estos iconos estén dispuestos horizontalmente, cambiaré el tipo del nodo padre para que sea un contenedor de caja horizontal. Esto organiza todos los nodos secundarios automáticamente. Se están estirando para llenar la altura vertical del contenedor de caja horizontal, que tiene el tamaño predeterminado de 40 píxeles. Restablecer este valor lo obligará a colapsar a la altura del niño más grande Me gustaría que estuvieran más cerca, así que bajo el tema anula las constantes de sección, estableceré la separación en ocho píxeles negativos Agregar más iconos a este contador es tan simple como duplicar el nodo hijo Es una buena idea diseñar tus elementos de HUD con sus límites máximos en mente Entonces tendré nueve íconos de salud, que es la cantidad máxima que planeo incluir en mi juego. Al seleccionar cualquiera de los nodos hijos, sus valores de posición ya no se pueden editar manualmente, ya que el nodo contenedor es ahora el encargado de controlar su posición. Así que ten en cuenta esta limitación. Si quisieras animar las posiciones de estas texturas individualmente, no podrías hacerlo mientras están dentro de un contenedor padre A continuación, agregaré otro nodo destrozado de textura para dibujar el medidor mágico del personaje A continuación, rellene su propiedad de textura con el activo desde la pestaña del sistema de archivos Si bien esta textura no es funcional como un medidor real, ayuda a dibujar todo lo que quieras incluir en tu capucha para tener una idea de cómo quieres que se presente antes de entrar en implementación. Al igual que los íconos de salud, quiero ver cómo este medidor mágico encajará en mi diseño cuando esté en su límite máximo. Estirar esta imagen para hacer que el calibre sea más largo estira los píxeles individuales de la imagen, lo que se ve mal. Nos ocuparemos de esto en el siguiente video, pero por ahora, solo necesitamos una idea de cuán grande o pequeño puede ser el medidor mágico. Es posible que desee tomarse un tiempo para obtener el diseño de los elementos de su cabaña con el aspecto que desee. Este diseño se ve bien. Pero cuando ejecuto mi juego, es muy pequeño y no coincide con la densidad de píxeles del resto del juego. Como estoy usando un zoom de cámara de dos, todos mis píxeles se duplican en tamaño. Entonces estableceré la escala de mi nodo vital en dos, duplicando los tamaños de todos sus hijos Esto es más fácil de leer y coincide mejor con la estética de mi juego. Cambiando los presets de anclaje del nodo padre vitals, podemos cambiarlo fácilmente para definir su posición relativa a cualquier esquina de la pantalla o al centro de cualquier borde O el centro de la pantalla como el mapa. Luego puedes ajustar las posiciones de los nodos secundarios en relación con el padre anclado, y ellos conservarán sus posiciones relativas incluso si decides cambiar la resolución de tu juego Mantendré el mío en la esquina superior izquierda y le daré 20 pixeles de relleno desde el borde de la ventana. Ahora tenemos algunas texturas dibujadas en la pantalla frontal, pero en realidad aún no están haciendo nada. Te veré en el siguiente video. 37. Calibre 5-2: Hola, amigos. En este video, implementaremos el medidor mágico mediante el uso de cajas de estilo. Empecemos por cambiar el tipo del nodo del medidor mágico. Hay un nodo de control que hace exactamente lo que necesitamos una barra de progreso. Cambiar el tipo elimina la textura. La barra de progreso se dibuja como un rectángulo gris semitransparente, y tiene un porcentaje mostrado en el texto. No quiero esta etiqueta porcentual, así que la deshabilitaré en el inspector. La palanca indeterminada no es aplicable a un medidor, sino que está destinada a barras de progreso que en realidad no miden ningún Después de establecer los valores mínimo y máximo para nuestro medidor mágico, podemos establecer el valor en cualquier número intermedio para ver cómo se llena la barra de progreso. El valor del paso es el más pequeño que el valor puede incrementar, obligándolo a ajustar al paso más cercano Las otras propiedades heredadas del rango no son realmente apropiadas para un medidor y pueden ignorarse. También podemos cambiar la dirección en la que se llenará la barra de progreso si queremos. Voy a dejar el mío como de principio a fin. El aspecto de la barra de progreso está determinado por el tema. Como aún no tenemos un tema, está usando el tema predeterminado proporcionado por Godot Si solo queremos cambiar el tema para este nodo por sí mismo, podemos ampliar la sección de anulaciones de tema Como no estoy usando la visualización de texto porcentual, los colores, constantes, fuentes y tamaños de fuente son irrelevantes Pero puedes usarlos para alterar cómo se escribe la fuente en tu barra de progreso si quieres. Debajo de la sección de estilos es donde podemos encontrar los cuadros de estilo para cómo dibujan el fondo y el relleno de las barras de progreso. Al hacer clic en el menú desplegable, podemos seleccionar el cuadro de estilo vacío, que simplemente no dibujará nada. Estilo de línea de caja para dibujar solo una línea simple, estilo cuadro plano para dibujar un rectángulo simple o textura de caja de estilo para usar un activo de textura importado. Al hacer clic en la textura de la caja de estilo para expandir sus propiedades, podemos rellenar la propiedad de textura con un activo desde la pestaña del sistema de archivos Si cambiamos el tamaño de la barra de progreso, la textura se estirará para llenar el espacio, lo que no se ve muy bien. Los cuadros de estilo tienen más propiedades para alterar la forma en que se dibujará la imagen cuando se estira. Los márgenes de textura convertirán la textura en una rebanada de nueve, rebanando la imagen dos veces horizontalmente y dos veces verticalmente, por lo que se divide en nueve segmentos No se estirarán las esquinas. Los bordes se estirarán en una sola dirección para conectar las esquinas, y el medio se estirará en ambas direcciones para llenar el resto del espacio. O podemos alternar el dibujo del centro de la textura y dibujar solo los bordes. Si no desea que se estiren los segmentos individuales, las propiedades de estiramiento del eje darán la opción de usar el mosaico en su lugar, o la opción de ajuste de mosaico utilizará una combinación de mosaico y estiramiento para adaptarse mejor al espacio asignado Expandir márgenes dibujará la textura más allá del rectángulo definido por la posición y tamaño de los nodos. puede usar una subregión para dibujar una región de una hoja de sprites Modulate funciona igual que lo hace con la visibilidad del elemento Canvas, multiplicando el color de cada píxel por Los márgenes de contenido son para cuadros de estilo utilizados para dibujar nodos contenedores, por lo que no serán aplicables aquí. Agregar otra textura de cuadro de estilo para el relleno de barras de progreso y rellenarlo con la textura adecuada Si no desea ingresar los valores de región de textura manualmente, también se puede usar el editor de subregiones para editar visualmente los márgenes de textura. Usando estos activos, el medidor mágico no está destinado a estirarse verticalmente. Voy a establecer su altura para que sea la misma que la de los activos en 16 píxeles. Pero usando las cajas de estilo, el calibre se puede estirar tanto como sea necesario horizontalmente, y se dibujará sin estirar los píxeles. El valor también se puede editar y la textura de relleno también se estirará tanto como sea necesario sin que se estiren los extremos de la barra. Si quisiéramos que estos cuadros de estilo se aplicaran a más de una barra de progreso, podemos hacerlo automático editando el tema en lugar de usar anulaciones de tema Seleccionando el nodo HUD luego expandiendo la sección de tema, podemos crear un nuevo tema desde el menú desplegable. Al hacer clic en el recurso temático se abrirá el panel temático en la parte inferior de la ventana del editor. Aquí podemos ver la mayoría de los nodos de control que Godot tiene para ofrecer y cómo están siendo dibujados actualmente por el tema, incluyendo una barra de progreso aquí Al hacer clic en el botón Más, podemos agregar la barra de progreso a este tema y anular sus propiedades de tema de la misma manera que lo hicimos desde el inspector para el nodo de la barra de progreso. Todas las mismas propiedades del tema están aquí para colores, constantes, fuentes, tamaños de fuente y estilos Si hacemos clic en los botones más junto al fondo y rellenamos, podemos agregar cuadros de estilo a este tema para la barra de progreso. Como ya creamos estos cuadros de estilo, podemos seleccionar el nodo de barra de progreso. Luego haga clic y arrastre los recursos del cuadro de estilo del inspector al editor de temas. La barra de progreso en la vista previa del tema se actualiza para usar los cuadros de estilo. Ahora cada barra de progreso que hereda del nodo HUD heredará este tema y utilizará estos cuadros de estilo para dibujar la barra de progreso automáticamente Esto nos da la opción de tener todos los nodos de control del mismo tipo dibujados de la misma manera o usar sobrescrituras de tema para dibujar nodos de control individuales de manera diferente Podemos eliminar las anulaciones de tema nodo de la barra de progreso ya que estos cuadros de estilo ahora se heredan del tema de HUDs Si quieres usar este tema para todo tu proyecto sin necesidad de copiarlo en cada escena, puedes guardarlo como recurso del proyecto. Luego en la configuración del proyecto, bajo el tema GUI, podemos establecer un tema personalizado seleccionando el recurso de tema guardado. Esto requerirá reiniciar el editor para que surta efecto. Ahora, cada barra de progreso en cada escena de todo el proyecto se dibujará de la misma manera. Pero imaginemos que quieres tener múltiples medidores mágicos que usen estas cajas de estilo y varias otras barras de progreso que usen otras cajas de estilo En lugar de tener múltiples temas, podemos usar variaciones de tipo de tema. Al hacer clic en el botón Más, podemos escribir un nombre personalizado para agregar al tema como Magic gauge. Después haz clic en el botón Herramientas y dale un tipo base de barra de progreso ya sea escribiéndola o seleccionándola de la lista. Ahora las otras pestañas contienen las propiedades heredadas de la Barra de Progreso, y podemos cambiar los valores de los cuadros de fondo y estilo de relleno. Copiaré las cajas de estilo de mi nodo de medidor mágico, luego haré clic en el icono del eslabón de la cadena para desvincularlas de donde fueron copiadas Cambiando a las propiedades del tema de la barra de progreso, eliminaré los cuadros de estilo, volviendo todo al tema predeterminado Después seleccionando el nodo de medidor mágico en el árbol de escenas, expandiendo la sección temática en el inspector. Puedo seleccionar el medidor mágico en la variación de tipo para decirles que usen las propiedades del tema para el medidor mágico. Ahora mi juego puede tener múltiples medidores mágicos si necesito sin tener que configurar los estilos para cada uno de ellos individualmente. Solo necesito decirle al tema que use las propiedades del tema del medidor mágico, y todavía puedo tener otras barras de progreso en mi juego que no sean medidores mágicos, que también se pueden dibujar usando diferentes estilos Ahora tenemos un medidor mágico simple, pero aún necesitamos implementar el contador de salud. Te veré en el siguiente video. 38. 5-3 Icono: Hola, amigos. En este video, crearemos un ícono de salud que tenga animaciones para cuando el personaje recupere o pierda la salud Actualmente tenemos los iconos de salud mostrados como nodos destrozados de textura organizados horizontalmente por el nodo contenedor de caja horizontal Si quisieras animarlos como sprites, podrías pensar en cambiarlos a Sprite Animado dos nodos D. Pero mezclar nodos de control con dos nodos D causa problemas. Rápidamente configuraré el recurso de fotogramas de Sprite de Animación para poder demostrarlo Dos nodos D no se comportarán como nodos de control. No anclarán sus posiciones relación con sus padres ni serán organizados por nodos contenedores o redimensionarán automáticamente para ajustarse a la resolución de la ventana En lugar de cambiar el tipo de nodo que estamos usando, necesitaremos animar este nodo wret de textura tal como es Si ampliamos el desplegable de propiedades de textura, podemos ver que hay una opción de textura animada Este recurso de textura animada solo puede contener una sola animación, ya, realmente no se ajusta a nuestras necesidades en este caso. Si quisiéramos usar esto para animar el icono, necesitaríamos establecer cada fotograma individual de la animación como una textura de atlas separada con una duración en segundos a través de esta interfaz torpe Y después de todo eso, necesitaríamos usar un script personalizado para controlar qué fotogramas de la animación se están utilizando de todos modos. Si quisiéramos tener la misma textura, reproducir múltiples animaciones. Por lo que sería mejor dejar esta propiedad de textura como una textura atlas. Si bien podríamos escribir un script personalizado para cambiar el valor de la propiedad region de esta textura de atlas, la cantidad de tiempo y esfuerzo que tomaría realmente no valdría la pena cuando ya existe el nodo Animation Player. Entonces, solo agreguemos un nodo de Animation Player como hijo de este ícono de salud. Antes de hacer alguna animación, sería una buena idea guardar primero este icono como escena propia. Esto encapsulará el nodo Animation Player, ya que no es realmente relevante para el contexto del HUD del juego En esta escena, primero, estableceré la región de los iconos a lo que quiero usar como su estado predeterminado, que estará vacío. Luego crea una nueva animación para cuando este ícono se llene, configurando la velocidad de fotogramas en 12 fotogramas por segundo, ajustando el Zoom y activando el ajuste de fotogramas Luego voy a marcar esto para el inicio de la animación y agregaré esto a la pista de reinicio. Aunque no quiero usar esto como el primer fotograma de la animación, ahora es el estado predeterminado que usa la animación de reinicio. A continuación, sobrescribiré la primera clave de mi animación de relleno con el primer fotograma real Después continúe con el resto de los marcos llenando el icono. Voy a establecer la duración de la animación en ocho fotogramas. Recuerda cambiar el modo de actualización a discreto cuando uses animaciones de fotogramas como esta. Eso se ve bien, así que lo duplicaré y haré otra animación para cuando el personaje sufra daños, lo que vaciará el icono. Como sé que mis sprites de hojas de sprites están todos espaciados uniformemente, simplemente puedo editar los valores de región con claves por múltiplos de 32 píxeles para obtener los fotogramas que Esta animación es más corta con solo seis fotogramas. Es importante que estas animaciones terminen con el frame que será persistente después de que terminen. Una vez que se reproduce esta animación vacía, el icono permanecerá vacío hasta que se reproduzca la animación de relleno. Asimismo, después de que se reproduzca la animación de relleno, el icono permanecerá lleno hasta que se reproduzca la animación vacía. Adjuntar un script al nodo raíz del icono de salud y guardarlo en una nueva carpeta para los scripts de la interfaz de usuario. Supondremos que este script se puede usar para cualquier icono animado en caso de que queramos usarlo para algo que no sea salud. Este script solo necesita obtener una referencia al nodo Animation Player cuando esté listo. Luego proporcionar funciones públicas para reproducir cada una de las animaciones cuando sea necesario. De vuelta a la escena del juego, podemos eliminar todos los demás íconos de salud. Cambiaré el nombre de este primero a ícono de Salud uno, luego lo duplicaré ocho veces para recrear el resto de ellos con el Reproductor de Animación y guión adjunto Si queremos probar esto, podemos usar el guión del jugador para decirle al ícono de salud que llene o vacíe con una pulsación de tecla Al presionar el botón Ejecutar, usaré la ruta del nodo anotado con el signo de dólar para decirle a este primer ícono de salud que debe llenar Cuando suelte el botón Ejecutar, haré lo mismo para decirle que se vacíe. Ya que esto es solo para fines de prueba, no necesito importarme lo ineficiente que es este código Ejecutar el juego, presionar el botón Ejecutar, llena todos los iconos, aunque solo le dije al primero que llenara. Esto se debe a que Godot naturalmente trata de ser lo más eficiente posible en recursos y ha creado solo un recurso de textura atlas para ser utilizado para todos los iconos Entonces, cuando animamos un icono, todos los íconos están usando la misma textura, por lo que todos están animados En la escena del ícono de salud, podemos anular este comportamiento expandiendo el recurso de textura del atlas en el inspector. En la sección de recursos, active la opción local a escena. Esto le dirá a Godot que cada instancia de la escena necesitará su propia copia única de este recurso de textura de atlas con su propia propiedad de región Esta hoja de sprites seguirá siendo compartida por todos los iconos, pero qué región de la hoja de sprites dibujan será única Ejecutando el juego otra vez. Esta vez solo se llena el primer icono cuando presiono el botón de ejecución y se vacía cuando suelto el botón Con la prueba exitosa, podemos eliminar o comentar las líneas adicionales de código. Ahora tenemos íconos animados de salud, pero el contador de salud en realidad no cuenta la salud de nuestro personaje. Te veré en el siguiente video. 39. Contador de 5-4: Hola, amigos. En este video, escribiremos un guión que gestione los íconos animados para reflejar un valor y un valor máximo. Aquí tenemos nuestros íconos animados, pero necesitamos adjuntar un guión al nodo padre que controlará cómo y cuándo se animan para reflejar el conteo de la salud del personaje del jugador Nombraré este contador de iconos y lo pondré en la carpeta de scripts de UI. No hay nada en este script específicamente usando las características del contenedor de caja horizontal, así que extenderé el tipo de control más genérico para permitir cambiar el tipo de este nodo más adelante si quiero. El guión necesitará dos enteros, uno para la salud máxima del personaje y otro para su salud actual Como quiero que este script sea útil para contar cualquier cosa, no solo salud, usaré el término genérico valor. Por ahora, podemos establecer el valor predeterminado de salud máxima para que sea igual al número de hijos tiene este nodo usando la etiqueta on ready. A continuación, necesitaremos dos funciones públicas que establecerán ambos valores, aceptando un parámetro entero y anulando el valor antiguo con el nuevo Cuando tengamos a nuestro personaje jugador tomando daño y recuperando la salud, podremos llamar a estas funciones públicas para comunicar los cambios de valor de salud al jugador. Será responsabilidad de este script controlar cuántos iconos se muestran y cuáles se llenan o vacian en función de los valores de estos enteros y cómo cambian Empezaremos por establecer el valor de su salud actual. Lo primero que debemos hacer es validar que el número nos están dando para establecer el valor sea un número válido. No podemos mostrar al personaje tenga menos de cero salud, ni nada mayor que el número de iconos disponibles, su salud máxima. Entonces primero estableceremos el valor al retorno del entero clamp entre cero y max health. Si intentamos llamar a esta función con un número negativo, su lugar establecerá la salud en cero. Y de igual manera, cualquier cosa por encima del máximo se limitará al máximo. A continuación, si estamos estableciendo el valor en el mismo número que ya es, no deberíamos tener que hacer nada, así que podríamos simplemente regresar de esta función. Una vez que hayamos establecido que estamos cambiando el valor que muestra este contador de iconos a un nuevo número válido, el proceso diferirá si el número aumenta o disminuye. Si el nuevo valor es mayor que el valor anterior, le diremos algunos de los íconos para llenar. Pero, ¿qué íconos? Los iconos son convenientemente dibujados por el contenedor de caja horizontal en el mismo orden que su índice hijo en el árbol de escena. Usando un simple bucle de cuatro, usando I como índice, podemos contar a través del rango de valor a nuevo valor. Range devuelve una matriz que contiene la secuencia de números enteros contando desde el primer número hasta el segundo, pero excluye el segundo Entonces, si el valor antiguo era uno y el nuevo valor es cuatro, esto nos dará los números uno, dos y tres. Dado que el índice hijo del primer hijo es cero, no uno, esto se alinea perfectamente con los índices de los iconos que necesitan ser llenados. Entonces obtendremos el nodo hijo en el Índice I y le diremos que llene. El proceso para disminuir el valor es muy similar. Sólo como sabemos que el nuevo valor es menor que el valor anterior, necesitamos proporcionar un argumento extra a la función range, uno negativo, que le dirá que cuente atrás. Si el valor antiguo era cuatro y el nuevo valor es uno, range devolverá 43 y dos. Estos no son los mismos que los índices hijos de los íconos, sino que son uno mayor. Entonces podemos arreglar esto restando uno de I en función get child y decirle a estos íconos Sólo después de que todo esto esté hecho, ¿establecemos el valor antiguo al nuevo valor? Podemos probar esto sin agregar scripts adicionales o asignaciones de entrada Todo lo que tenemos que hacer es agregar una función de entrada al script. Primero, verificaremos si el evento de entrada fue una tecla de evento de entrada y si el evento fue una tecla presionada. Luego usa una declaración de coincidencia en el coode clave del evento. Si la tecla que se presionó era alguna de las teclas numéricos, podemos establecer el valor del contador de iconos en ese número. Declarando una variable numérica como un entero, podemos calcular el número que se presionó simplemente restando la clave cero del código clave de eventos Esto funciona porque los coodes clave son una enumeración, una simple Cualquiera que sea el código clave para la clave cero, el código clave para la clave siete va a ser el coode clave para la clave cero Podemos imprimir una declaración que diga algo así como establecer la salud actual dos más el número convertido en una cadena. Luego llame a la función de valor establecido pasando el número. Si ejecutamos el juego, al presionar cualquier tecla numérica se establecerá el contador de iconos ese número y se animarán los iconos de acuerdo a si se están llenando o vaciando Y podemos hacer lo mismo para establecer el valor máximo también. Si bien ya podríamos tener el número máximo de iconos en la escena y simplemente ocultar los que no estamos usando, sería más escalable instanciar nuevos iconos según los necesitemos Como esto no sucede muy a menudo, no afectará el rendimiento y se acomodará agregando tantas más como necesitemos si decidimos que queremos contratar al máximo más tarde. Así que exportaremos una variable para mantener la escena del icono como una escena repleta. Copiar el contenido de la función de valor establecido. Después de cambiar cada instancia de valor a valor máximo, solo hay algunos cambios más que deben realizarse. Primero, no podemos validar el valor máximo basándonos en sí mismo. Así que tendremos que establecer algún límite a qué tan alto puede ser el valor máximo. Es posible que desee exportar este límite en lugar de codificar un valor. En lugar de llenar iconos, estaremos instanciando nuevos íconos y agregándolos como niños. Y en lugar de vaciar íconos, los estaremos retirando del árbol de escenas llamando gratis Para probar esto, usaré el mismo sistema de entrada de tecla numérica, pero requiero que mantenga presionada la flecha hacia arriba para establecer el valor máximo. Entonces, si se presiona la acción de punto de entrada, buscaré, entonces imprimiré Max Health y estableceré ese valor en su lugar y colocaré la parte de salud actual en el bloque else. ejecutar el juego, puedo cambiar el valor máximo de salud manteniendo presionada la flecha hacia arriba y presionando cualquiera de las teclas numéricos y soltando la flecha hacia arriba, todavía puedo cambiar el valor actual salud, también. Recuerde comentar la función de entrada después de la prueba. Ahora tenemos un contador de iconos animados que puede hacer un seguimiento de los personajes del jugador máximo y los valores de salud actuales. Pero ni el contador de iconos de salud ni el medidor mágico están realmente conectados con el personaje del jugador. Te veré en el siguiente video. 40. Caja de 5 a 5 heridos: Hola, amigos. En este video, le daremos al personaje algo de salud para que se conecte con el contador de iconos de salud. Podríamos agregar variables de salud al guión del personaje y rastrearlo de esa manera. Esto permitiría que cada personaje de nuestro juego tenga salud sin ningún trabajo extra. Pero si consideramos que las cosas que no son personajes también pueden necesitar tener salud, como paredes rompibles, por ejemplo, esto se vuelve menos beneficioso, sobre todo porque nuestro personaje es un personaje cuerpo dos D y el Muro rompible sería un cuerpo estático dos D. Y tal vez tengamos otro cuerpo rígido a D que también necesita Tendríamos que tener las mismas variables y funciones en múltiples scripts para cada uno de estos casos. Podríamos reescribir nuestro guión de personaje para heredar del cuerpo físico dos D, todo en nuestro juego que necesite salud también puede usar este Pero hay muchas cosas en este script que no serían aplicables a estos otros objetos. Sería derrochador tener todas estas variables y funciones unidas a una pared rompible que nunca necesitaría utilizarlas y así mismo, tener las variables y funciones destinadas un muro rompible unidas a En casos como este, es posible que desee usar el patrón compuesto en lugar herencia orientada a objetos para reutilizar sus scripts en su proyecto de juego. Al crear un componente de salud, puede existir independientemente de lo que esté apegado. Los personajes pueden tener un componente de salud y las paredes rompibles también pueden tener un componente de salud En la escena del personaje, agregaremos un nuevo hijo, un nodo Área dos D, y lo nombraremos Caja de daño. Luego agrega un nodo TD de forma de colisión como hijo de la Caja de Daño para definir su forma. Esta será la zona en el personaje aéreo donde si son golpeados, recibirán daños. Es posible que no siempre quieras que esta sea la misma que la forma de colisión del cuerpo de su personaje. Además, generalmente siempre querrás que la colisión del cuerpo del personaje permanezca activa, mientras que la Caja de Daño a menudo se desactivará para evitar que el personaje reciba daño mientras esquiva o durante escenas de corte, por ejemplo Por lo tanto, ayuda darle a tu Caja de Hurt un área de colisión separada. Voy a hacer la mía también una cápsula, pero un poco más pequeña que el cuerpo del personaje y pondré su color de depuración en verde para poder diferenciarlos más fácilmente. Esta zona no necesita ser responsable de monitorear nada. Solo necesita ser monitoreable para que los hit boxes puedan detectarlo Ampliando la sección colisión bajo colisión Objeto dos D, podemos establecer esto para que esté en la capa diez y quitar su máscara por completo. En la configuración del proyecto, voy a dar a dos D Physics layer ten el nombre del jugador Hurt Box. Ahora bien, cualquier cosa en el juego que sea tanto de monitoreo como enmascaramiento de la capa diez podrá lastimar al personaje del jugador. Adjuntando un script a este nodo, lo llamaré Hurt Box. Este script necesitará los mismos valores máximos de salud y salud actuales que tiene el contador de iconos. Como voy a estar indicando el valor de salud con iconos, estos tendrán que ser enteros. Si estás usando un medidor para la salud de tu personaje, tienes la opción de usar flotadores en su lugar ya que un medidor puede indicar valores decimales Por ahora, solo estableceré la salud máxima en cinco y usaré la etiqueta “on ready” para establecer la salud actual en Max Health. A diferencia del script de contador de iconos, la principal forma en la que una Caja de Daño estará modificando el valor de salud actual será recibiendo daños por caja de impacto o recuperando la salud. Por lo que estas serán nuestras funciones públicas, ambas aceptarán una cantidad de salud para perder o ganar como un entero. Al recibir daño, simplemente restaremos cantidad de la salud actual del personaje Entonces podemos usar la función max para devolver este valor o cero, lo que sea mayor, y establecerlo como el nuevo valor de la salud actual Esto evitará que su salud llegue alguna vez por debajo de cero. Podemos hacer que la función de recuperación sea multiuso dando al parámetro un valor predeterminado. Si llamamos a esta función de recuperación sin argumentos, asumiremos que eso significa que deben recuperar toda su salud hasta su máximo ajuste de su salud hasta su máximo salud actual a salud máxima. Si se le dio un argumento a la función de recuperación, entonces agregue esa cantidad a la salud actual del personaje y use la función MIN para devolver este resultado o Max health, lo que sea menor Por lo que la salud actual nunca superará la salud máxima. En ambos casos, se está cambiando el valor de la salud actual y necesitamos que este cambio sea reflejado por el contador de iconos en el HUD Pero el Hurt Box está en la escena del personaje y el contador de iconos está en la escena del juego. En la mayoría de los casos, siempre que necesites comunicar información entre nodos y diferentes escenas, la mejor manera será usar señales y formar su conexión a través su ancestro común más cercano En la escena del juego, el ancestro común más cercano entre el personaje y el contador de salud es el nodo raíz de escenas del juego , el administrador del juego Vamos a darle un nombre único al contador de salud. Entonces agarra una referencia a ello en el guión del manager del juego. Podríamos intentar decirle al contador de salud que monitoree la Caja Hurtada del personaje. Podemos usar la función Get node para recuperar la caja de daño del personaje. Pero entonces nuestro script de contador de iconos estará confiando en ciertas funciones o variables existentes en la entidad que está monitoreando. Por lo que esencialmente solo sería útil como contador de salud, que no es reutilizable como guión para contar otras cosas. revertir esta lógica, sería mejor decirle a la Caja Hurtada que sea monitoreada por ese contador de iconos. Entonces llama a una función que aún no hemos escrito como set counter y pásalo el contador de salud como argumento. Ten en cuenta que esta función get node fallará si cambias el nombre de tu nodo Hurt Box o reorganizas la estructura de tu árbol de escenas para que ya no sea un hijo directo Prefiero esta dependencia a escribir una nueva función en el script de caracteres para recuperar el nodo Hurt Box ya que ese script ya es bastante largo. De vuelta en el script de Hurt Box, escribiremos esta nueva función, aceptando un contador de iconos como parámetro de control de tipo, ya que no le dimos un nombre de clase específico. Ahora tenemos el Hurt Box y el contador de salud en el mismo guión, para que podamos comunicarnos fácilmente entre ellos. Más importante aún, el script del contador de iconos todavía se puede usar para lo que queramos, y cualquier Hurt Box en nuestro juego que no necesite ser monitoreado por un contador, puede simplemente ignorar esta función. Podríamos llamar directamente a las funciones de contadores de iconos, pero eso daría como resultado que cada Hurt Box en el juego verificara constantemente si tiene un contador de iconos monitoreándolo antes de llamar a estas funciones. Sería mejor usar señales para comunicar estos cambios, una para cuando cambia la salud máxima y otra para cuando cambia la salud actual. Ambos necesitarán parámetros enteros para sus nuevos valores. También podemos querer otro para cuando la salud llegue a cero, lo que no requerirá ningún parámetro. Ahora cuando su salud actual cambia a consecuencia de recibir daño o recuperar la salud, podemos emitir esta señal pasando su nueva salud actual como argumento. Si la salud actual es cero después de recibir daños, debemos emitir la señal teñida dos. Ahora cuando configuramos un contador para monitorear esta Caja Hurtada, simplemente podemos conectar estas señales a los contadores de iconos establecer funciones de valor, ya que los parámetros pasados por las señales coinciden con los parámetros de las funciones de contadores de iconos tanto en cantidad como en tipo. También sería una buena idea emitir estas señales de inmediato para que el contador de iconos pueda establecer sus valores para que coincidan con la Caja de Daño. Para probar esto, podemos escribir una función de entrada simple en este script. Si presiono hacia arriba, el personaje recuperará una salud. Si presiono hacia abajo, el personaje recibirá un daño, y si salto, el personaje recuperará la salud completa. ejecutar el juego, presionar hacia abajo el personaje recibe un daño con cada pulsación de botón. Se ignora recibir daños a cero salud. Al presionar hacia arriba se recupera una salud, y se ignora la recuperación de la salud en Max. Volviendo a bajar primero a un valor más bajo, luego saltaré y recuperaré completamente toda la salud. Recuerde eliminar o comentar esta función de entrada después de la prueba. Ahora tenemos a nuestro personaje capaz recibir daños y recuperar la salud, pero su salud no se está salvando. Te veré en el siguiente video. 41. 5-6 Datos: Hola, amigos. En este video, crearemos un recurso personalizado que puede realizar un seguimiento de las estadísticas del jugador y progresar en el juego entre sesiones de juego. Si queremos que el jugador pueda obtener mejoras de salud Max, entonces manténgalas la próxima vez que juegue. El juego necesitará una forma de saber lo que tienen y lo que no han encontrado en el juego. Para ello, podemos crear nuestros propios recursos. Ya hemos estado usando varios recursos en este proyecto, como el recurso Sprites Atlas Texture del personaje o el recurso de máquina de estado del árbol de animación Y el tema. Estos recursos son de todos los tipos definidos por el motor de juego Godot para proporcionar funciones específicas para los nodos que los utilizan. Pero también podemos crear las nuestras propias para satisfacer nuestras propias necesidades específicas. Vamos a crear una nueva carpeta dentro la carpeta llamada resources. Entonces podemos crear un nuevo script en esta carpeta llamado data en lugar de heredar del nodo, este script heredará del recurso Los recursos no se representan como nodos en el árbol de escenas. Lo primero que queremos hacer al crear un recurso personalizado es asegurarnos de darle un nombre de clase. De lo contrario, no podremos crear instancias del mismo. Dado que el propósito de este recurso es realizar un seguimiento de los datos del jugador, podemos incluir tantas variables como necesitemos para todo lo que queramos guardado entre sesiones de juego. Por ahora, voy a necesitar variables para los caracteres Salud máxima y salud actual como enteros. También agregaré su máxima magia y magia actual como carrozas Todas estas variables serán de acceso público a otros scripts. También podemos incluir cadenas para cosas como su nombre o booleanos para hacer un seguimiento de algo que se enciende o Las matrices se pueden utilizar para almacenar grupos de información relacionada, como una matriz de booleanos para saber qué actualizaciones han sido encontradas por el jugador y cuáles no Los diccionarios son muy útiles para almacenar clases enteras de información, ya que podemos usar nombres de atributos como claves en el diccionario con sus valores correspondientes. Más allá de los tipos de variables básicas, también podemos incluir otras clases integradas en Godot como vectores para almacenar dos coordenadas D, colores, o incluso otras clases personalizadas que creamos Cualquier variable que quieras guardar entre sesiones de juego necesitará tener la etiqueta de exportación. Otras variables que no tienen la etiqueta de exportación aún pueden ser útiles si, por ejemplo, no quieres guardar la salud actual del personaje, solo su salud Max e iniciar al jugador con plena salud cada vez que carga su juego. estas variables no exportadas seguirán permaneciendo si tu juego cambia embargo, estas variables no exportadas seguirán permaneciendo si tu juego cambia de escena durante la sesión de juego. Si tuvieras que hacer la transición fuera de la escena del juego por algún motivo, tal vez para jugar una escena de corte, luego regresaras a la escena del juego una vez más, estas variables conservarán su valor. Si bien también podemos escribir funciones en este script, no suele ser necesario. Si desea realizar alguna inicialización automatizada de su recurso, podemos anular la función init. Esta función innit será llamada automáticamente por Godot cada vez que creamos una nueva instancia de este recurso a través de un script Así podemos darle a las variables algunos valores predeterminados, establecer las longitudes de las matrices, o agregar algunas claves a nuestros diccionarios. Asegúrese de guardar este script con el nombre de clase definido antes de intentar usarlo de alguna manera. Entonces Godot reconocerá este nombre de clase. Necesitaremos otro script para acceder a nuestro recurso personalizado, que cubriremos en el siguiente video. Por ahora, podemos probar nuestro recurso personalizado creando uno en la pestaña del sistema de archivos. Hacemos clic, seleccionamos Crear nuevo recurso, luego tecleamos el nombre de la clase o lo seleccionamos de la lista. Entonces dale un nombre. Al crear este recurso lo abriremos automáticamente en el inspector, donde podremos ver y editar todas nuestras variables exportadas. Al crear un recurso de esta manera no se utiliza la función nit, sino que se utilizarán los valores proporcionados para las variables asignadas en sus declaraciones Si selecciona otra cosa y desea volver a editar este recurso, puede hacer doble clic sobre él en la pestaña del sistema de archivos. Voy a probar rápidamente la creación un recurso de datos en el script del administrador de juegos. Podemos crear una instancia de nuestro recurso declarando primero una variable con el nombre de la clase como tipo Después asigne el valor de esta variable para que sea el nombre de clase seguido del punto Nu. Entonces podremos acceder a cualquiera de las variables que declaramos en esta clase, tanto exportadas como no exportadas, sobrescribir sus valores y utilizarlos según sea necesario mientras jugamos el juego Recuerde eliminar o comentar este código de prueba y eliminar el archivo de recursos de datos de prueba. Ahora tenemos un recurso de datos que incluye a nuestros personajes Max Health y salud actual, pero aún no se está guardando. Te veré en el siguiente video. 42. Archivos de 5 a 7: Hola, amigos. En este video, guardaremos y cargaremos los datos del jugador usando nuestro nuevo recurso personalizado. Para ello, necesitaremos otro script que administre acceso al recurso que creamos en el video anterior. Este script deberá ser accesible desde cualquier parte del proyecto. El personaje necesita conocer sus estadísticas. Los cuartos necesitarán saber si el jugador ha abierto una puerta, encontrado una mejora o derrotado a un jefe. Incluso la interfaz de usuario y el mapa necesitarán acceder a los datos guardados. Podemos hacer que algunos nodos sean fácilmente accesibles así haciéndolos globales. Vamos a crear una nueva carpeta dentro la carpeta de scripts llamada Globals. Después crea un nuevo script en esta carpeta llamada file. El propósito de este script será proporcionar un acceso rápido y fácil a los jugadores guardar datos en cualquier otro script que escribamos a lo largo de todo el proyecto, además de guardarlo en el sistema del reproductor y cargarlo también. Necesitaremos una variable del tipo de nuestro recurso personalizado. Le voy a nombrar datos con una D. minúscula . Entonces necesitaremos tres funciones públicas para administrar estos datos, iniciar un nuevo juego, guardar el juego y cargar el Empezar un nuevo juego es sencillo. Solo necesitamos establecer el valor de los datos para que sea nuestro nombre de clase seguido de punto neu. Esto creará una nueva instancia del recurso e inicializará Cuando estemos listos para salvar nuestro juego, necesitaremos saber dónde queremos guardarlo también. Para ello, declararé una constante de cadena, ya que esto es algo que nunca voy a cambiar, la ruta a la ubicación donde quiero guardar el archivo de datos del jugador. Godot proporciona una taquigrafía simple que funciona en cualquier plataforma Windows, Mac, Linux, web y consolas pueden usar esto. Usuario Colon reenvía adelanteslash. Do reemplazará esto automáticamente con la ruta apropiada para la plataforma como una ubicación que es específica tanto para el usuario del sistema como para el juego. Declarando una variable para el nombre de archivo también como una cadena, voy a nombrar el mío guardar seguido punto TRS corto para Ahora para guardar el juego, podemos acceder a una clase Singleton del Godot, Ahorrador de recursos, luego llamada la función guardar Pasando el recurso que queremos guardar y la ubicación en la que queremos guardarlo agregando la ruta y el nombre del archivo Si quisiéramos tener múltiples ranuras para guardar, todo lo que tenemos que hacer es cambiar el nombre del archivo para cada ranura. Cargar nuestro juego es similar a guardar. Todo lo que tenemos que hacer es usar Godot loader Singleton. La función de carga solo requiere la ubicación del recurso que estamos cargando. Y devuelve el recurso. Entonces lo asignaremos a nuestra variable de datos. Como nuestro juego no tiene una escena de título, simplemente asumiré automáticamente que si existe un archivo guardado, querré cargarlo, o si no inicia un juego nuevo. Entonces en la función REDI, usaré el cargador de recursos para verificar si hay un archivo de datos para cargar, y si es así, cargarlo De lo contrario, inicia un nuevo juego. Incluso con una escena de título, es útil poder comenzar tu juego directamente desde la escena del juego sin tener que pasar por la pantalla de título cada vez mientras estás desarrollando y probando. Tenemos nuestro recurso de datos aquí. Podemos crearlo, guardarlo y cargarlo. Ahora todo lo que tenemos que hacer es hacer que este script sea fácil de acceder desde cualquier lugar de nuestro proyecto. Al abrir la configuración del proyecto, cambie a la pestaña Globales. Da clic en el botón de carpeta para abrir un navegador y navegar hasta el script de archivo que acabamos de crear. Luego haz clic en Abrir. Podemos proporcionar un nombre diferente para este nodo global si queremos o usar el proporcionado. Después haga clic en agregar para agregar el script a la lista de nodos globales. Ahora, cualquier script que escribamos puede acceder a este script de archivo con solo su nombre. De la misma manera hemos estado usando los singletons input, resource saver y resource loader Para probar esto, estableceré la salud máxima del personaje para que coincida con lo que hay en el Safle en lugar de configurarlo en la parte superior del guión Entonces agregaré una función inicializada a este script después de aceptar un nuevo parámetro de valor Max, configurando el antiguo valor máximo al nuevo valor máximo. Entonces el valor actual al valor máximo, emitiré ambas señales cambiadas. Ahora el administrador del juego después de obtener la Caja de Hurto del personaje puede inicializarla con el valor máximo de salud del archivo de datos del jugador También agregaré una función de entrada, que al presionar las teclas de flecha arriba o abajo aumentará o disminuirá la salud máxima del personaje en el archivo de datos y volverá la salud máxima del personaje en a inicializar la Caja de Daño para que coincida Entonces guarda el juego llamando a file dot save game. Voy a necesitar invertir el orden de estas operaciones para mostrar los valores correctos. ejecutar el juego, el personaje comienza con cinco Max Health, pero puedo cambiar este valor presionando las teclas de flecha arriba o abajo. Entonces cerraré el juego y lo ejecutaré nuevo para ver que su salud Max se ha guardado y cargado. Para encontrar el archivo de datos que guardamos en el menú del proyecto, seleccione Abrir carpeta de datos de usuario. Esto abrirá una ventana del navegador de archivos, y podremos ver nuestro archivo DotTRS guardado Haga clic derecho sobre este archivo y ábralo usando cualquier editor de texto. Podemos ver que solo se salvó la salud máxima. Godot realiza un seguimiento de qué variables son utilizadas por el juego y solo guardará las variables que realmente usamos y modificamos Así que ten esto en mente. De hecho, podemos editar este archivo aquí, y el juego realmente lo cargará con los valores editados siempre que el formato coincida. Esto es genial para nosotros mientras estamos construyendo y probando nuestro juego. Pero tal vez no quieras dejar que tus jugadores editen fácilmente su archivo seguro cuando estés listo para publicar. En el script del archivo, simplemente cambie la extensión TRS en el nombre del archivo a punto RES. En lugar de un recurso de texto, este ahora se guardará como un recurso binario, que no se puede abrir y editar en un editor de texto. Ejecutando el juego de nuevo, voy a abrir el archivo guardar puntos que acabo de crear. Esto ahora es imposible para mí de editar. Ahora tenemos la capacidad de guardar y cargar datos sobre el progreso del jugador a través de nuestro juego. En la siguiente sección, agregaremos nuestras habilidades desbloqueables Te veré en la siguiente sección. 43. 6-1 doble salto: Hola, amigos. En este video, le daremos a nuestro personaje la posibilidad de doble salto. Si bien muchos personajes de nuestro juego pueden necesitar la habilidad de caminar, correr, saltar y caer, las habilidades desbloqueables suelen ser exclusivas del personaje del jugador En el guión del personaje, en lugar de agregar más variables y funciones a este script, que ya es bastante largo, podemos crear un nuevo guión que solo será utilizado por el personaje del jugador. Asegúrate de que el guión de tu personaje tenga un nombre de clase y esté guardado antes de continuar. En la escena del personaje, haga clic derecho en el nodo raíz del personaje y seleccione adjuntar guión. En lugar de heredar de CharacterBody dos D, podemos heredar del nombre de clase de nuestro carácter de guión original Entonces dale un nombre a este nuevo script y guárdalo en la carpeta correspondiente. Dado que este nuevo script hereda del carácter, tiene acceso a todas las mismas variables y funciones que creamos para esa clase, y todos los valores para las variables exportadas y conexiones de señal también se copian a este nuevo script Pero ahora podemos agregar más que sólo son útiles para el personaje jugador. Siguiendo este patrón de herencia, personaje se llama la superclase y nuestro personaje jugador es una subclase Primero, necesitaremos una variable que nos diga si este personaje ha desbloqueado o no la capacidad de doble salto. Y para limitar al personaje a solo doble salto una vez, necesitaremos otra variable para saber si su doble salto está listo. También podría ayudar tener una señal para emitir cuando realizamos con éxito un doble salto para dibujar un efecto de partícula si quieres, igual que hicimos con el otro salto. Dado que el salto doble generalmente usa el mismo botón que el salto normal, no necesitamos hacer ningún trabajo adicional con el mapa de entrada en la configuración del proyecto o editar el script del reproductor para llamar a ninguna nueva función. Simplemente podemos anular la declaración de la función Jump. Al anular una declaración de función, la firma de función debe permanecer igual El nombre de la función, sus parámetros, cantidad, orden y tipos, así como el tipo de retorno. Dado que la función de salto original en el script de caracteres no aceptó parámetros y devolvió un booleano, esta anulación de salto tampoco debe tener parámetros y devolver un Todavía queremos que ocurra toda la funcionalidad original del salto. Por lo que este personaje podrá saltar si se cumplen las condiciones adecuadas. Podemos acceder a las funciones de superclase usando la palabra clave super luego usar un punto, el nombre de la función y paréntesis tal como llamaríamos a una función de cualquier otra manera Dado que la función salto de superclase devuelve un booleano, también podemos devolver el resultado para satisfacer el requisito de devolver Cuando el jugador presiona el botón de salto, el guión del jugador llamará a esta función de salto de personaje del jugador, que luego llamará a la función de salto de personaje más genérica. Esta estructura nos permite interceptar el proceso agregando código extra por encima de la línea de retorno, lo que nos permite verificar si este personaje jugador puede doble salto en respuesta a la solicitud de saltar primero, luego solo proceder con el comportamiento de salto predeterminado después Entonces, si este personaje jugador puede hacer doble salto y el doble salto está listo y el personaje no está en el suelo, entonces deberíamos permitirle realizar un doble salto y regresar verdadero. Si alguna de estas condiciones es falsa, entonces tenemos que proceder a verificar si este personaje puede saltar en condiciones normales usando la función de salto de superclase de personaje Podemos prácticamente simplemente copiar las líneas de código que implementan un salto al realizar un salto doble, pero emiten una señal diferente. Y tendremos que establecer el doble salto está listo variable a caídas para evitar que el personaje jugador realice más de un doble salto. En la mayoría de los juegos con un salto doble, la capacidad de realizar el doble salto se restablece después de aterrizar en el suelo. Dado que la clase de caracteres ya tiene una función a la que se llamará cuando el personaje aterrice, también podemos anularla. Cada vez que este personaje aterriza, si su doble salto no está listo, podemos volver a establecer la variable en true para que esté lista. Entonces llama a la función de superclase. En este caso, el orden de si queremos ejecutar la función de superclase antes o después no importará Para probar esto, agregaré una declaración print cuando el personaje doble salte con éxito. Y otra cuando se restablece el doble salto. Luego establece el valor predeterminado de C double jump a true. Ejecutando el juego, podemos presionar el botón de salto dos veces para doble salto. Al presionarlo tres o más veces no se producen más saltos, y la capacidad de doble salto se restablece al aterrizar. Ahora todo lo que tenemos que hacer es bloquear y desbloquear esta capacidad de doble salto. Entonces estableceré el valor predeterminado de C double jump back a false. En el reproductor guardar datos, voy a eliminar todas estas variables innecesarias. Necesitaremos variables que nos digan qué habilidades ha desbloqueado el jugador, que podemos almacenar en una matriz de booleanos Las matrices se indexan usando enteros, necesitaremos que a cada una de nuestras habilidades se le asigne un número en secuencia, comenzando desde el conteo cero hasta actuar como sus índices a esta Si no quieres memorizar un montón de enteros, podemos crear una enumeración para darle a cada entero un nombre que nos resulte más fácil de Me gusta poner estas enumeraciones en un guión separado llamado enums Si bien Godot nos obliga a heredar de una clase existente al crear el script, podemos eliminar esta línea de nuestro script después de que se Entonces dale a este script un nombre de clase para que podamos referenciarlo en otros scripts. Normalmente usaré el mismo script para contener todas las enumeraciones para todo el proyecto Podemos declarar una enumeración usando la palabra clave num, seguida de llaves Dentro de las llaves, podemos escribir los nombres de cada una de nuestras habilidades en una lista separada por comas Ya he creado un doble salto como mi primera habilidad desbloqueable, y voy a crear un salto de pared, un tablero, un sombrero y disparar un Las enumeraciones se nombran convencionalmente en caso Pascal mientras que las entradas de enumeración están en mayúsculas La enumeración asignará el valor de la primera entrada como cero, luego uno, dos, etc., lo que significa que podemos usar estos como índices a nuestra matriz con bastante facilidad Estos no necesitan estar en el orden en que serán desbloqueados por el jugador. El orden es arbitrario y sólo sirve para asignar a cada habilidad un número único. Al inicializar los datos de guardado del jugador, podemos cambiar el tamaño de la matriz para que coincida con el tamaño de la enumeración, dándonos automáticamente el número correcto de booleanos y por defecto Recuerde que las variables deben tener la etiqueta de exportación para ser guardadas. De vuelta en el guión del jugador, podemos hacer referencia a la matriz de habilidades desbloqueadas y almacenarla en una variable del mismo nombre usando la etiqueta on ready. Tenga en cuenta que esto no solo hace una copia de la matriz en su estado actual. Crea una referencia a la matriz, por lo que cualquier cambio afectará a ambos. Esto significa que para desbloquear una habilidad para que el personaje la use, solo necesitamos establecer su valor en el recurso de guardar datos. Ahora podemos reemplazar la variable de salto doble C con indexar la matriz de habilidades desbloqueadas con Enums dot abilities dot Double Esta matriz de habilidades desbloqueadas ahora se puede usar a lo largo de todo este script para cada habilidad. En el script del administrador del juego, usaré la función de entrada para probar desbloqueo de la capacidad de doble salto al presionar la tecla de flecha hacia arriba Configuración de archivo punto datos punto Habilidades desbloqueadas, índice punto enums habilidades de punto punto Doble Saltar a verdadero Entonces podremos guardar el juego para que esto sea permanente. Ejecutando el juego, mi personaje no puede hacer doble salto. De vuelta en el Editor Godot, cambiaré a la pestaña remota para ver el árbol de escenas del juego que se está ejecutando actualmente Aquí puedo ver el archivo nodo global, que tiene un recurso de datos. Dentro de este recurso de datos, la matriz de habilidades desbloqueadas tiene cinco booleanos, que son todos falsos El nodo de personaje jugador también tiene una referencia a la misma matriz. Volviendo a la simulación, presionar hacia arriba se desbloquea la capacidad de doble salto En el árbol de escenas remotas, puedo ver que el booleano en la matriz se estableció true tanto en el recurso de datos como en el personaje Cerrando el juego y ejecutándolo de nuevo. El doble salto ya está desbloqueado desde que se salvó. Podemos eliminar las declaraciones impresas ahora que se confirma que el doble salto está funcionando. Ahora tenemos una capacidad de doble salto desbloqueable, pero tenemos varias habilidades desbloqueables más Te veré en el siguiente video. 44. 6-2 Diapositiva de pared: Hola, amigos. En este video, permitiremos que el personaje se deslice por una pared, agregando fricción para ralentizar su descenso. Primero, tenemos que decidir qué va a hacer esta habilidad y cuándo queremos que suceda. Al implementar una nueva característica como esta, es una buena idea configurar primero las pruebas que quieras poder aprobar. Empezaré en la escena del contenido de la habitación y esconderé los árboles para poder ver mejor. Para crear una mecánica de deslizamiento de paredes, voy a crear dos paredes en mi habitación. Consideraré que mi mecánica de Wall Slide está completa cuando el personaje pueda saltar, luego deslizarme hacia abajo por cualquiera de las paredes a una velocidad de caída reducida. También me gustaría reproducir una animación diferente mientras esto sucede. La diapositiva de pared debe terminar cuando el personaje ya no está en contacto con la pared si toca el piso o presionamos la dirección del movimiento para alejarlo de la pared. Por lo que implementar esto será alterar la física aérea del personaje. En el guión del personaje del jugador, anularemos el proceso de física aérea del personaje. Entonces llama al proceso de Física Aérea de la superclase desde el guión del personaje Aquí podemos separar nuestro código en tres bloques separados. Cuando el personaje está realizando una diapositiva de pared, comprobando cuándo puede comenzar a realizar una diapositiva de pared, y en cualquier otra ocasión llamamos el proceso de superclase Airphysics Necesitaremos saber cuándo el personaje está realizando una diapositiva de pared, por lo que debemos declarar esto como una variable booleana También sería útil exportar un flotador para usarlo como multiplicador a la gravedad del personaje mientras realiza una diapositiva de pared. Voy a usar el 10%. Volviendo al proceso de física del aire, ahora podemos ramificarnos en función de si la variable de deslizamiento de pared es verdadera o falsa o no. Si el personaje ya está deslizando la pared, podemos continuar con el deslizamiento de pared o terminarlo dependiendo de si se cumplen otras condiciones. Si el personaje no es deslizamiento de pared, entonces necesitamos verificar si pueden deslizarse de pared, y si se cumplen las condiciones para iniciar el deslizamiento de la pared, entonces hágalo. Y finalmente, si todo esto es falso, entonces deberíamos proceder con la física aérea de la superclase como predeterminada Escribir tu algoritmo en comentarios de pseudocódigo como este hace que sea mucho más fácil completar después y reorganizar si es necesario También hace el resultado final ya comentado. Comencemos con iniciar una diapositiva de pared comprobando si la habilidad Salto de pared ha sido desbloqueada. Después añadir también la condición que este personaje debe estar en una pared. La clase de cuerpo de personaje proporciona esta función que actúa igual que en el piso. También me gustaría agregar más condiciones de que su velocidad Y debe ser mayor o igual a cero. No quiero que el personaje comience a deslizar la pared si se mueve hacia arriba, y el jugador debe estar presionando la entrada de dirección de movimiento hacia la pared. El cuerpo del personaje dos denodo también nos da otra función Consigue Wall normal. Esto devuelve un vector apuntando lejos de la pared. Entonces, si usamos la porción X de este vector, ésta siempre será negativa si la pared está a la derecha del personaje o positiva si la pared está a la izquierda del personaje. Comparando esto con la dirección de movimiento del personaje, multiplicaré ambos lados por uno negativo y requeriré que los resultados sean iguales. Esto no permitirá que la dirección del movimiento sea cero. Hay varias condiciones en esta declaración I, y no caben dentro de mi ventana de guión. Si desea escribir las condiciones de su declaración if en varias líneas, puede hacerlo envolviéndolas entre paréntesis. Esto puede hacer que tu código sea más fácil leer y depurar si prefieres este formato. Si bien mis paredes son perfectamente verticales, es posible que necesites usar el seno de las paredes normal X si tus paredes están anguladas. Si todo esto es cierto, permitiré que el personaje inicie una diapositiva de pared configurando I deslizamiento de pared true y tapando su velocidad Y a cero usando la función min. Esto creará un breve reinicio de la velocidad de caída para hacer que el deslizamiento de la pared se sienta más lento. También imprimiré una declaración para fines de prueba. Ahora asumiremos que el personaje ya está realizando un deslizamiento de pared, y queremos anular su gravedad para ralentizar su descenso. Simplemente agregando a la velocidad Y del personaje, tiempos de gravedad Delta el multiplicador de gravedad Wall Slide, que he establecido en 10% de la gravedad normal. Pensando en esto desde una perspectiva física, esto equivale a decir que existe un coeficiente de fricción de 0.9 entre el personaje y la pared. Y por último, podemos pensar en cuándo terminar el Wall Slide. Si el personaje ya no está en la pared o si el jugador presiona la dirección opuesta del movimiento alejándose de la pared. Entonces, si no está en la pared o si la señal de dirección de movimiento es la misma que las normales de pared X, entonces configuraré Is wall sliding false e imprimiré una declaración de que el Wall Slide ha terminado Sería más sencillo poner el tobogán de pared continuando como el bloque else a esta declaración I, así que lo cortaré y pegaré aquí. Hay una condición más que necesita terminar una diapositiva de pared cuando el personaje toca el piso. Como ya tenemos una función que se llama automáticamente cuando el personaje aterriza, simplemente voy a agregar otra declaración I aquí que termina el Wall Slide. Si el personaje es pared deslizante, establezca I pared deslizante en falso, luego imprima otra declaración. Ayuda si estas dos declaraciones son diferentes para que podamos ver cuándo cada una está sucediendo realmente durante nuestras pruebas. Esto funcionará para el teclado, pero no para un controlador ya que la dirección de movimiento puede ser un valor decimal. Entonces tendré que aplicar la función sign a ambas comprobaciones para trabajar con la entrada del controlador. Lo último que tengo que hacer es agregar una animación de Wall Slide al reproductor de animación del personaje. Entonces duplicaré su animación de caminata. Cambie la posición Y de la región de la hoja de cálculo que se esté utilizando y elimine la pista de pasos Agregar esta animación al recurso de la máquina de estado. Permitiré que el personaje haga la transición a este estado ya sea de salto o caída si el deslizamiento de I Muro se establece como verdadero. Luego, la transición de un tobogán de pared a caer si el deslizamiento de la pared se establece en caídas. O a la locomoción si tocan el piso. En el guión del administrador del juego, cambiaré desbloqueando el doble salto desbloquear el Wall Esto debería ser suficiente para pasar mi prueba, así que correré el juego. El personaje todavía puede saltar normalmente, y saltar contra la pared no realiza un deslizamiento de pared ya que esa habilidad aún está bloqueada. Pero presionando hacia arriba para desbloquear el Salto de Pared, ahora si salto mientras me muevo hacia la pared, se deslizan hacia abajo y se detienen cuando tocan el piso. Intentando esto en la otra pared, la corredera de pared termina cuando llegan al fondo de la pared. Y otro intento contra la primera pared, el tobogán de pared no comienza hasta que el personaje comienza a caer, y puedo terminar el deslizamiento de pared temprano alejándome de la pared. El comportamiento normal de salto del personaje no se ve afectado al realizar ninguna de estas acciones. Con todas las pruebas superadas, recuerde comentar las declaraciones impresas. Ahora tenemos a nuestro personaje capaz de realizar un Wall Slide, pero aún tenemos que implementar el Salto de Pared. Te veré en el siguiente video. 45. 6-3 Salto de pared: Hola, amigos. En este video, permitiremos que el personaje salte lejos de la pared mientras realiza un deslizamiento de pared. En el guión del personaje, ya hemos anulado la función de salto para hacer un doble Cuando queremos que el personaje salte de pared, todas estas condiciones en el doble salto también pueden ser ciertas. Por lo que primero tendremos que considerar el Salto de Pared como una posibilidad y descartarlo antes de verificar el doble salto ya que las condiciones para el Salto de Pared son más específicas. Solo tendremos que verificar si la habilidad Salto de pared se ha desbloqueado y si el personaje está realizando actualmente una diapositiva de pared. Si no se cumplen estas condiciones, entonces podemos verificar si el personaje puede saltar doble en su lugar. Sin embargo, esto no permitirá que el personaje realice un salto de pared hasta que el Wall Slide haya comenzado, lo que está esperando hasta que el personaje haya alcanzado la cúspide de su salto. Si quieres permitir el salto de pared antes de iniciar la diapositiva de pared cuando la velocidad Y del personaje es negativa, entonces también podemos agregar más condiciones. O los personajes que realizan una diapositiva de pared o no están en el piso y están en una pared, y la dirección de movimiento es hacia la pared. Con el orden de las operaciones para la lógica, necesitamos poner el o entre paréntesis para que se revise antes de la primera y. Podemos usar múltiples niveles de corchetes y sangría para establecer visualmente el orden de las operaciones de lógica compleja como esta para que sea más fácil de entender si es necesario Ahora que estamos listos para realizar un salto de pared, podemos hacer todas las mismas cosas como lo haríamos con cualquier otro salto. Entonces devuelve true, así el manejador de entrada sabe que esta pulsación de botón de salto fue exitosa En cuanto a establecer la velocidad del cuerpo del personaje, queremos que no solo suba sino que también se aleje de la pared. Entonces, en lugar de simplemente establecer la velocidad Y del personaje, estableceremos todo el vector de velocidad, creando también un nuevo vector. Para la X, podemos usar las paredes normales vector punto X, y para Y, podemos usar uno. Esto nos da un vector apuntando hacia arriba y lejos de la pared, así que tenemos la dirección correcta. Multiplicando esto por la fuerza de salto, obtendremos un vector con una magnitud mayor nuestro salto normal ya el vector original ya tenía una longitud mayor a uno Podemos normalizar este vector de dirección si queremos, pero la forma en que funciona en este momento realmente producirá un mejor resultado, en mi opinión, con la altura total del salto, más la fuerza extra que se aplica lejos de la pared. Pero como la fuerza de salto es un número negativo, esto invertirá el Muro normal para apunte hacia el muro en lugar de alejarse de él. Entonces agregaré un negativo al frente de wallnormalt X para que sea un doble negativo, lo que se vuelve positivo Para animar el Salto de Pared, la máquina de estado del personaje necesitará una transición de Wall Slide para saltar bajo la condición de que el personaje esté saltando Esto entra en conflicto con la transición a la caída ya que el personaje ya no es pared deslizante al mismo tiempo. Por lo que la transición al salto necesitará un valor de menor prioridad para ser considerado primero. En lugar de que el doble salto esté listo, tendremos que establecer Is wall sliding to falls al realizar el Salto de Pared. Si ejecutamos el juego, ya podemos realizar el salto de pared ya que se desbloqueó en el video anterior. Saltando contra la pared, podemos saltar de ella. La cantidad de velocidad lateral alejada de la pared es igual a la fuerza vertical que se aplica. Pero como la gravedad está tirando constantemente al personaje hacia abajo, es mucho menos notable que la fuerza que se aleja de la pared, que sólo se está reduciendo ya sea por el control de aire del personaje o por los frenos de aire. Preferiría que mi personaje tuviera mucha menos fuerza lateral aplicada y pudiera regresar a la misma pared después realizar un salto de pared y seguir escalando hacia arriba. Esto requerirá múltiples alteraciones diferentes de la física para que funcione correctamente, tanto reduciendo la cantidad de fuerza lateral que se aplica al Muro Saltar lejos de la pared, así como darle al personaje más control aéreo para poder regresar a la pared a mayor altitud. Primero, tratemos con la fuerza lateral. En lugar de codificar duro un valor, siempre es mejor usar variables exportadas para que puedan ser retorcidas y ajustadas. Exportaré un vector dos llamado Wall Jump force multiplicador y le daré un valor predeterminado de negativo uno positivo. Entonces podemos multiplicar el vector de velocidad resultante por este nuevo multiplicador de fuerza Wall Jump. Este negativo eliminará la necesidad tener el negativo aplicado al vector normal de pared, lo cual me parece más intuitivo ya que pienso en negativo como alejado de la pared. Al multiplicar dos vectores, el resultado será producto tanto de Xs como del producto de ambos Con estos valores, esto funcionará igual que lo hace actualmente. Pero como se exporta el valor, puedo cambiarlo en mi escena de personaje a 0.5 negativo, reduciendo la velocidad X a la mitad. Si quieres darte recordatorios de cómo funcionan tus variables, agregar un signo de número extra frente a un comentario encima de la declaración de la variable creará una punta de herramienta que se mostrará cuando pases el mouse sobre la variable en el inspector Ejecutando el juego de nuevo, mi personaje tiene toda la fuerza ascendente del salto, pero solo la mitad de la fuerza de salto se aplica en la dirección X. Pero todavía no puedo volver a la pared en un punto más alto para subir más alto. Para eso, voy a necesitar darle a mi personaje mucho más control aéreo, pero no quiero que el personaje tenga más control aéreo en ningún otro momento. Por lo tanto, tendré que anular el valor del control aéreo específicamente solo al realizar un Salto de Pared, luego volverlo a su valor normal. En las variables exportadas para salto de pared, exportaré un nuevo flotador para control de aire Wall Jump y lo pondré en algo muy alto, como cuatro. Esto hará que el personaje acelere cuatro veces más rápido de lo que lo haría en el suelo y ocho veces más rápido de lo que lo harían durante un salto normal con mi control aéreo por defecto en 0.5 También almacenaré esto en otra variable usando la etiqueta ready. Entonces, cuando quiera ponerla de nuevo a su valor normal, sabré qué es eso. Como no sé si el jugador estará saltando lejos de la pared o de regreso hacia ella o cualquier otra cosa que quiera hacer, la única forma confiable de volver a ajustar el control aéreo a su configuración predeterminada sería usar un temporizador. Añadiendo un nodo temporizador a la escena, lo llamaré Wall Jump, le daré un nombre único, luego obtendré una referencia a él con la etiqueta on ready two. Voy a nombrar esta anulación de control aéreo de Wall Jump para que quede un poco más clara en este contexto. Ahora, cuando realizamos el Salto de Pared, podemos cambiar el valor del control de aire a Control aire Wall Jump e iniciar el temporizador de anulación de control de aire Wall Jump. Seleccionando el nodo temporizador, podemos establecer su propiedad one shot true y darle un corto tiempo de espera. Voy a usar medio segundo. A continuación, conecte la señal de tiempo de espera del temporizador al script. Cuando el temporizador se agota, podemos volver a ajustar el control aéreo del personaje a su valor predeterminado. Probando esto, está más cerca, pero todavía no puedo subir por la pared. Entonces tendré que ajustar mi multiplicador de fuerza Wall Jump y los valores de control de aire Wall Jump hasta que funcione. Ejecutando el juego de nuevo, ahora cuando realizo un Wall Jump, mi personaje tiene suficiente aceleración para volver a la misma pared en un punto más alto, lo que me permite subir por la pared. Ahora tenemos nuestro personaje capaz de saltar a la pared para escalar superficies verticales. A continuación, agregaremos una habilidad elegante completa con marcos de invencibilidad Te veré en el siguiente video. 46. 6-4 Guiones: Hola, amigos. En este video, le daremos al personaje una habilidad de guión desbloqueable Comenzando en la configuración del proyecto, la pestaña Mapa de entrada necesitará un botón que se pueda usar para guiones. Usaré la tecla D o el botón del hombro derecho en mi controlador. Entonces en el guión del jugador en la función de entrada, si se presionó el botón del tablero, intente salpicar, y si no tiene éxito, búfer la entrada del tablero para volver a secar el siguiente fotograma, tal como hicimos con el salto El guión necesitará una dirección, la cual podremos obtener usando la entrada Singleton, obtener eje, movernos a la izquierda, movernos a la derecha Para proporcionar argumentos a un callable, usamos la función bind, luego pasamos los argumentos a esa función en su lugar Por lo que sería mejor llamar solo a la función de entrada get axis una vez y almacenar el resultado. Dado que esto solo sucederá durante los fotogramas cuando se presione el botón del tablero, no es tan malo declarar una variable aquí. Cuando se llama a la entrada en búfer, pasará los argumentos enlazados. Si el guión se presionó originalmente con el stick izquierdo inclinado, se almacenará en búfer con esa misma entrada direccional Ahora podemos escribir esta función dash en nuestro script de personaje jugador, aceptando la dirección a dash como parámetro y devolviendo un booleano, devolviendo false por defecto Antes de escribir esta función, necesitaremos algunas variables. La distancia que queremos que el personaje corra, yo estableceré el mío en 128 píxeles. La cantidad de fuerza requerida para alcanzar esa distancia calculada usando la etiqueta on ready, podemos usar la misma fórmula que el cálculo de altura de salto, la raíz cuadrada de distancia multiplicada por la fuerza negativa, que en este caso es la desaceleración por dos También me gustaría suspender gravedad mientras ocurre el guión. Así que también almacenaré la gravedad predeterminada del personaje en una variable usando la etiqueta on ready. Ahora para la función dash, si la habilidad dash ha sido desbloqueada, entonces queremos que el personaje mire hacia la dirección del guión, lo que podemos hacer estableciendo la dirección de movimiento a ese valor. Luego establece la velocidad del personaje para que sea un nuevo vector dos con la dirección del guión multiplicada por fuerza del tablero como la X y cero para la Y. Dado que el stick analógico izquierdo se puede inclinar, esto significaría que el jugador puede lanzar más lento o más rápido en función de lo lejos que incline el stick analógico en el controlador No quiero que esto suceda, así que usaré la función sinusoidal para eliminar la inclinación de la ecuación. Podemos suspender la gravedad mientras el guión está sucediendo, estableciendo el valor de la gravedad en cero, luego volver verdadero porque el guión fue exitoso y no necesita ser amortiguado. cuanto a la dirección a guión, hay varios casos a considerar, no sólo si el jugador está dando entrada direccional, sino también si no lo son y también si el personaje está realizando actualmente un deslizamiento de pared. Dado que ese es el caso más específico, primero lo revisaré. Si el carácter es muro deslizante, sobrescribiré el valor de dirección para ser signo de wallNRmaltx Si no son de pared deslizante y el jugador está dando entrada direccional cuando presionan al botón del tablero, entonces voy a usar el pecado de dirección como la dirección, eliminando cualquier inclinación analógica de la entrada para poder quitar esto de la línea de abajo. Si el jugador no está dando ninguna entrada direccional cuando presiona el botón del tablero, asumiré que quieren correr hacia adelante. Usaré un ternario si para establecer la dirección para que sea negativa si el personaje está orientado hacia la izquierda o uno positivo si no están restaurando la gravedad de nuevo a la normalidad, necesitaremos otra función para llamar al final del guión Esto no necesita ningún parámetro ni devuelve un valor. Simplemente volveremos a establecer la gravedad del personaje a su valor predeterminado. En la escena del personaje, el guión necesitará una animación en el nodo Animation Player. Al establecer los fotogramas por segundo y acercar el zoom, agregaré mis fotogramas clave para animar el guión Tendremos que agregar una pista de método de llamada y un fotograma clave en esta pista para llamar a la función end dash al final de la animación O cualquier fotograma que quieras para restaurar la gravedad del personaje. Usando este procedimiento, si es posible interrumpir esta animación por cualquier motivo, aún necesitaremos llamar a la función end dash para restaurar la gravedad del personaje, a diferencia del temporizador que usamos para restaurar el control de errores del personaje. Así que ten esto en mente y haz un comentario para recordarte esto más adelante. Añadiendo esta animación a la máquina de estado, debería ser posible realizar un guión desde cualquiera de nuestros estados de movimiento existentes. Por lo tanto, sería mejor poner esta animación en una nueva capa. Guardando la máquina de estado actual como recurso de proyecto, nombraré movimiento y pondré en la carpeta de escenas de personajes. Luego cree un nuevo recurso de máquina de estado para el Árbol de Animación. Añadiendo la máquina de estado de movimiento como nodo en esta nueva máquina de estado, renombraré a movimiento y crearé una transición de inicio a movimiento, por lo que es la predeterminada. Al agregar una nueva animación de guión a esta máquina de estado, podemos agregar una transición de movimiento a guión y de regreso al movimiento. Para reproducir una animación una vez, la transición que conduce a ella debe establecerse en habilitada, y la transición que sale de la animación debe tener su modo de conmutación configurado en al final y dejando el modo avanzado como automático. Podemos probar esta animación haciendo clic en el botón de reproducción en el estado. Con cada clic, juega una vez en su totalidad y vuelve al estado de movimiento cuando se termina. Dado que la transición que conduce a la animación no es automática, nos toca a nosotros activar esta animación manualmente a través de nuestro script. Declarando una nueva variable, esta será utilizada para múltiples habilidades diferentes, así que la pondré en la parte superior y solo la nombraré animación para abreviar El tipo de esta variable será una reproducción de máquina de estado de nodo de animación. Esto es lo que usa Godot para navegar por la máquina de estado y reproducir animaciones Seleccionando el nodo en el árbol de escenas, podemos ver este recurso de reproducción bajo parámetros de reproducción. Podemos recuperar este recurso haciendo clic y arrastrando el nodo Árbol de Animación para obtener su ruta de nodo Luego usa corchetes para obtener un recurso de este nodo. Hacer clic y arrastrar este recurso desde el inspector a los corchetes nos da la ruta al recurso Si ampliamos el movimiento y la locomoción, se puede ver que cada capa de la máquina de estado tiene su propio recurso de reproducción Si bien actualmente solo necesitamos este para activar manualmente el tablero, pronto agregaremos más habilidades Esta ruta también cambiará a medida que agreguemos más capas a la máquina de estado, por lo que deberá actualizarse. Para activar la animación de guión, al realizar con éxito un guión, podemos decirle a esta reproducción que viaje al estado de guión especificando su nombre de cadena como argumento. Esta línea de código equivale a presionar el botón de reproducción en el Árbol de Animación cuando previsualizamos la animación También quiero eliminar la capacidad del jugador para controlar al personaje mientras el guión está sucediendo. Así que anulando el proceso de física, podemos interrumpirlo rápidamente y verificar en qué estado se encuentra actualmente la máquina de estado de animación se encuentra actualmente la máquina de estado de animación usando la función G nodo actual Esto devuelve el nombre de cadena que escribimos en el nodo en el Árbol de Animación, que podemos comparar para ver si es movimiento o no. Si es otra cosa que no sea movimiento, estableceré la dirección del movimiento en cero antes continuar con el proceso normal de física de la superclase Esto evitará que el personaje se mueva o mire en una dirección diferente mientras realiza cualquiera de las habilidades en la capa superior de la máquina de estado. En el guión del administrador del juego, voy a cambiar la tecla de flecha hacia arriba para desbloquear la dashability Ejecutar el juego, presionar el botón del tablero no hace nada. Después de presionar la tecla de flecha hacia arriba para desbloquear la dashabilidad, podemos correr, haciendo que el personaje se desplace hacia adelante Al presionar una dirección, el personaje corra en esa dirección. Y si corremos mientras la pared se desliza, el personaje se alejará de la pared. Ahora tenemos nuestro personaje de jugador capaz de correr por el entorno, pero tendremos que agregar un temporizador de enfriamiento para evitar que el jugador lo use con demasiada frecuencia. Te veré en el siguiente video. 47. 6-5 horas de enfriamiento: Hola, amigos. En este video, agregaremos fotogramas de invencibilidad y un enfriamiento a nuestra habilidad de tablero Antes de comenzar a agregar marcos de invencibilidad al tablero, sería útil tener un hit box en nuestra escena para que podamos probar corriendo a través En la escena de contenido de la sala de inicio, agregaré un área para denodar y renombrarla para darle un toque a Box Luego agrega una forma de colisión cuando era niño. Dale una forma de rectángulo como recurso y establece su color de depuración en rojo. Te puedes imaginar que esto representará a un enemigo que daña al personaje del jugador al contacto. Voy a hacer que sea un azulejo de espesor, 32 píxeles, y dos teselas de alto, 64 píxeles. Después muévelo hacia la izquierda. Consideraré que mi prueba fue aprobada si el personaje del jugador puede correr por esta área sin ser perjudicado Para que esta zona de colisión inflija daño al jugador , deberá estar monitoreando. No necesita ser monitoreable, aunque dejar esta casilla marcada no hará ninguna diferencia No necesita existir en ninguna capa, sino que debe estar enmascarando la capa del jugador Hurt Box. Si te ayuda a entender mejor las colisiones, está bien considerar que esta caja de impacto existe en una capa de caja de impacto enemiga o una capa de peligro ambiental Los únicos requisitos son que debe estar monitoreando y enmascarando al jugador Hurt Box. Adjuntando un script a este nodo, conectaremos su señal de entrada en el área al script. Después de verificar si el área tiene un método de toma de daño, llamaremos a este método y pasaremos uno como la cantidad de daño. Esto asegurará que el área que ingresa esta tenga el script de Hurt Box que creamos anteriormente, que tiene el método take damage, aceptando la cantidad de daño como parámetro. Si otra área activa la señal sin un script de Hurt Box, causaría un error ya que no habría un método de toma daño para llamar. Para poder ver nuestras formas de colisión mientras probamos el juego, podemos abrir el menú de depuración y seleccionar formas de colisión visibles. Si ejecutamos el juego, podemos ver el hit box, y el personaje jugador recibe un daño cada vez que ingresa a esta área. Hay un mensaje de error porque el contenido de la habitación se está cargando en respuesta a que nuestro personaje ingrese a un área de colisión, y a Godot no le gusta agregar otra área de colisión durante un evento de colisión Ignoraremos esto por ahora ya que solo estamos realizando una prueba, y esto no va a ser parte de nuestro juego final. En la escena del personaje, selecciona el nodo Reproductor de animación y la animación de guión. Para agregar fotogramas de invencibilidad a nuestra animación de tablero, todo lo que tenemos que hacer es fotogramas clave la propiedad monitoreable de Hurt Box Podemos establecer el marco exacto cuando la Caja Hurt se apaga y cuando se vuelve a encender. Si lo deseas, también puedes fotogramas clave la visibilidad de tu Hurt Box para que coincida con su propiedad monitoreable para que pueda verla apagarse y volver a encenderla mientras juegas al juego Esto hace que sea más fácil saber cuándo tu personaje es realmente invencible También podría ser útil desactivar la visibilidad de la forma de colisión del cuerpo del personaje para ver mejor la Caja de Daño. ejecutar el juego, ahora podemos atravesar el hit box sin recibir ningún daño. Caminar hacia el área aún inflige daño al igual que terminar el guión dentro del área Ahora agreguemos un Cooldown al guión. Comenzaremos agregando un nodo temporizador a la escena del personaje. Voy a nombrar a este temporizador Dash Cooldown y estableceré su propiedad de one shot en true Dejaré su tiempo de peso como 1 segundo. Este será el tiempo de enfriamiento de la habilidad. Teniendo en cuenta que esta es la segunda habilidad con un nodo temporizador asociado, y es posible que queramos agregar más en el futuro, es posible que desee considerar usar un nodo normal como una carpeta plegable para contenerlos. Pero ayudará a darle un nombre único en caso de que queramos reestructurar el árbol de escena No necesitamos conectar la señal al script para usar este nodo temporizador como enfriamiento. En las declaraciones de variables para Dashability, usaré la etiqueta on ready para obtener una referencia a este nuevo nodo temporizador Todo lo que tenemos que hacer es iniciar el temporizador ya sea al arrancar o al finalizar o al salpicar. Depende de tu preferencia cuál, pero si quieres comenzar el enfriamiento al final del guión, se requerirá otra condición para evitar que el jugador se apague dos veces seguidas Iniciaré el temporizador de Enfriamiento después de que termine el tablero. Después volvemos a la declaración I donde comprobamos si este personaje puede comenzar a correr. Podemos verificar si el nodo actual de la máquina de estado de animación es movimiento. Esto también tendrá beneficios agregados más adelante, ya que no permitiremos que el personaje se desplace mientras realiza otras habilidades de acción similares. Para hacer cumplir el temporizador de Enfriamiento, solo necesitamos verificar si este temporizador está parado para saber si deberíamos poder volver a correr Si la animación del tablero ya se está reproduciendo o el temporizador de enfriamiento no se detiene, eso significa que el tablero fallará Ejecutando el juego ahora, presionando el botón del tablero permite al personaje correr solo una vez, luego obliga a un enfriamiento de 1 segundo antes de que puedan volver a correr. Esto funciona, pero no se está comunicando al jugador de ninguna manera. Por lo general, juegos como este tendrán un indicador diagético, algo que existe en el juego, no en el HUD para decirle al jugador cuándo termina el enfriamiento Así que agreguemos un nodo Animated Sprite two D a la escena del personaje y llamémosle el efecto Dash Cooldown. Al crear un recurso de marcos Sprite para este nodo, podemos importar una hoja de Sprite Simplemente pondré esto en la carpeta de polvo por ahora en lugar de crear una nueva carpeta de activos para una hoja de Sprite Y agrega los marcos Sprite de la hoja Sprite. Desactivaré el ciclo, estableceré los fotogramas por segundo en 12, y también agregaré un fotograma en blanco al final de la animación Esto no está centrado en el personaje, así que lo voy a mover hacia arriba 12 píxeles. Esta animación es de más de 1 segundo, pero la marca de 1 segundo es cuando quiero que el enfriamiento se considere terminado. Voy a darle un nombre único a este nodo. De vuelta al guión, todo lo que tenemos que hacer es agarrar una referencia a este nodo. Un dígale que juegue cuando termine el guión. Pero como mi animación es más larga que el temporizador Dash Cooldown, en realidad tendré que detener la animación antes de reproducirla en caso de que todavía se esté reproduciendo Esto restablecerá la animación de nuevo al inicio. A Ahora, cuando ejecutamos el juego y usamos la habilidad dash, se reproduce la animación, pero no está siguiendo al personaje. Esto se debe a que un nodo normal no tiene una transformada. Por lo tanto, no tiene una posición. Esto rompe la línea de herencia del nodo raíz del personaje. Por lo que el nodo animado Sprite dos D ahora está comenzando su propia ascendencia para dos transformaciones D, comenzando en la posición 00 Podemos cambiar el tipo de la carpeta de habilidades a no dos D para que proporcione una línea de sucesión a través del árbol de escenas, y el Sprite Animado seguirá el nodo raíz Ahora es claro para el jugador que su habilidad de tablero está en Cooldown y exactamente cuándo puede volver a correr sin tener que agregar ninguna información extra sobre el HUD Ahora tenemos nuestra capacidad de tablero capaz de atravesar cajas de impacto sin que nos golpeen y enfriemos antes de poder volver a usarse. A continuación, agregaremos una habilidad pasiva que cambia la apariencia del personaje. Te veré en el siguiente video. 48. 6-6 sombreros: Hola, amigos. En este video, implementaremos una habilidad pasiva que altera la apariencia del personaje Comenzando en la escena del contenido de la habitación, duplicaré el área de colisión de antes para esta prueba. Esta vez, el área de colisión representará específicamente un calor intenso desde el interior de un volcán. Voy a cambiar el color a naranja así sé cuál es cuál. Quiero que el jugador no pueda pasar por esta área hasta que no haya desbloqueado un sombrero mágico que le permita proceder ilesos Pero llevar el sombrero aún les permitirá recibir daños de cajas de impacto normales. Entonces, en lugar de tener esto enmascarando la capa normal del jugador Hurt Box, usaré una capa diferente. Utilizaré la capa 14 como una capa dedicada a este efecto de calor ambiental. Esto me será fácil de recordar ya que está directamente por debajo de diez. En la configuración del proyecto, voy a nombrar a esta capa de calor. Entonces en la escena del personaje, voy a hacer que la Caja de Hurto también exista en esta capa. Ahora bien, esto funcionará de la misma manera que antes el área de colisión, infligiendo un daño al jugador cada vez que ingrese a esta área. Sólo está comprobando colisiones en la capa 14 en lugar de en la capa diez Entonces, todo lo que tenemos que hacer para que el personaje del jugador sea inmune al daño por calor mientras usa el sombrero es quitar la capa 14 de su propiedad de capa de colisión Hurt Box. Para alterar la apariencia del personaje, colocaré sprites adicionales sobre el personaje Importaré nuevas hojas de sprites para tres mejoras diferentes, una gema, una capa y un sombrero Después en la escena del personaje, agregaré un nodo Sprite Tu Di extra para cada uno de ellos. Todo con texturas atlas al igual que el sprite corporal. A continuación, asigne las hojas de sprites como la propiedad atlas para cada nodo La forma en que se dibujaron estos activos, voy a necesitar ponerlos específicamente en el orden del gato, luego la capa específicamente en el orden del gato, , luego el sombrero, y la mermelada en la parte superior Comenzaré cada uno con el primer sprite en la posición 00 con un tamaño de 32 por 36 píxeles y les daré el mismo desplazamiento para moverlos hacia arriba por 18 píxeles Estos activos se dibujan para animar sincrónicamente con el sprite de carácter normal Por lo que todos los valores de región serán los mismos para cada capa al mismo tiempo. Todo lo que tengo que hacer es agregar región de textura del atlas de cada sprite a la animación Después copia y pega las teclas del cuerpo de la pista de Sprite a las otras pistas Y cambiar su modo de actualización a discreto. Ahora la animación también incluye todas las capas de sprites en perfecta sincronización Voy a necesitar hacer esto para todas mis animaciones, pero no va a tomar tanto esfuerzo. Para voltear cada uno de estos sprites, podríamos establecer todas sus propiedades flip H cada vez que cambien de dirección Pero hay una manera más fácil usar la herencia del árbol de escenas. Si hacemos que todos los demás sprites hijos del sprite corporal, heredarán su transformación de él Y podemos voltear un sprite usando su transformada estableciendo su escala X a una negativa Tenga en cuenta que este truco no debe usarse para nada que involucre física o colisiones. Aquí funciona bien porque solo estamos dibujando sprites. En la función cara izquierda en nuestro script de caracteres, lugar de establecer flip H, podemos establecer el punto de escala X a uno negativo, si se deja, de lo contrario, uno positivo. Esto sincronizará ahora el volteo de todos los sprites Con toda la configuración de los sprites completa, configuraré la visibilidad de los otros sprites por defecto, luego los encenderé a medida que se desbloqueen las habilidades En el guión del personaje del jugador, necesitaremos una función para gestionar qué capas de Sprite son visibles en función de qué habilidades ha desbloqueado el jugador Lo llamaré Actualizar visibilidad de Sprite. Luego, dale a cada uno de los sprites un nombre único y establece su visibilidad para que coincida con el valor de habilidades desbloqueadas para la habilidad de emparejamiento Al doble salto se sumará el manto. El sombrero es obvio. Y la capacidad de disparar proyectiles agregará la gema. En el guión del administrador del juego, cuando empezamos a jugar el juego por primera vez, podemos llamar a esta función para actualizar la visibilidad de Sprite de los personajes de inmediato en caso de que hayamos cargado una cerveza segura con habilidades ya desbloqueadas Mientras jugamos el juego, también querremos llamar a esta función cada vez que el jugador desbloquee una nueva habilidad Entonces agregaremos una señal a este script para cuando se haya desbloqueado una habilidad, con el número entero de habilidades como parámetro. Después escribe una función pública para desbloquear una nueva habilidad, aceptando el mismo número de habilidad y omitiendo la señal Entonces podemos conectar esta señal al personaje del jugador. Sin embargo, no escribimos la función de visibilidad de Sprite de actualización para aceptar ningún parámetro Entonces, cuando conectamos la señal, debemos desvincular un argumento para evitar causar errores Esto funcionará para cambiar la apariencia del personaje, pero seguirán tomando daño por calor mientras llevan puesto el sombrero. Al actualizar la visibilidad del sprite del personaje en el caso específico de adornar el sombrero, también eliminaré la capa de colisión daño por calor para que sean inmunes a ella Para eliminar una sola capa específica de una máscara de bits, primero, coloca el cursor del mouse sobre la capa y toma nota de su valor La capa 14 tiene un valor de 8,192, que es dos a la potencia de 13 o dos a la potencia de 14 menos uno La capa de colisión es en realidad un entero, que en binario es una secuencia de ceros y unos. Actualmente, es todo ceros, salvo que los bits décimo y 14 son uno Todo lo que tenemos que hacer es cambiar el bit 14 a cero para eliminarlo de esa capa. Empezaremos agarrando una referencia a la caja het. Dado que esta función no se llama muy a menudo, está bien usar una ruta de nodo. Para eliminar la capa de colisión, podríamos restar su valor 8,192 Sin embargo, esto depende la capa de colisión existente actualmente en la capa 14. Si llamáramos a esta función por alguna razón cuando la capa 14 ya está apagada, resta simple no funcionaría Usando el operador de bits y en la capa de colisión de nuestra caja Hurt, si podemos proporcionar una secuencia de todos los con solo el bit 14 como cero, el resultado será establecer el bit 14 20 independientemente de su valor actual. Para obtener ese número, podemos revertir los bits de 8,192, el valor de las capas Esto se hace con el operador nada bit a bit, que en GDScript es Esta es una forma matemáticamente eficiente de eliminar las capas de colisión Si quieres agregar una capa de colisión, estableciendo su bit en uno, todo lo que tienes que hacer es usar el operador u en lugar de y y quitar el nudo. Pero no nos interesa hacer eso aquí. En el guión del administrador del juego, actualizaré mi función de entrada para desbloquear cada nueva habilidad en secuencia al presionar la flecha hacia arriba para mi prueba. Declarando una nueva variable aquí, por lo que se incluye con mi código de prueba Recordaré eliminar esto junto con la función de entrada cuando ya no la necesite para probar. Voy a nombrarla siguiente habilidad como un entero que naturalmente por defecto es cero Cada vez que presione la flecha hacia arriba, desbloquearé la siguiente habilidad e imprimiré el nombre de esa habilidad. Podemos usar la función keys en una enumeración para obtener una matriz de cadenas que son las mismas que las que escribimos como las entradas de enumeraciones Entonces, al indexar la matriz de claves con el número de habilidad, se obtiene el nombre de esa habilidad Luego incrementaré la siguiente habilidad, pero la mantendré sujeta para que esté entre cero y el tamaño de la enumeración de habilidades menos uno para evitar errores Eliminaré el archivo seguro actual para que mis habilidades comiencen bloqueadas y enciendan formas de colisión visibles. Ejecutando el juego, comenzamos sin habilidades desbloqueadas y el personaje predeterminado Sprite Abriré el árbol de escenas remoto y seleccionaré a los personajes Hurt Box para verificar que están en las capas diez y 14. Presionando una vez la flecha hacia arriba, la habilidad de doble salto ahora está desbloqueada, por lo que el personaje lleva una capa Al presionar nuevamente la flecha hacia arriba, se desbloquea el salto de pared, pero la apariencia del personaje permanece sin cambios ya que esa habilidad no se asoció con un cambio cosmético. Al tocar cualquier área de colisión el personaje sufrirá daños. Presionando una vez más, ahora el guión también está desbloqueado, y aún así el personaje se ve igual. De nuevo para desbloquear el sombrero mágico, y podemos ver que la Caja de Hurto del personaje ya no está en la capa 14, sino en la capa diez. Tocar la caja de golpe normal causa daño, pero entrar en la nueva caja de impactos de calor volcánico no lo hace, lo que significa que el personaje es inmune a ella mientras usa el sombrero. Presionando una última vez, desbloqueamos la habilidad de disparar y agregamos la gema, pero aún no la hemos implementado. Ahora tenemos nuestro personaje cambiando atuendos para que coincida con su progreso a lo largo del juego. La última habilidad que agregaremos es disparar un proyectil. Te veré en el siguiente video. 49. 6-7 Proyectil: Hola, amigos. En este video, agregaremos un hechizo de proyectil que el jugador puede disparar gastando sus puntos mágicos Primero, tendremos que darle a este personaje puntos mágicos para gastar. En el guión del personaje del jugador, agregaré una nueva categoría de exportación para lanzar hechizos Después dos variables por su magia máxima y su magia actual tanto como carrozas También necesitaremos señales para emitir cada vez que cambien estos valores para poder actualizar el HUD Anulando la función ready, podemos establecer la magia máxima al valor de los datos de guardado del jugador Entonces solo arrancaré al jugador con magia completa, configurando el valor actual al valor máximo y emitiré las señales cambiadas para actualizar el HUD Desde la escena del juego, podemos conectar fácilmente las señales del personaje del jugador al medidor mágico ya que existen en la misma escena. El medidor mágico no tiene un guión adjunto, pero no necesita uno. Dado que la barra de progreso ya proporciona las funciones que necesitamos, solo tenemos que desactivar los métodos de script solamente. La clase range nos da la función set max aceptando un parámetro float. Así como la función set value, aceptando también un parámetro float. Ahora el medidor mágico se actualizará automáticamente con las variables mágicas del personaje del jugador. En la configuración del proyecto, la pestaña Mapa de entrada necesitará un botón que pueda ser presionado por el jugador para lanzar un hechizo. Usaré la tecla C o el botón Face superior en mi controlador. Después en el guión de los jugadores, podemos copiar el mismo formato que el salto para intentar lanzar un hechizo y si no tiene éxito, amortiguar la entrada para volver a intentar el siguiente fotograma De vuelta en el guión del personaje del jugador, podemos escribir la función cast, no aceptando parámetros y devolviendo un booleano Todo lo que realmente necesitamos hacer aquí es verificar si la habilidad ha sido desbloqueada y si el personaje no está ocupado realizando otras acciones, si el nodo actual de la animación es el movimiento. Entonces dígale a la animación que viaje a la animación del elenco y devuelva true si la entrada fue exitosa o false si no lo fue. En caso de que no queramos que el lanzamiento de nuestro hechizo sea instantáneo, todo lo demás tendrá que suceder en una función separada Vamos a nombrar a este proyectil de un disparo. No necesita ningún argumento ni devolver ningún valor, y aún no tenemos ninguna información para escribir esta función, pero necesitaremos que esta función sea declarada y guardada antes de poder incluirla en la animación de casting. Cambiando a la escena del personaje, comenzaremos agregando un Sprite Animado para dende para usarlo como efecto de lanzamiento Esto necesitará un recurso de marcos Sprite. Antes de importar mis hojas de sprites para lanzar hechizos, haré una nueva carpeta para sprites mágicos y moveré el efecto de enfriamiento del guión a Después importa los sprites para el lanzamiento, el proyectil y sus sprites de impacto Agregar los sprites de animación de lanzamiento al recurso de fotogramas de Sprite Y Lo pondré 12 cuadros por segundo, no en bucle Y agregaré un fotograma en blanco al final de la animación, luego lo moveré hacia arriba 18 píxeles con el desplazamiento Y. Esto se ve bien, pero si le hacemos esto al personaje Sprite, también volteará para enfrentar la misma dirección que el personaje Seleccionando el nodo Animation Player, podemos duplicar cualquiera de las animaciones existentes para crear una animación de casting. Después de eliminar pistas innecesarias y actualizar todos los fotogramas clave de la región de Sprite, agregaremos pistas del método de llamada tanto al nodo raíz del personaje al efecto de casting Sprite animado no dos D. Para el efecto casting, todo lo que tenemos que hacer es decirle que Para el personaje, agregaremos un fotograma clave para disparar el proyectil Estos fotogramas clave se pueden ajustar fácilmente para que ocurran en cualquier momento durante la animación de casting Comenzaré el efecto de lanzamiento en el segundo fotograma y dispararé el proyectil en el tercer marco El resto de la animación actuará como recuperación. En el Árbol de Animación, solo necesitamos repetir el mismo proceso que usamos con el guión. La transición al reparto está habilitada, y estamos volviendo al movimiento al final de la animación A continuación, ensamblemos el proyectil real. Comience agregando una nota D del área dos a la escena del personaje. Entonces dale una forma de colisión y un recurso de forma. Usaré un círculo pero reduciré su radio a ocho píxeles, y cambiaré su color de depuración a algo que aún no he usado, como el morado. Después agrega un Sprite Animado para denodar y dale un recurso de marcos de Sprite Primero, agregaremos los fotogramas de sprite para el proyectil como queremos que comience y lo usaremos como la animación predeterminada de Sprite Esto será en bucle y estableceré mi velocidad de fotogramas en 12 fotogramas por segundo Después haremos clic en el botón agregar Animación para crear una segunda animación de Sprite y nombraremos a ésta algo así como Impact Ahora podemos agregar más fotogramas Sprite para una animación de impacto que será reproducida por el mismo proyectil cuando choca También es posible que desee agregar un fotograma vacío al final de esta animación para permitir que el último fotograma se dibuje durante toda su duración. Recuerda establecer la animación predeterminada para reproducción automática, así que reproduciremos esta animación cuando el proyectil genere Aún dentro de la escena del personaje, reposiciona el proyectil hacia donde quieras que comience en relación con el Puedes hacerlo más fácil seleccionando el proyectil y el árbol de escena y sosteniendo Alt mientras lo mueves El mío es de 12 píxeles a la derecha y arriba desde el origen del personaje. A continuación, agregue un marcador dos nodos D como hijo del proyectil Esto asegurará que su posición coincida exactamente con el proyectil El marcador al nodo D es exactamente el mismo que un nodo dos D, excepto que dibuja un pequeño artilugio en el editor para que podamos ver exactamente dónde está Esto nos da la posición en la que queremos generar el proyectil en nuestra escena al lanzar el hechizo Así podemos nombrar el nodo Marker Tutti en consecuencia. Después reparar el nodo Marcador Tutti al personaje Sprite Al ser hijo del personaje Sprite, volteará su exposición cuando el personaje cambie su dirección de orientación automáticamente Guarda la rama del proyectil como escena propia y guárdala en una nueva carpeta de escenas para proyectiles Después elimínelo de la escena del personaje. Ahora tenemos un proyectil y sabemos dónde lo queremos generar, así que volveremos al guión del personaje del jugador Podemos exportar el proyectil como una escena repleta y poblarlo en el inspector También podemos tomar una referencia al marcador de spawn. Sería mejor que tuviera un nombre único. Y tendremos que especificar un costo mágico para disparar este proyectil Pondré el mío en 16 puntos mágicos. Antes de permitir que el jugador comience a lanzar el hechizo, también debemos verificar si tiene suficientes puntos mágicos comprobando si su magia actual es mayor o igual al costo mágico. Entonces, cuando la animación de reparto llama a la función de proyectil disparar, ya que hay una ventana de tiempo muy breve entre cuando se llaman estas dos funciones, no es mala idea verificar también que el personaje tiene suficiente magia restante para lanzar el hechizo nuevamente aquí Por lo que comprobando si la magia actual es menor que el costo, al regresar de esta función no se disparará el proyectil Sabiendo que este no es el caso, podemos restar el costo de nuestra magia actual y emitir la señal de magia actual cambiada para actualizar el HUD Después crearemos un nuevo proyectil instanciando la No queremos que esto siga al personaje alrededor niño más bien como hermano dentro del mundo, para que pueda moverse por sí solo Así que primero conseguiremos al padre antes de agregar este proyectil cuando era niño Luego establece su posición dentro del mundo para que sea la posición global del marcador de generación de proyectiles Tenemos que usar la posición global aquí porque la posición local del marcador está en relación con la posición del personaje, pero el proyectil se está agregando al nodo mundial, no al personaje Entonces queremos la posición del marcador en relación con el mundo. Y por último, le diremos a este proyectil en qué dirección está disparando Podemos pasar un argumento como Vector dos puntos izquierda si el carácter está orientado hacia la izquierda o hacia la derecha, de lo contrario. Ahora tendremos que escribir esta función para nuestro proyectil, abrir la escena del proyectil, luego agregar un script a su nodo raíz, lo llamaremos Proyectil y lo guardaremos en la Ayudará darle a este script un nombre de clase para que podamos hacer referencia a él más adelante. Este proyectil necesitará algunas variables exportadas, como una velocidad de lo rápido que se mueve y la cantidad de daño que hace cuando golpea algo Voy a nombrar este daño por defecto para que pueda ser anulado y darle un valor de uno También necesitaremos una referencia al nodo Animated Sprite Tu Di para decirle qué animación reproducir Necesita saber en qué dirección se está disparando y cuánto daño infligirá realmente, si no el predeterminado, y si se está moviendo o no actualmente. Cuando se nos dice que disparemos, podemos aceptar la dirección como un vector dos y la cantidad de daño como un entero con un valor predeterminado de cero, convirtiéndolo en un parámetro opcional. Estableceremos la dirección al parámetro direction y voltearemos el sprite si el punto de dirección X es algo menor que cero, es decir, left Luego establece daño en daño si se proporcionó algún valor de daño, lo contrario, use el daño predeterminado para el daño, y finalmente set se está moviendo a true. Anular la función de proceso. Si este proyectil se está moviendo, entonces podemos establecer su posición para que sea más igual dirección multiplicado por velocidad por Delta Este proyectil necesitará chocar tanto con cuerpos como con Entonces tendremos que conectar tanto en el área ingresada como en las señales ingresadas en el cuerpo al guión. Los cuerpos con los que colisionará este proyectil serán el terreno, mientras que las áreas serán cajas de Hurt Ambos harán mucho de las mismas cosas. Entonces llamaremos a una función privada separada de ambas y la nombraremos en cuanto al impacto. Cuando el proyectil impacte en algo, haremos que deje de moverse luego desactive más colisiones poniendo su máscara de colisión a cero Esto apaga todas las capas de la máscara de colisión. Luego reproduce la animación de impacto y conecta la señal de animación terminada a la función de cuarto para eliminar automáticamente el nodo de la escena. Si el proyectil choca contra una caja Hurtada, podemos decirle a esa Caja de Daño que tome la cantidad de daño antes de llamar al impacto No estamos usando el parámetro body, así que podemos marcarlo como no utilizado con un guión bajo Si el proyectil no golpea nada, aún necesitamos limpiarlo. Una forma sencilla es hacer que la habitación la destruya automáticamente cuando sale de la habitación en la que se generó Desde el guión de la sala, en lugar de conectar esta señal a través del inspector cada vez por cada habitación, sería más fácil hacerlo a través del scripting. Entonces escribiremos una función on area salida, aceptando un área como un no dos D y devolviendo ningún valor Si el área que salió de esta habitación era un proyectil, haremos cola para que se libere del árbol de escena Luego conecte la señal de área de salida en la función ready También podemos hacer esto para conectar automáticamente las señales ingresadas al cuerpo, también. Solo recuerda que si alguna de las escenas de tu habitación ya tiene estas señales conectadas, debes desconectarlas para evitar errores. Pero a medida que creamos cientos de habitaciones, hacer que estas conexiones de señal se registren automáticamente nos ahorrará mucho más tiempo y esfuerzo Para que el colisionador de la habitación detecte un proyectil que sale de ella, necesitará enmascarar la capa de colisión en la que se encuentra el proyectil Ejecutando el juego, ya empiezo con cada habilidad desbloqueada del video anterior y mi medidor mágico está lleno. Abriré el árbol de escenas remotas para que pueda ver mi proyectil engendrar y limpiarme Al regresar al juego, al presionar el botón disparar se lanzó un hechizo, que dispara el proyectil El proyectil choca con la pared y explota Mi medidor mágico se reduce por el costo del hechizo. Apuntando en la otra dirección, el proyectil no tiene nada que golpear, por lo que saldrá de la habitación actual Pero en lugar de seguir moviéndose hacia el infinito, se destruirá una vez que abandone los límites de esta sala. Ahora tenemos todas nuestras habilidades desbloqueables en el juego, y estamos listos para comenzar a agregar enemigos Te veré en la siguiente sección. 50. Ritmo 7-1: Hola, amigos. En esta sección, agregaremos algunos enemigos a nuestro juego. Empezaré haciendo una nueva carpeta para contener a mis sprites enemigos e importar una hoja de sprites de mi primer enemigo, el ratón ciego También necesitaremos una nueva carpeta de escenas para los enemigos. Podemos hacer las cosas más fáciles si duplicamos nuestro personaje de jugador existente para usarlo como plantilla para hacer nuestro enemigo. Después muévalo a la carpeta del enemigo. Al abrir la nueva escena, renombraré el nodo raíz para que coincida con el nombre de la escena. Después pasa por la jerarquía de escenas y decide qué nodos son necesarios para el enemigo y cuáles no. Todavía necesitaremos una forma de colisión para chocar con el terreno, una caja de daño para recibir daño y un sprite para dibujar al personaje Pero los hijos del Sprite no son necesarios, ya que este enemigo no tiene ningún otro sprites ni la capacidad de disparar proyectiles Conservaremos el Reproductor de Animación, el árbol y los nodos de efectos de sonido, aunque es posible que desee cambiar los sonidos. El temporizador Coyote no será necesario. Si quieres o no que tus enemigos sean dibujados en el mapa depende de tu preferencia, pero obviamente necesitarás cambiar la textura si decides mantener el ícono del mapa. Y también podemos eliminar todos los nodos de habilidad. El nodo raíz tiene el script del personaje del jugador adjunto. Tendremos que reemplazarlo con el guión de personaje normal, ya que este no es el personaje del jugador y no tienen ninguna de las habilidades del personaje del jugador. Seleccionando el nodo Sprite Toti, podemos reemplazar la propiedad atlas texturas atlas con una hoja Sprite para Dado que la hoja de sprites es diferente a la de mi personaje jugador, tendré que pasar por cada una de mis animaciones en mi nodo Animation Player y verificar que tengan el número correcto de fotogramas y los valores de región correctos Este enemigo tiene menos animaciones que el personaje del jugador, así que puedo borrar todo lo que no sea ocioso y caminar. La animación inactiva funciona bien, ya que los valores de región con clave coinciden exactamente, pero la animación de caminata no coincide, así que tendré que arreglarla para que coincida con los valores de región para la hoja de sprite Actualizaré rápidamente a los valores de la región Y con clave para que esta animación funcione Ignoraremos las animaciones de hit y dead por ahora ya que aún no podemos probarlas. El Árbol de Animación necesitará una máquina de estado mucho más simple para este enemigo, no la misma que está usando el personaje jugador. Entonces haremos un nuevo recurso de máquina estatal. Luego agregue las animaciones de ralentí y caminata transición de inicio a ralentí por defecto para caminar si la velocidad X no es cero, luego vuelva a ralentí si la velocidad X es cero Eso es todo lo que este enemigo tiene que hacer por ahora. Echando un vistazo al guión del personaje por un momento, el guión ya tiene todo lo que necesitamos para hacer un ritmo de carácter de ida y vuelta. Aunque como no quiero que mis enemigos tengan tiempo de coyote, tendré que mover cualquier código relacionado con él para que solo esté en el guión del personaje del jugador, o simplemente puedo asegurarme de que ninguno de códigos relacionados con el tiempo Coyote se ejecute si no hay tiempo o nodo Coyote Como ya he usado el nodo get o la función null para verificar el nodo temporizador Coyote, esta variable será nula si no existe tal nodo La única vez que estamos usando el nodo temporizador Coyote es en el proceso de física, y solo podemos verificar si hay un nodo temporizador Coyote antes de intentar llamarlo función start para evitar errores Este mismo proceso también podría usarse si no quieres incluir todos los mismos nodos exactos en tus diversas escenas de personajes y enemigos para cosas como sonidos o efectos de partículas. Cambiemos a cualquiera de nuestras escenas de contenido de sala existentes y agreguemos a este nuevo enemigo a la habitación. Mi plan para este enemigo es que tengan un ritmo de ida y vuelta. Cuando chocan contra una pared, quiero que se den la vuelta, esperen un segundo y luego caminen en sentido contrario. Entonces editaré mi terreno para crear una plataforma sencilla con paredes a cada lado. Entonces este enemigo va a caminar de un lado a otro aquí. También agregaré otra plataforma sin muros, y el enemigo debería salir de la repisa en este caso Es posible que desee escribir otro guión como el guión del personaje del jugador que hereda del personaje, que también incluye este comportamiento Pero es mejor pensar en este comportamiento como una alternativa al nodo jugador en la escena del juego, a través del cual el jugador puede controlar al personaje del jugador. En cambio, escribimos un guión que controla el comportamiento de este enemigo. Entonces crearemos un nuevo nodo como hijo del enemigo. Voy a nombrar a este nodo pace. De esta manera, se puede usar el mismo script de comportamiento para múltiples enemigos diferentes, y también el mismo tipo de enemigo podría tener múltiples scripts de comportamiento diferentes. Incluir este nodo en la escena propia del enemigo haría que se aplicara automáticamente a todos los enemigos del mismo tipo. Si bien ponerlo en la escena del contenido de la sala permitirá que los mismos enemigos tengan potencialmente comportamientos diferentes. Adjuntaremos un script a este nodo y lo pondremos en una nueva carpeta de scripts para enemigos. Para decirle a un enemigo qué hacer, necesitaremos una referencia al propio enemigo almacenada en una variable. Podemos llamar a la función G parent para obtener el padre directo de este nodo y asignarlo a la variable usando la etiqueta ready. Tenga en cuenta que esto solo funcionará si el nodo de comportamiento es un hijo directo del enemigo. También deberíamos exportar una variable para decir en qué dirección irá primero este enemigo. Entonces le nombraré dirección y le daré un valor por defecto de uno, es decir, a la derecha. Anulando la función de proceso, todo lo que tenemos que hacer es establecer la dirección de movimiento del enemigo en esta dirección para que comiencen a caminar Cuando el enemigo está en una pared, podemos decirle al personaje que mire hacia la izquierda y ponga su dirección de movimiento a cero, para que se detenga. Para esperar poco tiempo, necesitamos un temporizador. Dado que este nodo no tiene un tipo, podemos usar este nodo como el propio temporizador cambiando su tipo. El tipo que este script extiende también necesitará cambiar a temporizador para acceder a cualquiera de los nodos, propiedades o funciones del temporizador. No necesitamos conectar la señal de tiempo de espera, ya que todo lo que realmente necesitamos saber es si el temporizador está parado o no Si se detiene el temporizador, estableceremos la dirección de movimiento del enemigo en dirección. De lo contrario, podemos ponerla a cero porque este enemigo está esperando actualmente. Cuando el personaje choca contra una pared, estableceremos el valor de dirección para que sea el seno de las paredes X normal y arrancaremos el temporizador. Para hacer que el personaje derecha cuando choca contra una pared a su izquierda, también tendremos que hacer que esto dependa del seno de los muros X normal. También solo queremos detener al personaje y darle la vuelta si su dirección de ritmo actual no es la misma que la normal de las paredes Estamos llamando a esta función normal get Wall varias veces, por lo que sería más eficiente almacenarla en una variable local. Hagamos un poco de refactorización de la luz aquí. En la escena del contenido de la habitación, podemos ajustar la cantidad de tiempo de espera y establecer la propiedad one shot en true. Duplicaré el nodo de ritmo y lo adjuntaré al otro enemigo. Entonces dale a mis dos enemigos valores diferentes para su dirección inicial de ritmo. Ahora cuando ejecutamos el juego, con la ayuda de nuestro guión de comportamiento, los enemigos caminan, uno a la izquierda y otro a la derecha. El segundo enemigo se baja de la repisa, pero el primero choca contra la pared, se da la vuelta y espera un segundo antes de darse la vuelta y caminar en la otra dirección Y ambos repiten este comportamiento. Pero es posible que hayas notado que sus animaciones no siempre coinciden con su velocidad. Ambos personajes en realidad se están animando en sincronización Esto se debe a que al igual que los íconos de la salud, están compartiendo un recurso. En la escena de los enemigos, tendremos que seleccionar el nodo Sprite two D y hacer que el recurso de textura del atlas sea local para esta escena Ahora cada instancia de este enemigo tendrá su propia textura atlas y podremos animarnos independientemente unos de otros Sin embargo, si alguna de tus animaciones está cambiando la propiedad de textura del nodo Sprite two D, esto puede romper las animaciones que están haciendo referencia Eliminaré esta pista de mi animación de reinicio. Tampoco necesitamos la conexión de señal, que se copió de la escena del personaje del jugador, que se utiliza para jugar Jump efforts. Ejecutando de nuevo el juego, ahora podemos ver que son capaces de reproducir correctamente sus animaciones inactivas y caminando. Ahora tenemos un enemigo que puede caminar de un lado a otro, dando la vuelta en las paredes, pero también tenemos que asegurarnos de que no puedan salir de la habitación. Te veré en el siguiente video. 51. 7-2 paredes invisibles: Hola, amigos. En este video, impediremos que nuestros enemigos salgan de la habitación en la que fueron engendrados Para ello, necesitaremos que nuestros enemigos tengan colisiones con paredes invisibles que no afecten al personaje del jugador Tenemos el cuerpo del personaje del jugador en la capa nueve de colisión, enmascarando el terreno en la capa uno. En la escena de nuestros enemigos, estableceremos la capa de colisión corporal algo diferente, como la capa 17. Todavía necesitan enmascarar la capa del terreno, pero también vamos a hacer que enmascaren una segunda capa que usaremos para muros invisibles. Voy a usar la capa cinco. Abriendo los ajustes del proyecto, nombres de capa Física dos D. Nombraré a la capa 17 como enemiga y a la capa cinco como muros invisibles. En la escena de mi habitación, voy a copiar el nodo de capa Tile Map, que está dibujando el mapa, ya que este ya tiene los límites de la habitación. Después pégalo en la escena del contenido y cámbiele el nombre a Muros invisibles. Con la nota de capa Mapa de teselas seleccionada, haciendo clic en el recurso Conjunto de teselas, necesitaremos agregar una capa de física a este conjunto de teselas, existente en la capa cinco para muros invisibles. Desde el panel Conjunto de azulejos, podemos pintar esta capa de física sobre la baldosa. cambiar al panel Mapa de azulejos con la herramienta de pintura y el mosaico seleccionado, podemos cerrar las puertas de esta habitación, sellando completamente la habitación por todos lados con una capa de física que solo está enmascarada por los enemigos y no por el personaje del jugador No queremos que estos muros invisibles se dibujen en el mapa, así que no deberían estar en la capa de visibilidad dos, y queremos poder verlos mientras estamos probando. Pongámoslos en la capa de visibilidad uno. Editaré el terreno y moveré a mis enemigos para que puedan caminar libremente por toda la habitación. Ahora, cuando corremos el juego, los enemigos caminan hacia el borde de la habitación pero son volteados por las paredes. Mientras que nuestro personaje jugador puede caminar a través de ellos. Yo preferiría que estas paredes estuvieran fuera del área visible de la habitación, así que las moveré cada una de ellas una baldosa más. Todo lo que tenemos que hacer para que las paredes sean completamente invisibles para el jugador es desactivar su propiedad visible, ya sea en el árbol de escenas o en el inspector. Ahora tenemos que hacer que este enemigo realmente amenace al jugador, cosa que ya hemos hecho antes. Todo lo que tenemos que hacer es agregar un área al nodo D, nombra golpear Box. Dale una forma de colisión al nodo D como hijo y dale al nodo Tut de forma un recurso de forma a la forma de colisión Establece la caja de golpe para enmascarar la Caja de Daño del jugador. Y debe ser monitoreo. A continuación, adjunte el script de Hit box y conecte la señal ingresada en el área de encendido. A ahora cuando ejecutamos el juego, hacer contacto físico con un enemigo hace que el personaje del jugador sufra daño. Nos ocuparemos de hacer que el combate más atractivo en la siguiente sección. Por ahora, tratemos con estos mensajes de error. Estos mensajes de error ocurren cuando cargamos el contenido de una habitación. Esto se debe a que estamos cargando el contenido de la sala en respuesta a un evento de colisión cuando el cuerpo del personaje del jugador entra en una habitación. Y a Godot no le gusta que agreguemos más áreas de colisión u objetos mientras ya está ocupado resolviendo colisiones para este fotograma actual Entonces, si seguimos los consejos que nos dan los mensajes de error y usamos llamados diferidos, esto le dirá al motor del juego que cargue el contenido de la sala después de que se complete la resolución de colisión para el fotograma actual El ciclo de Godot comienza con manejo de entrada, seguido de la física, que incluye colisiones, luego procesa y termina con llamadas diferidas Entonces podemos usar esto para realizar cualquier acción que queramos como lo último antes del final de cualquier frame. Ejecutando el juego de nuevo, ya no hay más mensajes de error. Nuestro enemigo ahora se quedará en esta sala y puede herir al personaje del jugador. Pero necesitamos agregar más variedad enemiga a nuestro juego. Te veré en el siguiente video. 52. 7-3 Detección de bordes: Hola, amigos. En este video, agregaremos otro enemigo que puede detectar cuñas y darse la vuelta en lugar de alejarse de ellas. Empezaremos duplicando a nuestro enemigo existente. Al abrir la escena del enemigo, cambiaremos el nombre del nodo raíz para que coincida con el enemigo. Importe su hoja de sprites y configúrela como atlas en el inspector Todos los sprites para la hoja de Sprite son los mismos que el primer enemigo, así que no hay nada que arreglar en términos de animaciones En mi escena de contenido de habitación, eliminaré a los dos enemigos y agregaré este nuevo enemigo luego editaré el terreno para que estén en una terraza elevada con una repisa a cada lado de diferentes alturas Quiero que este enemigo se detenga en la repisa más alta, espere un momento, luego se dé la vuelta y camine en la otra dirección Pero entonces deberían caminar fuera de la repisa más corta. En lo que respecta a los muros, deben actuar de la misma manera que el enemigo anterior. Dado que este comportamiento es tan similar, sería bueno usar el mismo script. Entonces agregaré una nota de temporizador como hijo del enemigo. Renombrarlo, adjuntarle el guión de ritmo y establecer su propiedad one shot en true. Entonces este enemigo debería comportarse exactamente como el ratón ciego. Ahora solo tenemos que averiguar cuándo el enemigo está caminando hacia una repisa, lo cual podemos hacer usando un nuevo tipo de nodo, un nodo D de lanzamiento dos Nombraremos este detector de borde de nodo. Después muévalo una corta distancia hacia la derecha del personaje y hacia arriba. El rayo tiene una máscara de colisión que ya está establecida en la capa uno para el terreno. Ampliando el colisionar con sección, nuestro terreno es un cuerpo físico, por lo que el rayo chocará con él Si usa un nodo de transmisión de rayos para detectar áreas, deberá verificar las áreas aquí antes de que funcione. El reparto de rayos se representa en el editor como una flecha, pero será invisible mientras el juego se esté ejecutando, al igual que nuestros nodos de área de colisión. Dispara un rayo partiendo de su posición en dirección a la flecha e informa si golpea o no algo. En este caso, tanto si golpea terreno como si no. Entonces, si golpea terreno, el enemigo seguirá caminando hacia adelante, y si no lo hace el personaje necesita detenerse. La distancia a la derecha del personaje determinará qué tan adelante buscarán la repisa La distancia hacia arriba desde el suelo no tendrá mucho efecto siempre y cuando esté por encima del suelo y por debajo de la altura del personaje. La posición objetivo debe apuntar hacia abajo para detectar el suelo, pero hasta qué punto dispara el rayo afectará lo que considera que es una repisa y lo que no Voy a poner el mío para que sea 64 píxeles abajo o dos mosaicos. Esto quiere decir que si el enemigo se encuentra con una repisa que solo tiene una baldosa de altura, seguirá caminando. Pero si son dos o más tejas de altura, el rayo no golpeará el terreno, y por lo tanto, el enemigo se detendrá. Sin embargo, a diferencia de las áreas de colisión, el nodo de lanzamiento de rayos no emite ninguna señal a la que podamos reaccionar. Así que tendremos que adjuntar nuestro propio script a este nodo. Lo pondré en la carpeta de guiones enemigos. Podemos comenzar declarando nuestra propia señal, que vamos a querer admitir cuando se detecte una repisa y pasar por la dirección de la repisa en relación con el enemigo como No es tan sencillo como si el rayo está pegando o no a algo, aunque. Similar a como hicimos que el temporizador Coyote solo arrancara en el marco exacto cuando el personaje se baja de una repisa, solo queremos detectar una repisa una vez durante el fotograma exacto cuando el rayo deja de chocar con el Entonces necesitaremos una variable booleana para saber si el rayo golpeó o no el último fotograma del terreno y otros cuatro si golpeó terreno este Durante el proceso de física, vamos a establecer estaba colisionando con el valor anterior de está colisionando, luego colisionando al valor actual devuelto por el Si el rayo estaba colisionando último fotograma pero no está colisionando este fotograma, este es el momento exacto en el que hemos detectado una repisa y emitiremos nuestra señal La dirección de la repisa puede ser solo el signo de la posición del nodo Conectemos nuestra señal detectada de repisa al script de ritmo y llamemos a una función llamada wait and turnaround Podemos copiar estas tres líneas desde arriba, que le dicen al enemigo que se detenga, cambia la dirección del ritmo y arranca el temporizador Después reemplazarlos por una llamada a nuestra función. Pero tendremos que pasar lo contrario de las paredes normales X como argumento de dirección para que coincida con lo que está pasando por el detector de bordes. El detector de repisa envía la dirección hacia la repisa. Entonces aquí tenemos que dar la dirección hacia la pared. La nueva dirección de estimulación es, por lo tanto la opuesta al parámetro de dirección Esto funcionará siempre y cuando el enemigo se mueva hacia la derecha, pero tendremos que reposicionar el nodo de lanzamiento a la izquierda del enemigo cuando se dé la vuelta Afortunadamente, ya hemos emitido una señal cada vez que un personaje cambia de dirección. Entonces todo lo que tenemos que hacer es conectar esta señal al detector de borde para reaccionar ante él. Vamos a renombrarlo en enemigo cambió de dirección. Dado que esto nos da su nueva dirección, simplemente estableceremos la posición de los nodos para que sea el valor absoluto de su posición multiplicado por uno negativo si la dirección es menor que cero o positiva en caso contrario. Rastreando esta omisión de señal de dirección cambiada nuevo al guión del personaje Originalmente escribí esto pasando la variable de dirección de movimiento como parámetro de señal. Sin embargo, esto no funciona en el contexto en el que estamos usando este personaje enemigo, ya que el valor de la dirección de movimiento no necesariamente coincidirá con la dirección que les estamos diciendo que enfrenten. Entonces, en lugar de pasar la dirección del movimiento, es más preciso pasar uno negativo si le dice al personaje que mire hacia izquierda o uno positivo para la derecha. Ahora, el ray cast dende siempre estará frente al personaje, ya sea que estén mirando a la izquierda o a la derecha Vamos a activar las formas de colisión visibles para que podamos ver el lanzamiento del rayo mientras el juego se está ejecutando y golpear play. El rayo fundido se dibuja en rojo cuando está colisionando con algo Nuestro enemigo se acerca a la primera cornisa. El lanzamiento del rayo se vuelve azul para indicar que no está golpeando nada, y el enemigo se detiene por un corto tiempo, luego se da la vuelta y va por el otro lado. Al acercarse a la repisa más corta, el rayo lanzado es lo suficientemente largo como para que aún golpee el terreno, por lo que el enemigo se aleja y continúa en la misma dirección Eventualmente chocan contra la pared invisible en los bordes más alejados de la habitación y se dan la vuelta como lo hace el enemigo anterior. Ahora tenemos un segundo tipo de enemigo que se comporta de manera diferente al primero, pero necesitamos mucha más variedad para que nuestro juego sea divertido Te veré en el siguiente video. 53. 7-4 Vuelo: Hola, amigos. En este video, agregaremos un enemigo volador que rebota alrededor de una habitación Empecemos importando una nueva hoja de sprites para el enemigo volador Después duplicando una de las escenas enemigas existentes. Después de abrir la nueva escena enemiga, cambiaremos el nombre del nodo raíz para que coincida e intercambiaremos el atlas con la hoja de sprites adecuada Estos sprites son de 32 píxeles cuadrados, a diferencia de los otros enemigos hasta ahora Entonces voy a ajustar la posición Y del Sprite ahora para bajarlo ligeramente Este enemigo no tiene animaciones separadas de ralentí y caminando, así que eliminaré la animación de caminata y editaré la animación inactiva para tener el número correcto de fotogramas. Luego edite los valores con clave para que la animación inactiva tenga la altura de píxel correcta Ahora la animación inactiva se ve correcta. Al activar la visibilidad de la forma de colisión del cuerpo del personaje, giraré 90 grados para que la cápsula quede horizontal, lo que coincide más cerca de la forma de este enemigo y ajustaré su radio y altura según sea necesario. Entonces haz lo mismo con la Caja Hurtada. Y el daño de contacto golpeó la caja, asegurándose de que se ajusta al tamaño y forma del enemigo, por lo que cualquier daño infligido al jugador se sentirá justo En cuanto a la máquina de estado del árbol de animación, ya que en este momento solo hay una animación, solo necesita tener un estado inactivo que haga la transición de inicio a inactivo En cuanto al guión adjunto al nodo raíz de este enemigo, no necesitamos que este enemigo camine o salte, pero aún necesitamos que este enemigo pueda enfrentar a izquierda o derecha, tener aceleración y desaceleración, verse afectado por la gravedad y la velocidad terminal, etcétera Así que hay suficiente beneficio para seguir usando el mismo guión de caracteres aquí en lugar de comenzar desde cero. Pero hay suficiente diferencia en el comportamiento de un enemigo que puede volar como para que escribamos una nueva subclase que herede del carácter Así que vamos a crear un nuevo script llamado Flying Enemy, heredando del personaje, y guardarlo en la carpeta de scripts enemigos Nuestro enemigo volador necesitará una dirección para volar. A diferencia de caminar o correr, que se representa como un flotador, ya que solo necesita preocuparse por el eje X, una dirección de vuelo puede ser cualquier dirección en el espacio D, por lo que la almacenaremos en un vector dos. También necesitaremos una variable booleana para saber si este enemigo está volando o no actualmente Luego podemos anular el proceso de física para incluir una nueva verificación para ver si el enemigo está volando, y si es así, llamar a una función de física voladora. Si el enemigo no está volando, entonces podemos llamar como normal a la definición de súper clase del proceso de física. También es posible que desee exportar una velocidad de vuelo como flotador si desea tener un enemigo que tenga diferentes velocidades de caminata y vuelo. Le voy a dar un valor predeterminado de 100 píxeles por segundo. Sostendré Control o comando y pulsaré sobre esta función llamada al proceso de física de la superclase para ir directamente a su declaración para que podamos echar un vistazo a lo que contiene Tenga en cuenta que la llamada a la función move and slide está dentro de la definición de superclase de nuestro proceso de física debe llamar a esta función para aplicar el cuerpo del personaje a la velocidad de los Dnodes y verificar si hay colisiones También queremos que nuestro enemigo volador enfrente a la dirección en la que están volando. Entonces tendremos que hacer eso en la función de física voladora. Copiaré este bloque de código y volveré al guión del enemigo volador y lo pegaré en mi física voladora. En lugar de verificar el valor de la dirección de movimiento, tendremos que verificar el valor de la dirección de vuelo punto X. También tendremos que llamar a la función de movimiento y deslizamiento si el enemigo está volando. Entonces podemos aplicar una lógica similar que usamos para el control aéreo en nuestros personajes no voladores para hacer volar a nuestro enemigo volador. Si la dirección de vuelo tiene un valor, moveremos la velocidad del enemigo hacia la dirección de vuelo multiplicada por velocidad de vuelo a una velocidad de aceleración multiplicada por el control aéreo multiplicado por Delta. O si no se da ninguna dirección de vuelo, podemos mover su velocidad hacia el vector dos punto cero a una tasa de desaceleración multiplicada por los frenos aéreos multiplicados por Delta O. Cuando estábamos editando solo Velocity dot X, que es un float, un tipo de datos primitivo, tuvimos que llamar a Godot move direction function para poder editarlo Pero como un vector dos es una clase, puede tener sus propias funciones. Sostener control o comando y hacer clic en el nombre de la clase nos lleva a la documentación de esa clase donde podemos ver todas sus propiedades y funciones si es necesario. Así que aquí tenemos la opción de llamar a velocity dot move into, que difiere de Godot función move into en que el primer parámetro ya se conoce como el vector mismo También es posible que desee exportar diferentes valores para aceleración de vuelo, desaceleración, control de aire y frenos de aire para sus enemigos voladores si desea que usen valores diferentes mientras no están volando También necesitaremos una función pública que le diga a este enemigo que vuele, aceptando un parámetro vector dos para la dirección a volar. Y otro para cuando dejar de volar. Esto controlará la variable está volando y establecerá la dirección de vuelo al mismo tiempo. Recuerda adjuntar este guión enemigo volador al nodo raíz del enemigo en su propia escena. En la escena del contenido de la sala, igual que nuestros enemigos existentes tienen un nodo separado que les dice cómo comportarse, haremos lo mismo con nuestro nuevo enemigo volador. Eliminaré a este enemigo de la escena y agregaré dos de estos nuevos enemigos voladores. Después editaré el terreno para encerrar a uno de ellos dentro de una caja de terreno para que podamos ver cómo se comporta un Quiero que estos murciélagos vuelen en dirección diagonal y reboten en cualquier pared, techo o piso con el que entren en contacto. Entonces adjuntando un nodo básico a ambos, lo llamaré rebote Después, adjunte un script a este nodo y guárdalo en la carpeta de scripts enemigos. Este script necesitará una variable exportada para la dirección de vuelo inicial. Voy a usar el vector 21, que está abajo a la derecha. También necesitaremos una referencia al enemigo cuyo comportamiento estamos controlando establecido a estos nodos, padre usando la etiqueta on ready. Anulando la función ready, sería una buena idea normalizar la dirección de la mosca La normalización de un vector asegurará que tenga una longitud de exactamente uno Dado que un vector con un valor de 11 es más largo que uno, esto daría como resultado que el murciélago volara más rápido que su velocidad de vuelo. Pero si normalizamos el vector, solo estamos usando la dirección del vector, no su longitud. Al anular la función de proceso, podemos decirle al enemigo que vuele en la dirección de vuelo deseada Pero antes de hacer eso, tendremos que verificar si este enemigo está actualmente en contacto con alguna pared, techo o piso. Entonces podemos establecer el punto de dirección de vuelo X o punto e Y al valor apropiado en cualquiera de estos casos. Para el techo, el valor será el valor absoluto del punto Y de dirección de vuelo, haciéndolo siempre positivo, que es abajo. Y el piso es lo contrario, multiplicando el valor absoluto por uno negativo, que está arriba Para las paredes, podemos simplemente multiplicar el valor absoluto del punto X en dirección de vuelo por el signo del punto X normal de pared, que apunta lejos de la pared. le adjuntaré el guión de rebote al otro enemigo, También le adjuntaré el guión de rebote al otro enemigo, luego le pegaré a play Cuando ejecutamos el juego, podemos ver que el bate rebota alrededor, rebotando en cada pared, techo y piso que toca, creando un obstáculo interesante para que el jugador evite Ahora tenemos un enemigo volador para luchar, pero al menos deberíamos tener un tipo de enemigo más para que nuestros jugadores se enfrenten. Te veré en el siguiente video. 54. Arrastrar de 7 a 5: Hola, amigos. En este video, haremos un enemigo que pueda arrastrarse a lo largo de cualquier superficie, incluyendo paredes y techos Empecemos importando una hoja de sprites para este enemigo. Después duplique al enemigo volador. Después de abrir la nueva escena enemiga, voy a renombrar el nodo raíz. Luego intercambia el atlas de la textura del atlas de dos nodos D de Sprite por la hoja de Sprite apropiada En el Jugador de Animación del enemigo, actualizaré la animación ociosa para que tenga el número correcto de fotogramas que proporciona la hoja de Sprite Actualización de los valores de región con clave según sea necesario. Como queremos que este enemigo se arrastre no solo por el suelo sino también por las paredes y el techo, sería útil que podamos rotar al enemigo Con el origen del enemigo a sus pies, la forma en que hemos hecho a todos los demás enemigos, girándolos girará todo sobre este punto. Para facilitar un poco las cosas, sería mejor hacer que el punto de origen de los enemigos que se arrastran esté en su centro para que estas rotaciones se vean Entonces centraré el sprite y todas las formas de colisión para que se centren en el punto de origen Ahora cuando rotemos a este enemigo, éste permanecerá en la misma posición relativa. Ajustaré rápidamente la caja de daño y la caja golpes para que se ajuste mejor a la forma de este enemigo. Para la forma de colisión del cuerpo del personaje, sin embargo, usaré un círculo en lugar de una cápsula. Dado que este enemigo puede rotar, la forma de colisión al ser un círculo significa que las rotaciones no darán lugar a ningún cambio en lo que este enemigo está colisionando con Si estás usando rotaciones estrictas de 90 grados, una forma de colisión cuadrada también funcionaría, pero requeriría algunos pasos adicionales cuando se trata de esquinas convexas Entonces me apegaré a usar un círculo. En la escena del contenido de la habitación, retiraré los murciélagos y los reemplazaré por dos caracoles El objetivo es que estos caracoles se arrastren por la superficie interior y exterior de esta Al igual que creamos un nuevo guión heredado del personaje para enemigos voladores, escribiremos otro para rastrear enemigos y lo guardaremos en la carpeta de scripts enemigos Después reemplace el guión adjunto al enemigo por este nuevo guión. Voy a reducir la velocidad de mi caracol ajustando su velocidad de caminata a solo 32 píxeles por segundo Primero, necesitamos saber la dirección hacia la superficie en la que este enemigo se arrastra actualmente como vector dos Entonces también la dirección de rastreo hacia adelante como otro vector dos También tendremos que manejar nuestras propias colisiones aquí en lugar de confiar en la función de movimiento y deslizamiento del cuerpo del personaje para hacer toda la física por nosotros. Entonces podemos almacenar datos de colisión en otra variable de tipo colisión cinemática dos D. Anulando el proceso de física, verificaremos si este enemigo está actualmente pegado a una superficie, y si es así, llamaremos al proceso de física para gatear Si no están pegados a una superficie, podemos llamar al proceso de física de superclase Esto funciona porque un vector dos con sus valores predeterminados de cero, cero será tratado por la sentencia if como falso y cualquier otro valor como verdadero. Si no están pegados a una superficie, también vamos a querer comprobar si este enemigo puede pegarse a una superficie. Llamando a una función ligeramente diferente a move y slide, llamaremos move y colisionaremos Esta función acepta el movimiento del personaje como primer parámetro, que es su velocidad multiplicada por Delta. La función devuelve una colisión cinemática dos D, que podemos asignar a nuestra variable la misma manera que nuestro vector dos se puede usar en una declaración if, también lo pueden hacer estos datos de colisión. Si no se produjo ninguna colisión, se considerará como falsa. Y si se produjo una colisión, se considerará verdadera. Si este enemigo chocó con algo, entonces asumiremos que quieren atenerse a él y establecer el valor de pegado a la superficie Podemos acceder a las colisiones normales llamando a la función get normal Este es un vector que apunta lejos de la superficie con la que el personaje colisionó en el punto de colisión Como queremos que el valor de esta variable esté hacia la superficie, no lejos de ella, simplemente podemos girarla 180 grados llamando a la función girada. Pero las rotaciones en Godot no usan grados. Utilizan radianes, y 180 grados es lo mismo que los radianes Pi Oh, si el enemigo no colisionó con ninguna superficie, entonces llamaremos al proceso de física de superclase Pero el proceso de física de la superclase también está aplicando la velocidad del personaje cuando llama mover y deslizar Siguiendo este código, la velocidad del personaje se está aplicando dos veces cada fotograma siempre y cuando no toquen ninguna superficie. Podemos arreglar esto pasando un segundo parámetro opcional a la función move and collide, que es una prueba con nombre booleano Si es true, esta función solo verificará colisiones pero en realidad no moverá al personaje Ahora que nuestro enemigo se adherirá automáticamente a cualquier superficie, podemos adentrarnos en la física de arrastrarnos por esa superficie Primero, aplicaremos gravedad hacia la superficie a la que está pegado el enemigo, ya que no lo hicimos antes para la prueba de colisiones, y esto también ayudará a mantener al enemigo en la superficie por la que se arrastran Llamando a mover y colisionar, pasando la dirección hacia la superficie, multiplicado por gravedad, multiplicado por Delta, nuestros datos de colisión ahora mantendrán la colisión con la superficie Entonces podemos ramificarnos en base si ocurrió o no una colisión. En caso de que el ángulo de la superficie cambie, podemos actualizar la dirección hacia la superficie de rastreo, luego calcular la dirección hacia adelante, que es solo la dirección hacia la superficie girada 90 grados Si Pi es 180 grados, entonces Pi dividido por dos es 90 grados. No obstante, el sentido de rotación dependerá de si el enemigo está mirando hacia la izquierda o hacia la derecha. Si están orientados hacia la izquierda, entonces tenemos que rotar en el sentido de las agujas del reloj. Si están orientados hacia la derecha, giramos sentido antihorario para obtener su dirección orientada hacia adelante como un vector dos Y si estos valores han cambiado desde el fotograma anterior, también necesitaremos actualizar la rotación del enemigo para dibujarlos de la manera correcta. Dado que el enemigo está mirando hacia la derecha en su escena con una rotación de cero, todo lo que tenemos que hacer es usar la dirección hacia adelante y luego llamar a la función de ángulo. La función ángulo devuelve el ángulo entre cualquier vector dos y el eje X positivo. Pero como estamos usando una escala X negativa para voltear al personaje cuando mira hacia la izquierda, también tendremos que corregir esto en la rotación, girando otros 180 grados o radianes Pi si el enemigo está mirando hacia la izquierda Ahora que tenemos al enemigo pegado a la superficie, y sabemos en qué dirección quieren gatear, entonces si se le dice al enemigo que se mueva, finalmente podremos usar la función mover y colisionar nuevamente para moverlos en su dirección hacia adelante, multiplicada por la velocidad de movimiento, multiplicada por Delta Si hay alguna colisión como resultado de este movimiento, eso significa que han chocado con una esquina cóncava Todo lo que tenemos que hacer aquí es recalcular la dirección hacia la nueva superficie El siguiente marco de física se encargará del resto. Si no hubo colisión, entonces el enemigo se arrastra suavemente a lo largo de una superficie plana o convexa Si no se dio dirección de movimiento, se quedarán quietos. Volviendo todo el camino de regreso a la primera declaración if, si la gravedad hacia la superficie no resultó en una colisión, eso significa que el enemigo de alguna manera ha perdido el contacto con la superficie sobre la que se arrastraban Entonces deberíamos llamar a una función que los restablecerá de nuevo a una orientación normal. Lo llamaré unstick y lo haré público para que otros guiones puedan llamarlo. Esta función restablecerá la dirección a la superficie de nuevo al vector 20 y la rotación a cero, devolviéndolos a un estado de comportamiento que es igual que cualquier otro enemigo. todavía falta una cosa Sin embargo, todavía falta una cosa en nuestra física de rastreo, que es decirle al enemigo que se enfrente a la dirección en la que se mueve, ya que eso se estaba haciendo en el proceso de física de la superclase En lugar de copiar y pegar el mismo código aquí, movamos esto a una función privada en la clase de caracteres Entonces podemos llamar a esta función tanto en este guión de personaje, también en el guión enemigo que se arrastra En lugar de crear un nodo y un script separados para decirle a este enemigo que se arrastre, exportaré una variable entera para la dirección Krall Luego anule la función de proceso y hágalo aquí. Para fines de prueba, también anularé la función de entrada para que la flecha hacia abajo los fuerce a despegarse de cualquier superficie en la que se estén arrastrando Cuando corremos el juego, el caracol se arrastra alrededor de esta caja, girando tanto en las esquinas cóncavas como convexas para trepar por las paredes y nuevamente para arrastrarse por el techo Al presionar la flecha hacia abajo, los hace desprenderse de la superficie y caer a la gravedad como lo haría cualquier otro enemigo Ahora tenemos nuestro tipo de enemigo final, uno que puede arrastrarse por paredes y techos Pero nuestros enemigos deberían ser más agresivos hacia el personaje jugador. Te veré en el siguiente video. 55. Vista de 7-6: Hola, amigos. En este video, daremos a algunos de nuestros enemigos la capacidad de percibir y reaccionar ante la presencia del personaje jugador. En la escena del contenido de la habitación, voy a quitar los caracoles y la caja de terreno Reemplácelo por un bloque en dos lados, luego ponga una nota del ratón en su interior que vaya a caminar de un lado a otro entre ellos. Añadiré el nodo temporizador, adjuntaré el script de ritmo y estableceré su propiedad one shot en true. Para que este enemigo actúe agresivamente hacia el personaje jugador, necesita una forma de detectarlo. Tendremos que usar múltiples herramientas para lograrlo. Primero, agregaremos un nodo D de área dos a nuestro enemigo. Y un nodo de forma de colisión para el área. Esta zona representará todo el alcance del campo de visión del enemigo. Es posible que desee usar un cuadrado girado 45 grados una cápsula o un círculo. Si usa un nodo D de polígono de colisión dos en lugar de un nodo D de forma de colisión dos, en realidad puede crear un polígono personalizado en lugar de usar formas preestablecidas Simplemente haga clic en el editor para dibujar cada vértice de la forma que desee Esto nos permite hacer un triángulo o un abanico, que es una mejor representación de un campo de visión. Ampliando la propiedad del polígono en el inspector, podemos ver las posiciones de cada vértice, editarlas y reorganizarlas Sea cual sea la forma que elijas usar, asegúrate de que tu forma solo tenga ángulos convexos. Si tu polígono es cóncavo, Godot lo dividirá en múltiples formas convexas más pequeñas y como resultado, duplicará el costo de los cálculos de colisión si decides usar , si decides usar una forma de colisión simétrica normal, Sin embargo, si decides usar una forma de colisión simétrica normal, voltear al enemigo izquierda y derecha es mucho más fácil, ya que solo puedes usar el mismo método que usamos con el lanzamiento del detector de bordes, estableciendo su propiedad de posición el enemigo cambie de dirección Con el polígono de colisión dos nodos D, sin embargo, el proceso es un poco más complicado No podemos simplemente mover su posición, y tampoco debemos cambiar su propiedad de escala. Si abrimos la documentación para este nodo, específicamente advierte contra esto afirmando que probablemente no se comportará como se esperaba. Si decidimos usar estos polígonos de colisión para formas no simétricas que necesitamos voltear, tendremos que editar manualmente las posiciones de cada uno de los vértices en , el campo de visión no será suficiente por sí solo Sin embargo, el campo de visión no será suficiente por sí solo, ya que no hay nada que le impida atravesar muros. Si queremos que el enemigo detecte al jugador con una línea de visión despejada, necesitaremos otro nodo para verificar que un rayo arroje dos nodos D. Querrás posicionar esto cerca de los ojos del enemigo desde donde realmente estarían observando, pero mantenlo centrado horizontalmente. Voy a cambiar el nombre de esto a la línea de visión. La línea de visión estará colisionando tanto con el terreno como con el cuerpo del personaje del jugador, siendo ambos cuerpos Esto permitirá que el terreno bloquee su línea de visión, incluso si el personaje del jugador está dentro de su campo de visión. Con el campo de visión seleccionado, solo necesitaremos esto para estar monitoreando, enmascarando el cuerpo del jugador. Eliminaré el nodo de forma y solo usaré el polígono como mi área de colisión Entonces dale tanto a él como al elenco nombres únicos. Adjuntando un script al área de campo de visión para dende, lo guardaremos en la carpeta de scripts enemigos Tomemos referencias al nodo de forma o polígono y al nodo de línea de visión usando la etiqueta ready Lo que me gustaría de esta configuración es que el enemigo reaccione ante el personaje del jugador después de que ambos hayan entrado al campo de visión y el enemigo tenga una línea de visión directa con el jugador. Si el personaje jugador sale del campo de visión y se rompe la línea de visión, entonces me gustaría que el enemigo volviera a su comportamiento normal. Consideremos cómo queremos que este nodo se comunique con otros nodos a través de señales. Vamos a necesitar este nodo para reportar dos cosas cuando el enemigo haya adquirido un objetivo y cuando haya perdido su objetivo. Estos serán los momentos exactos en los que queremos cambiar su comportamiento de su ritmo predeterminado de ida y vuelta y en su lugar decirles que comiencen a actuar de manera más agresiva o viceversa Podemos conectar las señales de cuerpo ingresado y de salida del cuerpo desde el campo de visión al guión Y esto nos dice con bastante facilidad cuando el personaje jugador entra y sale del campo de visión. Tendremos que almacenar esto en una variable llamada target. Como el parámetro es un no dos D, también estableceremos el tipo de variable como un no dos D para mantener las cosas simples. También necesitamos una variable booleana para saber si el enemigo está actualmente apuntando o no, si el objetivo se encuentra actualmente dentro del campo de visión y si el enemigo tiene actualmente línea de visión hacia el Cuando un cuerpo entra en el campo de visión, entonces set is in field of view a true y establece target to be body. Cuando el cuerpo abandona el campo de visión, podemos ponerlo de nuevo en falso. Recuerda que solo estamos enmascarando al personaje jugador, así que ya sabemos que este cuerpo es el personaje jugador. Anulando el proceso de física, si todavía no hay un objetivo, simplemente podemos regresar ya que no hay nada que hacer Ahora podemos suponer que el personaje jugador ha entrado al campo de visión al menos una vez. A continuación, apuntaremos la línea de visión al objetivo. Podemos crear un vector apuntando de A a B restando A de B. Así que la posición objetivo del raycast será la global del objetivo menos nuestra posición global Entonces el valor de está en línea de visión va a ser cierto si lo que está golpeando el colisionador es lo mismo que el objetivo Si el lanzamiento del rayo golpea el terreno o no golpea nada en absoluto, esto será falso. Tenga en cuenta que cuando ocurre el proceso de física, las colisiones ya han sido calculadas por Godot Entonces, cuando apuntemos la línea de visión al personaje del jugador en la línea de arriba, los datos de colisión que resulten no estarán disponibles hasta el siguiente fotograma. Lo que estamos comprobando aquí son los resultados de colisión del cuadro anterior. Si por alguna razón necesitas absolutamente un elenco para actualizarlo de inmediato, puedes llamar a su función force RycaStudate Pero con el juego funcionando a 60 cuadros por segundo, el retraso no se notará y esto funcionará bien tal y como está. Ahora todo lo que tenemos que hacer es emitir nuestras señales en los momentos correctos. Si el enemigo no está apuntando actualmente, pero el objetivo está en su campo de visión, y tiene línea de visión hacia el objetivo, entonces el objetivo ha sido adquirido. Así que vamos a establecer está apuntando a true y emitir la señal adquirida objetivo, pasando el objetivo como argumento. Y en el escenario completamente opuesto, si actualmente están apuntando, pero el objetivo no está en su campo de visión y no tienen línea de visión, entonces hemos perdido el objetivo. En este caso, también sería una buena idea volver a establecer el valor de target en Nulo, lo que impedirá que el proceso de física revise algo más hasta que vuelvan a ingresar al campo de visión. También vamos a imprimir cuándo suceden estos eventos para que podamos probarlos. Lo último que tenemos que hacer es voltear nuestro polígono de colisión cuando el enemigo cambia de dirección, lo que podemos hacer conectando la señal de dirección cambiada a nuestro script Si estás usando una forma simétrica, todo lo que necesitas hacer es reposicionarla al otro lado del personaje Pero estoy usando un polígono, lo que significa que voy a necesitar editar los vértices individuales Comenzaré por obtener la matriz existente del polígono y almacenarla en una variable El tipo es una matriz de dos vectores empaquetados. Entonces puedo iterar a través de cada uno de los vértices y usar la misma estrategia para voltear su exposición al otro lado del personaje si están orientados hacia la La matriz de vértices proporcionada por el polígono aquí es solo una copia, no la matriz real en sí Entonces, cuando editamos sus valores, en realidad no afecta al polígono de colisión Para que los cambios realmente funcionen, necesitamos sobrescribir la matriz existente con la copia editada Vamos a activar formas de colisión visibles desde el menú de depuración y probarlo. Podemos ver a nuestro enemigo paseando de un lado a otro entre las dos paredes y el polígono de colisión se voltea cuando se dan Al entrar al campo de visión, el nodo de lanzamiento de rayos comienza a rastrear nuestra posición, pero el enemigo aún no ha visto ya que su línea de visión está bloqueada por el terreno. Si saltamos hacia arriba, la línea de visión ya no se obstruye y obtenemos la salida del mensaje objetivo adquirido Dejando el campo de visión del enemigo y también su línea de visión, el mensaje del objetivo perdido aparece y el elenco ya no está rastreando nuestra posición. Ahora tenemos a nuestro enemigo capaz detectar la presencia del personaje jugador, pero aún así necesita reaccionar ante ella. Te veré en el siguiente video. 56. 7-7 Agresión: Hola, amigos. En este video, tendremos al enemigo persiguiendo y atacando al jugador. Comenzando en la escena del enemigo, tendremos que agregar un ataque para este enemigo. Duplicando la animación inactiva, rápidamente fotografearé los sprites adecuados para la animación de ataque del enemigo. Esta animación de ataque realmente no comunica la cantidad de área que va a golpear el ataque. Sólo muestra el propio movimiento del enemigo. Necesitaremos un sprite separado para eso. Haré una nueva carpeta de Sprite para los sprites de efecto e importaré una hoja de sprites para el efecto de ataque de este enemigo. Añadiremos un Sprite Animado para denodar como hijo del Sprite del enemigo, por lo que automáticamente volteará horizontalmente cuando el enemigo se dé la vuelta horizontalmente cuando el enemigo se dé la Luego crea un nuevo recurso de marcos de Sprite y agrega los sprites de la hoja de Sprite Como siempre, agregaré un sprite en blanco al final de la animación, estableceré su velocidad de fotogramas en 12 fotogramas por segundo y no en un ciclo. Pondré esta animación en su primer sprite, que muestra con precisión el tamaño y la forma del ataque Después, colóquelo frente al enemigo. Esto hace que sea mucho más fácil agregar un hit box a este ataque. Así que vamos a duplicar el hit box existente. Cambiaré el nombre de la caja de acierto original para que contacte con daños y dejaré esta nueva como caja de acierto. Ahora podemos hacer que esta caja de golpes como forma de colisión coincida con el efecto de ataque. A diferencia del Sprite Animado, no deberíamos usar el truco de escalado negativo para voltear nuestro hit box Así que tendremos que conectar la señal de cambio de dirección del enemigo al guión de hit boox y reposicionarlo manualmente Como hemos hecho antes, solo tomaremos una referencia a la forma de colisión. Y establecer su posición a su valor absoluto multiplicado por uno negativo si la dirección es menor que cero o positiva en caso contrario. En el estado predeterminado de este enemigo, no estará atacando, por lo que este hit box no estará activo. Entonces, apaguemos su propiedad de monitoreo y visibilidad. Luego, vuelve a la animación de ataque donde podemos fotogramas clave estas propiedades para activarlas durante la animación de ataque y retroceder nuevamente. Esto también agregará ambos a la pista de reinicio con sus valores predeterminados. Y también podemos decirle al efecto de ataque que juegue al mismo tiempo. En la escena del contenido de la sala, actualmente tenemos el comportamiento normal de este enemigo caminando de un lado a otro y una forma para que el enemigo vea al personaje del jugador Cuando este nodo emita la señal adquirida por el objetivo, vamos a querer cambiar el comportamiento del enemigo de ritmo a ser más agresivo Y cuando pierdan la pista de su objetivo, deberían retomar su ritmo original Pero puede que no necesariamente queramos que esto se aplique a todos los enemigos u otros personajes que estén usando el guión de ritmo. Entonces deberíamos crear un nodo separado para un comportamiento agresivo. Usaré otro nodo temporizador y lo nombraré agresión. Después, adjunte un script a este nodo y guárdalo en la carpeta de scripts enemigos. Al igual que con el guión de ritmo, necesitaremos una referencia al enemigo que este script está controlando usando la etiqueta ready. También tendremos que almacenar una referencia al objetivo en una variable hacia la que este enemigo está actuando de manera agresiva. Y también necesitaremos conocer la dirección hacia el objetivo como vector dos, así como la distancia al objetivo como flotador. Conocer estos valores permitirá que el enemigo se acerque a su objetivo para entrar al alcance de ataque antes de atacar. Pero también tendremos que especificar el rango de ataque de este enemigo como una variable exportada, que sería un flotador. Si quieres, también puedes especificar un rango mínimo de ataque también. Si cambiamos el tipo del rango de ataque a un vector dos, podemos usar el valor X como rango mínimo y el Y como máximo. Voy a establecer su valor predeterminado para que esté al menos a 32 píxeles del reproductor y hasta un máximo de 64 píxeles. Entonces, si el enemigo está a más de 64 píxeles del personaje jugador, quiero que el enemigo corra hacia ellos. O si el enemigo está a menos de 32 píxeles del personaje jugador, quiero que el enemigo huya de ellos. Pero dentro de ese rango, el enemigo atacará. Anulando la función de proceso, podemos ignorar a Delta, y si no hay objetivo para este enemigo, podemos regresar Esto no debería suceder, pero nunca es mala idea tener un failsafe Podemos calcular la dirección hacia el objetivo restando la posición de nuestro enemigo de la posición del objetivo y luego obtener la distancia tomando ese mismo vector y calculando su longitud Si la distancia al objetivo es mayor que nuestro rango máximo de ataque, entonces este enemigo debe moverse hacia el objetivo estableciendo su dirección de movimiento al signo de dirección al punto X objetivo Si la distancia al objetivo es menor que nuestro rango mínimo de ataque, entonces este enemigo debe alejarse del objetivo, haciendo exactamente lo contrario. Si ambas condiciones fueran falsas, entonces el objetivo está dentro del alcance de ataque. Entonces el enemigo debe prepararse para atacar. Me aseguraré de que el enemigo deje moverse estableciendo su dirección de movimiento a cero y también de cara hacia el objetivo por si acaso no lo están ya. No quiero que el enemigo ataque enseguida, ya que mi animación de ataque es muy corta, no está telegrafiada Entonces arrancaré el temporizador aquí y esperaré a que se agote el tiempo antes de atacar. La propiedad de un solo disparo de este temporizador debe establecerse en true para que solo cuente atrás una vez. La propiedad de tiempo de espera será el tiempo que el enemigo permanezca dentro del rango de ataque antes de atacar. Conectando la señal de tiempo de espera al guión, aquí es donde le diré a mi enemigo que ataque También es una buena idea volver a mirar hacia el objetivo en caso de que algo haya cambiado desde que se inició el temporizador. Solo quiero iniciar el temporizador si actualmente está parado. También detendré el temporizador cada vez que el objetivo esté fuera del alcance de ataque. Esto debería ser suficiente para nuestro comportamiento. Ahora solo necesitamos cambiar de un lado a otro entre nuestros dos scripts de comportamiento en los momentos apropiados. No queremos que nuestro script de agresión esté activo cuando el enemigo genere por primera vez, así que configuraremos su modo de proceso en deshabilitado Seleccionando el campo de visión en el árbol de escenas, conectaremos la señal de destino adquirida al script de agresión, y podremos renombrar esta función si queremos. Para mantener las cosas consistentes entre mis diferentes scripts de comportamiento, lo llamaré zoom. Esta función establecerá el valor de objetivo, cambiará el modo de proceso para heredar, y también le dirá al enemigo que corra, lo que hará que comiencen a actuar agresivamente hacia el objetivo Pero también necesitamos pausar el guión de ritmo. Entonces también conectaremos la misma señal al nodo de ritmo. Y esta vez llamamos a una función llamada pausa, pero esta señal proporciona un argumento, y no lo necesitamos para pausar este comportamiento. También podemos imaginar un escenario que quisiéramos pausar este comportamiento en otras circunstancias y no quisiéramos proporcionar un argumento arbitrario e innecesario para llamar a la función de pausa. Entonces desvincularemos el argumento proporcionado por la señal, lo que la función conectada no tiene argumentos Aquí, todo lo que tenemos que hacer es establecer el modo de proceso en deshabilitado. Cuando el enemigo vea un objetivo, detendrá su comportamiento de ritmo y reanudará su comportamiento agresivo Entonces cuando pierden su objetivo, podemos hacer lo contrario, conectando la señal a los scripts y llamando a las funciones opuestas. Configurando su modo de proceso para heredar para activarlos o deshabilitados para desactivarlos Al activar el comportamiento de ritmo, también vamos a querer decirle al enemigo que camine Ahora en el guión del personaje, tendremos que activar la animación de ataque cuando le digamos al enemigo que ataque. Para ello, necesitaremos una referencia a la reproducción de la máquina de estado del árbol de animación. Pero esto provocará un error en el guión del personaje del jugador si tenemos otra variable del mismo nombre, ya que el personaje jugador hereda del personaje Entonces habría una variable de animación heredada del personaje, pero también otra declarada en el personaje del jugador, que no está permitida, pero estamos usando para el mismo propósito, así que en realidad podemos simplemente eliminar esta del guión del personaje del jugador. De vuelta en el guión del personaje, cuando se le dice que ataque, solo necesitamos decirle a esta reproducción que viaje a la animación de ataque. En el Árbol de Animación, agregaremos la animación de ataque y la transición a ella desde Inactivo con Avance Habilitado y volveremos a inactivo al final de la animación. Si no quieres que el enemigo pueda moverse o cambiar de dirección mientras atacas, entonces podemos agregar verificaciones rápidas para ver si el nodo actual de la reproducción de animación es ataque. Y o bien establece la dirección de movimiento a cero o regresa fuera de la función por completo. Ahora, cuando ejecutamos el juego, una vez que el enemigo nos tiene tanto en su campo de visión como en su línea de visión, su comportamiento cambia de ritmo a ser más agresivo Nos perseguirán y atacarán tras una breve pausa. Ahora tenemos un enemigo mucho más agresivo con el que enfrentará nuestro personaje jugador, pero nuestro personaje de jugador realmente no puede defenderse Te veré en la siguiente sección. 57. Combinación 8-1: Hola, amigos. En este video, le daremos al personaje del jugador ataques propios para que puedan luchar contra nuestros enemigos. Ya le hemos dado un ataque al Caballero ratón, y el proceso será muy similar. Sin embargo, nuestro personaje jugador tiene dos ataques diferentes. Podemos copiar algunos de los nodos de la escena nocturna del ratón para ahorrar algo de tiempo, el hit box y el nodo animado Sprite dos D. Cambiando a la escena del personaje, podemos pegar estos nodos en la escena, luego reorganizarlos según sea necesario El nodo animado Sprite dos D se puede ordenar bajo el Sprite del personaje, lo que se volteará automáticamente para que coincida con la dirección en la que se enfrenta el personaje Voy a renombrarlo para atacar efecto. Sé qué sprite animado específico es este. El hit box, generalmente me mantendré ordenado al lado de la Caja Hurtada como hermano Para que los personajes del jugador golpeen la caja inflijan daño a la Caja de daño del enemigo, tendremos que asegurarnos de que las capas de colisión y las máscaras estén establecidas en consecuencia. Como mi personaje jugador está en la capa de colisión nueve y su Caja de Daño está en la capa de colisión diez, entonces tendré a mis enemigos en la capa de colisión 17 y sus cajas Hurt estarán en la capa de colisión 18. abrir la configuración del proyecto, agregaré la caja de daño enemiga a mis dos nombres de capa física D como capa 18. Entonces recuerda editar todas mis escenas enemigas existentes para poner sus cajas Hurt en esta capa también. El cuadro de golpe de los personajes del jugador se puede configurar entonces para enmascarar la capa 18 con el fin de causarles daño. Para darle la vuelta al hit box, necesitaremos reconectar la señal en esta escena, ya que esa conexión de señal no habrá copiado de la otra escena Pero la función que escribimos antes en el guión Hit box a la que queremos conectar esta señal se nombra en enemigo cambió de dirección. Esto no importará, pero si quieres ser consistente con la forma en que nombra las cosas en tu juego, es posible que quieras cambiar el nombre de esta función el personaje cambiado de dirección. Esto agregará otra función al script, y podemos fácilmente simplemente mover el código a esta nueva función y eliminar la anterior, ya que simplemente hará lo mismo. Sin embargo, ahora tenemos que entrar en la escena de los enemigos y editar su conexión de señal para conectarnos a la nueva función. Cuanto antes en tu proyecto puedas identificar estos problemas, menos tiempo y esfuerzo necesitarás dedicar más tarde a refactorizar. De vuelta en la escena del personaje del jugador, seleccionaremos el nodo Animation Player de la jerarquía de escenas y agregaremos una nueva animación. Nombraremos a este ataque uno ya que hay dos animaciones de ataque diferentes y tendremos que diferenciarlas. Después de agregar los marcos Sprite del personaje. Voy a copiar los fotogramas clave a las otras pistas para la ropa del personaje También podemos encender la propiedad de monitoreo del hit box. Y la visibilidad, también, si te gusta verla encendida y apagada en modo de depuración. Echando un vistazo al efecto de ataque, esto no coincide con la animación de ataque. Entonces voy a importar los sprites de efecto adecuados para este ataque. Luego agrega una nueva animación al recurso Sprite frames. Lo nombraré ataque uno, apagaré el ciclo, estableceré la velocidad de fotogramas y agregaré un fotograma vacío al final Ahora la animación de ataque puede decirle al efecto de ataque, Sprite Animado dos nodos D para reproducir el ataque un efecto La llamada a la función keyframed es solo play, que ha estado funcionando bien siempre nuestro nodo Animated Sprite two D solo tenga una animación para Pero ahora tenemos dos animaciones diferentes, y necesitamos especificar cuál queremos jugar. Al hacer clic en el fotograma clave, podemos editarlo en el inspector Ampliando la sección de argumentos, podemos ver que la función play en realidad tiene tres argumentos, todos los cuales son opcionales. Sólo nos preocupa el primer argumento, el nombre de la animación, que podemos escribir en el campo de texto. Si tienes curiosidad, los otros argumentos son para ajustar la velocidad de la animación o reproducir la animación hacia atrás. La ortografía debe coincidir exactamente con el nombre de la animación. Voy a cambiar el nombre de la animación predeterminada para atacar dos para que coincida con lo que puse en la animación. Duplicando la animación de ataque uno, también podemos hacer una animación de ataque dos Después de cambiar los fotogramas de sprite del personaje, voy a copiar los fotogramas clave a las otras pistas Después cambiar el argumento pasando al efecto ataque para jugar ataque dos en lugar de atacar uno. Seleccionando Seleccionando el nodo Árbol de Animación, podemos agregar el ataque uno y atacar dos animaciones. Después agrega una transición de movimiento a ataque uno, luego de ataque uno a ataque dos. Ambos tendrán su modo avanzado establecido en habilitado, lo que significa que activaremos estas transiciones desde nuestro script. Al agregar transiciones, dejando cualquiera de las animaciones de ataque volviendo al movimiento, estas tendrán sus modos de cambio establecidos al final. La transición del ataque uno al ataque dos también tendrá su modo de conmutación configurado al final. Esto nos permitirá hacer la transición a atacar uno si se presiona el botón de ataque, y luego del ataque uno al ataque dos si el botón de ataque se presionó una segunda vez durante la primera animación de ataque. Para agregar un botón de ataque a nuestro juego, tendremos que entrar en la configuración del proyecto, la pestaña Mapa de entrada y agregar un nuevo evento de entrada para atacar. Usaré la tecla X en el teclado y el botón de la cara izquierda en mi mando, que también es X. Luego en el script del reproductor, podemos agregar otro bloque I para ataques, amortiguando la entrada de la misma manera que tenemos con cada otra acción Dado que el botón para activar el primer ataque y el segundo ataque es el mismo, el guión de los jugadores solo debe preocuparse de decirle al personaje que ataque, no qué ataque específico realizar. En el script del personaje del jugador, podemos agregar esta función de ataque, devolviendo un booleano igual que cualquier otra entrada en búfer Esto no se bloqueará y no tiene ningún costo, a diferencia de la función cast. Si la reproducción de la animación del personaje se encuentra actualmente en estado de movimiento, entonces voy a permitir que ataquen. Si tiene éxito, entonces podemos decirle a la reproducción de animación que viaje al ataque una animación y que devuelva true o return false si el personaje estaba ocupado haciendo otra cosa. Hay un error porque la función de ataque está anulando la función de ataque de la clase de personaje, pero la firma no coincide Esto significa que o bien los parámetros o el tipo de retorno son diferentes, lo que no está permitido. mantener el control o comando y hacer clic en la función nos lleva a la definición de superclase de esta función donde podemos ver que devuelve void, no un booleano Para poder usar esta estructura de herencia con nuestros enemigos y nuestro personaje jugador, sin dejar de permitir entradas en búfer, necesitaremos que la función de ataque de superclase también devuelva un booleano Simplemente volveremos true para satisfacer este requisito, y volviendo al guión del personaje del jugador, se soluciona el error. Pero, ¿qué pasa con el segundo ataque? Podemos agregar un else if block y verificar si la reproducción de la animación está actualmente en la animación attack one. Entonces dile que viaje al ataque dos animación en su lugar. Activemos las formas de colisión visibles en el menú Depurar, luego presionemos Reproducir y probarlo. Al presionar el botón de ataque, nuestro personaje reproduce el ataque One Animation. activa el cuadro de aciertos y se reproduce la animación del efecto. Al presionar nuevamente el botón de ataque durante el primer ataque, también se juega el segundo ataque. Volviendo al editor, podemos abrir el árbol remoto para ver nuestro juego actual funcionando. Explorando el árbol de escena hasta que encontremos la noche del ratón, podemos seleccionar su caja de daño y ver sus propiedades en el inspector, incluyendo su estado de salud actual. De vuelta al juego, podemos atacar a nuestro enemigo y ver como cada ataque le golpea por una salud cada vez hasta que lleguen a cero. Vamos. Ahora tenemos a nuestro personaje capaz de atacar a los enemigos, pero nuestros personajes y enemigos no reaccionan al ser golpeados. Te veré en el siguiente video. 58. 8-2 hits: Hola, amigos. En este video, haremos que nuestros personajes reaccionen ante ser golpeados por ataques. Comenzando en la escena del personaje del jugador, seleccionando el nodo Animation Player, necesitaremos agregar una nueva animación para ser golpeados. Para facilitar las cosas, duplicaré la animación de guión para crear la animación de éxito. Después de actualizar los fotogramas clave de Sprite, copiaré y pegaré en las otras pistas para animar también la ropa del personaje Debido a que dupliqué la animación de guión, esta animación de éxito ahora también incluye fotogramas de invencibilidad Esto es muy útil para evitar que los personajes daño de múltiples cajas de golpe en rápida sucesión, lo que a menudo se siente injusto para el jugador y también hace que el personaje asuma repetidamente daños de cajas de golpe persistentes, como peligros ambientales, por ejemplo, porque se activará una nueva colisión cuando se reactive la Caja Hurt al final de la animación, si la Caja de Daño todavía se superpone con la caja de impacto. También tenemos el método track llamando a la función end dash, que si recuerda, la forma en que se implementó en la sección anterior, debe llamarse si se interrumpió el guión. Sería una buena idea mover esta llamada de función al inicio de la animación hit. Echemos un vistazo a esta función en el guión del personaje del jugador. Dependiendo de los fotogramas que actives o desconectes la caja de daño, es posible que el personaje sea golpeado mientras se reproduce la animación del guión y, por lo tanto, interrumpa la animación del guión. Lo que significa que nunca se llamaría a la función de tablero final, la gravedad del personaje nunca se restablecerá y el enfriamiento del guión nunca comenzó Obviamente, esto es problemático, pero podemos arreglarlo fácilmente. Todo lo que realmente necesitamos hacer es rastrear cuando el personaje está flotando con una variable booleana Cuando empiece el guión, lo pondremos en true. Entonces, cuando se llame a la función end dash, comprobaremos si el personaje está flotando primero y si es así, haremos todas las mismas cosas Entonces el conjunto se corre a falso después. Ahora podemos llamar a esta función en cualquier momento que necesitemos independientemente de si el personaje es o no gallinero. Si el personaje no es rápido, la función simplemente no hará nada Seleccionando el nodo Árbol de Animación y echando un vistazo a la máquina de estado, me gustaría que la animación hit pudiera interrumpir cualquiera de estas animaciones de acción existentes, así como cualquier animación de salto o movimiento, también. Por lo tanto, sería una buena idea usar otra máquina de estado. Entonces voy a guardar esta máquina estatal como hice con las anteriores. Le nombraré acciones y la guardaré en la carpeta de mi personaje junto con las demás. Luego reemplace esta máquina de estado una nueva y cargue la máquina de estado de acciones como nodo. Bien. A continuación, puede agregar la animación de hit a esta máquina de estado. Agregar una transición de inicio a acciones lo convierte en el estado predeterminado. Luego una transición de acciones a golpear con su modo avanzado configurado a habilitado, y otro de volver a golpear a acciones con su modo de cambio configurado al final. Esto nos permite activar la animación desde cualquier estado existente, jugar a la vez, luego regresar a nuestros otros estados. En el guión de caracteres, ya que quiero que esto se aplique a todos los personajes, no solo a mi personaje jugador, necesitaremos hacer una nueva variable para mantener la reproducción de esta nueva máquina de estado. Podemos duplicar la variable existente y cambiarle el nombre a algo así como animaciones Hurt. La ruta a esta propiedad de reproducción es parámetros Playback, ya que es la raíz del Árbol de Animación. Si seleccionamos el Árbol de Animación en el árbol de escenas y expandimos su sección de parámetros, podremos ver las reproducciones para cada una de nuestras máquinas de estado Así que la ruta de propiedad de reproducción de la máquina de estado de acción ha cambiado, y necesitamos actualizarla. Para aclarar mejor el uso de esta reproducción en relación con las animaciones Hurt, voy a nombrar estas animaciones de acción de reproducción. Luego use la función de reemplazo para cambiar todas las instancias de esta variable con su nuevo nombre. Dado que el script del personaje del jugador hereda esta variable, también necesitaré reemplazar todas las instancias del nombre antiguo por el nuevo nombre en ese script, también Esto funcionará para el personaje jugador, pero para que funcione para los enemigos, también necesitaremos actualizar sus máquinas de estado del Árbol de Animación para que coincidan con este nuevo formato. Sólo actualizaré mi noche de ratón ya que ese enemigo está en mi sala de inicio, y el proceso será el mismo para cada enemigo. Haré la animación hit en el nodo Animation Player. A continuación, guarde la máquina de estado del árbol de animación como recurso del proyecto. Reemplácelo con una nueva máquina de estado. Agrega la vieja máquina de estado como nodo, agrega la animación de golpe, agrega las transiciones con los mismos modos de avance y cambia. Renombrarlo acciones para que coincidan con lo que buscará el script. Ahora este enemigo tiene la misma estructura de animación que el personaje del jugador, por lo que los guiones funcionarán igual, teniendo dos playbacks separados para reproducir la animación hit y otra para acciones Una vez que se configura la máquina de estado, puede eliminar la máquina de estado guardada. Esto hará que la máquina de estado se localice la escena en lugar de un recurso compartido entre múltiples escenas. Ahora que tenemos acceso a la reproducción de nuestra máquina de estado, necesitamos activar la animación. Empezaremos en el guión de Hurt Box. Tenemos una señal que se emite cuando cambia la salud del personaje, cual estamos utilizando para actualizar el elemento HUD Pero esta señal también se emite cuando inicializamos la salud del personaje al inicio, así como cada vez que el personaje recuperaría la salud Por lo que no es la mejor señal para usar para recibir daños. Declararemos una nueva señal para eso. Si quieres que el personaje reaccione ante diferentes cantidades o tipos de daño, es posible que quieras darle parámetros a esta señal. Voy a añadir un parámetro para la dirección de la que proviene el daño, como factor dos. Pero no podemos obtener esa información de aquí. Solo tenemos acceso a la Caja de Heridos y no a la caja de impacto que causó los daños. Entonces cambiando al guión de Hit box, aquí tenemos acceso tanto al hit box como al Hurt Box. Entonces agregaremos esto como otro argumento pasado por la función take damage. Podemos calcular la dirección de A a B restando A de B, luego normalizar el resultado Normalizando ignoraremos la distancia entre A y B estableciendo la longitud del vector en uno De vuelta en el script de Hurt Box, agregaremos el parámetro direction. Cuando nuestra caja de Rebaño reciba daño, emitiremos la señal y pasaremos por la dirección con ella. Nuestro guión de personajes ahora puede reaccionar a esta señal. Cambiaré el nombre de la función conectada a on damage received for simplicity. Bien. Primero le diremos a la reproducción de animación Hurt que viaje al estado hit. Después también agrega una fuerza al cuerpo del personaje en la dirección del daño. Dado que la dirección está normalizada, tendrá una longitud de un píxel. Podemos multiplicar esto por cualquier número que queramos para alterar cuán impactante se sentirá la fuerza knockbck Incluso es posible que desee exportar esto como una nueva variable para que se pueda ajustar para cada carácter individual También tendremos que hacer esta conexión de señal en todas nuestras escenas de personajes. Et lo prueban. Mi personaje ahora puede atacar al enemigo y el enemigo reacciona al ser golpeado tanto por el juego como por la animación y también se aplica una fuerza de retroceso. Lo mismo le sucede también a mi personaje cuando el enemigo me ataca. Ahora tenemos a nuestros personajes reaccionando al recibir daño, pero nuestro combate no se siente muy jugoso. Te veré en el siguiente video. 59. 8-3 jugos: Hola, amigos. En este video, agregaremos algunos efectos de partículas a nuestro combate para que se sienta más impactante. Comenzando en nuestra escena de personajes de jugador, agregaremos un nuevo tipo de nodo a nuestra escena, un nodo emisor de partículas Godot tiene dos tipos diferentes, CPU y GPU. El nodo de partículas de la CPU renderizará las partículas de la misma manera que estamos dibujando nuestros sprites de personajes usando el procesador central del dispositivo, que es menos eficiente pero más compatible con dispositivos más antiguos Mientras que un nodo de partículas GPU delegará dibujo de estas partículas por completo a la tarjeta gráfica del dispositivo, que es más eficiente pero solo en dispositivos modernos. El nodo de partículas GPU puede manejar número mucho mayor de partículas sin sacrificar el rendimiento Solo recomendaría usar partículas de CPU si estás apuntando específicamente a teléfono o tableta para tu juego. De lo contrario, deberías usar partículas GPU. Añadiendo un nodo GPU Partículas dos D a nuestra escena de personajes, solo lo nombraré partículas, lo moveré hacia arriba para estar en el centro del personaje y echar un vistazo a sus propiedades en el inspector. Antes de que un emisor de partículas dibuje algo, necesita un material de proceso Este es un recurso que le dice al emisor cómo generar partículas y cómo deben comportarse las partículas después de haber Hay dos opciones diferentes para nuestro material de proceso, un material de proceso de partículas o un material Shadum El material de proceso de partículas se creará como un recurso de proyecto que podemos editar aquí mismo en el inspector, mientras que un material de sombreado nos permitirá escribir un script de Shader para hacer lo mismo Los scripts de sombreado no están escritos en GDScript como todos nuestros scripts hasta ahora Están escritos en shader GD, que no serán cubiertos en este curso Entonces usaremos un recurso material de proceso de partículas en su lugar. Haga clic en el recurso para ver y editar sus propiedades. Ahora que nuestro nodo emisor de partículas tiene un material de proceso, genera píxeles blancos individuales desde su punto de origen que caen debido a Para que las partículas sean más fáciles de ver, esconderé mi sprite de personaje Antes de entrar en cada propiedad individual, ayuda a apagar primero la gravedad, que está debajo de la sección de aceleración. Y como estas partículas van a ser utilizadas para impactar durante el combate, pondré su explosividad en una Tengo una hoja de sprites que me gustaría usar para mis partículas, así que la importaré a mi carpeta de efectos, luego la asignaré como propiedad de textura de mis emisores de partículas Pero esto solo dibuja toda la hoja de sprites para cada partícula Para animar una partícula, tenemos que darle un material personalizado bajo las propiedades heredadas del elemento Canvas Haremos un nuevo material de elemento Canvas y luego activaremos su propiedad de animación de partículas. Ahora podemos cambiar el número de fotogramas de animación horizontal y verticalmente en la hoja de sprites Las partículas ahora están dibujando solo el primer fotograma. Ampliando la sección de animación del material de proceso de partículas, podemos establecer la velocidad de animación para las partículas. Quiero que mis partículas tengan una velocidad consistente, así que estableceré tanto la mínima como la máxima en una. También se puede usar una curva para alterar la aleatorización de la velocidad de animación de cada partícula Y también se pueden proporcionar los mismos valores para dar a cada partícula su propio desplazamiento de animación. Ampliando la sección span, podemos editar la posición donde van a desovar las partículas, su ángulo de rotación y su velocidad inicial Podemos cambiar la forma de emisión de un solo punto a ser una variedad de otras formas y cambiar el tamaño de la forma si queremos. Las formas de emisión puntual suelen ser las más adecuadas para las partículas de combate. El ángulo permite la aleatorización de la rotación de las partículas Para que sea completamente aleatorio, simplemente establezca max en 360. Ya que estoy usando pixel art, no quiero que mis partículas roten. La velocidad inicial hará que nuestras partículas se sientan más explosivas. La cantidad de fuerza se aleatorizará para cada partícula entre min y max, haciendo que las partículas se sientan menos uniformes El spread creará una forma de abanico. Al máximo a 180 grados, la dirección será completamente aleatoria La sección de velocidad animada contiene variables que puede usar para aplicar una variedad de diferentes velocidades constantes a sus partículas a lo largo de su vida útil Angular los hará rotar. Direccional continuará moviéndolos en cualquier dirección en la que ya se estén moviendo. Orbital los hará orbitar alrededor del punto de desove. La radio los alejará del punto de generación. Y el límite de velocidad utiliza una curva para limitar la velocidad de cada partícula. La sección de aceleraciones contiene variables similares que puedes usar para afectar la velocidad de cada partícula gradualmente a lo largo de su vida útil, lo que las hará sentir más realistas La gravedad es una fuerza constante en una dirección para todas las partículas. Lineal es la dirección en la que ya se mueve la partícula. Radial está lejos del punto de desove. Y tangencial es similar a orbital. La amortiguación es una fuerza útil que hará que las partículas se desaceleren a lo largo de su vida útil, lo cual es útil para partículas explosivas o de impacto como las que estamos fabricando actualmente Los atractores de partículas no están disponibles para dos D, por lo que este ajuste no hará nada Ampliando la sección de visualización, podemos cambiar la forma en que se dibuja cada partícula. La escala hará que las partículas aleatoriicen su propio tamaño. Si agregamos una curva de escala, esto cambiará la forma en que cada partícula cambia su escala a lo largo de su vida útil. Pronto repasaremos el editor de curvas. escala sobre la velocidad hará que la escala de las partículas sea relativa a su velocidad en lugar de su vida útil. Esto es particularmente útil para hacer nubes de polvo que se disipan Las curvas de color tienen múltiples propiedades diferentes, comenzando con un color base para todas las partículas. La rampa de color nos permitirá hacer un gradiente con cada partícula progresando desde el color a la izquierda hasta el color de la derecha a lo largo de su vida útil Este color se multiplica por el color base para producir el resultado. La rampa inicial de color aleatorizará el color inicial de cada partícula a través del La curva de emisión se puede utilizar para hacer que tres partículas D emitan diferentes cantidades de luz a lo largo de su vida útil, que no se usa en dos D. La curva Alfa es útil solo para editar el Alfa de sus partículas a lo largo de su vida útil. Vamos a crear un nuevo recurso de textura curva aquí. Este recurso de textura curva requiere otro recurso de curva propio. Al hacer clic sobre esto se abre un editor de curvas que podemos usar fácilmente para crear una amplia variedad de efectos. El eje X de esta gráfica es tiempo siendo cero cuando se genera la partícula y uno es el final de la vida útil de la partícula. No 1 segundo. El eje Y es el valor que estamos editando, que son los colores de partículas Alfa, siendo uno opaco y cero siendo invisible. Podemos editar los valores mínimo y máximo para nuestro eje, pero no necesitamos hacerlo en este contexto. Simplemente haciendo clic en la gráfica agregará un punto que podremos arrastrar según sea necesario. Quiero que mis partículas comiencen opacas y se desvanezcan a invisibles a lo largo de su vida. Esto es genial para hacer que las partículas se desvanezcan en lugar de simplemente desaparecer tangentes se aplican automáticamente a los puntos para crear una curva Seleccionando cualquier punto de la gráfica, podemos editar las tangentes para crear cualquier tipo de curva que necesitemos También podemos editar manualmente los puntos y tangentes expandiendo la sección de puntos en la parte inferior variación de tonalidad se puede usar para aleatorizar el tono de tus colores de partículas, lo que hace que se vean menos uniformes El resto de las propiedades no son muy aplicables a nuestro proyecto tot, pero te daré un breve resumen de para qué sirven La turbulencia se puede aplicar para simular cómo las corrientes de aire afectarían a tus partículas Puede editar el patrón de ruido utilizado para calcular la turbulencia cuando se enciende Las partículas se pueden detener o matar por colisiones. Las colisiones aquí no son lo mismo que las colisiones que hemos estado usando hasta ahora porque las partículas están siendo manejadas por la tarjeta gráfica Solo pueden colisionar con oclusores de luz, no con objetos de física Y si tus partículas escalan, entonces su radio de colisión también se puede escalar con ellas. Y se puede usar un sub emisor para crear efectos como fuegos artificiales, generando omisiones de partículas adicionales Para que mis partículas coincidan con las otras velocidades de fotogramas de mi juego, estableceré la vida útil de las partículas ocho fotogramas divididos por 12 cuadros por segundo. Ahora que el emisor de partículas está configurado, deberíamos establecer su propiedad one shot en true Ahora solo emitirá partículas en una sola ráfaga, que podemos desencadenar a través de nuestro script. Volveré a encender mi sprite de personaje, luego abriré el guión de mi personaje Dando un nombre único al nodo particles, podemos almacenarlo en una variable con la etiqueta on ready. Entonces, cuando el personaje recibe daños, podemos decirle a la nieve que emita partículas estableciendo su propiedad emisora en true. Tenga en cuenta que esto no funcionará si se usa en rápida sucesión, ya que el emisor de partículas ya estará emitiendo partículas Así que solo establecer la emisión a true no generará más partículas Para momentos como este, querrás generar un nuevo nodo de partículas de GPU por cada golpe o llamar a la función de reinicio en su lugar reinicio obligará al emisor de partículas a detener su emisión actual y comenzar de nuevo con un nuevo conjunto de partículas Recuerda copiar este nodo en tus escenas enemigas según sea necesario. Et lo prueban. Atacando al enemigo, ahora emiten partículas cuando son golpeados. Y el personaje jugador también emite partículas cuando recibe daño. Ahora tenemos efectos de partículas desencadenados por nuestros ataques, pero hay más que podemos hacer para que combate se sienta aún más crujiente Te veré en el siguiente video. 60. 8-4 Agitar: Hola, amigos. En este video, agregaremos un batido de cámara que puede hacer que el combate se sienta aún más impactante. Comenzando en el script de la cámara, necesitaremos una variable que podamos usar para sacudirla, que será un vector dos. Si bien hay una variedad de formas diferentes en las que podemos crear un efecto de sacudida de cámara, creo que tiene sentido usar una pregeneración, ya que es un cambio de propiedad que ocurre a lo largo de un tiempo específico Así que vamos a declarar una nueva variable de tween llamada shake tween. Entonces también declaramos una nueva función que será de acceso público que pueda sacudir la cámara. Primero, comprobando si la cámara ya está temblando comprobando si el shake tween ya existe y si es así, mátalo Entonces podemos crear una nueva premamá. No hay necesidad real de tipos especiales de transición o flexibilización para esto No queremos interponer una propiedad de manera uniforme de un valor a otro, sino simplemente llamar un método varias veces a lo largo de una corta duración Tendremos que declarar la función a la que vamos a llamar, pero voy a llamarla set shake como una función privada. Entonces necesitamos proporcionar un argumento para pasar a la función desde el principio hasta el final de la tween Esta será la intensidad del efecto temblor medido en píxeles. Podemos aceptar esto como un parámetro de la función shake para que cualquier script que desee activar una sacudida de cámara pueda especificar la intensidad. Luego a lo largo de la duración de la cámara, el temblor reduce gradualmente la intensidad hasta cero. Opcionalmente, es posible que desee convertir este otro parámetro si desea permitir batidos de cámara que tengan una intensidad consistente o creciente El argumento final es la duración de entre, que también podemos convertir en otro parámetro. A continuación, escribiremos la función set shake, que acepta la intensidad como parámetro. Esta función se llamará a cada fotograma durante la duración de la sacudida con la intensidad cambiando gradualmente desde el valor proporcionado en la llamada a la función original a cero. Entonces todo lo que tenemos que hacer es establecer el valor de shake en un nuevo vector dos. Si empezamos con el vector dos punto a la derecha, entonces rotarlo a una dirección aleatoria. Un ángulo de rotación aleatorio puede ser un flotador aleatorio entre cero y tau. Entonces podemos multiplicar los resultados por intensidad. Si por alguna razón tu tween de shake no concluye estableciendo el valor de shake en cero, entonces tendrás que hacerlo al final de la tween Podemos conectar la señal de shake tweens terminada a la función set shake y enlazar cero como intensidad Esto asegurará que el valor de la sacudida en cualquier momento después la cámara haya terminado temblar se restablecerá a cero. Para que el vector shake realmente mueva la cámara, todo lo que tenemos que hacer es agregarla a la posición de la cámara en nuestra función de proceso. A en nuestra escena de juegos, ahora podemos conectar cualquier señal que queramos para activar un movimiento de cámara a la función shake de nuestra cámara. Como, por ejemplo, cuando el personaje del jugador ataca a un enemigo o cuando recibe daño. En el guión del personaje del jugador, podemos agregar señales para estos eventos. Luego, de vuelta a la escena del juego, podemos conectar estas señales a la función shake de la cámara. Para agregar argumentos a una conexión de señal, necesitamos ampliar la sección avanzada. Luego podemos seleccionar float de la lista de tipos de argumentos ya que el parámetro intensity es un float en nuestro script. Después haga clic en el botón Agregar. El batido también necesita una duración, que también es de tipo flotador. Para que podamos volver a hacer clic en el botón Agregar para agregar otro flotador. Los valores que proporcionamos para el Argumento uno cambiarán la intensidad de la sacudida medida en píxeles, y el Argumento dos será la duración del batido en segundos. Voy a hacer que mis personajes de jugador ataquen a causa de un movimiento de cámara con una intensidad de cuatro píxeles en un cuarto de segundo. Pero cuando reciban daños, sacudiré la cámara con una intensidad de ocho píxeles en medio segundo. Cambiando a la escena del personaje del jugador, necesitamos emitir estas señales en los momentos apropiados, comenzando con nuestra señal Hurt boxes damage received signal, que ya está conectada a una función nombrada en el daño recibido en el guión del personaje. Si anulamos esta función en el guión del personaje del jugador, podemos llamar a la función de superclase, luego emitir la señal A continuación, podemos seleccionar el hit box y agregar otra conexión de señal a la señal ingresada en el área on y hacer que llame a una nueva función. Vamos a nombrar esto al ataque aterrizado. Esto no necesita preocuparse por el otro nodo de área, por lo que podemos usar la sección avanzada para desvincular este argumento de la conexión de señal Como desvinculamos el argumento area, la función no tiene parámetros Todo lo que esta función tiene que hacer es emitir la señal para provocar el temblor de la cámara. No, vamos a probarlo. Si ataco al ratón Caballero, esto desencadena las casillas de golpe se ingresan señal, lo que burbujeará a través del personaje del jugador hasta la escena del juego y activará un temblor de cámara. Dejar que el ratón Caballero golpee al personaje del jugador activa la señal recibida dañada de la caja Hurt, lo que provoca un temblor de cámara más intenso. Ahora tenemos nuestra cámara temblando en respuesta a que el personaje del jugador ataca los enemigos y recibe daño, pero nuestros personajes no mueren cuando se les acaba la salud. Te veré en el siguiente video. 61. 8-5 Muerte: Hola, amigos. En este video, haremos que nuestros personajes mueran cuando se les acabe la salud. Comenzando en la escena nocturna del ratón, seleccionando el nodo Animation Player, rápidamente haré una nueva animación muerta duplicando la animación de éxito Después de cambiar el sprite al marco correcto en la hoja de Sprite, es una buena idea apagar la Caja de Daño para que ya no puedan recibir daños y no volver a encenderla Lo mismo se puede hacer para toda la otra área a los nodos Di, desactivando el daño de contacto y el cuadro de golpe dos, por lo que el enemigo muerto ya no puede infligir daño al personaje del jugador. Seleccionando el nodo Árbol de Animación, podemos agregar esta animación muerta a la máquina de estado y automáticamente hacer la transición a ella si este personaje está muerto. A diferencia de otras animaciones, no hay necesidad de una transición fuera del estado muerto. Ahora solo necesitamos agregar esta variable Is dead al script de caracteres. Lo pondré en la parte superior del guión como booleano. Y también declaramos una señal de muerte dos, si acaso alguna vez queremos que algo reaccione ante la muerte de ciertos personajes. Después escribe una función pública llamada die que establecerá el valor de esta variable en true y emitirá la señal. En cualquier lugar de este script donde un personaje pueda realizar cualquier acción que no se deba permitir después de morir, solo podemos verificar primero el valor de la variable is dead. Entonces, si se le dice al personaje que se enfrente a una dirección, pero están muertos, deben ignorar esa petición. De la misma manera lo ignoramos si están atacando. De manera similar, si a este personaje se le dice que salte, pero están muertos, no deberían saltar. Lo mismo con atacar. Y en el proceso de física, también estableceré su dirección de movimiento a cero si están muertos, por lo que nunca se moverán mientras estén muertos, sino que se verán afectados por la física. En el guión de Hurt Box, ya creamos la señal teñida y la emitimos cuando el personaje se queda sin salud cuando escribimos el guión en la sección anterior. Pero para reproducir una animación de muerte y no una animación de golpe cuando el personaje recibe daño y muere como resultado, necesitamos asegurarnos de que solo emitimos la señal teñida en ese momento. Entonces moveremos la señal de daño recibido a un bloque se, dando prioridad a la señal teñida. Todo lo que tenemos que hacer es conectar la señal teñida de la Caja Hurt a la función de morir del enemigo para activar la animación. Ya sea en la escena del enemigo o en la escena del contenido de la sala, donde sea que tengas los nodos de IA de tu enemigo, también puedes querer conectar la señal did del enemigo a la función libre de estos nodos. Alternativamente, puedes hacer esto en los propios guiones. Al anular la función de listo, enemigo muerto se puede conectar a ure Esto le ahorrará tener que conectar la señal manualmente cientos de veces a lo largo de todo el proyecto. Vamos a probarlo. ataco al Caballero ratón cinco veces, su salud llega a cero, y muere, que reproduce la animación de la muerte, y detiene todas las acciones. También puedo tocarlo sin sufrir ningún daño. Ahora para el personaje jugador, en realidad no tengo sprites de animación de muerte para este personaje Lo que voy a hacer en cambio es reutilizar la animación hit, duplicándola para crear una animación de muerte, ya que sé que cuando este personaje muere, la escena del juego se desvanecerá y restablecerá de todos modos Al igual que el enemigo, es una buena idea apagar también todas las cajas lastimadas y las cajas de golpes. El único cambio real que voy a hacer aquí es tener el loop de animación. En el Árbol de Animación, agregaré la animación muerta, la misma que antes, con una transición automática si el personaje está muerto. Pero esta vez, añadir también una transición fuera del estado muerto bajo la condición de que ya no estén muertos, ya que el personaje jugador será revivido después de morir Después de conectar la señal de muerte de Hurt Box al guión del personaje, cambiaré al guión del personaje del jugador. Tendremos que escribir una función de reactivación que pueda ser utilizada para devolver la vida al personaje del jugador, estableciendo la variable I dead de nuevo en false. También podemos decirle a la Caja de Hurtos que recupere la salud completa al mismo tiempo. Para agregar más a la animación de muerte del personaje del jugador, anularé la función die en el guión del personaje del jugador. Comenzaré llamando a la función de superclase, luego haré algunas otras cosas específicas para el personaje del jugador Reutilizando el nodo de efectos de partículas, estableceré su propiedad one shot en false, su explosividad Y está emitiendo propiedad a verdad, convirtiendo el estallido instantáneo de partículas en un flujo constante Además de eso, también entretendré el color de modulación del personaje para que tenga una mayor intensidad Después de crear una nueva tween, interpelaré el color de modulación de este nodo a un nuevo color con valores RGB de 255 Luego en la función de revivir, volveré a poner todos estos a sus valores normales. A en la escena del juego, la cámara también puede reaccionar ante la muerte del jugador con otro temblor de cámara aún más intenso. El manager del juego también tendrá que reaccionar ante la muerte del personaje del jugador para restablecerlo todo. Así podremos conectar la señal dD del personaje del jugador al guión del manager del juego. Nombremos esta función en Player DD. Cuando el jugador muere, primero, podemos desactivar el manejador de entrada ya no puedan controlar al personaje Esperaré 1 segundo primero para dejar que se reproduzca la animación de muerte de mi personaje, lo que se puede hacer diciéndole al árbol de escenas que cree un temporizador. Podemos obtener el árbol de escenas en cualquier momento usando la función get tree y llamar a la función create timer, que acepta un argumento para la duración del temporizador. Esto devuelve el temporizador ya iniciado para que podamos esperar su señal de tiempo de espera. Esto detendrá la ejecución de esta función en esta línea durante exactamente 1 segundo. Después de desvanecerse a negro, tendremos que reposicionar al personaje del jugador donde queremos que responda. Como aún no tenemos los sistemas adecuados para manejar esto, solo los pondré en el origen de la escena del juego y dejaré un comentario de que esto necesita implementarse más tarde. Ahora podemos revivir al personaje del jugador, volver a aparecer y volver a habilitar el controlador de entrada para que el jugador pueda seguir jugando Si desea mostrar algún texto, puede agregar un nodo de etiqueta a la capa Canvas. Voy a nombrar Mind game y darle un nombre único. Después poblarlo con algo de texto, centrarlo. Dale un tamaño de fuente más grande. Y anclarlo al centro de la pantalla. Antes de desvanecerse a negro, también crearé una preadolescente que desvanecerá el Alpha de la etiqueta hasta uno Modularé su Alfa a cero, lo que es invisible por defecto Sin ninguna espera, esto sucederá al mismo tiempo que la pantalla se va desvaneciendo a negro La etiqueta deberá dibujarse frente al desvanecimiento para que sea visible. Después de reposicionar el personaje del jugador, luego esperaré otro 1 segundo antes de desvanecerme en el texto Pero lo haré más rápido de lo que se desvaneció. Después de revivir al personaje del jugador, mostraré un mensaje diferente medida que el juego se desvanece de nuevo. Duplicaré el juego existente sobre mensaje, nombraré a este revivir y cambiaré el texto. Antes del desvanecimiento para borrar, usaré otra preadolescente para hacer que este texto se desvanezca Espera otro 1 segundo, luego vuelve a desvanecer el texto. Vamos a probarlo. Dejaré que la noche del Ratón mate a mi personaje jugador. Ahora tenemos a nuestros personajes muriendo y el manager del juego reaccionando a la muerte del personaje del jugador, pero nuestro juego aún no tiene un jefe en él. Te veré en el siguiente video. 62. 8-6 Director 1: Hola, amigos. En este video, construiremos un jefe para nuestro juego que sea más complejo que nuestros otros enemigos. Empezaré por crear una nueva carpeta de activos para contener los activos para este jefe. Después importa los sprites. Luego crearé una nueva escena en mi carpeta de escenas enemigas llamada Mac Mouse con un tipo de nodo raíz de CharacterBody dos D. Este jefe está compuesto por múltiples componentes de sprites diferentes que necesitaré ensamblar y superponer uno sobre otro Primero, agregaré una D normal no dos que puedo usar para voltear todos los componentes visuales del jefe cuando se dan vuelta y lo nombran flip Luego agrega múltiples sprites para los diversos componentes. Voy a necesitar un sprite para el blindaje, que será una textura atlas Y después de poblar la textura, seleccionaré la región apropiada de la hoja de sprites Esto se compensará hacia arriba en 48 píxeles. Duplicando este nodo de sprite, cambiaré el nombre de este para que sea engranajes y cambiaré su tipo a Sprite animado dos D. Dando al nodo un recurso de fotogramas Sprite, agregaré los sprites de engranaje a la Después cambia su velocidad de animación a 12 fotogramas por segundo. Esto debería dibujarse detrás del blindaje, así que reordenaré los nodos Duplicando de nuevo el nodo de sprite de blindaje, haré otro sprite para el fondo detrás de los engranajes Después de hacer que la textura del atlas sea única para este nodo, entonces puedo seleccionar una región diferente para dibujar y reordenar este nodo para que se dibuje detrás de los demás Este fondo también está destinado a sujetar los engranajes para que no se dibuje nada fuera del cuerpo. Podemos hacer esto poniendo los engranajes como un hijo del nodo de fondo. Después, seleccionando el fondo debajo de la sección de visibilidad, cambie los niños del clip de deshabilitados a recortar y dibujar. Ahora los engranajes solo dibujan dentro del cuerpo. También hay una llave de viento que está animada. Entonces duplicaré mi nodo de engranajes para hacer otro nodo de tout de Sprite animado y nombrarlo clave. Después de hacer que el recurso de marcos Sprite sea único para este nodo, reemplazaré los marcos de Sprite de engranaje con los marcos clave de sprite Después volveré a colocar la llave para estar en la posición apropiada en la parte posterior del cuerpo del ratón Mc Voy a necesitar más Sprite Animado dos nodos D para las ruedas, así duplicaré la clave para hacer una rueda animada Después de hacer que el recurso de marcos Sprite sea único, cambiaré los marcos clave de Sprite para los marcos de sprite de rueda Después coloca la rueda en una buena posición y desplázala hacia arriba para estar en el suelo. O. Para dibujar las ruedas detrás del cuerpo, reordenaré para que estén por encima del cuerpo en el árbol de escena Duplicaré la rueda delantera para hacer una segunda rueda y reposicionarla. El último componente visual de este jefe es un barril que se extiende desde su boca, que solo será un sprite ordinario Después de asignar la textura del sprite, moveré para que esté alrededor boca del ratón Mc y la colocaré detrás de los sprites del cuerpo I Cuando este barril dispara proyectiles, quiero que esté sobresaliendo de la boca del ratón Mc, por lo que tendrá un desplazamiento de 16 píxeles negativos Voy a añadir un área nodo Tutti en esta posición, que será el proyectil Entonces dale un nodo Tutti Sprite Animated con el recurso Sprite frames y agrega los dos fotogramas de sprite de bola de fuego Después de establecer la velocidad de fotogramas, también tendré esta reproducción automática por defecto. Esto necesitará una forma de colisión, que solo será un círculo. Para funcionar como proyectil, necesitará el guión del proyectil adjunto El guión del proyectil espera que el proyectil tenga una animación de impacto, así que agregaré uno usando los mismos sprites de impacto que mi Esto tendrá que estar monitoreando y enmascarando la capa de Hurt Box del jugador. Podemos conectar el área ingresada y las señales de entrada del cuerpo al guión del proyectil para activar la animación de impacto y el daño. O. Con la bola de fuego ensamblada, podemos guardarla como escena propia en la carpeta del proyectil. Voy a añadir un marcador de nodo Toti como hijo de la bola de fuego para que actúe como la ubicación donde van a generar los proyectiles, al igual que hicimos Después reordene el nodo marcador Tutti para que sea hermano de la bola de fuego, manteniendo su posición relativa y eliminar la bola manteniendo su posición relativa y Luego reinicie el desplazamiento de barriles a su posición predeterminada. Además de voltear el cuerpo a izquierda y derecha, también quiero que el cuerpo del mouse Mc rumble pero no las ruedas Entonces voy a poner todo lo que quiero retumbar como hijos de otro no dos D llamado cuerpo Cada vez que el ratón Mc se mueve, quiero que el polvo y las rocas sean levantadas del suelo por las ruedas. Entonces voy a añadir una partícula GP dos nodo D para las rocas. Luego asigne un sprite de roca como textura y haz un material de proceso de partículas Bien. Hacer que las rocas pateen desde el suelo, todo lo que realmente necesito hacer es cambiar la dirección de la velocidad hacia arriba y darle a cada roca una velocidad aleatoria 32-64 píxeles por segundo Para el polvo, comenzaré duplicando el emisor de partículas de roca y cambiarle el nombre Luego asigne la misma hoja de sprites de partículas que utilicé para impactos de ataque como la propiedad de textura Dado que se trata de una hoja de sprites que está destinada a ser animada, este nodo necesitará un material de elemento de lienzo con su propiedad de animación de partículas activada con el número correcto de fotogramas Después de hacer que el material del proceso de partículas sea único, mantendré la misma velocidad, pero eliminaré la gravedad y agregaré suficiente amortiguación para contrarrestar la velocidad inicial Debajo de la pantalla, agregaré una velocidad de animación de uno para animar las partículas y una curva Alfa para que se desvanecen con el tiempo Quiero esto dibujado al frente, así que estableceré su propiedad orden en uno. Esto debería ser suficiente, así que duplicaré los dos nodos de partículas y los agregaré a la otra rueda. No quiero que emitan por defecto, así que agruparé los seleccionaré a todos y apagaré sus propiedades emisoras. Al igual que cualquier otro enemigo, este necesitará una forma de colisión para chocar con el medio ambiente además de herir cajas y golpear cajas Como este enemigo tiene una forma más única, usaré un polígono de colisión en lugar de una forma de colisión Al agregar algunos vértices al polígono para obtener la forma general del cuerpo del jefe, tendré que asegurarme de que el polígono de colisión haga contacto con el Tampoco realmente quiero molestarme en voltear este polígono, así que lo haré simétrico. Esto será suficiente para colisiones con el entorno, pero también permitirá que el personaje del jugador se ponga encima del enemigo, Para el Hurt Box, me preocupa un poco menos igualar la forma del enemigo tan de cerca, así que usaré una cápsula ordinaria. Si desea combinar múltiples formas estándar para hacer una caja de daños más compleja, simplemente puede agregar más nodos de forma de colisión. Voy a añadir una segunda cápsula por encima de la primera para cubrir más del cuerpo. Tampoco quiero molestarme en voltear estas cajas Hurt, así que ayuda que sean simétricas El nodo D del área dos emitirá sus señales como si todas las formas se combinaran en una sola forma. Pero ten en cuenta que si las formas están muy separadas, es posible que algo entre en una forma de colisión, luego salga de ella, luego ingrese otra forma de colisión causando múltiples colisiones También agregaré una caja de daño separada para la llave de viento. Darle a esta llave su propia Caja de Hurto significa que no necesita estar conectada a la salud del jefe, sino que puede emitir señales cuando el jugador la ataca Esto solo puede tener una forma simple de colisión circular, pero deberá voltearse Entonces me aseguraré de que la exposición del nodo shape sea lo que está determinando de qué lado está la Caja Hurt Y por último, este enemigo necesita una caja de impacto. Esto se utilizará cuando el mouse Mc cargue hacia adelante. Quiero que esto lastime al personaje del jugador si están delante o encima del jefe. Entonces usaré una cápsula girada 90 grados que se extiende más allá del polígono de colisión del cuerpo frente a él y por encima de él, pero no detrás de él Al seleccionar el nodo raíz del cuerpo del personaje, el enemigo deberá considerarse terreno para que el personaje del jugador pueda pararse sobre él, pero también existir en la capa enemiga y enmascarar solo el terreno. Ninguna de las cajas Hurt o hit boxes necesitará ser monitoreada o monitoreable por defecto Los activaremos a través de guiones o animaciones cuando necesiten activarse. Pero las cajas de daño se pueden configurar la capa de colisión de Caja de daño enemiga, y las cajas de impacto se pueden configurar para enmascarar la capa de colisión de Caja de daño del jugador capa de colisión de Caja de daño para que cuando se enciendan, funcionen. Ahora tenemos un jefe ensamblado para nuestro juego, pero aún no tiene ningún guion que lo controle. Te veré en el siguiente video. 63. 8-7 Jefe 2: Hola, amigos. En este video, le daremos a nuestro jefe algunos comportamientos más complejos que a nuestros enemigos normales. mecánica de progresión real se cubrirá en la siguiente sección. Pero por ahora, ayudará a pensar en cómo debería existir nuestro jefe en relación a su arena. Entonces, pongamos a este jefe enemigo en una arena sencilla con una pared a cada lado. En términos generales, los jefes en Metroidvania atrapan al jugador en una arena, y una vez que el jugador entra, deben derrotar al jefe antes de que se Este es un evento que deberá ser activado por el personaje del jugador entrando en el nodo Área dos D, lo que agregaremos uno a la escena y lo nombraremos Jefe Encuentro. Entonces dale una forma de colisión. Usaré un rectángulo y haré que cubra un área muy grande para que el jugador no pueda sortearlo y hacer que monitoree el cuerpo del personaje del jugador. Esto necesitará un script adjunto, pero lo crearé desde la pestaña del sistema de archivos en una nueva carpeta de scripts enemigos para jefes, que podemos nombrar Boss Encounter, extendiendo el Área dos D. Este script se encargará controlar el flujo general del encuentro con jefes, incluso cuando comienza, cuando termina, y cualquier transición de fase, cosas como tarjetas de título, cambiando la música, etcétera. Tendremos que darle a esto un nombre de clase para que podamos extenderlo más tarde. Para reaccionar ante el personaje jugador entrando en este encuentro con jefes, podemos seguir adelante y escribir la función en el cuerpo ingresado, que aceptará un parámetro llamado body de tipo no dos D y no devolverá nada. El personaje jugador entra en este encuentro con jefes, primero, debemos desactivar todas las colisiones futuras con esta área usando set deferred para establecer la propiedad de monitoreo Recuerda que cuando una función es llamada por un evento de colisión, no debemos alterar nuestros objetos de colisión al mismo tiempo, por lo que aplazamos eso hasta después de que se hayan manejado las colisiones Entonces podemos cerrar la arena, atrapando al jugador dentro y realizar cualquier inicialización requerida Pero llegaremos a eso más tarde. Por ahora, declararemos una variable exportada que tiene al enemigo jefe como objetivo al enemigo jefe y otra para el personaje del jugador. Cuando el personaje jugador entra en el encuentro con el jefe, podemos establecer el valor de target para que sea el cuerpo, así como una variable de fase local como un entero. Luego agrega una función de inicio, una función de fin, y también una función de transición de fase, aceptando la fase como parámetro y actualizando la variable a su nuevo valor. En la función de inicio, podemos establecer fase a uno y llamar a nuestra función de toma de decisiones para iniciar la pelea. También necesitaremos una función que le diga al jefe qué hacer a continuación. Por ahora, llamaré a la función Inicio cuando el personaje del jugador entre a la arena jefe. Asegúrese de guardar este script para que el nombre de la clase esté registrado. Ahora que tenemos la estructura básica en su lugar, adjuntemos un nuevo script a nuestro nodo de encuentro con jefes. Voy a nombrar esto después de mi jefe, Neck mouse encounter extend boss encounter and save it in the appropriate folder. Con el guión adjunto, podemos asignar al enemigo jefe a la variable exportada, establecer la máscara de colisión a la capa del personaje del jugador y conectar la señal ingresada al cuerpo. Dado que la función on body entering ya existe en la superclase de encuentro con jefes, no necesitamos preocuparnos por ello en este guión Sin embargo, anularemos la función de toma de decisiones y le daremos a este encuentro con jefes en particular su propio algoritmo para decidir qué hará a continuación. Estructurar el encuentro con el jefe de esta manera facilita alterar el comportamiento de un jefe en función de qué fase se encuentra actualmente o agregar peligros ambientales a la arena en reacción a las acciones del jefe o sincronizar el comportamiento de múltiples jefes en un Cualquier encuentro con nuevos jefes que queramos crear también puede extender la clase de encuentro con jefes y proporcionar sus propias implementaciones únicas para cada jefe específico. Primero, es una buena idea verificar si el jefe está muerto antes de dejar que decida qué hacer a continuación. Entonces, si ya están muertos, entonces sólo podemos regresar. También es una buena idea espaciar las acciones de un jefe con una breve pausa esperando la señal de tiempo de espera de un temporizador Podemos hacerlo menos predecible aleatorizando la duración del temporizador e incluso hacer que la cadencia de la pelea aumente con cada fase dividiendo por el número de fase Y no importa lo que decida hacer el jefe, probablemente deberían enfrentar hacia el objetivo. Entonces podemos llamar a una función para decirle al jefe que mire a la izquierda si la exposición global del objetivo es menor que la suya Usando una declaración de coincidencia en la variable de fase, podemos proporcionar fácilmente diferentes opciones de acción para diferentes fases. Como mi jefe es tan sencillo, optaré por aumentar la intensidad de las acciones por fase en lugar de introducir otras nuevas. Con otra declaración de coincidencia en un entero aleatorio 0-1, voy a crear una oportunidad par para decidir entre dos acciones diferentes O el jefe se moverá a una posición aleatoria en la arena, que será la posición global de este nodo de encuentro con jefes más un número aleatorio entre 300 negativo y 300 positivo, o bien el jefe disparará bolas de fuego al jugador Aleatorizaré el número de bolas de fuego en función de la También quiero que el jefe tenga una tercera acción, que es cargar al personaje del jugador a mayor velocidad, pero sólo bajo ciertas condiciones. Entonces, si el mouse Mc está listo para cargarse, entonces se cargará. Si no se cobra, entonces la acción será aleatorizada. Y le voy a dar la señal de la posición global del objetivo menos la posición global del Mc Mouse como dirección. Planear qué acciones quieres que use tu jefe y cuándo te da exactamente qué variables y funciones públicas necesitarás escribir en sus guiones. Entonces podemos ver en este guión, el guión de nuestro jefe necesita una variable is dead, una variable lista para cargar, y también funciones de cara izquierda, cargar, mover a la posición y disparar bolas de fuego Esta es una manera fácil de abordar la encapsulación al escribir scripts complejos Podemos escribir primero el script que necesita interactuar con él para que ya sepamos exactamente lo que necesitamos. La encapsulación también nos ayuda a lograr la abstracción, también. Ya que solo nos enfocamos en lo que necesita ser de acceso público, también podemos asumir que todo lo demás debe ser privado. A continuación, adjuntemos un script al nodo raíz de McMus y lo guardemos en la carpeta de scripts enemigos Podemos declarar todas las variables y funciones aceptando los parámetros coincidentes del script Boss encounter. Si declaramos una señal y la nombramos como terminada, entonces podemos emitir esta señal de todas las acciones que fueron seleccionadas de la función de toma de decisiones. Por ahora, vamos a imprimir lo que esperábamos que hiciera el jefe. Primero podemos verificar si este enemigo está muerto, y si es así, emitir la señal terminada inmediato y regresar para que no pase nada. Después espere 1 segundo antes de emitir la señal terminada. Después seleccionando el nodo jefe enemigos en la escena de contenido, que podemos hijo para que el jefe se encuentre si queremos y conectar la señal terminada a la función de toma de decisiones. Ahora, cada vez que este jefe enemigo complete alguna de las acciones, automáticamente decidirá qué hacer a continuación. Esto debería ser suficiente para demostrar el flujo de nuestra batalla de jefes. Entonces probémoslo. Podemos ver por la salida cada segundo o dos, el enemigo está tomando una decisión sobre qué hacer a continuación. Ahora tenemos a nuestro enemigo jefe controlado por un guión de encuentro con jefes, pero aún necesitamos implementar cómo funciona todo internamente dentro de la escena del jefe. Te veré en el siguiente video. 64. 8-8 Jefe 3: Hola, amigos. En este video, voy a repasar cómo escribí las funciones de mi jefe para que puedas comparar mis métodos la forma en que implementaste los tuyos. Primero, adjunté los guiones de Hit box y Hurt Box a los hit boox y Hurt Boxes del jefe respectivamente. Entonces comenzó en los guiones jefe enemigo. Declaré señales para cualquier cosa que se usara para iniciar o terminar la pelea de jefes o causar una transición de fase. Otro para cuando el jefe cambia dirección así sé cuándo darle la vuelta a las cosas, y un par más por saber cuándo el jefe ha llegado a su destino previsto o se estrelló contra una pared Luego también está la señal, que se omitirá cuando se complete la acción decidida actual del patrón, y necesita decidir qué hará a continuación Conecté la señal de cambio de dirección a la caja Hit y las llaves enrolladas Hurt Box para que puedan ser volteadas El script de Hurt Box en realidad no tenía esta función, así que lo copié del script de Hit boox No obstante, las llaves de viento Hurt Box está detrás del jefe, así que necesitaba agregar una variable exportada para invertir la dirección para este caso específico. De vuelta al guión de Mac Mouse, necesitaba una referencia al cuerpo del jefe para que retumbara. Entonces esto se almacena en una variable, ya que la estaré usando muy frecuentemente. Y, claro, voy a necesitar saber si el jefe está vivo o muerto. Me gustaría que mi pelea de jefes comenzara con el Mcmuse apagado y que el jugador ataque la llave de viento varias veces para ponerlo en marcha Por lo que declaré una variable para si el motor está actualmente arrancado o no más una velocidad para la llave de viento, arrancándolo a una octava parte de la velocidad normal, y una tween que puedo usar para alterar la velocidad gradualmente con el tiempo Para crear este efecto, tuve la animación wind up keys reproduciendo automáticamente, pero con una escala de velocidad de cero y su caja de daño monitoreable por defecto Luego conecté su señal dañada al guión de mi jefe, llamando a una función llamada en ataque clave. Para asegurar que la caja de daño de la llave nunca muera, llamo su función de recuperación, ya que esto no es un reflejo de la salud del jefe, simplemente otro objetivo para que ataque el personaje del jugador Después de configurar la escala de velocidad de animación de teclas de viento al doble, utilicé la preadolescentes para reducirla gradualmente nuevo a su valor esperado en el transcurso de 1 segundo Si el motor ya se ha arrancado, entonces atacar la tecla de viento hará que el mouse de Mac cargue hacia el personaje del jugador como su siguiente acción. De lo contrario, dupliqué la velocidad de la llave y verifiqué si había alcanzado un valor de al menos uno. Con el valor predeterminado de un octavo, esto sucederá después de la tercera vez que se ataca la llave de viento. Cuando eso sucede, llamé una función para arrancar el motor del mouse Mc. Todo lo que hace esta función es decirle la animación de engranajes que comiencen a reproducirse, comiencen un temporizador de rumble, que se establece en una 12 de segundo, por lo que el motor se arranca variable a true y emita la señal Cada 12 de segundo, cuando el temporizador de estruendo se agota, moví la posición Y del cuerpo a un entero aleatorio entre uno negativo y uno positivo que el cuerpo retumbara hacia arriba y hacia abajo Hacer la cara de jefe izquierda fue muy similar a como se hizo con el personaje jugador con la excepción de que este jefe enemigo se enfrenta a la izquierda por defecto. Para hacer que el jefe conduzca y cargue hacia el personaje del jugador, utilicé muchas de las mismas variables de locomoción en el guión del personaje solo con diferentes nombres, y también incluí el destino del jefe y la distancia a su destino como carrozas, así puedo usarlas para determinar a dónde necesita ir el jefe en el proceso También incluí gravedad por si acaso y establecí la velocidad de movimiento para que fuera la velocidad de conducción por defecto. Guardé las ruedas en una matriz para poder sincronizarlas fácilmente. Si bien esto puede parecer innecesario para solo dos ruedas, escribirlo de esta manera funcionará para cualquier número de ruedas. Usé una variable pública para decir si este mouse Mc ha tenido atacada o no su llave de viento y está listo para realizar un ataque de carga y un entero para contar el número de veces que se han estrellado contra una pared Cuando el script de encuentro con jefe decide que el mouse Mc debe moverse a una posición dentro de la arena de jefe y proporciona la posición a la que moverse como parámetro, verificando rápidamente si el jefe está muerto para que la solicitud pueda ser ignorada, almacené el destino, establecí la dirección de movimiento, la velocidad de movimiento y se está moviendo a true. Llamé a una función privada para animar todas las ruedas, luego esperar mi señal llegada antes de emitir la señal terminada La señal llegada se emitirá desde el proceso de física posteriormente. El argumento pasado a hacer girar las ruedas controla qué tan rápido se animarán, así como si la animación se reproducirá hacia adelante o hacia atrás Entonces, si el mouse del Mac está orientado hacia la izquierda y mueve hacia la izquierda o hacia la derecha y moviéndose a la derecha, voy a reproducir la animación con una velocidad de uno. De lo contrario, una velocidad de negativo reproduce las animaciones al revés. Cargar al personaje del jugador hace casi todas las mismas cosas. No obstante, quiero que el mouse Mc siempre orientado hacia la dirección en la que se está cargando y haga girar las ruedas a doble velocidad. Usando una breve pausa, esto telegrafiará la carga al jugador para que pueda reaccionar y salirse del camino. Dado que la carga es un ataque, el hit box tiene su propiedad de monitoreo establecida en true. Después de que el ajuste se esté cargando a true, espero la señal que se emitirá después de que el Mcmuse se haya estrellado contra una pared y uso otra breve pausa para mantener al jefe aturdido por Recuerda conectar la señal ingresada en el área de cajas de impacto para realmente infligir daño. Girando las ruedas y aceptando la dirección del giro como parámetro, iteré a través de cada una de las ruedas en mi matriz de ruedas y le dije a cada una que reproduzca su animación predeterminada usando el valor absoluto de dirección como velocidad de animación y si la dirección era negativa o no para determinar si la animación debía reproducirse en reversa También inicié los emisores de partículas de roca y polvo unidos a cada rueda al mismo tiempo si el valor de dirección era algo más que cero De lo contrario, se apagarán. Ahora para el proceso de física, que hará posibles ambas acciones, si el jefe ya está muerto, entonces no puede moverse voluntariamente, por lo que su dirección de movimiento se establecerá en cero Luego apliqué aceleración o desaceleración a la velocidad X del jefe, así como la gravedad a su velocidad Y antes llamar a la función de movimiento y deslizamiento para aplicar la velocidad al cuerpo del personaje Si el jefe está manejando actualmente, tendré que verificar si ha llegado a su destino, o si está cargando y actualmente está tocando una pared, entonces sé que se ha estrellado Para saber si el jefe ha llegado a su destino previsto, primero necesito saber la distancia a su destino, que es el valor absoluto del destino menos la exposición global actual del jefe invertir la fórmula de altura de salto, podemos determinar si el jefe está lo suficientemente cerca del destino para comenzar a desacelerar Si la distancia es menor que la velocidad al cuadrado dividida por la desaceleración, dividida por dos Cuando esto es cierto, dejo de hacer girar las ruedas, establecer la dirección de movimiento a cero está conduciendo a falso y emito la señal llegada. Cuando el jefe choca contra una pared, hice la mayoría de las mismas cosas, pero también agregué velocidad lejos de la pared para que reboten de ella. Y apagó la caja de aciertos. También conté el número de veces que esto sucede, y en el tercer choque, dañé el blindaje del ratón Mc por lo que entrarán en la segunda fase. Cuando la armadura se daña por chocar demasiadas veces, aumenté la velocidad de la llave de viento hasta dos Para dañar el blindaje, todo lo que necesitaba hacer era cambiar la región de la hoja de sprites que estaba dibujando el nodo de sprite de armadura También dupliqué la velocidad tanto de la tecla de bobinado como de las animaciones de engranajes, así como del temporizador de rumble para hacer que la escena del jefe sea aún más inestable Y volví verdadera la propiedad monitoreable de la Caja Hurtada para que el personaje del jugador ahora pueda atacar el cuerpo del mouse Mc para hacerle daño Luego emitió la señal para activar la transición de fase. Para disparar las bolas de fuego, necesitaba una escena llena para las bolas de fuego, así como las nuevas bolas de fuego, estaría instanciando el marcador de dónde instanciarlas , más el cañón y una preadolescentes para más el cañón Cuando se le dice al jefe que disparara varias bolas de fuego, primero esperé extender el cañón, luego giré varias veces, haciendo una pausa de cuarto de segundo antes de cada disparo, luego disparando una luego Después de disparar todas las bolas de fuego, esperaba retraer el cañón antes de emitir la antes de emitir la Extender o retraer el barril fue una simple preadolescentes que interpela los barriles compensaron X al número deseado durante un cuarto de segundo Disparar una sola bola de fuego es casi lo mismo que con los proyectiles del personaje del jugador Simplemente agregándolo como un hermano poniéndolo en la posición correcta y disparando en la dirección orientada hacia adelante En mi guión de proyectil, al decirle a una Caja Hurtada que reciba daño, también necesitaré proporcionar la dirección del daño. Por último, cuando el jefe se queda sin salud, uso set deferred para apagar el hit box y ambos cuadros Hurt y detener todas las animaciones antes de emitir la señal teñida para terminar el encuentro con el jefe En la escena del contenido de la sala, conecté la señal de arranque del motor al jefe encuentra la función de arranque y la señal de muerto para terminar el encuentro dos. También conecté la señal dañada de armadura a la función set phase, vinculando dos como argumento para desencadenar la transición a la fase dos. Comenté la llamada a la función de arranque para poder activar el arranque de la batalla para que ocurra después de arrancar el motor. Sí. Oh. Ahora tenemos a nuestro jefe realizando una compleja secuencia de acciones con intensidad creciente en múltiples fases Pero nuestro juego carece de algún tipo de progresión significativa. Te veré en la siguiente sección. 65. 9-1 Punto de ahorro: Hola, amigos. En esta sección, convertiremos esta plataforma dos D en una Metroidvania siguiendo correctamente el progreso del jugador Empezaremos añadiendo un punto de guardado a nuestro juego. He trasladado mi encuentro con el jefe su propia habitación y lo moví al lado de mi mapa en una región volcánica separada y también hice un nuevo espacio guardado para mi región forestal a la izquierda. Dejé a mi personaje jugador aquí arriba. Yo sólo restableceré su posición de nuevo al origen. Comencemos en los jugadores guardar datos donde necesitaremos almacenar la ubicación donde el jugador guardó su juego por última vez. forma en que almacenas esta información variará en función de la estructura de tu juego. Pero para mi juego, usaré una matriz de cuerdas. Si bien podría ser más eficiente almacenar puntos de guardado como números, esta es solo una variable única, por lo que el impacto será insignificante También ayuda a mantener el archivo guardado legible por humanos para fines de depuración El primer elemento de la matriz será el nombre de la región, y el segundo será el nombre de la habitación. Este patrón sigue la estructura de mi árbol de escena. Cuando cargo los jugadores guardan datos, todo lo que tengo que hacer es encontrar la región que coincida con la primera cuerda, luego buscar la habitación que coincida con la segunda cuerda y colocar al personaje del jugador en el punto de guardado de esa sala. Tenga en cuenta que este punto de guardado debe existir en el juego en el momento en que se cargan los datos guardados y aún no se ha cargado el contenido de la habitación. Por lo tanto, el objeto Guardar punto debe estar en la escena de la habitación en lugar de en la escena del contenido de las habitaciones. Voy a añadir un nodo dos D a mi escena de guardar habitación y nombrarlo savepoint Para que las cosas sean simples, colocaré este nodo para que esté en la posición en la que quiero engendrar al personaje Ya que necesitaremos tener múltiples de estos puntos de guardado en nuestro juego, éste debería guardarse como su propia escena. Entonces podemos editarlo de forma aislada. La forma en que quieras activar tu punto de guardado depende de ti. Solo usaré un simple evento de colisión. Entonces, cada vez que el jugador toque un punto de guardado, su progreso se guardará. Entonces agregaré un nodo D de área dos a la escena y lo desplazaré del suelo 96 píxeles para que el jugador tenga que saltar para tocarlo. He importado algunos activos para mi punto de guardado, que es un libro y también un sprite de efecto que dibujaré detrás del libro para que brille Voy a añadir un Sprite dos D no al nodo de área para dibujar primero el resplandor Después agrega un Sprite Animado dos D para el libro. Dale un recurso de marcos de Sprite y llénalo con los sprites del libro Reproduciendo la animación hacia adelante y luego nuevamente hacia atrás. El área necesita una forma de colisión, así que le daré un círculo y usaré el radio del resplandor, que es de 32 píxeles. Dado que esto está en la escena de la habitación, no en la escena del contenido de la habitación, deberá ordenarse frente al contenido de la habitación. Tendrá que vigilar el cuerpo del personaje del jugador. A adjuntando un guión al punto de guardado, entonces podemos conectar la señal ingresada en el cuerpo del área al guión. Cuando el personaje jugador toca el punto de guardado, estableceremos el valor de last saved at en sus datos de guardado para que sea una nueva matriz con el primer elemento de la matriz siendo el nombre de la región y el segundo elemento, el nombre de la sala. Podemos automatizar estos nombres usando la etiqueta on ready, ya que el padre del punto de guardado siempre será la habitación en la que se encuentre, y el padre de la habitación siempre será la región. La naturaleza del árbol de escena que requiere que los hermanos tengan nombres únicos asegurará que esto sea suficiente para determinar exactamente en qué habitación guardaron por última vez. También podemos tomar una referencia al nodo Animated Sprite two D y decirle que reproduzca su animación cuando esto suceda No olvides decirle al nodo global de archivos que guarde el juego cada vez que quieras hacer algo permanente. Cambiando al guión del administrador del juego, tendremos que cargar la última posición guardada del jugador. Después de que se haya realizado toda la inicialización, llamaremos a una función para posicionar al personaje del jugador Si los datos guardados del jugador tienen un valor para el último guardado en, entonces podemos obtener la región por su nombre ya que sabemos que es un hijo del nodo mundial. Y luego hacer lo mismo para recuperar la habitación, sabiendo que la habitación es un niño de la región. Luego podemos posicionar al personaje del jugador en la posición global del punto de guardado en esa sala. Esto provocará que el jugador entre a esa sala, cargue su contenido y se desvanezca como esperamos. Si el jugador aún no ha llegado a un punto seguro, los pondré en el origen para iniciar el juego. Un problema surge cuando el jugador muere, sin embargo, ya que también vamos a querer poner al personaje del jugador en la última posición guardada en ese momento. Tanto la secuencia de eventos de muerte como el jugador que entra en una habitación estarán manipulando el desvanecimiento al mismo tiempo Hay múltiples formas de resolver este problema, pero para mantener las cosas simples, voy a comprobar si el personaje del jugador es vestuarios cuando muere. Si mueren y reaparecen en la misma habitación, entonces el jugador que ingresó a la habitación no se activará, por lo que la secuencia de muerte puede manejar el De lo contrario, lo reemplazaré con una simple pausa por 1 segundo. Para saber si reposicionar el personaje jugador ha cambiado de habitación, haré que esa función devuelva un booleano Y regresa si la nueva habitación es la misma que la habitación actual o falsa por defecto. Et lo prueban. Cuando cargo mi juego por primera vez, mi personaje comienza en la posición predeterminada en mi sala de inicio. Si voy por la izquierda, encontraré el punto de guardado. Saltar a los gatillos del punto de guardado salvando mi juego. Si cierro el juego y vuelvo a jugar, ahora mi personaje jugador empieza en el punto de guardado. Para que mi punto de guardado sea un poco más mágico, haré que flote arriba y abajo. Exportaré un par de variables para el rango de oscilación y velocidad con un valor predeterminado de 16 píxeles y una oscilación por segundo Lo que se va a mover es el nodo de área, que también moverá los sprites como son hijos Voy a necesitar saber su posición inicial Y y cuánto tiempo ha pasado. Anulando la función de proceso, configuraré T para que sea él mismo más Delta multiplicado por la velocidad de oscilación envuelta entre cero y tau Esto permitirá que la oscilación se repita infinitamente sin llegar nunca al máximo de un número de punto flotante La posición Y del área puede entonces establecerse su posición inicial más seno de T multiplicado por el rango de oscilación Para dibujar el punto de guardado en el mapa, simplemente podemos agregar un Sprite dos D a la escena del punto de guardado y darle la textura que queremos dibujar Escalarlo realmente grande para que sea visible para la cámara del mapa, luego escóndalo para que no esté en el camino y adjunte el script del icono del mapa. Tendrá que estar en la capa de visibilidad dos, no en la capa uno, y todos sus antepasados en el árbol de escenas deben ser visibles tanto en la capa uno como en la capa dos. También quiero probar el problema de la muerte, así que agregaré una función de entrada simple al guión de mi personaje de jugador. Entonces cuando presiono la barra espaciadora, el personaje muere. Ahora cuando ejecuto el juego, el punto de guardado está flotando arriba y abajo, y lo puedo ver en el mapa. Cuando presiono la barra espaciadora, el personaje muere y responde en el punto de guardado. Si me mudo a otra habitación, puedo hacerlo de nuevo y responder una vez más en el punto de guardado. Ahora tenemos un punto de guardado que recordará la última posición guardada del jugador y la cargará en la ubicación correcta. En el siguiente video, agregaremos la habilidad desbloquear elementos que definen una Metroidvania Te veré en el siguiente video. 66. 9-2 Metroidvania: Hola, amigos. En este video, agregaremos elementos para que el jugador los recoja que desbloquearán sus habilidades Metroidvania Comenzaré creando una nueva carpeta de escenas llamada Upgrade. Luego duplique mi escena de punto guardado, asígnale el nombre Gem y póngala en la nueva carpeta Upgrade. Después ábrelo para editarlo. A diferencia del punto de guardado, no quiero que esto se dibuje en mi mapa, así que eliminaré el icono del mapa. No hay necesidad de que esto se desvíe de su origen, así que restableceré la posición de los nodos de área. Después hacer el área dos nodo D, el nodo raíz, renombrarlo GEM y eliminar el antiguo nodo Save Point dos D. Voy a sustituir el libro Sprite frames por otros nuevos dibujando una gema giratoria Luego tener esta animación reproducción automática y bucle a 12 fotogramas por segundo Luego podemos adjuntar un nuevo script para nuestras actualizaciones. Reconectando el Área dos nodos D cuerpo señal ingresada al guión, podremos desbloquear los personajes del jugador nueva habilidad cuando toquen esta actualización Para ello, exportaremos una variable de tipo Enums dot abilities, haciendo referencia al script Enums que Esto crea un conveniente menú desplegable en el inspector que nos permitirá seleccionar una de nuestras habilidades para que se desbloquee este elemento de actualización. Pero recuerda que una enumeración es solo un entero con un nombre En mi juego, la gema desbloqueará la capacidad del personaje jugador para disparar proyectiles De vuelta en el guión, cuando el cuerpo del personaje jugador entra en esta área, podemos establecer el valor del archivo dot data dot Habilidades desbloqueadas indexadas a la habilidad a true Después guarda el juego para que esta actualización sea permanente. Para que esto se sienta más impactante, probablemente querremos hacer muchas cosas elegantes antes y después de esto, luego eventualmente eliminar este nodo cuando hayamos terminado Podemos asegurarnos de que solo ocurra un solo evento de colisión con este nodo usando set deferred para desactivar su propiedad de monitoreo después de la primera colisión En mi escena de contenido de guardar habitaciones, pondré esto en alguna parte para que pueda probarlo. A sin embargo, quería flotar arriba y abajo como lo hace el punto guardado. En lugar de copiar y pegar al código de un script a otro, deberíamos convertirlo en un componente que se pueda adjuntar a cualquier nodo dos D, igual que los scripts de comportamiento enemigo. De vuelta en la escena de gemas, agregaré solo un nodo normal y lo nombraré float. A continuación, copie y pegue en el código desde el script de punto guardado en este script. En lugar de un tote de área, este solo será el padre del nodo flotante, aunque debe ser un no tutti o algún antepasado de un no tutti para tener Luego podemos copiar este nodo en la escena Save Point y eliminar el código del script Save Point. Estos tres scripts son mucho más reutilizables cuando se escriben para que solo sirvan para un solo propósito, además de ser más fáciles de entender y depurar. Otra cosa que debemos hacer es no tener aquí este ítem de mejora B si el jugador ya ha desbloqueado esta habilidad. Anulando la función ready, verificaremos el valor de las habilidades desbloqueadas en los datos de guardado de los jugadores para ver si esta habilidad ya está desbloqueada y pondremos en cola este nodo para ser liberado si tiene . Ahora vamos a probarlo. Cuando ejecuto el juego, puedo ver mi elemento de actualización flotando allí. Presionar el botón para disparar proyectiles no funciona ya que aún no he desbloqueado esta habilidad Al saltar para agarrar el objeto de actualización, desaparece y ahora puedo disparar proyectiles Cerrando el juego y luego jugando de nuevo, el elemento de actualización no está ahí ya que ya lo he recogido, y aún puedo disparar proyectiles porque la habilidad estaba permanentemente desbloqueada Ahora queremos que coleccionar este artículo se sienta mucho más impactante para el jugador Para probar esto, tendremos que eliminar nuestros datos guardados. En el menú del proyecto, seleccione Abrir carpeta de datos de usuario para abrir esta carpeta en su administrador de archivos, donde podemos ver guardar los puntos, y podemos eliminarlo. Ahora cuando ejecutamos el juego, el jugador no tiene la última posición guardada y no tiene habilidades desbloqueadas. Solo volveré a la sala de guardado y golpearé mi Save Point, luego cerraré el juego. Si quieres intentar hacer la secuencia de eventos para recolectar el ítem por ti mismo, probablemente quieras agregar efectos de partículas u otros nodos para lograr tu resultado. Pausa el video aquí, y luego repasaremos lo que hice. Después de implementar mi secuencia de eventos, es como se ven mis resultados. Primero, declaré un color constante blanco brillante. Esto no es solo blanco sino que tiene una intensidad máxima, lo que significa que hará otros colores cercanos al blanco, también. Cuando el personaje del jugador toca el ítem, detengo inmediatamente la flotación hacia arriba y hacia abajo y congelo al personaje del jugador deshabilitando el procesamiento Entonces comencé un emisor de partículas que emitía las partículas de alrededor del artículo moviéndose hacia adentro Luego, preteje el elemento a la posición del personaje del jugador más a mitad de camino para estar alrededor del centro de su cuerpo mientras también se interpelan los colores tanto del elemento como del personaje a blanco brillante la posición del personaje del jugador más a mitad de camino para estar alrededor del centro de su cuerpo mientras también se interpelan los colores tanto del elemento como del personaje a Agregar paralelo a una función de preadolescentes significa que todas estas sucederán al mismo tiempo en lugar de esperar a que una termine antes de comenzar la siguiente Después desbloqueo la habilidad y guardo el juego igual que antes. Y después de desbloquear la habilidad, oculta todos los elementos visuales, detiene las partículas interiores, inicia una ráfaga de partículas hacia afuera y actualiza el sprite del personaje para incluir el nuevo elemento Después de volver a ajustar el color del personaje del jugador al blanco normal, luego vuelvo a activar el procesamiento del personaje del jugador y elimino este elemento del árbol de escenas Las partículas interiores están reutilizando los mismos sprites de las partículas de polvo del jefe. Están emitiendo desde una esfera con un radio de 32 píxeles. Las partículas tienen una velocidad radial negativa para atraerlas hacia el punto central, sin gravedad. Alfa curvo 1-0 y animado. Las partículas de explosión hacia afuera son en su mayoría las mismas excepto que es una explosión de un solo disparo con explosividad Emitiendo desde un punto con máxima dispersión y suficiente amortiguación para cancelar la velocidad inicial. Ahora tenemos objetos coleccionables en nuestro juego que le darán al jugador nuevas formas de explorar el mundo Pero nuestro juego sería mucho más divertido explorar si tuviera atajos. Te veré en el siguiente video. Y 67. 9-3 Atajo: Amigos. En este video, agregaremos un atajo que el jugador puede desbloquear para que la exploración de nuestro juego sea más fluida y gratificante. Voy a usar la segunda habitación a la derecha de mi sala de inicio para construir mi atajo en la escena de contenido de la segunda sala. He dividido la sala en dos mitades distintas, y colocaré mi atajo en el medio para que el jugador no pueda pasar por esta habitación si entraba por la izquierda. Comenzando con un cuerpo estático para denodar para proporcionar detección de colisiones, y un nodo Sprite Toti para Usaré una textura de atlas y poblaré mi terreno forestal como el atlas, luego usaré las tres baldosas verticales para dibujar un muro Al agregar una forma de colisión como una caja y cubrir la pared con colisión de terreno, el jugador no podrá atravesar. Luego podemos agregar otro nodo Sprite tutti usando una textura de atlas, y ya he importado una nueva hoja de sprite para un Usaré el primer sprite intacto y lo colocaré en el lado derecho de la Entonces, si el jugador entra a esta habitación por el lado derecho, podrá atacar este aparato ortopédico, dañarlo y destruir la pared para abrir el atajo. El aparato ortopédico necesitará un área de caja de daño dos nodos D con una forma de colisión dos nodos D hijo. Usaré otra forma de caja y haré que cubra el sprite. O. Sería una buena idea poner esto en una capa de colisión diferente para que podamos controlar cuidadosamente qué puede dañarla. Usaré la capa dos para mis atajos. No olvides nombrar tus capas de física en la configuración del proyecto para que puedas recordar para qué sirven. Tendremos que tener a nuestros personajes la caja de golpe de ataque masculino enmascarar esta capa para que puedan dañar el corsé. Así como cualquier proyectil que puedan disparar. De vuelta a la escena del contenido de la sala, deberíamos hacer de este atajo su propia escena, ya que probablemente tendremos múltiples de ellos en nuestro juego. Este atajo se realizará específicamente solo para la región forestal. Así que lo guardaré en esa carpeta, y tendré que hacer otras escenas de atajos para mis otras regiones. Al abrir esta escena, podemos adjuntar el script de Hurt Box al nodo Hurt Box y también adjuntar un nuevo script al nodo raíz para el comportamiento de los atajos. El propósito principal de este script será guardar cuando este atajo sea destruido y mantenerlo destruido al cargar el contenido de esta sala. Para hacer eso, usaremos algo comúnmente llamado flag exportando una variable de cadena para el nombre de la bandera. En la escena de contenido de la habitación, necesitaremos especificar un nombre de bandera para este acceso directo. Podemos nombrar a esta bandera lo que queramos, pero debe ser única para cada atajo en nuestro juego. Voy a nombrar al mío Bosque segundo atajo de habitación. Cambiando al script de datos, necesitaremos una nueva variable exportada para mantener nuestras banderas en un diccionario. Usando la cadena como clave y el valor será un booleano De vuelta en el script de acceso directo, cuando se destruye este atajo, podemos establecer el valor de file dot data dot flags siendo la clave nuestro nombre de bandera y establecer el valor en true. Después guarda el juego para que esto sea permanente y después de hacer algunas cosas visuales, quita el atajo del árbol de escenas. Anulando la función ready, podemos verificar el valor de nuestra bandera para ver si el atajo ya ha sido destruido y eliminarlo del árbol de escenas si lo fue Sin embargo, si el atajo aún no ha sido destruido, el diccionario aún no tendrá ningún valor para este nombre de bandera. Así que en realidad necesitamos verificar si el valor existe primero antes de intentar acceder a él. Conectemos la señal de daño recibido de la caja Hurt a la función de destrucción de atajos, desvinculando el argumento Voy a mover la segunda habitación para que esté a la izquierda de la sala de ahorro para poder probarla. Al entrar a esta habitación por la derecha, la pared impide que mi personaje pase por ella. Puedo atacar el aparato ortopédico para destruirlo, lo que destruye el muro, y puedo atravesarlo Cerrando el juego y ejecutándolo de nuevo, el atajo permanece abierto. Sin embargo, hay un pequeño problema. Reorganizaré mis habitaciones para que la segunda habitación esté de vuelta a la derecha, luego eliminaré mi archivo seguro para restaurar el acceso directo Ejecutando el juego otra vez. El muro sí impide que mi personaje proceda. No obstante, todavía puedo romper el atajo abierto desde este lado. Así que tendremos que evitar que nuestro personaje pueda atacar a través de las paredes. Al abrir la escena del personaje, podemos agregar un nodo D cast two al hit box. Usaremos la misma estrategia que usamos para la agresión enemiga para verificar si hay una línea clara desde la caja de impacto hasta la Caja de daño. Para ello, el rayo debería estar originado desde el centro del personaje, y tendremos que enmascarar todo lo que este cuadro de impacto pueda golpear más cualquier cosa que pueda obstruirlo como terreno, incluyendo tanto cuerpos como áreas El rayo también puede originarse dentro de algunos de estos colisionadores, por lo que también necesitará poder golpear áreas y cuerpos desde el interior de sus formas. En el script Hit box, podemos tomar una referencia a este nodo de reparto con una etiqueta on ready, pero voy a cambiar la ruta del nodo para usar get node o null. De esta manera, no todos los hit box nuestro juego necesitan tener un raycast adjunto Cuando ocurra una colisión, primero verificaremos si el rayo existe, luego le diremos que apunte a la Daño que fue golpeada por la caja de impacto y la obligaremos a actualizarse de inmediato. Si el elenco de rayos está golpeando algo y ese algo es otra cosa que no sea la zona, eso significa que hay algo más en el camino. Regresar evitará que se produzcan los daños. Si ejecutamos el juego ahora, atacar el atajo desde el lado equivocado será bloqueado por el colisionador de muros Si muevo esta habitación hacia el lado izquierdo y entro por la derecha, puedo atacar el corsé y destruir la pared ya que el rayo disparado desde la caja de impactos del personaje no está obstruido Si quieres, puedes hacer una pausa aquí y agregar efectos de partículas, sacudir e incluso requerir múltiples ataques para romper el corsé antes de destruir la pared. Ahora que he agregado mis efectos, es como se ven mis resultados. Después de un ataque, la pared emite partículas de polvo, sacude y el corsé queda visiblemente Después de un segundo ataque, el corsé se rompe en varios pedazos, se retira la pared y se vuelven a emitir las partículas Para lograr este efecto, agregué partículas de GPU al nodo emitiendo las mismas partículas de polvo utilizadas anteriormente, pero esta vez emitiendo desde una forma de caja. Agregué un nodo de escombros como carpeta que contenía tres piezas diferentes como cuerpos rígidos. Y un temporizador de batido que emitirá una señal 12 veces por segundo. Conectando la señal recibida dañada de la caja Hurt a una función recibida dañada, reinicié el emisor de partículas, luego verifiqué si es la primera vez que se Si ya está dañado, apago detección de colisiones en la Caja de Daño y destruí la pared. De lo contrario, establezca el daño en true, actualice el corsé, sprite para dibujar la versión dañada, luego inicia el temporizador de sacudidas y deténgalo 1 segundo después La señal de tiempo de espera del temporizador llama a esta función de sacudida, que solo desplaza la pared píxel en una dirección aleatoria Cuando se destruye el muro, actualicé los datos guardados como antes, pero también dispersé algunos escombros, escondí tanto la pared como el corsé. Después espera a que las partículas terminen antes de retirar toda la escena. Para dispersar los escombros, lo hice visible, luego descongelé todas las piezas y les agregué fuerzas de impulso iguales a sus posiciones relativas al padre Ahora tenemos un atajo que el jugador puede abrir, haciendo que retroceder sea mucho más fácil medida que explora nuestro mundo Pero todo el mapa es claramente visible para que ellos lo vean desde el inicio del juego Te veré en el siguiente video. 68. Mapa de 9-4: Hola, amigos. En este video, ocultaremos nuestro mapa al jugador y solo revelaremos habitaciones a medida que el jugador entre en ellas. Comenzando en nuestro script de guardar datos, podemos usar la misma estrategia que hicimos con el punto de guardado para rastrear qué salas ha ingresado el jugador. Exportaremos una nueva variable llamada map of type dictionary. Las claves de este diccionario serán los nombres de las regiones, y los valores serán otro diccionario. Las claves del segundo diccionario serán los nombres de las habitaciones de esa región, y los valores serán booleanos rastreando si el jugador ha ingresado o no a esa sala Si miramos en alguna de nuestras escenas de habitación, el mapa será dibujado por alguna forma de nodo Tu Di. En mi juego, están siendo dibujados por un nodo de capa de Tile Map. Sea cual sea el nodo, cambiar su visibilidad es bastante trivial Describiremos una referencia a este nodo en nuestro script de sala. Puedes usar la etiqueta ready si el nodo de mapa es uniforme para todas las habitaciones de todo tu proyecto o una etiqueta de exportación si quieres más flexibilidad, pero tendrás que asignarlo manualmente para cada habitación. También necesitaremos cada habitación para saber el nombre de la región en la que se encuentra, que podemos automatizar con una etiqueta lista, obteniendo el nombre del nodo padre de la habitación en el árbol de escenas. Entonces podemos escribir una función para actualizar la visibilidad del mapa en función de si el jugador ha entrado o no a esta sala antes. Comprobando archivo dot data dot Map indexado al nombre de la región nos da otro diccionario para la región, que podemos indexar al nombre de la habitación Esto será un booleano para saber si el jugador ha entrado o no a esta sala previamente Y si es cierto, estableceremos visibilidad de los mapas en true. Sin embargo, al igual que con el diccionario flag, debemos tener cuidado de no intentar acceder a las entradas del diccionario que no existen. Pero esto brinda una oportunidad extra en este caso, ya que podemos utilizar la ausencia de la entrada del diccionario como información adicional. Por ejemplo, podemos verificar si el diccionario de mapas tiene una entrada para esta región. Si no lo hace, eso significa que el jugador nunca ha entrado en esta región antes. De igual manera, si la entrada a la sala no existe, entonces el jugador no tiene conocimiento que esta sala siquiera existe. Primero tendremos que verificar si la entrada de región existe en el diccionario de mapas. Si no es así el jugador no debería poder ver este mapa, y podemos simplemente regresar fuera de esta función. Entonces haz lo mismo con la entrada de habitación en el diccionario de la región. Si la entrada no existe, voy a ocultar el mapa. Sin embargo, si existe, entonces podemos establecer la visibilidad true y verificar el valor del booleano Si el booleano es verdadero, entonces estableceré los mapas modulan Alpha a Pero si es falso, lo configuraré para que sea semitransparente. Esto significa que puedo diferenciar las habitaciones en el mapa que el jugador conoce de las que han ingresado previamente. Alternativamente, es posible que desee usar un nodo diferente para dibujar estos diferentes estados y alternar la visibilidad de cada nodo individual. Podemos inicializar la visibilidad del mapa durante la función ready Podemos escribir otra función para descubrir una habitación y revelar su mapa. Para crear nuestros dos estados de mapa diferentes, podemos aceptar un parámetro booleano para saber si esta habitación está siendo descubierta ingresándola Todo lo que esta función tiene que hacer es establecer el valor del archivo dot data dot Map, indexado en el nombre de la región, indexado en el nombre de la habitación al valor de Introducido Pero si este valor ya existe y se ha establecido en true, no queremos volver a establecerlo en false. Podemos usar la operación lógica o para establecerla en false solo si no es ya cierta. Luego llame a la función Actualizar visibilidad del mapa para comenzar a dibujarlo en consecuencia. Si la región aún no existe en el diccionario de mapas, entonces esta es la primera sala que el jugador ha descubierto en esta región. Esta sería una buena oportunidad para hacer algo interesante, como mostrar una carta de título o jugar una escena de atajo para introducir al jugador a la nueva región. Voy a llamar a una función aún no escrita para la región llamada Discover. Este se encargará de inicializar la entrada del diccionario de mapas para la región Cambiando al guión del manager del juego, cuando el personaje del jugador entra en una nueva habitación, podemos descubrir esa habitación con un argumento de verdad para dibujarla opaca en el mapa. En la escena principal del juego, podemos adjuntar un guión a las regiones de nuestro juego. Al escribir la función de descubrimiento, esto se llamará la primera vez un jugador entra en alguna habitación de esta región. Así podemos comenzar creando la entrada del diccionario de mapas para esta región en el reproductor guardar datos. También aprovecharé esta oportunidad para agregar la región al mapa del jugador llamando a una función de revelar Mapa. Esto simplemente iterará por cada habitación de esta región y la descubrirá, pero con un argumento de falso, por lo que se dibujará semitransparente Este script deberá adjuntarse a todas las regiones. En cada una de las escenas de mi región, también agregaré un nodo de etiqueta para mostrar el nombre de esa región en el mapa. Para que esto sea legible en la cámara de mapas, necesitará tener un tamaño de fuente muy grande. Voy a establecer el tamaño de fuente en 256. Luego establece el color de fuente para que coincida con el color de las habitaciones. Para que destaque más, también agregaré una sombra y un contorno. Tendrá que estar en la capa de visibilidad dos para que la cámara del mapa la vea. Voy a copiar esta nota de etiqueta en mi región volcánica y cambiar su color de texto para que coincida con esa región. Al agregar una capa de lienzo a la escena de la región dos, podemos hacer una carta de título simple para mostrar cuando el jugador ingresa por primera vez a cada región. Con otro nodo de etiqueta, mostraré el nombre de esta región en el centro de la pantalla con un tamaño de fuente grande. Voy a hacer esto invisible por defecto y solo lo mostraré cuando el jugador entre a esta región por primera vez. En el script de región, animaré esta pantalla con una preadolescentes, tweening el Alpha del nodo label hasta uno, esperando 1 segundo, luego tweening de nuevo a cero Se necesitará tener un Alfa de cero para comenzar y hacerse visible. Esto se puede copiar en mis otras regiones y actualizarse con sus nombres. Cuando se descubra la región, guardaré el juego y haré visible la etiqueta del mapa. Esto también deberá inicializarse en la función ready en función de si la entrada de región existe o no en el diccionario Map Ahora que las regiones tienen niños que no son habitaciones, tendré que verificar si los niños son realmente habitaciones antes de llamar a sus funciones de descubrimiento. Vamos a probarlo. Cuando comienza el juego, el jugador ingresa automáticamente a la región del bosque. Por lo que se muestra la tarjeta de título para la región forestal. Se revelan los datos del mapa, pero solo la sala de inicio es opaca ya que esa es la única habitación a la que he ingresado. Al entrar en cada habitación, las habitaciones cambian de transparentes a opacas. He quitado el atajo de la otra habitación para facilitar las cosas. Aún no se ha ingresado a la región volcánica, por lo que no se revela en el mapa. Y cuando entro a la región volcánica, muestra su tarjeta de título y sus habitaciones se agregan al mapa. Aunque todavía no he construido nada apropiado para esta región. Al regresar a la región forestal, la región ya ha sido descubierta, por lo que no muestra su tarjeta de título. Ahora tenemos un sistema para revelar el mapa de nuestro juego gradualmente a medida que el jugador explora nuestro mundo. Pero las regiones de nuestro juego se sentirían mucho más distintas con algo de música de fondo. Te veré en el siguiente video. 69. Música de 9-5: Hola, amigos. En este video, agregaremos algo de música de fondo que cambiará con cada región de nuestro juego. Esto no solo ayudará a enfatizar la apariencia única de cada región, sino que también proporcionará una sensación extra de progresión. Cuando importas música de fondo a tu proyecto de juego, selecciona los archivos en la pestaña Sistema de archivos, luego abre la pestaña Importar y cambia el modo de bucle para reenviar. De lo contrario, tu música sólo se reproducirá una vez y luego se detendrá. Esto requerirá una reimportación de los activos. En cada una de nuestras escenas de la región, podríamos poner un nodo reproductor de flujo de audio para reproducir estas pistas de música. Pero eso requeriría que manejemos cuál está jugando en un momento dado, lo cual es una especie de molestia. Por lo general, no vamos a querer tener más de una pista de música de fondo sonando a la vez de todos modos. Por lo que sería más fácil tener un solo nodo reproductor de flujo de audio dedicado a reproducir música de fondo al que podamos acceder desde cualquier lugar de nuestro juego. Pero cada región aún necesita saber qué música de fondo se debe tocar para ello. En nuestro script de región, podemos exportar una variable para contener la música de fondo para esta región como una transmisión de audio. Después, poblar la variable exportada para cada región en sus escenas individuales con diferentes archivos de música Luego podemos crear un script global para administrar nuestra música de fondo, heredando de Audio Stream Player Luego abra la configuración del proyecto, la pestaña Globales y agregue este script a la lista de nodos globales Volviendo al guión, realmente solo necesitamos dos funciones públicas, una que le diga al guión que reproduzca una pista de música y acepte la transmisión de audio como parámetro, y otra para dejar de reproducir música. Pero detener la música de repente sería un poco discortante. Es bastante común desvanecer la música al reducir su volumen gradualmente antes de detenerse. Comenzando con la función de reproducción de pista, podemos establecer la transmisión que se está reproduciendo al parámetro de pista y llamar la función de reproducción de reproductores de flujo de audio para comenzar a reproducirla. Pero si algo ya está jugando, tenemos que detenerlo primero. Entonces, si este guión ya está reproduciendo algo y lo que está reproduciendo es lo mismo que lo que queremos tocar, podemos simplemente regresar. Si no es lo mismo, entonces podemos esperar a desvanecerse al volumen primero, y después de eso, podemos cambiar a la nueva pista y volver a desvanecerse Para desvanecer el volumen gradualmente, necesitaremos una tween y una función para tweening el volumen, aceptando el valor final para el volumen como parámetro Después de verificar si la preadolescente ya existe y matarla, crearemos una nueva preadolescente y el volumen hasta su valor final durante Solo usaré 1 segundo. El volumen generalmente se mide en decibelios, que no es una unidad de medida lineal Por lo que no se recomienda ajustar el volumen en decibelios. En su lugar, usamos el valor de volumen lineal, que es un flotador simple que va desde cero para el silencio hasta uno para el volumen normal. Podemos devolver la señal de tween terminada para que podamos esperarla. Para dejar de reproducir música, solo tenemos que esperar a que el volumen llegue a cero, luego llamar a stop y devolver la señal terminada. Y después de cambiar de pista, deberíamos volver a desvanecer el volumen a uno para que podamos escuchar la nueva música. Ahora solo tenemos que decirle a este nodo qué pista de música reproducir y cuándo. Por simplicidad, asumiré que cuando se carguen los contenidos de una habitación, quiero reproducir la música que está asociada a esa región. Así que llamando a la música play Track, voy a pasar por la región, que es el padre de la habitación punto Música. Si se le dice que reproduzca la misma música que ya se está reproduciendo, el nodo global de música simplemente ignorará la solicitud. Entonces no hay necesidad de revisar lo que ya se está reproduciendo. Vamos a probarlo. Ejecutando el juego, empiezo en la región forestal, y así suena el tema de la música forestal. Vestuarios, la música no cambia mientras yo siga en la región forestal. Pero si hago la transición a la región volcánica, el tema de la región forestal se desvanece y el tema de la región volcánica juega en su lugar Probablemente habrá momentos en los que quieras tocar temporalmente una pista de música específica, como durante una escena de corte o una pelea de jefes. Así que agreguemos dos funciones más a nuestro guión musical. Uno para anular la pista de música actual y otro para volver a la pista de música anterior Necesitaremos una variable para mantener la música de fondo de la región actual. Cuando se nos dice que anulemos la música de fondo con una nueva pista de música, primero almacenaremos la música de fondo de la región en nuestra variable. Entonces espera el fade out y toca nuestro nuevo tema. Después de que el evento haya terminado, podemos volver a música de fondo de nuestra Región desvaneciéndonos luego tocando la vieja pista de música En nuestro guión de encuentro con jefes, podemos exportar una variable para contener una pista de música especial para nuestra música de jefe. Entonces en el encuentro con el jefe de Mc Mouse, podemos darle a esta pelea de jefes su propia pista musical especial. Se le puede decir al nodo global de música que reproduzca esta música cuando comience el encuentro con el jefe. Y vuelve a la música de fondo de la región cuando termina la pelea Y por último, a este nodo de música se le debe decir a qué bus pertenece en el Audio Bus para que podamos controlar su volumen en otras configuraciones más fácilmente. Así que anulando la función ready, podemos establecer manualmente el valor del bus para que sea música Ahora tenemos un sistema de música global que podemos usar para reproducir cualquier música que necesitemos para nuestro juego, pero nuestro encuentro con el jefe todavía necesita algo de trabajo. Te veré en el siguiente video. 70. Jefe final de 9 a 6: Hola, amigos. En este video, completaremos el encuentro con el jefe con una arena y impediremos que el jefe reaparezca una vez que sea derrotado He reorganizado mis habitaciones para que el jugador comience en la sala de guardado justo al lado de la sala de jefes Al abrir el contenido de las salas de jefe, he seguido adelante y construí la escena de contenido de la sala Boss con múltiples capas de Parallax Para que el nodo D de la capa dos de Tile Map pudiera desplazarse por Parallax, tuve que crear un nuevo script heredando de capa Tile Map sin el desplazamiento automático Dado que el nodo D de capa dos de Tile Map no tiene la propiedad region destrozada, no puede usar el mismo método si quisiéramos que se desplazara automáticamente Cada una de las capas de Tile Map a Di nodos tienen una escala de desplazamiento diferente y modulan más hacia el color de fondo Para hacer un seguimiento de qué jefes ha derrotado el jugador, abramos el script de datos y agreguemos una nueva variable llamada Boss is derrotado Una alternativa al uso de un diccionario es una matriz. Cada vez que un jefe es derrotado, podemos simplemente agregar su nombre a esta matriz En el guión de encuentro con jefes, podemos anular la función ready para verificar si este jefe ya ha sido derrotado. Si file dot data dot boss es derrotado tiene una entrada que coincide con el nombre del jefe, entonces el jugador ya ha derrotado este jefe y podemos eliminar este encuentro de jefe. Cuando el jefe es derrotado, podemos agregar el nombre del jefe a la serie de jefes Después guarda el juego para que sea permanente. A diferencia de los diccionarios, las matrices pueden tener duplicados. Entonces, cuando estés almacenando información de esta manera, es posible que quieras verificar si la entrada ya existe antes de agregarla. Quitar el nodo de encuentro de jefe del árbol de escenas en este momento también eliminará al jefe en sí, lo que no quiero hacer. Pero si el jugador saliera de la habitación y volviera a entrar, el jefe será removido por la función listo. Esto será suficiente para que el jefe se quede derrotado, pero el encuentro en sí podría usar algunas mejoras. Lo primero que quiero hacer cuando comience la batalla de jefes es cerrar una puerta bloqueando al jugador dentro de la arena. Al igual que con el atajo, utilicé un cuerpo estático para de nodo, reutilizando el mismo sprite de pared que el terreno Y una forma de colisión rectangular. Sin embargo, el sprite y la forma de colisión se colocan muy por encima del punto de origen de la puerta, lo que la puerta está abierta por defecto Cuando se le dice que se cierre, la puerta reposiciona la forma de colisión, luego preajusta la posición de los sprites para que coincida, y al abrir la puerta se devuelve la forma de colisión y el sprite a sus posiciones originales Dando a esta puerta un nombre único, podemos cerrarla en el guión de encuentro del jefe cuando comience la batalla y abrirla cuando termine la batalla Recuerda llamar a las funciones de superclase para hacer también todo lo demás en las funciones de inicio y fin, también. También quiero hacer que el jefe luche más duro al dejar caer rocas llameantes desde el techo Entonces he hecho otra escena para los cantos rodados llameantes, que son un cuerpo rígido dos nodos D. Esto simplemente manejará automáticamente la gravedad por mí. Están siendo dibujados y animados por un Sprite Animado dos nodos D, bucle a través de los sprites importados a 12 fotogramas por segundo automáticamente El cuerpo rígido está en una nueva capa de colisión apartada específicamente para peligros y no está enmascarando nada. Por lo que no chocarán con nada, incluido el terreno Simplemente caerán desde arriba de la arena hasta debajo de la arena, y hay un hit box adjunto, monitoreando la Caja Hurtada del personaje del jugador. No olvides conectarte a la señal ingresada por el área para infligir daño. En mi script de encuentro con Mc mouse, he exportado una variable para sostener esta roca llameante como una escena repleta, que puedo instanciar como un nuevo cuerpo rígido de roca llameante Cuando me dijeron que engendrara cantos rodados en llamas, hice un bucle varias veces aleatoriamente entre el número de fase y el número de fase por dos para que el número de cantos rodados aumente Instanciar una nueva roca, agregué a la escena y la coloqué encima la arena en una posición aleatoria entre las paredes izquierda y derecha Para que el evento de choque sea aún más impactante, también agregaré un movimiento de cámara. Godot hace que sea bastante fácil acceder a la cámara actual desde cualquier lugar Primero, solo necesitamos llamar a la función Get Viewport, luego llamar a las ventanas gráficas Get camera two D Entonces podemos llamar a nuestra función de sacudir para sacudir la cámara. Le daré una intensidad de dos píxeles por cuarto de segundo. Entonces puedo conectar la señal estrellada del ratón Mc al guión de encuentro para desencadenar el desove de los cantos rodados en llamas en respuesta Dado que los cantos rodados son cuerpos rígidos, caerán naturalmente debido a la gravedad Entonces puedo limpiarlos después de que hayan caído por debajo del fondo de la arena usando un área dos D. Esta área de recolección de basura es solo un área rectangular que cubre el fondo de la arena, lo suficientemente lejos por debajo de que cualquier cosa que ingrese esta área no será visible para la cámara. El nodo de área está monitoreando y enmascarando la capa de peligros. Su señal ingresada en el cuerpo se conecta de nuevo al script del contador del mouse Mc para eliminarlos del árbol de escenas. Con los cambios realizados en el hit box de nuestro personaje, requiriendo que el elenco del hit box al Hurt Box no estuviera obstruido, tuve que reorganizar la tecla del mouse de mi Mac Entonces ahora la Caja Hurtada está determinando la posición y la forma de colisión está en su posición de origen local. Dado que el nodo Área dos D está determinando la posición en sí, el script ya no necesita hacer referencia a la forma de colisión y en su lugar voltea su propia posición en respuesta a que el personaje cambie de dirección Vamos a probarlo. Entraré a mi habitación de jefes y encontraré a mi jefe enemigo ahí sentado. Puedo atacar la llave para darle cuerda y comenzar el encuentro con el jefe. Esto desencadena el inicio de mi pelea de jefes, que cambia la música y cierra la puerta a la arena, atrapándome Mientras lucho contra el jefe, cada vez que choca contra una pared, desencadena un movimiento de cámara y deja caer rocas llameantes desde el techo Si bien no podemos ver qué pasa con los cantos rodados en llamas ya que caen por debajo de la cámara, están siendo limpiados por el área de recolección de basura Cuando el jefe entra en su segunda fase, aumenta el número de cantos rodados llameantes generados, y derrotar al jefe termina el encuentro, cambiando la música de nuevo a la música región volcánica y abriendo la puerta Al salir de la habitación y regresar, el encuentro con el jefe ya no está ahí. Ahora tenemos todo lo que necesitamos para construir un juego completo de Metroidvania En el siguiente video, repasaremos nuestros próximos pasos. Te veré en el siguiente video. 71. 9-7 final: Hola, amigos. Enhorabuena por completar el curso. Ahora tienes todas las herramientas y habilidades necesarias para construir un juego básico de Metroidvania, completo con habilidades desbloqueables que poco le darán al jugador acceso a más del mundo para explorar un mapa que muestre la ubicación actual del jugador y guardar puntos para hacer Todo lo que queda por hacer ahora es repetir muchas de las lecciones que se imparten a lo largo del curso para crear más de él. Más habitaciones, llenando más regiones con más enemigos que luchar y más atajos para desbloquear. Sigue estos pasos para sacar más provecho de este curso y seguir aprendiendo más habilidades que puedes usar para construir tu propio juego Metroidvania Paso uno. Si este es tu primer gran proyecto de juego, deberías poder construir un juego siguiendo esta plantilla con al menos tres regiones diferentes, cada una con múltiples salas que contengan diferentes tipos de enemigos, desafíos de plataformas, y estas regiones deberían sentirse distintas entre sí Siguiendo los principios de diseño de juegos de Metroidvania, tu juego debe demostrar al jugador obstáculos que no puede superar antes de desbloquear la capacidad El camino crítico a través del juego debería requerir retroceder por áreas anteriores y darle al jugador múltiples oportunidades nuevas para explorar con sus nuevas habilidades Intenta hacer un juego que tarde al menos 10 minutos en completarse de principio a fin sin ser demasiado repetitivo Paso dos, después de que hayas terminado con tu juego y quieras más de un desafío, tal vez quieras pensar algo que quieras cambiar. A lo mejor no te gusta la forma en que funciona el salto de pared o quieres agregar fuerza de retroceso al ataque del personaje del jugador Intenta idear una forma de ajustar la mecánica para que funcione de la manera que prefieras y cambiar la forma en que se implementa en el juego. Intenta evitar hacer algo completamente nuevo todavía. Solo concéntrate en hacer ajustes a lo que ya está ahí. Paso tres. Una vez que puedas hacer cambios en la mecánica que ya existe, tu siguiente paso debería ser agregar una nueva mecánica que utilice las herramientas ya proporcionadas. Algunas cosas que quizás quieras agregar al juego pueden ser un objeto coleccionable que aumente la salud máxima del jugador o un nuevo hechizo que cure al personaje del jugador Agregar estas mecánicas al juego no requiere nuevas habilidades, pero requiere que aprendas a integrar múltiples sistemas existentes juntos de una manera nueva. También es posible que desee buscar algunos activos nuevos para usar para sus nuevas mecánicas o intentar crear los suyos propios. Paso cuatro. Ahora que puedes hacer que los mecánicos existentes funcionen de la manera que quieras e integrarlos con nuevos sistemas, es hora de diseñar y construir una nueva mecánica desde cero. Esta podría ser una habilidad de Metroidvania completamente nueva que permite al jugador acceder a más del mundo, agregando NPC para que el jugador hable con un sistema de diálogo, haciendo que los enemigos dejen dinero para que el jugador los recoja y permitiéndoles gastar ese dinero en una tienda para Antes de comenzar, asegúrese tomarse un tiempo para pensar en todos los sistemas existentes que necesitarán comunicarse con el nuevo mecánico. Considera qué partes de tu diseño se deben abstraer o qué se puede heredar de los scripts existentes Paso cinco. Si puedes crear un sistema completamente nuevo e integrarlo con éxito en este juego, entonces deberías estar listo para hacer un nuevo juego desde cero. O encuentra un paquete de activos diferente en línea o crea tus propios activos para usar mientras construyes un juego de Metroidvania completamente nuevo desde cero y completamente de tu Le invitamos a compartir su trabajo en nuestro servidor de discordia mientras continúa aprendiendo y crecer sus habilidades con este proyecto Paso seis. Una vez que tu juego esté listo, puedes compartirlo en plataformas como Ich para obtener comentarios de los jugadores e incluso vender el juego cuando esté completo. Probablemente no ganarás mucho dinero vendiendo juegos en IH, pero los comentarios serán invaluables para mejorar tus habilidades de desarrollo de juegos Si tienes un juego que ha funcionado bien en Ich, entonces podrías intentar venderlo en Steam para llegar a un público mucho mayor. Pero el listón de calidad para que un juego tenga éxito en Steam es mucho mayor. Y necesitarás tener una estrategia de mercado si quieres que tu juego sea notado por los jugadores. Buena suerte al completar tu proyecto. Espero con ansias ver su trabajo.