¡Crea un juego de plataformas de píxeles completo en Godot 4! | Thomas Yanuziello | Skillshare
Buscar

Velocidad de reproducción


1.0x


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

¡Crea un juego de plataformas de píxeles completo en Godot 4!

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.

      Introduccion

      1:23

    • 2.

      0-1 Introducción a la programación

      8:03

    • 3.

      0-2 Constantes y variables

      9:11

    • 4.

      0-3 Declaraciones y condiciones de If

      9:46

    • 5.

      0-4 Bucles y operadores en while

      9:23

    • 6.

      Matrices 0-5 y bucles para

      10:32

    • 7.

      0-6 Stacks y funciones

      10:53

    • 8.

      Partido y vuelta 0-7

      9:34

    • 9.

      0-8 Árbol de escenas y herencia

      10:21

    • 10.

      0-9 Abstracción y encapsulación

      10:41

    • 11.

      Polimorfismo 0-10

      8:01

    • 12.

      Diccionario 0-11

      8:54

    • 13.

      0-12 Debug

      9:08

    • 14.

      Configuración 1-0

      10:21

    • 15.

      1-1 Personaje

      6:44

    • 16.

      1-2 Entradas

      8:58

    • 17.

      1-3 Locomoción

      8:32

    • 18.

      1-4 saltos

      6:45

    • 19.

      1-5 Animación

      5:53

    • 20.

      Máquina de estados 1-6

      6:05

    • 21.

      1-7 efectos

      10:21

    • 22.

      2-1 Tilemap

      6:07

    • 23.

      2-2 Decoraciones

      6:17

    • 24.

      2-3 cámara

      9:04

    • 25.

      2-4 Tubularios

      7:07

    • 26.

      2-5 Fondo

      9:55

    • 27.

      2-6 Agua

      11:16

    • 28.

      2-7 Límites

      9:09

    • 29.

      Datos 3-1

      8:07

    • 30.

      3-2 monedas

      8:57

    • 31.

      Interfaz de usuario 3-3

      9:01

    • 32.

      3-4 vidas

      10:24

    • 33.

      3-5 Pecho

      10:20

    • 34.

      3-6 Cerradura y llave

      10:02

    • 35.

      Mapa 3-7

      10:10

    • 36.

      4-1 Daño

      9:55

    • 37.

      4-2 Reacción

      9:59

    • 38.

      4-3 Recuperación

      9:51

    • 39.

      4-4 Punto de control

      9:30

    • 40.

      4-5 Muerte

      10:05

    • 41.

      4-6 enemigos

      10:27

    • 42.

      Fin del juego 4-7

      13:17

    • 43.

      5-1 Espada

      11:24

    • 44.

      Ataque 5-2

      12:03

    • 45.

      5-3 Ataque aéreo

      9:43

    • 46.

      5-4 Patrulla

      9:28

    • 47.

      5-5 Agresión

      9:45

    • 48.

      5-6 Proyectil

      14:01

    • 49.

      Jefe 5-7

      13:52

    • 50.

      6-1 Pausa

      8:59

    • 51.

      6-2 Título

      9:49

    • 52.

      Selección de nivel 6-3

      9:19

    • 53.

      6-4 Guardar

      8:40

    • 54.

      6-5 Desbloquea

      10:35

    • 55.

      6-6 Música

      9:43

    • 56.

      6-7 Exportación

      7:33

  • --
  • 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.

374

Estudiantes

1

Proyectos

Acerca de esta clase

¡Aprende a construir un juego de plataformas de píxeles completo en Godot 4 siguiendo este curso!  Ya sea que seas nuevo en el desarrollo de juegos, nuevo en el motor Godot o que quieras mejorar tus habilidades con algunos principios de diseño de alto nivel, ¡aprenderás mucho aquí!  El comienzo del curso se centra en cómo escribir scripts y el lenguaje GDScript.  Si ya estás familiarizado con Godot y GDScript, puedes saltarte estas lecciones y saltar directamente a la lección de Configuración.

¡Haz clic en el enlace de mi sitio web en mi perfil para unirte a nuestro servidor de Discord!

Cada sección del curso generalmente se centra en 1 aspecto del juego; personaje, niveles, tesoros, enemigos, etc.  Las secciones se dividen en 7 lecciones en video, cada una enfocada en enseñar 1 característica del motor Godot, 1 script o 1 parte específica del desarrollo de juegos.  Al final de cada sección, tendrás una plantilla para crear los diversos aspectos de tu juego.

Hay una tarea que deberás completar antes de continuar con el resto del curso, repitiendo muchas de las lecciones que se enseñan a lo largo de la sección para implementar más de los activos del juego, al tiempo que proporciona desafíos adicionales para aquellos que quieran probarlos.  Los desafíos son opcionales y no son obligatorios para proceder con las lecciones.

Este curso incluye la escritura de scripts en el lenguaje de programación Godot.  Si es la primera vez que usas scripts, puedes seguirme y te explicaré los elementos individuales a medida que avanzamos.  Para evitar abrumar a los estudiantes nuevos, trataré de no explicar todo a la vez, sino de centrarme en elementos individuales que sean relevantes para cada lección.  Si tienes experiencia con el script en otros idiomas, el script de Godot es extremadamente fácil de aprender y podrás apreciar lo bien que está optimizado para el motor y el desarrollo de juegos en general.

Los recursos utilizados en este curso están disponibles de forma gratuita en itch.io y FreeSound.org.

Conoce a tu profesor(a)

Teacher Profile Image

Thomas Yanuziello

Indie Game Developer

Profesor(a)
Level: Intermediate

Valoración de la clase

¿Se cumplieron las expectativas?
    ¡Superadas!
  • 0%
  • 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. Promo V2: Has empezado a aprender a Dios. Has tomado tutoriales y has hecho proyectos más pequeños, pero estás listo para llevarlo al siguiente nivel y crear un juego completo con nivel profesional, código, estructura y diseño. Este curso te enseñará a construir una plataforma de píxeles completa desde cero y cómo construir un juego escalable con código reutilizable que se pueda aplicar a juegos de otros géneros. Aprenderás a construir un personaje que el jugador pueda controlar y diseñar niveles, rastrear el progreso del jugador a través tu juego y responder en los puntos de control, crear un sistema de combate con enemigos y una pelea de jefes, y aprender principios de diseño escalables para Gadot que puedes aplicar a cualquier proyecto de Gadot Cuando termines, tendrás una plantilla de juego completo que podrás poblar con más niveles, más mecánicas, más elementos y más enemigos Si necesitas ayuda, nuestro servidor de discordia está lleno de otros estudiantes y desarrolladores de juegos que pueden responder cualquier duda que puedas tener Haz clic en el enlace del sitio web y en mi perfil para unirte. Empezaremos con un proyecto en blanco en Godot versión 4.2 y usando activos libres de su punto IO Pero eres bienvenido a seguir tu propio proyecto usando diferentes activos. También se han agregado notas y videos adicionales para actualizar nuevas funciones en la versión 4.3 de Godot Empecemos a construir tu primer juego completo. 2. 0-1 Introducción a la programación: Hola amigos. necesitarás descargar el GDOGameEngine de gdongine.org Si aún no lo has hecho, necesitarás descargar el GDOGameEngine de gdongine.org . El motor es gratuito, pero puedes donar para apoyar el proyecto si quieres. No hay ningún proceso de instalación. Simplemente puede extraer el archivo zipped y abrirlo. Asegúrese de reubicar el ejecutable a una mejor ubicación. La ventana de lanzamiento inicial es una lista de sus proyectos actuales. Pero si aún no tienes ningún proyecto, te pedirá que explores proyectos de demostración. Podemos ignorar esto y simplemente crear nuestro propio nuevo proyecto ya sea haciendo clic en este botón en la lista de proyectos o en el botón Crear en la parte superior de la ventana. Aquí podemos darle un nombre a nuestro proyecto, que normalmente sería el nombre de tu juego. Voy a poner intro a la programación. El proyecto necesita ser almacenado en el disco duro de nuestra computadora, y crearemos una nueva carpeta con el mismo nombre del proyecto. Por defecto, quiere almacenar todo en la carpeta de documentos, pero sería mejor crear una nueva subcarpeta para los proyectos de Godot El renderizador cambia la forma en que se renderizan ciertos dos objetos D y tres D, pero no vamos a dibujar nada, por lo que podemos ignorar estas opciones El renderizador también se puede cambiar más tarde. Y la compatibilidad de control de versiones con Github se incluye por defecto si quieres usarlo para hacer copia de seguridad de tu proyecto o compartirlo con otros. Cuando esté listo para comenzar, haga clic en Crear y editar. La ventana de GDOEditor abrirá nuestro proyecto vacío recién creado El editor se divide en cinco muelles principales. Un adelanto de nuestro juego está en el centro. El dock inferior izquierdo contiene un navegador de archivos que muestra el contenido de la carpeta del proyecto que acabamos de crear. Actualmente sólo contiene el icono de Gadot. El muelle superior izquierdo contiene el árbol de escenas, una lista de todo lo que hay en nuestra escena actual, que actualmente está vacía, por lo que quiere que creemos una raíz para el árbol de escenas. No vamos a estar dibujando nada, así que no necesitamos especificar si esta escena es dos D o tres D o una interfaz de usuario. Así que sólo podemos seleccionar otro nodo. Hay muchos nodos diferentes que podemos crear, pero solo nos interesa aprender a escribir scripts, así que solo usaremos un nodo predeterminado. Podemos renombrar nuestro nuevo nodo haciendo clic sobre él después de haber sido seleccionado o haciendo clic derecho para abrir su menú contextual y seleccionando renombrar. Nombremos a este nodo Lección uno. Al seleccionar cualquier nodo en el árbol de escenas se revelarán sus propiedades en el inspector, que está acoplado al lado derecho de la ventana Podemos ver el nombre del nodo que se selecciona y sus propiedades organizadas en categorías expandibles, pero ninguna de estas propiedades aplicable a lo que estamos haciendo. Antes de hacer otra cosa, debemos guardar nuestra nueva escena, ya sea seleccionando Guardar escena en el menú de escena o usando el atajo Control S o Comando S. Esto abre un cuadro de diálogo donde podemos especificar un nombre para nuestra escena con la TSCNETension, y una carpeta y una Vamos a crear una nueva carpeta para la Lección uno y luego guardar la escena en esta carpeta. Ahora podemos ver en la pestaña del sistema de archivos que nuestra nueva carpeta ha sido creada para la lección uno, y contiene la escena Lesson one, que está marcada con el icono de Clapperboard A continuación, adjuntaremos un script al nodo raíz de nuestra escena, ya sea seleccionando el nodo raíz y haciendo clic en el botón del script adjunto o haciendo clic derecho sobre él y seleccionando el script adjunto. El lenguaje es GD Script, que es el lenguaje de programación que vamos a estar aprendiendo Cada script heredará del tipo de nodo al que está asociado por defecto Dado que el nodo raíz es un tipo de nodo predeterminado, nuestro script hereda del nodo No estamos usando una plantilla ni un script incorporado, y podemos especificar dónde se almacenará este script dentro del proyecto. Pongamos esto en la misma carpeta. Lección uno. Al nombrar scripts, es importante no ser arbitrario, sino describir el tipo de objeto o comportamiento que estamos creando a través del script Así que vamos a nombrar este hola. Los scripts tienen la extensión de archivo dotGD. Después haga clic en Crear para crear el script. Esto cambiará nuestra vista previa a la vista de script, mostrando nuestro script hello recién creado. También podemos ver nuestro script en la pestaña del sistema de archivos que se indica con un icono de diente, y el nodo raíz de Lesson one tiene el icono de script para mostrarnos que tiene un script adjunto a él, que al pasar el cursor sobre él, nos dirá el nombre del Al hacer clic en este icono también se abre el script si no está abierto ya. Nuestro script solo tiene una línea, que describe su herencia del tipo de nodo básico usando la palabra clave extends. Esto solo significa que nuestro script puede hacer todo lo un nodo puede hacer más cualquier cosa que escribamos aquí. También nos permite anular los comportamientos del nodo que ya existen con nuevos comportamientos propios. Por ejemplo, los nodos tienen una función llamada ready, pero no hace nada. Entonces, si queremos que nuestro script anule este comportamiento de no hacer nada, podemos declarar nuestra propia función del mismo nombre usando la palabra clave funk A continuación, al funk le sigue el nombre de la función, normalmente escrito en minúsculas de serpiente, lo que significa que todas las letras minúsculas separan palabras Muchas de las funciones definidas por los nodos van precedidas de un guión bajo, y el nombre debe ser una coincidencia exacta para anular el comportamiento El nombre de la función debe ir seguido de paréntesis y dos puntos Vamos a repasar por qué más tarde. Al presionar Intro después de esta línea, la siguiente línea se sangra automáticamente en un nivel Así es como GD Script sabe qué líneas están contenidas dentro de la función y dónde termina La línea se resalta en rojo porque no se permite que las funciones estén vacías. Por lo que es una buena idea escribir la palabra pase para darle a las nuevas funciones un cuerpo que no haga nada. Ahora que el error se ha ido, podemos ver este icono de flecha azul aparecer frente a la declaración de función, que es el símbolo de anulación, lo que indica que este script ahora está anulando el comportamiento listo de nuestro nodo En lugar de no hacer nada, queremos que nuestro nodo diga hola, lo que podemos hacer con una declaración de impresión, reemplazando la línea que anteriormente decía pasar. La declaración print se parece a una declaración de función con un nombre seguido de paréntesis porque está llamando a una función incorporada Esta función requiere un argumento, que es lo que va dentro de los paréntesis Y este argumento es lo que se va a imprimir. Usando comillas, podemos escribir lo que queramos, y será impreso por nuestro script cuando el nodo esté listo. Dado que el script se llama hola, el comportamiento que queremos crear es que el nodo diga hola. Con nuestro script listo, podemos ejecutar nuestro juego usando el botón Ejecutar escena actual en la parte superior derecha o usando el atajo F six. Esto mostrará una ventana vacía, ya que nuestro juego no dibuja nada, sino que también abre el quinto dock, mostrando el panel de salida. Y en nuestra salida, podemos ver que nuestro nodo ha impreso las palabras hola mundo cuando estaba listo. Podemos terminar esta simulación cerrando la ventana, haciendo clic en el botón de parada, o usando el atajo F ocho. Podemos cambiar el texto que se imprime para que diga lo que queramos y volver a ejecutarlo para ver que nuestro nodo puede imprimir cualquier cosa que le digamos. Ahora sabemos cómo adjuntar scripts a los nodos y ejecutarlos. En la siguiente lección, aprenderemos sobre constantes y variables Te veré en la siguiente lección. 3. 0-2 Constantes y variables: Hola, amigos. Comenzaremos cada lección creando primero una nueva carpeta para la lección. Después creando una nueva escena en esa carpeta del mismo nombre. Haga doble clic en una escena en la pestaña del sistema de archivos para abrirla. Con múltiples escenas abiertas, podemos cambiar entre ellas haciendo clic en sus pestañas en el documento de vista previa. Hoy, discutiremos las diferencias entre constantes y variables usando días como nuestro marco de referencia Así que vamos a adjuntar un nuevo script al nodo raíz de la escena y ponerle el nombre días. Comencemos con constantes y declaremos una en la parte superior del script usando la palabra clave const, seguida del nombre de nuestra nueva constante, que convencionalmente está escrita en mayúsculas de serpiente Una constante es como un contenedor donde podemos almacenar información, pero esa información nunca se le permite cambiar. Algo que consideraríamos una constante podría ser el número de días de la semana. Como no se puede cambiar, le debe dar un valor de inmediato, razón por la cual tenemos un error. Debemos seguir el nombre con un signo igual, el operador de asignación para darle un valor a la constante. El número de días en la semana es de siete. Es razonable suponer que siempre serán siete y es lo mismo para todos. Por lo tanto, nunca debería necesitar cambiar su valor. Por el contrario, tenemos variables, que también son contenedores para almacenar información, pero las que están diseñadas para ser cambiadas. Podemos declarar una variable la misma manera usando la palabra clave VR, luego dándole un nombre escrito convencionalmente en minúscula serpiente. Esto hace que sea fácil ver la diferencia entre constantes y variables en nuestros scripts Algo que cambia frecuentemente podría ser el valor de hoy. A diferencia de las constantes, se permite que las variables estén vacías. Anulemos la función ready de nuestro nodo base e imprimimos los valores tanto del número de días de la semana como de hoy. Podemos ver que el número de días en la semana es de siete, pero el valor de hoy se imprime como nulo, lo que significa vacío o ningún valor. Arreglemos eso inicializando hoy para que sea jueves. Y podemos hacer que nuestra salida sea más legible agregando algo de contexto, comenzando con algo como hoy es entonces dejar un espacio después es un signo más, luego nuestra variable. En este caso, se está utilizando el signo más para sumar dos piezas de oración juntas Si tratamos de hacer lo mismo con nuestra constante, sin embargo, provocará un error porque nuestra constante es un número, no una palabra. Cuando declaramos nuestra constante, le asignamos un valor de siete, que es un número sin ningún punto decimal, que en matemáticas se llama entero. Entonces nuestra constante tiene un tipo de entero. Hoy, por otro lado, se le asignó un valor de algunos caracteres envueltos entre comillas. En la programación, llamamos a esto una cadena. Entonces nuestra variable tiene un tipo de cadena. El operador plus solo se puede usar cuando los tipos de ambos operandos son compatibles Podemos sortear esto usando una función incorporada para cambiar el tipo tal como se está usando aquí a una cadena, pasando la constante como argumento a la función. Esto no cambiará el tipo de la constante original, solo cómo se está utilizando aquí dentro del contexto de la operación append Y podemos seguir agregando más contexto después con otra cadena anexada también, recordando agregar un espacio extra en la parte delantera. Así que ahora podemos imprimir nuestras constantes y variables usándolas en frases fáciles de entender. Después de estas líneas, pretendamos que pasa un día. Podemos agregar contexto adicional a nuestros scripts que nunca serán vistos por los jugadores, sino que solo existe para ayudarnos como desarrolladores a entender nuestro propio código o código escrito por otros. Estos se llaman comentarios y se crean usando el signo o hashtag OctathorpPound Cualquier texto escrito después de este símbolo se coloreará en gris y no afectará la forma en que se ejecuta el script de ninguna manera. Pueden estar en sus propias líneas o al final de una línea de código. Entonces usemos un comentario para explicar que estamos fingiendo que ha pasado un día entre el código arriba de esta línea y el código de abajo Cambiaremos el valor de hoy para que sea viernes e imprimiremos otra frase. Hoy es más Hoy, que ahora tiene un valor diferente. Podemos ver que el valor de hoy primero se imprimió como jueves y luego se cambió y se imprime como viernes en la siguiente línea. El comentario no tuvo efecto en el script que se estaba ejecutando. Si tratamos de cambiar el valor de nuestra constante, obviamente, esto provocará un error porque no se permite que se cambien las constantes Si ya no queremos usar algunas líneas de código en nuestro script, podemos cambiarlas fácilmente a comentarios resaltándolas y presionando Control K o Comando K, agregando el símbolo de comentario al frente de cada línea resaltada. Al presionarlo de nuevo se eliminarán los comentarios. Podemos especificar el tipo de variable o constante añadiendo dos puntos después del nombre. Seguido del nombre del tipo, queremos restringir esta constante o variable también. Vamos a restringir nuestra constante para que sea de tipo int y hoy de tipo string. Aparte de cadenas y enteros, hay otros dos tipos primitivos que podemos usar para almacenar información básica Si un número tiene puntos decimales, ya no es un entero y en su lugar un tipo diferente llamado número de punto flotante, que usa el nombre de tipo float. Agreguemos otra variable para la fecha de hoy y le demos un tipo de número de punto flotante con un valor de 12.05, que es la fecha de hoy 5 de diciembre Y el último tipo se llama Boolean usando el nombre abreviado Boole, que puede ser verdadero o Entonces agregaremos otra variable para saber si hoy es feriado o no. Voy a restringir esto para que sea booleano, pero no le voy a dar un valor inicial Agreguemos dos sentencias print más para imprimir los valores de estas variables con contexto. La fecha de hoy es más fecha, y hoy es feriado. Colon plus es un día festivo. Cuando ejecutamos esto ahora, podemos ver nuestra fecha impresa, pero es un feriado dice falso, a pesar de no darle un valor. Esto se debe a que todos los tipos primitivos tienen un valor predeterminado, pero el valor predeterminado solo se puede asignar si especificamos el tipo de variables. Ya que especificamos que es un feriado es un booleano, se le asignó al valor predeterminado para un booleano, El valor predeterminado tanto para un número entero un número de punto flotante son ambos cero, y el valor predeterminado para una cadena es solo una cadena vacía, que no es lo mismo que null, sino una cadena sin caracteres en ella. Si no especificamos el tipo de una variable, su valor predeterminado será nulo, pero se le puede asignar un valor de cualquier tipo, y su tipo puede cambiar en cualquier momento. Eliminemos el tipo a partir de la fecha. Entonces dale un nuevo valor del 13 de diciembre e imprímela por segunda vez. La variable comienza a asignarse un valor de un número de punto flotante, es utilizada por la sentencia print, luego se le asigna un valor de cadena antes de volver a imprimirse. Esto está permitido porque GD Script es un lenguaje poco escrito Esto ofrece una mayor flexibilidad a la hora de escribir nuestros scripts, pero también una mayor responsabilidad para evitar errores de compatibilidad de tipos como vimos con el operador plus. Se recomienda que siempre le des un tipo a tus variables, no sólo para evitar errores, sino también para mejorar la eficiencia de ejecutar tus scripts. Si el motor conoce el tipo de tus variables, entonces también sabe exactamente cuánta memoria necesita ocupar. Esto también se aplica al uso constantes en lugar de variables Si el motor sabe que el valor no puede cambiar, entonces se puede usar de manera más eficiente. En la siguiente lección, aprenderemos sobre cómo controlar el flujo de nuestros guiones. Te veré en la siguiente lección. 4. 0-3 Declaraciones y condiciones de If: Hola, amigos. Ya me adelanté y creé una nueva escena en una nueva carpeta para esta lección. Hoy aprenderemos a controlar el flujo de nuestros scripts para ejecutar diferentes líneas de código, tomando decisiones sobre si podemos ver o no. Así que vamos a adjuntar un nuevo script al nodo raíz de nuestra escena y ponerle el nombre visión. Comenzaremos nuestro script anulando la definición de nodos base de la función ready El método más básico para controlar el flujo de nuestros scripts es la declaración I, que comienza con la palabra clave I. I va seguida de una declaración condicional que debe ser verdadera o falsa. Por ahora, pongamos la verdad, que luego le sigue un colon. Similar a los dos puntos al final de nuestra declaración de función, esto marca el final de la sentencia, y continuando a la siguiente línea, se sangró automáticamente otro nivel Cualquier línea de código que siga a esta sentencia if, que están sangradas solo se ejecutará si la condición de la sentencia if es verdadera Así que vamos a imprimir algo así como que la condición era cierta y luego ejecutemos la escena actual para ver nuestra declaración impresa funcionando. Si cambiamos true a false, podemos ver que la declaración print se omite durante este tiempo Podemos agregar otra línea después de las sentencias if con sangría body en el mismo nivel de sangría que la instrucción I simplemente con la palabra clave se seguida Esto crea otro cuerpo condicional que se ejecutará sólo si no se cumplió la condición de la declaración I original. Duplicemos la declaración print y la cambiemos para decir algo diferente. Como la condición era falsa, se ejecutó el bloque se en lugar del bloque I. Y si cambiamos la condición a verdadera, ocurrirá lo contrario. Esto no es muy útil si siempre sabemos que el resultado de la declaración condicional es verdadero o falso, pero podemos reemplazarlo por una variable. Declaremos una variable booleana, que es si la luz está encendida o no en la habitación booleanos se denominan convencionalmente tal manera que implican su uso como condición En este caso, la luz está encendida se implica que es verdadera o falsa en función de cómo se le nombra. Ahora nuestra declaración if puede establecer su condición para que sea si el valor de nuestra variable es igual o no a true. Al comparar dos valores para ver si son iguales, utilizamos un signo doble igual, conocido como el operador igual, que es diferente de un solo signo igual como usamos antes como operador de asignación. Entonces imprimiremos o puedo ver o no puedo ver como resultado de si la luz está o no en ser igual a verdad. Como el valor por defecto de un booleano es false, podemos ver la salida como no puedo Pero si establecemos la variable en true , cambia a puedo ver. Dado que la variable en sí es un booleano, ya sea verdadero o falso, podemos eliminar la operación de comparación por completo y simplemente usar el booleano como condición y obtener exactamente el Podemos revertir el valor de cualquier booleano, es decir, si es verdadero, se vuelve falso o si es falso, se vuelve verdadero mediante el uso de la palabra clave not Al igual que la función STR que usamos en la lección anterior, esto solo cambia la forma en que se está usando en el contexto local y en realidad no cambia el valor almacenado en la variable. Entonces si no, la luz está encendida, entonces no podemos ver, y de lo contrario podemos ver. Nada también puede ser representado por un signo de exclamación. Cambiemos el valor de las luces encendidas y volvamos a ejecutarlo. Después volveré estos cambios a la forma en que estaban antes Podemos hacer nuestras condiciones mucho más complejas combinando múltiples condiciones juntas usando operadores lógicos. Vamos a crear otra variable llamada Tiene visión oscura. Esta variable implica que deberíamos poder ver aunque la luz no esté encendida. Entonces podemos sumar a nuestras declaraciones if condicionar que sea que la luz esté encendida o que tengamos visión oscura. Y si alguna de estas condiciones es cierta, entonces podemos ver. Sólo si ambas condiciones son falsas, ¿ resultará en que no podamos ver? Y si, en lugar de tener visión oscura, estamos usando gafas de visión nocturna, ya que solo nos permiten ver en la oscuridad pero no en la luz. Cambiando el nombre de la variable, la condición de nuestra declaración I necesita cambiar. Ya que si ambas condiciones son ciertas, entonces no deberíamos poder ver. Sólo si los valores de estas dos condiciones son diferentes, ¿debemos considerar que se cumple la condición a ver? Podemos usar el operador no es igual para verificar si los dos valores no son iguales entre sí. Si está familiarizado con las operaciones lógicas, esto se conoce en otros idiomas como un exclusivo o. Ahora, sólo si o bien la luz está encendida o estamos usando gafas de visión nocturna y no ambas, podremos ver. A continuación, consideremos que nuestra persona hipotética podría no ser humana y sumar una variable para el número de Is que tienen, que debería representarse como un entero Por ahora, le daremos un valor de dos Is. Ignorando las otras variables, ¿cuál sería la condición que establecemos para poder ver en base a esta variable Si el número de ojos que tenemos es algo mayor que cero, entonces deberíamos poder ver. También podemos expresarlo usando otro operador, mayor o igual a y cambiar el lado derecho a uno. Por lo que deben tener ojos mayores o iguales a uno. Estos son operadores de comparación que devolverán un resultado booleano comparando el valor de los números en sus lados izquierdo y derecho Podemos concluir lógicamente que debería ser imposible cualquier criatura humana o otra manera tenga un número negativo de ojos El valor de nuestra variable sólo debe ser cero o algo mayor que cero. Y la condición para poder ver realmente se reduce a estas dos opciones ¿Tenemos ojos cero o ojos distintos de cero? Al igual que la variable booleana se puede usar implícitamente como una condición, un entero también se puede usar de esta manera con cero siendo considerado una condición falsa y cualquier otra cosa que no sea cero La misma lógica también se aplica a los números de punto flotante. Podemos declarar una variable flotante, llamémosle rango de visión y darle un valor arbitrario de 7.8 metros. Podemos usar nuestros operadores de comparación para determinar si este número es mayor que menor o igual a cierto valor, o podemos usarlo implícitamente en su propia condición con cero siendo considerado falso y cualquier otra cosa considerada verdadera ¿Qué pasa con las cuerdas? Cambiemos las cosas ligeramente y declaremos una variable de cadena para lo que escuchamos y le demos un valor de baches en la noche. Entonces podríamos usar lógicamente esto como una declaración if como si lo que oí no fuera una cadena vacía, entonces podemos decir, escuché algo De lo contrario, no escuché nada. Y al igual que los otros tipos de variables, podemos dejar caer la comparación y usar la propia variable como condición. Con todas las variables, sus valores predeterminados se consideran falsos, y cualquier otra cosa siempre se considera verdadera cuando se usa como condición. Si declaramos una variable sin un tipo, llamémosla como estoy viendo, pero no le demos un valor, entonces ya sabemos que su valor predeterminado será nulo. Incluso sin un tipo o un valor, cualquier variable puede ser utilizada como condición de acoso. Cualquier variable que esté vacía, es decir, su valor es nulo se considera falsa. Si tuviéramos que poblar esta variable con un objeto, entonces su valor como condición se consideraría verdadero Actualmente no tenemos ningún otro objeto con el que jugar, pero siempre podemos usarnos a nosotros mismos. Así que vamos a establecer el valor de lo que estoy viendo para que sea la palabra clave yo. Y esto da como resultado poder ver. En la siguiente lección, usaremos bucles para repetir líneas de código varias veces. Te veré en la siguiente lección. 5. 0-4 Bucles y operadores en while: Hola, amigos. Hoy aprenderemos a repetir líneas de código varias veces con bucles imaginando a una dama que se ha enamorado por primera vez sosteniendo una flor Así que vamos a escribir un nuevo guión y ponerle nombre flor. Luego anula la definición de nodos base de la función ready. Nuestra dama imaginada sostiene una flor que tiene varios pétalos, los cuales almacenaremos en una variable y restringiremos su tipo a un entero. Entonces dale un valor de algún número arbitrario, digamos cinco. También declararemos otra variable llamada He Loves Me, como booleana, que creemos con su valor predeterminado de false Podemos comenzar nuestro guión imprimiendo una historia sobre la dama enamorada que sostiene su flor. Ella quita cada pétalo de la flor uno por uno, declarando o él me ama o no me ama. Primero, necesitamos reducir uno el número de pétalos en la flor. Entonces comenzaremos con la variable número de pétalos, luego usaremos el operador de asignación para asignar a la variable un nuevo valor. El valor que queremos asignarle es el número que ya tiene menos uno. Luego queremos cambiar el valor de la variable booling. A él me quiere ser su opuesto. Entonces él me ama, se le asigna a la nada Él me ama, revirtiendo el valor de falso verdadero o viceversa. A continuación, podemos imprimir los resultados. Él me ama. Es posible que queramos encapsular esta parte entre comillas, pero si tratamos de poner comillas dentro de nuestra cadena, en su lugar marcará el final de la cadena Algunos caracteres especiales como las comillas se pueden crear dentro de una cadena usando una barra diagonal inversa Si escribimos comillas invertidas, esto ahora representa un carácter de comillas, no el final de la cadena Y podemos incluir otra después de la declaración de Damas. Duplicemos esta línea y cambiemos la declaración para decir, Él no me ama. Otro ejemplo de un carácter especial que podemos escribir usando la barra diagonal inversa es la barra inversa misma También podemos combinar las dos líneas anteriores y separarlas con barra diagonal inversa N, que representa una nueva Por lo que se imprimen en dos líneas de salida a partir de una sola declaración de impresión. Ahora tenemos dos posibilidades que queremos imprimir en base al valor de nuestra variable booleana Entonces parecería que deberíamos envolverlos en una declaración if. Si me quiere, entonces imprima esto. Si no me quiere, entonces imprima eso. Pero en los casos en los que si las declaraciones están supeditadas una sola variable booleana para hacer un cambio menor, hay un método más eficiente Entonces volvamos al formato original. Nuestra declaración será él me ama, si me ama, de lo contrario, no me quiere a mí. Esto no es lo mismo que una sentencia if a pesar de usar las mismas palabras clave, pero se llama operación ternaria Dado que no crea un nuevo bloque de código con sangría, realidad se ejecuta de manera más eficiente y se recomienda su uso en casos simples como este De hecho, podemos reducir aún más el tamaño de la variación cambiando solo para que sea un signo de exclamación o un espacio seguido de la palabra no, luego el signo de exclamación Esto funciona para el caso si me ama, pero si cambiamos el valor a true por defecto, entonces solo vemos no en el otro caso. Al igual que las matemáticas, existe un orden específico de operaciones en el que nuestros scripts ejecutarán múltiples operaciones en la misma línea. Ya que tanto el string append el ternario I son ambos operadores, uno debe ser ejecutado antes que el otro, y en este caso, será el string Y al igual que en matemáticas, los brackets son siempre los primeros en ser ejecutados. Por lo que podemos envolver cualquier operación entre paréntesis para asegurarnos de que se ejecutará primero en el orden de las operaciones. Envolviendo nuestra declaración ternaria entre paréntesis, ahora se ejecutará antes de que la cadena anexe y nos dará nuestro resultado esperado Entonces ahora tenemos nuestro bloque de código que necesita repetirse mientras la flor todavía tenga pétalos. Usando la palabra clave WW, igual que una sentencia if, podemos repetir un bloque de código con sangría siempre y cuando la condición permanezca verdadera La condición en este caso es que el número de pétalos en la flor no sea cero. Sea cual sea el número de pétalos en la flor, se reducirá en uno cada vez. Entonces después de la sentencia print, el flujo lógico de este script volverá al inicio del WWLoop para verificar nuevamente la condición Cuando el número de pétalos llega a cero, la condición ya no se cumple y el bucle se rompe, procediendo con el resto del guión, si hay alguno. Entonces, escribamos una breve conclusión de nuestra historia basada en los resultados. Se pone de pie con lágrimas en los ojos. Pero basado en el valor final de He Loves Me, ella es feliz o triste, e imprimiremos la frase final diferente. Ejecutando esta escena, podemos ver nuestra historia impresa en el panel de salida, y con cinco pétalos, la señora está feliz. Si cambiamos el número de pétalos a seis, entonces obtenemos un resultado diferente ya que el bucle se repitió seis veces en lugar de cinco. Pero, ¿qué pasa si cambiamos a cero el número de pétalos en la flor? El bucle no corre en absoluto, y el amor estaba condenado desde el principio No recomiendo seguir este ejemplo, sino solo ver qué pasa si le damos a la flor un número negativo de pétalos. Si bien esto es realista imposible, en nuestro código, es muy problemático Dado que la condición de nuestro bucle de pared nunca se cumplirá, nunca se romperá, y el guión queda atrapado dentro de él, nunca terminando. Este es un bucle infinito y debe evitarse a toda costa. En este caso, podemos evitar el bucle infinito cambiando nuestra condición para que sea si el número de pétalos es mayor que cero, ya que un número negativo seguirá rompiendo el bucle. Podemos usar otro operador a la hora reducir el número de pétalos como atajo. Eliminando la necesidad de escribir el nombre de nuestra variable dos veces, podemos realizar operaciones matemáticas simples sobre nuestro número de variables usando un operador de asignación especial. En este caso, el operador menos igual puede cambiar esta línea de código a número de pétalos menos igual a uno. Estos atajos existen para todas las operaciones aritméticas básicas más iguales multiplican iguales o dividen iguales, y se pueden usar con cualquier número o variable como el otro operando Hay un operador más que existe también para la aritmética básica, el operador de módulo, representado por el signo porcentual El módulo realiza una operación de división, pero no devuelve el cociente como resultado como lo hace el operador de división En cambio, devuelve el resto de la división. Todo este guión, aparte de la historia que se cuenta, realidad solo está determinando si el número de pétalos en la flor es un número par o impar, pero lo está haciendo de la manera más ineficiente posible, contando hacia atrás cada pétalo individual Así que vamos a comentar todo el bucle de pared y en su lugar usar el módulo para acelerar el proceso. Sabiendo que todos los números pares son divisibles por dos, podemos usar número de pétalos módulo dos El único resultado posible como resto de esta división será cero si el número de pétalos es par o uno si el número de pétalos es impar. Nuestro guión podría simplificarse a solo si el número de pétalos módulo dos es igual a uno, entonces la dama es feliz. De lo contrario, está triste. Ya que entendemos cómo se interpretan los enteros como condiciones, ni siquiera necesitamos realizar la operación de comparación aquí y solo podemos acortarla a I número de pétalos módulo El resultado de la operación de módulo podría asignarse directamente a la variable booleana para obtener el mismo resultado sin la necesidad de una sentencia if, y el cero o uno se convertirán automáticamente en falso o verdadero Podríamos ir más allá eliminando la variable y simplemente usando la operación de módulo directamente dentro de la declaración turny En la siguiente lección, aprenderemos sobre colecciones de variables relacionadas. Te veré en la siguiente lección. 6. Matrices 0-5 y bucles para: Hola, amigos. Hoy consideraremos cómo podemos organizar grandes cantidades de variables, especialmente cuando contienen información relacionada. Ya he seguido adelante y creé un script llamado censo y anulé la definición de nodos base de la función ready Para nuestro hipotético escenario en esta lección, estamos imaginando a un trabajador del censo que necesita registrar cuántas personas viven en cada casa en una sola carretera Podemos declarar una sola variable para contener toda esta información, Vamos a llamarlo Main Street. Y el tipo de esta variable será una matriz. Una matriz puede contener una lista de variables de cualquiera de los otros tipos. En este caso, el tipo de variables que estamos buscando son enteros, que representan el número de personas que viven en cada casa Podemos especificar el tipo de contenido de una matriz usando corchetes después la matriz type name y poniendo el tipo de contenido dentro de los corchetes. Ahora bien, esta matriz solo puede contener enteros como su contenido. Antes de que podamos acceder al contenido de una matriz, necesita tener un tamaño, el número de variables que están contenidas en su interior. A diferencia de otras variables, los arrays son más complejos y tienen sus propias funciones. Podemos acceder a estas funciones siguiendo el nombre de la variable con un punto, luego el nombre de la función. En este caso, la función resize, que establece el número de direcciones dentro de esta matriz, representando el número de casas en Main Street, que diremos es seis Nuestro pueblo imaginado es un poco inusual ya que los números de casa en Main Street comienzan en cero. Por lo que nuestro trabajador del censo inicia en la casa en calle principal cero y llama a la puerta para preguntarle al residente del hogar cuántas personas viven en la casa Podemos almacenar un valor en una matriz comenzando por su nombre, luego usando corchetes para marcar la dirección del entero específico, en este caso, dirección cero, luego usando el operador de asignación. Podemos asignar un entero a esa dirección. Entonces digamos que la casa número cero de la calle principal tiene cinco personas viviendo en ella. pasar a la siguiente casa en dirección número uno de la calle principal, alguien contesta el golpe en la puerta y le dice trabajador del censo que hay dos personas viviendo en esa casa. En la casa de al lado, dirección número dos, la casa está en construcción y tiene un letrero de venta, lo que significa que esta casa está claramente desocupada, y nuestro trabajador del censo registra el número de residentes como cero En la calle principal número tres, nadie abre la puerta, a pesar de que hay un automóvil en la calzada y señales de ocupación ¿Qué podríamos considerar que el trabajador del censo debe registrar como el número de residentes? Podríamos pensar que podría ser cero. Pero, ¿cómo diferenciaríamos entre un número desconocido de ocupantes y una casa desocupada Si consideramos que el número de ocupantes de una casa nunca debe considerarse un número negativo, podríamos usar el número negativo uno para significar que el número de ocupantes de la casa es un valor desconocido Y en la calle principal número cuatro, nuevo, no hay respuesta en la puerta. Pero la casa también parece estar descuidada, y probablemente nadie haya vivido allí desde hace bastante tiempo. Podríamos suponer que el número de ocupantes es cero tal vez usó el mismo valor negativo para un número desconocido de ocupantes o crear códigos de valor más negativos para diferentes situaciones como usar dos negativos para significar probablemente desocupados pero La dirección número cinco Main Street ni siquiera tiene casa, pero es solo un terreno baldío Entonces nuevamente, esto podría representarse con un cero u otro valor negativo para codificar algún tipo de reunión. Imprimamos los resultados del censo y veamos cómo se ven. Podemos ver nuestra matriz representada como una lista separada por comas de números encapsulados entre corchetes Esto hace un trabajo decente al representar el número de personas que viven en cada casa de Main Street. Pero, ¿y si quisiéramos usar estos datos para obtener un número total de ocupantes de todas las casas de Main Street o en promedio Si calculamos la suma de todos estos números, los números desconocidos que se representan como negativos sesgarían los Uno de los mejores beneficios de usar arreglos para almacenar información relacionada de esta manera es lo fácil que es recorrerla. Usando la palabra clave four, escribimos a continuación el nombre de una nueva variable, una que representará cada elemento individual dentro de la matriz, seguido de la palabra clave in, luego el nombre de la matriz. Al igual que las funciones, si las sentencias son bucles wa, esto va seguido de dos puntos y un bloque de código con sangría que se repetirá Estas líneas de código se repetirán una vez por cada una de nuestras seis casas en Main Street, y podemos nombrar a la casa variable, ya que se utilizará para acceder a cada casa individual dentro del bucle. Digamos que primero queremos encontrar el promedio de ocupantes que viven en una casa ocupada Eso significaría sumar todos los números positivos luego dividiendo por el número de casas ocupadas. Entonces necesitaremos tres nuevas variables, una para el número total de ocupantes, otra para el número de casas ocupadas, ambas como números enteros, y un número de punto flotante para el promedio Por cada casa en Main Street, podemos verificar si la casa está ocupada, si el número almacenado en la matriz en esa dirección ahora almacenada en la variable house es algo mayor que cero. Si esto es cierto, entonces el número total de ocupantes en las casas ocupadas se puede incrementar por casa, y el número de casas ocupadas se incrementa Después de que se hayan revisado las seis casas de Main Street, el bucle se rompe, y tenemos nuestros dos números enteros. Así podemos calcular el promedio dividiendo el número total de ocupantes por el número de casas ocupadas Después imprime los resultados. Hay más casas ocupadas, más casas ocupadas en la calle principal, con un promedio de más ocupantes promedio más ocupantes Pero si ejecutamos este código, el promedio se representa como un entero, tres, lo que sabemos que no es correcto, ya que hay un total de siete ocupantes en dos casas ocupadas, el promedio debería ser de 3.5 Esto sucedió porque realizamos una operación de división con dos enteros, y el resultado de la operación también será un entero, aunque lo estemos asignando a una variable de número de punto flotante Godot también proporciona una advertencia contra el uso de enteros en operaciones de división Para resolver esto, podemos cambiar nuestras variables enteras a números de coma flotante en sus declaraciones, o podemos cambiar su tipo localmente antes de realizar la división. De la misma manera que cambiamos enteros en cadenas antes de anexarlos, podemos cambiar un entero en un número de punto flotante antes de realizar una división Cambiar el resultado de la división a un número de coma flotante también. Cambiar el tipo de una variable de esta manera se llama casting. Estamos lanzando un entero a un flotador. Ahora podemos ver los resultados que esperábamos con un promedio de 3.5 ocupantes por casa ocupada Un beneficio de GD Script, ser un lenguaje poco escrito es que no necesitamos especificar los tipos de nuestras variables, incluyendo los tipos contenidos dentro de Si permitimos que nuestra matriz contenga cualquier tipo de variable, podemos cambiar la forma en que nuestro trabajador censal registra la información. Supongamos que la dirección cero sigue siendo la misma con cinco ocupantes Pero la dirección uno también proporcionó los nombres de los dos residentes que allí viven. En lugar de grabar a los ocupantes como número dos, podríamos grabar sus nombres en una cadena Por lo que la dirección número uno de Main Street está ocupada por Jordan y Ashley Smith. La casa número dos estaba desocupada, lo que podríamos representar como un cero Pero también podríamos considerar grabarlo como un booleano en su lugar, y darle un valor de falso para significar que la casa está en construcción y no puede posiblemente tener En el número tres, nadie estaba en casa, pero definitivamente hay gente viviendo ahí. Simplemente no sabemos cuántos. También podríamos almacenar este valor como un booleano y darle un valor de verdad En el número cuatro, realmente parece que ahí no vive nadie. Quizá queramos marcarlo como cero ocupantes. En la dirección número cinco, ya que no hay ni siquiera una casa ahí, en realidad podríamos considerar usar null como valor ya que null representa la ausencia de cualquier valor. Podemos usar la palabra clave null para asignar esto a la matriz en la dirección cinco. Ahora nuestra matriz impresa se ve bastante diferente, que contiene variables de todos los tipos diferentes en lugar de solo números enteros. Y podemos discernir más información de ello. Las matrices pueden incluso contener otras matrices como su contenido. Así que vamos a cambiar nuestra lista de nombres de una sola cadena a una matriz de cadenas. Podemos crear esta matriz al mismo tiempo que se le está asignando usando corchetes, luego poblándola con una lista de cadenas separadas por comas como su contenido Entonces, si quisiéramos saber cuánta gente vive en la Dirección uno en Main Street, podríamos imprimirlo como el SIE de un punto de En la siguiente lección, aprenderemos más usos de las matrices para crear colecciones de datos más dinámicas. Te veré en la siguiente lección. 7. 0-6 Stacks y funciones: Hola, amigos. Hoy seguiremos trabajando con arreglos de diferentes formas configurando un juego de Old made. Ya he seguido adelante y creé un script llamado Old Made y anulé la definición de nodos base de la función ready Para jugar old made, necesitamos una baraja de cartas, que es una colección de variables que podemos contener dentro de una matriz. Dado que al juego de Old Made realmente no le importan los trajes de las cartas, podemos ignorar esa información, y cada elemento de la matriz solo necesita contener el rango de cartas del as al rey como un entero. Para generar nuestro mazo, podemos usar un bucle de cuatro. Pero en lugar de usar los cuatro bucles para iterar a través de una matriz, solo se puede usar para contar a través de nuestros rangos de cartas. Comenzando con cuatro, podemos declarar una variable para representar el rango de una carta, seguida de la palabra clave in, luego especificar un número. Si tuviéramos que considerar a King como un número, sería el rango 13. Por ahora solo vamos a imprimir rango para que podamos ver qué pasa. El bucle cuatro inicia con un valor de rango en cero y cuenta hasta 12, repitiendo este bucle e imprimir sentencia 13 veces. Por el bien de la cordura, podría ser una buena idea considerar que carta número dos esté representada por el rango dos, y así As sería uno, y el rey sería 13 Si bien comenzar un bucle cuatro en cero es realmente útil para iterar a través de matrices ya que su primer número de índice es cero, no es tan útil en este caso Podemos cambiar la forma en que cuenta un bucle cuatro reemplazando el 13 con una llamada a función, range. Las llamadas a funciones van seguidas de paréntesis que contienen argumentos Los argumentos para esta función son los límites inferior y superior del rango. El límite inferior se incluirá en el rango, pero no se incluirá el límite superior. rango 114 contendrá todos los números 1-13, podemos ver que se imprime en la salida Otra forma de agregar información a una matriz en lugar de usar los corchetes y número de índice es usar una función llamada append Esta función append acepta un argumento del valor que se agrega a la matriz Esto posicionará el valor que se agrega al final de la matriz, donde sea que esté. Y como hay cuatro de cada rango en una baraja de cartas, una por cada palo, deberíamos repetir esta línea de código cuatro veces por cada rango. Podemos hacer esto con otro bucle de cuatro, esta vez comenzando en cero y contando hasta, pero sin incluir cuatro. Al imprimir la baraja, podemos ver que nuestra matriz tiene cuatro de cada número 1-13 para un total de 52 cartas Pero para jugar viejo hecho, queremos quitar a tres de las reinas, o en este caso, 12. Entonces en nuestro bucle de cuatro que está iterando a través de los trajes de cartas, vamos a comprobar si el rango es 12 Y en este caso específico, solo queremos permitir que se agregue 112, usando la palabra clave break para salir instantáneamente de este bucle. Break solo terminará el bucle con más sangría en el que se encuentra actualmente Entonces terminaremos el palo por bucle, pero no el rango para bucle. Esto aumentará entonces el rango a 13 y procederá a sumar cuatro trece a la baraja Y probándolo, podemos ver como sólo hay 112. Lo primero que sucede en nuestro juego es barajar la baraja de cartas, que en el guión GD es una sencilla función incorporada de rayse Sólo necesitamos llamar a esta función y podemos ver que las cartas se barajan en nuestro mazo También necesitaremos otra variable, un conjunto de manos de cartas para representar a nuestros jugadores. Cada mano dentro de la matriz de manos necesita contener múltiples tarjetas, por lo que también son matrices, que necesitaremos inicializar antes de poder usarlas. Entonces contando desde cero hasta pero sin incluir cuatro, podemos agregar una nueva mano a la matriz Nuestra mano comienza como una matriz vacía representada por corchetes. Si imaginamos nuestra baraja de cartas, siendo el frente de las cartas el lado con el sonó y el palo, estando el dorso de la carta en blanco, entonces también podríamos imaginar que la baraja está boca abajo El frente de la matriz es la parte inferior de la cubierta, y la parte posterior de la matriz es la parte superior de la cubierta. El proceso de repartir las cartas se puede hacer iterando a través de nuestro mazo, pero en realidad no necesitamos hacer referencia a cartas específicas en absoluto, ya que realmente no importa cuáles sean solo que la carta sea tomada de la parte superior de la baraja y entregada a un jugador Entonces, para quitar una carta de la parte superior de la baraja, podemos llamar a otra función. A éste se le llama pop back. No solo devuelve el último elemento de la matriz, sino que también lo elimina de la matriz. Luego queremos agregar esta carta a la mano del jugador y comenzaremos con el jugador uno, asumiendo que el jugador cero es el crupier. Al igual que podemos usar pop back para eliminar una tarjeta, también podemos agregar una tarjeta con retroceso La carta que estamos empujando en el dorso de la mano del jugador es la misma carta que estamos sacando del dorso de la baraja Simplemente podemos poner esta llamada a la función dentro de los corchetes de la llamada a la función y usar su valor de retorno como argumento a la función push. Usar pushback es exactamente lo mismo que append. La función append es un legado de cadenas, ya que generalmente se almacenan como matrices de caracteres, mientras que push y pop provienen de usar pilas o señales como lo estamos haciendo ahora Para repartir nuestra siguiente carta, tendremos que incrementar la mano a la que se reparten Vamos a almacenar eso en una variable como un entero y darle un valor inicial de uno. Al reemplazar el de nuestro índice de matriz con nuestra variable, tendremos que incrementarlo en uno después de que se reparte cada carta Pero esto obviamente solo contará hasta 51, y no hay tantas manos. Entonces necesitaremos que este número vuelva a cero cada vez que llegue a cuatro. Esto se puede lograr usando nuestro operador de módulo fiduciario, asignando mano para ser módulo es igual a Pero si queremos permitir que nuestro código funcione con cualquier número de jugadores, sería mejor reemplazar cuatro con el tamaño de nuestra matriz de manos. Para ver dónde estamos hasta ahora, imprima nuestras manos iterando a través la matriz de manos e imprimiendo cada una Después imprima la cubierta. Podemos ver nuestras cuatro matrices y la cubierta está vacía. Incluso podemos cambiar el número de jugadores y las cartas repartirán al número correcto de manos. Nuestra función de listo se está volviendo bastante grande. Podemos organizar mejor nuestro código declarando nuestras propias funciones Separando nuestra lógica en pequeños trozos, tenemos una sección que crea nuestra baraja inicial de cartas, una que crea las manos del jugador y otra que reparte las cartas Usando la palabra clave funk, podemos darle a cada uno de estos bloques de código un nombre seguido de paréntesis y Deck inicializado, inicializar manos, y tratar. Entonces la función ready puede llamar a cada una de estas funciones en secuencia. Nuestras funciones también pueden aceptar argumentos, como el número de manos que queremos tener. Pasemos cuatro como argumento. Para escribir nuestra función para aceptar el argumento, necesitamos agregar un parámetro coincidente dentro de los paréntesis de la declaración de función Al igual que declarar una variable, tiene un nombre y opcionalmente también un tipo Ya que estamos usando esto para cambiar el tamaño de una matriz, es una buena idea restringirla para que sea un entero Entonces podemos usar el parámetro dentro la función de la misma manera que usaríamos cualquier otra variable. Lo último que tenemos que hacer para comenzar a jugar sería quitar todas las duplas de la mano de cada jugador. Entonces iterando por cada mano en la matriz de manos, podemos llamar a otra función para eliminar los pares de esa mano, pasando la mano como argumento Dando una definición a esta función, entonces podemos aceptar una mano como un parámetro de matriz. Tendremos que iterar a través de la mano con una variable. Vamos a llamarlo tarjeta uno. Pero podemos detenernos antes de llegar a la última tarjeta. Entonces solo pasaremos de cero hasta el tamaño de la mano menos uno. Entonces podemos iterar una segunda vez la misma manera, pero esta vez, comenzar en la tarjeta después de la tarjeta uno y recorrer todo el camino hasta el final del tamaño de la mano Dentro de estos 24 bucles, carta uno y la carta dos ahora contienen cada par único de cartas en nuestra mano, así que podemos comparar fácilmente las dos cartas para ver si son una coincidencia. Si lo son, se pueden quitar de la mano, empezando por la tarjeta dos. Si primero retiramos la carta uno, entonces el índice de la tarjeta dos cambiaría realmente como resultado, ya que todas las cartas se moverían una posición. Si encontramos una coincidencia, no queremos continuar este bucle ni ninguno de los dos bucles, pero queremos reiniciar de nuevo todo el proceso. Una forma sencilla de hacer esto sería con un bucle while, una variable booleana para saber si encontramos o no un par con un valor predeterminado de true Si bien se encontró un par, inmediatamente podemos establecerlo en falso. Esto nos permite ingresar al bucle pero no quedarnos aquí a menos que se encuentre un par. En otros idiomas, podrías hacer esto con un bucle do Wile en su lugar Si encontramos un par, podemos establecer la variable en true, luego también romper de ambos bucles reiniciando el bucle while Si ambos cuatro bucles completan sin encontrar un par coincidente, par encontrado será falso y el bucle while se romperá. Podemos ejecutar repetidamente nuestra simulación y ver que ninguna de las manos de nuestros jugadores contendrá pares coincidentes, y los jugadores están listos para comenzar a jugar su juego de Old Maid En la siguiente lección, usaremos otra forma de control de flujo. Te veré en la siguiente lección. 8. Partido y vuelta 0-7: Hola, amigos. Hoy utilizaremos otra forma de control de flujo para simplificar condiciones complejas. Ya he seguido adelante y creé un script llamado months y anulé la definición de nodos base de la función ready Empecemos declarando una variable para mantener el mes actual y establecerla enero y una segunda variable en enero y una segunda variable para mantener el número de días del mes, que quedará como cero por defecto Podemos imprimir una frase simple en la que se indique que el número de días en enero es de 31. Pero primero, queremos poblar nuestra variable con el número de días basado en el valor del mes Entonces escribamos una función que pueda hacer precisamente eso. Asignar el número de días en el mes a devolver de una función que escribiremos, que aceptará el mes como argumento. Dando una definición a esta función, aceptando el mes como parámetro de tipo string, también necesita un dato más, un tipo de retorno. El tipo de valor devuelto por una función se define después los paréntesis con un guión y mayor lansinn una flecha, seguido del nombre del En este caso, se trata de un número entero, que representa el número de días en el mes. Si no especificamos un tipo de retorno, el tipo de retorno para cualquier función que escribamos es nulo por defecto. Dentro de nuestra función, necesitamos devolver un entero, lo que significa que debemos declarar un entero en la parte superior de la misma, y deberá contener el número de días en el mes. Entonces en la parte inferior de la función, devolveremos el valor que se mantiene en esta variable. Entre estas dos líneas, necesitamos poblar nuestra variable con el número correcto de días basado en el mes Si el mes es enero, entonces el número de días es 31. Anteriormente aprendimos que podemos proporcionar una alternativa con la palabra clave se, pero eso solo nos brinda dos opciones de las 12 que necesitamos. Podemos usar otra palabra clave, if, short for se si para proporcionar otra condición que se verificará si la condición original era falsa. Entonces si el mes es febrero, entonces el número de días es 28. Y podemos repetir esto tantas veces como sea necesario, brindando un caso para cada posibilidad. Pero muchas de estas opciones tienen el mismo resultado, ya sea 30 días o 31 días. Podríamos mejorar enormemente la eficiencia de esta declaración if combinando el resultado más común, 31 días para ser el caso predeterminado y reemplazarlos todos con una sola palabra clave else al final Entonces, si el mes no es febrero o cualquier mes con 30 días, entonces el número de días debe ser 31. Todos los casos que resulten en 30 días también se pueden combinar en una sola declaración utilizando el operador u. Si el mes es septiembre o si el mes es abril o si el mes es junio, o si el mes es noviembre, entonces el número de días es 30. Pero la afirmación es bastante larga con más casos, podría salir corriendo de la pantalla. Para declaraciones simples caso por caso como esta, hay una palabra clave más limpia y más fácil de usar que la declaración I llamada match. Coincidir es seguido por el nombre de una variable, dos puntos y luego un bloque de código con sangría Dentro de un bloque de coincidencia, podemos especificar cualquier número de casos específicos para el valor de la variable. Empecemos con febrero. Al caso también le siguen dos puntos y otro bloque de código con sangría Este código solo se ejecutará si el valor del mes es febrero. Podemos agrupar casos juntos en una lista separada por comas. Por lo que nuestra condición de declaraciones I se puede acortar en sólo una lista de cuatro meses. Si el valor del mes es septiembre, abril, junio o noviembre, entonces el número de días se establecerá en 30, y nuestro bloque puede ser reemplazado por un comodín representado con un guión bajo, estableciendo el número de días en 31 si el valor del mes es cualquier otra cosa no especificada anteriormente Esto es lo mismo que usar default en otros idiomas. Cada uno de estos bloques de código se denominan ramas. Y en el script GD, una sentencia de coincidencia sólo ejecutará alguna vez la rama superior cuya condición se cumplió En otros idiomas, esto es similar a una sentencia switch, pero difiere en que las sentencias switch pueden ejecutar más de una rama si se cumplen múltiples condiciones. Debido a esta restricción, no es necesario incluir descansos en las ramas de partido. Si quisiéramos imprimir el número de días en cada mes, probablemente querríamos usar un bucle, pero no podemos simplemente contar o incrementar una cadena como enero para que de alguna manera se convierta en febrero Por lo que es común en código cuando se representan cosas que existen en orden secuencial ponerlas en una lista numerada llamada enumeración Una enumeración en el script GD es solo un grupo de constantes relacionadas Podríamos tener una constante para enero con un valor de uno, otra para febrero con un valor de dos, etcétera Pero usando la palabra clave Enum, podemos nombrar al grupo de constantes, vamos a nombrarlo meses seguidos Dentro de las llaves, podemos agrupar las constantes y a cada una de ellas se les asignará un número automáticamente en función de su posición en esta lista Cualquier cosa contenida dentro de las llaves no necesita permanecer en una línea y se puede dividir en cualquier formato que prefiera para que sea más legible sangría no importa aquí, pero generalmente al escribir algo encerrado en llaves, la mayoría de los codificadores sangrarán al contenido, por lo que se ve similar a por lo que Si bien prefiero que los tirantes se alineen verticalmente, muchos codificadores prefieren poner el corsé de apertura en la línea de declaración así Al igual que Constance, las entradas de enumeración nombran convencionalmente en mayúsculas de serpiente Ahora que tenemos una enumeración, el mes puede restringirse al tipo de esta enumeración También podemos asignarle un valor de la enumeración, comenzando por su nombre, seguido de un punto, luego la entrada en la lista El mes que se agrega a la salida de la cadena ya no es una cadena en sí misma y se debe convertir en una cadena antes de que pueda ser agregada. El argumento que se pasa al número de días ya no es una cadena y ahora es un mes, y podemos alterar nuestra función para aceptar un mes como parámetro también. Como mes ahora es un mes, no una cadena, necesitaremos cambiar nuestras condiciones para que coincidan usando el nombre de la enumeración seguido de un punto, luego las entradas en la lista Pero cuando imprimimos los resultados, vemos que en lugar de enero, nuestro mes está escrito como el número cero. Mientras que el tipo de nuestra variable es un mes, que es una enumeración, el valor real se trata como un entero, su posición dentro de la enumeración Dado que enero es la primera entrada, su valor como entero es cero. Febrero sería uno, etcétera. Esto nos permite modificar el valor del mes con aritmética simple, por lo que enero más uno se convierte en febrero Si envolvemos este código en un bucle que se repite 12 veces, podemos iterar a través de los 12 meses con facilidad Pero, ¿qué pasa con escribir el nombre del mes como una cadena? Podríamos hacer esto de un par de maneras diferentes. Nuestro tipo de enumeración tiene una propiedad llamada keys, que es todas nuestras entradas como una matriz de cadenas Si indexamos esta matriz usando nuestra variable entera, nos da el nombre de entrada como una cadena que coincide con ese número. Pero siguiendo la convención de nomenclatura de mayúsculas de serpiente, es posible que no queramos imprimir el nombre de esta manera Podríamos cambiar el nombre de todas nuestras claves de enumeración en el caso Pascal, o podríamos declarar una constante que contenga la matriz de cadenas, manteniendo todos nuestros nombres de meses en un formato más presentable Luego usa el mes como índice en esta matriz. Otra cosa que podemos hacer con las enumeraciones es establecer manualmente los valores de las entradas usando el operador de asignación Digamos que queremos que enero sea uno en lugar de cero. El resto de las entradas actualizarán automáticamente sus valores para incrementar a partir de una, por lo que febrero es ahora dos Pero esto ya no coincide con los índices de matriz constante. Entonces, si quisiéramos usar esto para escribir el nombre de los meses, necesitaríamos o bien sumar una entrada vacía para el índice cero, O restar una del mes ya que se está utilizando para indexar la matriz En la siguiente lección, aprenderemos más sobre cómo el motor usa y ejecuta nuestros scripts Te veré en la siguiente lección. 9. 0-8 Árbol de escenas y herencia: Hola, amigos. Hoy aprenderemos sobre cómo el motor utiliza el árbol de escenas para ejecutar nuestros guiones. Todavía no he adjuntado un script al nodo raíz del árbol de escenas, pero en su lugar comenzaremos esta lección agregando más nodos. Pulsando con el botón derecho sobre el nodo raíz, luego seleccionando agregar nodo hijo, todavía solo un nodo normal, podemos renombrarlo para que sea presidente y pretender que nuestro árbol de escenas es la estructura de una empresa. El nodo presidente tiene sangría porque es hijo del nodo raíz de la escena Con un nodo seleccionado, también podemos usar el atajo Control A o Comando A para agregar otro nodo hijo. Vamos a nombrar a este gerente de operaciones, y se le sangra otro nivel porque es hijo del presidente Ahora vamos a adjuntar un nuevo guión al nodo presidente y nombrarlo empleado. Anulando la definición de nodos base de la función ready, podemos simplemente imprimir el nombre de este nodo y append está Este script se puede adjuntar a más de un nodo. Así que adjuntemos el mismo script al nodo del administrador de operaciones arrastrándolo desde la pestaña del sistema de archivos hasta el árbol de escenas Después corre la escena para ver qué pasa. Podemos ver que el gerente de operaciones está listo, luego el presidente está listo. Ambos nodos que tienen el script adjunto ejecutan el script, y como tienen diferentes nombres, la salida fue diferente. También podemos ver que el gerente de operaciones estaba listo antes de que el presidente estuviera listo. Para entender por qué necesitaremos agregar más empleados. El gerente de operaciones supervisará a una serie de operadores Añadiré otro nodo hijo al gerente de operaciones y le nombraré operador uno. A continuación, adjunte el guión del empleado. Podemos hacer clic derecho sobre cualquier nodo excepto el nodo raíz y seleccionar duplicado para crear una copia del mismo. El nombre de los duplicados incluirá automáticamente un número creciente, por lo que podemos tener el operador dos, tres y cuatro, etcétera Dado que el nodo que duplicamos tenía un script adjunto, las copias creadas también tienen el mismo script adjunto. Dado que los operadores tienen el mismo nivel de sangría y son todos hijos del gerente de operaciones, se les llama hermanos, y a los hermanos no se les permite tener el mismo Nuestra empresa debería tener más de un departamento, así que dupliquemos todo el departamento de operaciones duplicando al gerente de operaciones Todos los nodos hijos también están duplicados. Dado que los operadores no son hermanos directos, se les permite conservar sus nombres originales. Cambiemos el nombre del gerente para que sea gerente de marketing, y solo tendrán dos marketers trabajando en su equipo Los nodos principales también se pueden contraer para ocultar a sus hijos o expandirse para mostrarlos. Todos los empleados de esta empresa tienen el mismo guión de empleado adjunto a ellos. Así que vamos a correr la escena y tener una mejor idea del orden en que se ejecutarán los guiones. Podemos ver que el primer operador es el primero en estar listo, seguido de cada operador en secuencia, y finalmente, el gerente de operaciones. Lo mismo sigue para el departamento de mercadotecnia. Entonces finalmente, el presidente de la compañía es el último en estar listo. ¿Cómo decide Gadot esta orden de ejecución? El motor arranca en la parte superior del árbol de escenas y se abre camino hacia abajo, pero no considera que ningún nodo esté listo hasta que todos sus hijos estén listos. Entonces el presidente no está listo porque el gerente de operaciones no está listo. El gerente de operaciones no está listo porque los operadores no están listos. Los operadores están listos en secuencia, ya que no tienen hijos. Una vez que todos los operadores estén listos, entonces el gerente de operaciones está listo. Pero el presidente aún no está listo porque el presidente tiene otro hijo que no está listo. El gerente de mercadotecnia no estuvo listo hasta que todos los marketers estén listos, y finalmente, el presidente es el último en estar Dado que el nodo raíz no tiene un script adjunto a él, su función ready es la de un nodo predeterminado, que está vacío. Además de listo, hay otras funciones de nodo que podemos anular para ser ejecutadas más tarde después de que un nodo esté listo. El más común es proceso, también precedido de un guión bajo El motor hará todo lo posible para ejecutar la función de proceso de cada nodo en el árbol de escenas 60 veces por segundo utilizando la velocidad de fotogramas predeterminada del proyecto. Así proceso utiliza un parámetro llamado Delta, que es un número de punto flotante para representar el número de segundos que han pasado desde el fotograma anterior. Entonces, la mayor parte del tiempo será uno 60, pero no siempre. No necesitamos usar este parámetro para nada hoy, por lo que podemos continuar el nombre de este parámetro con un guión bajo, así Gudo sabe que no necesitamos usarlo y no debemos molestarlo Pero para anular la función de proceso, debe tener el mismo número y tipos de parámetros. Digamos a nuestros empleados que hagan algún trabajo en cada fotograma imprimiendo una declaración que diga su nombre adjunto a hace trabajo. Al ejecutar esta escena, vemos que todos nuestros empleados están trabajando muy duro, escribiendo sus declaraciones impresas 60 veces por segundo. Esto no es lo mismo que un bucle infinito ya que el trabajo en realidad se está haciendo de la manera en que se pretende y no se rompe nada. Hagamos esto un poco más fácil de entender al permitir que solo cada empleado haga una unidad de trabajo usando una variable de Bolan ha hecho trabajo con un valor predeterminado de false En la función de proceso, si el empleado no ha realizado ningún trabajo, entonces hará trabajo y cambiará el valor a true. Una 60 de segundo después, ya que la variable es verdadera, ya no van a funcionar. Pero si declaramos esta variable dentro de la función de proceso, entonces solo existirá dentro la función de proceso y solo para una sola iteración de la misma Siguiente fotograma, cuando la función de proceso se ejecuta la segunda vez, la variable se declara nuevo y todavía por defecto es false Entonces esto no tendrá ningún efecto. Para que nuestra variable persista, necesita existir fuera del contexto de la función de proceso. Entonces lo declararemos fuera la función sin ninguna sangría Las variables declaradas aquí se pueden acceder en cualquier parte de todo el script. Este concepto se llama alcance y es una de las principales razones por las que utilizamos sangría en nuestros Así podemos ver qué variables existen dentro de qué ámbito. Ejecutando la escena ahora, podemos ver a cada uno de nuestros empleados declara que están listos para trabajar. Entonces solo una vez que todos están listos, cada uno hace una unidad de trabajo, pero ahora en un orden diferente. El orden en que los nodos y el árbol de escenas ejecutan sus funciones de proceso sigue el orden exacto del árbol de escena de arriba a abajo. Los padres no necesitan esperar a sus hijos como la función de listo. Es posible que queramos que todos los empleados de nuestra compañía sean similares pero no exactamente iguales. El trabajo de un gerente no es realmente el mismo que el de un trabajador. Podemos usar la herencia para crear diferentes comportamientos para objetos similares. De la misma manera estamos escribiendo scripts que extienden nodo, pero cambiando cómo se preparan y cómo procesan. Primero, necesitamos darle a este script un nombre que podamos usar como referencia, usando la palabra clave class name, seguido de un nombre que describa el comportamiento del script, generalmente el mismo que el nombre del script, pero escrito en mayúscula Pascal Ahora que el motor sabe que se trata de un empleado, vamos a crear un nuevo guión y nombrar a este gerente. Pero en lugar de heredar del nodo, esta vez podemos heredar del empleado Debido a que nuestro script de gerente extiende al empleado, todo lo escrito en el guión del empleado seguirá aplicándose a este, pero podemos agregar más o hacer cambios. Un gerente sigue siendo un empleado, pero la forma en que trabajan es diferente. Deberíamos reemplazar el script adjunto a nuestros nodos manager por el nuevo script manager. Anulemos la definición del empleado de la función ready. Entonces, cuando un gerente esté listo, no solo dirán que están listos, sino que dirán que todo su departamento está listo. Para que nuestros dos gerentes puedan dar salida al nombre de sus departamentos, necesitarán una variable para contener el nombre de su departamento como cadena. Pero, ¿cómo podemos poblar esta variable para mantener diferentes valores para diferentes departamentos Si procedemos a nuestra declaración de variables con la etiqueta en la exportación, esta variable será accesible por otras partes del motor Gadot, es decir, el panel inspector Para que una variable sea exportada, debe declararse a nivel de ámbito de script. Seleccionando el gerente de operaciones y la escena, ahora hay un campo en el panel inspector donde podemos darle a la variable de departamento un valor De esta manera, el gerente de operaciones y el gerente de marketing pueden tener cada uno su propio valor para esta variable que podemos controlar fácilmente. Ejecutando la escena, podemos ver que los nodos que tienen el script del gerente adjunto ahora declaran que su departamento está listo, mientras que los demás empleados utilizan la definición anterior en el script de empleado. La función de proceso en el script del empleado también es heredada por los gerentes y se ejecuta de la misma manera que antes. Entonces cambiemos la función de proceso de nuestro gerente. Los gerentes dirán algo diferente. Name plus gestiona a los trabajadores para hacer su trabajo. La variable ha hecho trabajo del guión del empleado también fue heredada y no necesita ser declarada aquí para ser utilizada. De hecho, no podemos declarar una variable con ese nombre ya que causaría un conflicto con la variable heredada del mismo nombre. Volvamos a correr la escena y veamos cómo nuestros gerentes ahora hacen su trabajo de manera diferente a otros empleados. En la siguiente lección, aprenderemos más sobre el uso de nodos en el árbol de escenas y principios de diseño orientado a objetos. Te veré en la siguiente lección. 10. 0-9 Abstracción y encapsulación: Hola, amigos. Hoy exploraremos cómo escribir clases que sean más fáciles de usar y entender. Imaginando un automóvil como nuestro marco de referencia. Vamos a crear dos nodos en nuestra escena, un conductor y un auto como hijo del conductor. A continuación, adjunte un nuevo guión a cada uno del mismo nombre. Los autos son piezas de maquinaria muy complejas, y la mayoría de las personas que los conducen no tienen idea de cómo funcionan realmente. Sólo entienden cómo operar su auto. Comencemos en el guión del auto y le demos un nombre de clase de auto, luego agreguemos una variable para el año del auto como número entero. Otro para la marca del auto como cuerda y otro para el modelo también como cuerda. Exportando todos estos, configuraré mi auto para que sea un Honda Civic 2007. Al crear una nueva clase, asegúrese de guardar el script antes de intentar usarlo. En el guión del conductor, el conductor necesitará una referencia al automóvil, que podemos almacenar en una variable de tipo auto. Los nodos pueden acceder a otros nodos en el árbol de escenas, mayoría de las veces sus hijos usando otra etiqueta similar a la exportación llamada on ready. Usando la etiqueta on ready, podemos asignar el valor de la variable después de que el nodo esté listo, lo que significa que todos sus hijos también están listos, pero antes de llamar a la función ready de este nodo. Podemos asignarlo al valor de retorno de un nodo G de función incorporada, que acepta una ruta de nodo como parámetro. Si especificamos el nombre del nodo hijo entre comillas, ahora tenemos una referencia al nodo hijo almacenada en una variable, y podemos acceder a sus propiedades y funciones, incluidas las del script adjunto. Anulando la definición de la función ready, podemos acceder al nodo del automóvil e imprimir su año, marca y modelo La función ready se ejecuta después de las etiquetas on ready. Existe un atajo para la función get node sea más fácil, el signo de dólar, seguido de la misma ruta de nodo. Et vuelve al guión del auto y agrega otra variable. Éste especificando si el motor está funcionando o no como un booleano Como conductor, sabemos si el motor está funcionando y tenemos control sobre si el motor está funcionando o no, ya que podemos elegir arrancar o detener el motor usando la llave. Por lo que consideraríamos que esta variable es pública. Otra propiedad de nuestro auto podría ser el número de cilindros en el motor como un entero, y lo asignaré para que tenga un valor de cuatro. Esto es algo que el conductor no necesita saber, no puede acceder fácilmente y nunca se le debe permitir cambiar. Entonces, a diferencia de la variable pública, ésta sería considerada privada, y podemos marcarla como privada procediendo su nombre con un guión bajo En el guión del conductor, podemos establecer el valor de engine is on a true poniendo la llave en el encendido y girándola. Pero primero, deberíamos estar apretando el pedal del freno. Usemos una función para establecer presión que se está aplicando al pedal del freno, que asumiremos es de hasta un máximo de 20 kilogramos de fuerza. Entonces, para arrancar nuestro auto, probablemente deberíamos establecer la presión del freno en algún lugar alrededor de 10 kilogramos. De vuelta en el guión del auto, necesitaremos definir esta función que establece la presión del freno. Al igual que el motor está en variable, esto se llamaría función pública, ya que está siendo utilizada por otro script. Esta función aceptará un número de punto flotante como parámetro que representa la cantidad de presión que se aplica al pedal. Pero, ¿qué hace realmente el auto cuando aplicamos presión al pedal del freno? Desde la perspectiva del conductor, el conductor elige aplicar una cierta cantidad de presión al pedal sin saber nunca la posición exacta. Desde la perspectiva del automóvil, la posición del pedal es lo que se mide y se utiliza para detener el automóvil. El automóvil utiliza la posición del pedal de freno para ajustar la cantidad de presión se aplica a las pinzas que sujetan las pastillas de freno contra las ruedas del automóvil, sin mencionar la complejidad de los frenos antibloqueo u otros sistemas Entonces, si realmente estuviéramos programando un auto real, necesitaríamos escribir aquí varias funciones complejas que conviertan la simple acción del conductor aplicando presión al pedal del freno a la compleja mecánica de apretar las pinzas Esto forma parte de las funciones internas del automóvil y no nada que sea controlado o accesible para el conductor a través cualquier medio que no sea aplicar presión al pedal del freno. Por lo que consideraríamos que estas son funciones privadas, ya que sólo están destinadas a ser utilizadas por el propio automóvil. Y podemos marcar nuestras funciones privadas procediendo sus nombres con un guión bajo Observe cómo esto es lo mismo que el proceso y las funciones listas. La forma en que GDScript usa variables y funciones privadas es más parecida a la forma otros lenguajes usan las protegidas en el sentido de que son accesibles para los herederos GD Script en realidad no hace cumplir estas reglas de privacidad Sin embargo, GD Script en realidad no hace cumplir estas reglas de privacidad y los scripts aún pueden acceder a miembros privados Estas convenciones existen únicamente para facilitar una mejor estructura y diseño de clases. Otra forma de usar comentarios en GD Script es crear regiones de nuestros scripts que estén relacionadas, usando la palabra clave region seguida del nombre de la región Podemos terminar una región usando la palabra clave y la región. Entonces hagamos una región pública y una región privada en nuestro guión de autos, separando lo que debería ser accesible para el conductor y lo que no debería. Para que las cosas sean simples, digamos que el conductor solo necesita poder encender o apagar el motor, aplicar presión al acelerador, aplicar presión al pedal del freno o girar el volante. Lo que realmente sucede dentro de cualquiera de estas funciones públicas es la mecánica interna del propio automóvil. El conductor no necesita saber cómo funciona ninguno de ellos para operar el automóvil. Por ejemplo, al presionar el acelerador, lo que realmente está sucediendo es que el automóvil abre una válvula de admisión de aire en el motor, dejando entrar más aire y oxígeno en el motor. Por lo que el automóvil necesita usar un sensor para medir la cantidad de flujo de aire y la cantidad de oxígeno que ahora fluye hacia el motor. Luego use eso para ajustar la cantidad de combustible que se inyecta en los cilindros del motor. Todas estas funciones son privadas, ya que no necesitamos saber qué hacen realmente para conducir el automóvil. forma en que nuestro automóvil se mueve estaría en la función de proceso, y necesitaremos otra variable privada llamada fase para representar en cuál de las cuatro fases se encuentra actualmente cada cilindro. En la función de proceso del automóvil, si el motor está funcionando, podemos iterar a través de cada uno de los cilindros del motor Sumando el cilindro y la fase, luego módulo cuatro, obtenemos una fase diferente para cada cilindro. Coincidiendo con este número, podemos decirle a cada cilindro que realice una fase diferente, la carrera de admisión, carrera de compresión, la carrera de combustión o la carrera de escape, aceptando cada uno el cilindro como argumento. Después aumenta la fase y vuelve al ciclo a cero cuando llega a cuatro. Cada una de estas funciones puede entonces controlar las válvulas de admisión, válvulas de escape, inyectores de combustible y bujías de cada cilindro para hacer funcionar el motor La cantidad de fuerza que producen las carreras de combustión de cada cilindro movería entonces el automóvil hacia adelante mientras las pastillas de freno intentan detenerlo, y la posición del volante cambia su dirección. La posición del auto se movería entonces por la dirección, velocidad y el tiempo Delta. No te preocupes si nada de esto tiene sentido para ti porque ese es precisamente el punto de esta lección. No hace falta que lo entiendas. Dado que todo esto se encuentra en la región privada del guión, el conductor no necesita saber cómo funciona nada de esto para poder conducir el automóvil. Solo necesitan saber usar la región pública del guión. La separación de lo público y lo privado impone dos importantes principios de programación orientada a objetos encapsulación es la región pública, proporcionando acceso a variables públicas o funciones fáciles de usar y fáciles de entender, y la abstracción es la región privada, ocultando los detalles de sistemas o mecánicos complejos que no necesitan ser entendidos para ser utilizados de manera efectiva Sabrás si tus clases se adhieren a estos principios si puedes ocultar todos los contenidos privados y aún así entender fácilmente cómo está destinado a ser utilizado. Por lo que nuestro conductor ahora puede simular conducir el automóvil accediendo solo a las regiones públicas del guión del auto, desde presionar el freno y arrancar el motor hasta soltar el freno, presionar el acelerador, girar el volante, etcétera Estos principios no solo son importantes para nuestros propios scripts, sino que también nos permiten usar scripts escritos por otros desarrolladores sin comprender completamente cómo funcionan internamente. También hacen que los scripts R sean más flexibles. Imagínese si cambiáramos nuestro auto de gasolina por un auto eléctrico ¿Algo en el guión del conductor tendría que cambiar? Solo habría que cambiar el guión del auto por un guión de automóvil eléctrico, ya que todas las variables y funciones públicas seguirían existiendo en el guión de los autos eléctricos. De igual manera, también podríamos cambiar el script del conductor a un script de piloto automático, uno que solo necesita ser dado un destino y automáticamente podrá operar el automóvil En la siguiente lección, aprenderemos aún más sobre los principios de diseño orientado a objetos. Te veré en la siguiente lección. 11. Polimorfismo 0-10: Hola, amigos. Hoy cubriremos el último de los principios de programación orientada a objetos, el polimorfismo Ampliando los conceptos de herencia y abstracción, podemos escribir clases que representan un concepto más abstracto, una colección de clases más específicas que están relacionadas. Usemos animales como ejemplo creando un script llamado animal que extienda nodo, pero no necesitamos adjuntar este script a ningún nodo en el árbol de escenas. Aquí podemos darle al script un nombre de clase, luego definir propiedades y comportamientos que son comunes a todos los animales, como una variable para contener el plural del animal como una cadena, y otra para el nombre para una agrupación de este animal. Y definamos también una función para que el animal se mueva, coma o hable. Si bien podemos definir fácilmente el plural de animal como animales, no hay palabra para un grupo de animales. Tampoco podemos definir cómo se mueve o come un animal sin saber qué tipo de animal es. Por lo que los cuerpos de estas funciones pueden permanecer en blanco. Pero podríamos considerar que algunos comportamientos son lo suficientemente comunes como para que tengan un defecto, como hablar. Si bien hay muchos mamíferos diferentes que hacen una amplia variedad de ruidos, la mayoría de los animales no, incluyendo peces e insectos La mayoría de la gente no los describiría como hablando. Entonces, al decirle a cualquier animal al azar que hable, podríamos considerar que el comportamiento predeterminado es el silencio. Entonces agreguemos algunos animales diferentes a nuestro árbol de escena, empezando por un gato. Ahora podemos usar herencia, como tenemos antes para hacer cualquier número de diferentes escrituras de animales que hereden de animal como gato Luego anularemos la función ready para dar a las variables que se heredan del animal un valor apropiado para un gato. El plural serían gatos, y un grupo de gatos se llama Clouder Las funciones de comportamiento también pueden ser anuladas para cambiar el comportamiento del habla silenciosa a Los gatos caminan sobre cuatro patas para moverse, y voy a decir que comen pescado. El contenido real de estas variables y funciones no son relevantes, pero el foco está en cómo se heredan del concepto abstracto de un animal a una instancia más específica de un gato. Podemos repetir este proceso para hacer muchos más tipos diferentes de animales para agregar a nuestra escena árbol como un pájaro o un pez. Y dando a cada uno un nuevo script heredando del animal, cada uno puede proporcionar sus propios valores únicos para las variables e implementaciones de las funciones que heredaron El plural de ave es aves. Un grupo de aves se llama rebaño. Vuelan para moverse, comen gusanos y gorjean para hablar Voy a tener ventaja en mi guión de peces copiando el contenido del guión de gato. Y el plural de los peces es el pescado. Un grupo de peces se llama escuela. Nadan para moverse, comen algas, pero no hablan. Al omitir la función de hablar, fish utilizará la definición heredada de la escritura animal para hablar Hasta ahora, todo lo que hemos hecho es usar los principios orientados a objetos que ya conocemos para heredar, abstraer y encapsular las propiedades y comportamientos de los animales Pero todo esto nos permite utilizar el polimorfismo tratando a todos los animales como si fueran iguales e intercambiables Primero, agreguemos un script al nodo raíz de nuestra escena y lo llamemos Zoo, heredando del nodo Nuestro zoológico está lleno de diferentes animales, pero no importa cuáles sean esos animales en realidad. Anulando la definición de la función ready para nuestro Zoo, podemos iterar fácilmente a través de nuestra lista de animales y tratarlos a todos como si fueran solo Una manera rápida y fácil de almacenar todos nuestros animales en una sola variable. Vamos a llamarlo animales es usar una función de nodo llamada Get children. Esto devuelve una matriz de nodos, todos los nodos hijos de este nodo convenientemente organizados en una matriz en el mismo orden que el árbol de escenas. Debido a que esto depende de los niños, debemos usar la etiqueta en on ready. Como sabemos que todos los animales tienen las mismas propiedades y comportamientos, podemos iterar a través de cada animal en nuestra variedad de animales y decirle a cada uno de ellos que hable Y a pesar de tratarlos a todos como animales, cada uno hablará a su manera única como lo definen sus propios guiones particulares o utilizará la definición heredada del animal si no tiene la suya propia. Podemos crear tantos niveles de herencia como queramos. Así que vamos a crear otro guión abstracto para mamíferos, heredando del animal Los mamíferos son una subcategoría de animales, incluyendo a todos los animales que tienen glándulas mamarias y los utilizan para cuidar a sus crías Estas son propiedades y comportamientos únicos de los mamíferos que no se aplican a otros animales. Así podemos agregar una nueva variable al guión mamífero para el número de glándulas mamarias que tiene este animal y escribir una nueva función llamada enfermera Nuevamente, los contenidos de las funciones no son relevantes para esta lección. Este script también necesitará un nombre de clase para ser heredado. Cambiando al guión del gato, ya que los gatos son mamíferos, y así podemos darle al número de glándulas mamarias un valor para los gatos, que debería ser ocho Y podemos agregar nuevos mamíferos a nuestro zoológico, también, como un mono. Los monos también son mamíferos, pero sólo tienen dos clanes mamarios Volveré a copiar el contenido de otro guión para hacer las cosas más rápidas. El plural de mono es monos. Un grupo de monos se llama tropa. Se mueven trepando árboles. Comen plátanos, y voy a decir que dicen oh. Nuestro guión del zoológico ahora puede aprovechar esta nueva estructura de herencia para aplicar condiciones únicas específicamente para animales que son mamíferos. Podemos usar directamente nombres de clase en declaraciones condicionales para decir, si el animal actual es un mamífero, entonces ejecutaremos algún código extra exclusivamente para mamíferos. Voy a imprimir algunas líneas adicionales que describen a nuestros mamíferos. Y podemos ver que nuestra salida es vez consistente para todos los animales, pero también tiene algo único específicamente para los dos mamíferos. Te puedes imaginar cómo podríamos cambiar nuestra lista de animales en nuestro zoológico para que sean cualquier tipo diferente de animales, y podríamos alterar nuestra estructura de herencia para categorizarlos con la mayor precisión que necesitemos En la siguiente lección, aprenderemos sobre otra recopilación de datos que podemos usar para agrupar información relacionada. Te veré en la siguiente lección. 12. Diccionario 0-11: Hola, amigos. Hoy usaremos una alternativa a la matriz que a veces se usa como una clase sin ninguna función llamada diccionario. Imagina una fila de casilleros como la que encontrarías en una escuela secundaria o un gimnasio Si declaramos una matriz de variables, podríamos considerar que el índice de matriz de cada una es el número de casilleros. Digamos que hay diez casilleros, y podemos acceder a cada casillero individual para poner algo dentro, comenzando en el casillero cero, uno, y así sucesivamente. Lo que pongamos dentro de cada casillero no importa. Puede ser un entero, float, string, booleano, nulo o una instancia de una clase Y podemos imprimir el contenido de las taquillas para verlas. Ahora imagina que cuando metemos algo en una de las taquillas, no solo cerramos la puerta del casillero, sino que también le ponemos un candado de almohadilla. Este candado requiere una combinación de números de tres dígitos para abrirse Anteriormente, si deseamos recuperar el contenido del casillero, solo necesitábamos conocer el número de casilleros, caminar hacia él y sacar el contenido. Ahora podemos ignorar el número de los casilleros, y en su lugar, necesitamos saber la combinación para abrir el candado Digamos que la combinación es 149. Como matriz, asignar algo al número 149 significaría que la matriz tendría que tener 150 casilleros Si cambiáramos el tipo de nuestra matriz a un diccionario, esto seguiría funcionando excepto que no necesitamos establecer un tamaño para el diccionario antes de poder acceder a su contenido. Observe cómo ha cambiado la salida. Los diccionarios están representados por llaves en lugar de corchetes, y cada entrada es un número que representa una clave seguida de un valor de lo que está contenido en el casillero bloqueado por esa clave Tampoco hay entradas en el diccionario para ninguna clave a la que no se le asignó un valor. Como diccionario, este número no es un índice ni una dirección. Es una llave que utilizamos para abrir una cerradura. Y así como el contenido del casillero puede ser cualquier tipo de datos, las claves que usamos para bloquearlas también pueden ser cualquier tipo de datos con una sola restricción Cada clave debe ser única. De lo contrario, no podemos encontrar el casillero que coincida con la llave. Entonces intentemos cerrar un casillero con otro tipo de candado, uno que use letras en lugar de números. Entonces la clave de esta entrada del diccionario es una cadena, pero su valor es un número. Todo lo contrario de este casillero, cuya clave es un número y el valor es una cadena. Bloqueemos el siguiente casillero con un candado giratorio, que requiere tres números para desbloquearlo, que podríamos almacenar en una matriz. Entonces nuestra clave de entradas de diccionario es una matriz representada por corchetes que contiene una lista separada por comas de tres enteros A lo mejor este número de cerraduras incluye un punto decimal, por lo que la llave es un flotador. Y de alguna manera este casillero está bloqueado por la fotosensibilidad y solo se puede abrir si las luces están apagadas. Entonces su clave es un booleano. Incluso podemos usar clases personalizadas como nuestras claves o valores en diccionarios. Escribamos una nueva clase para key, que no necesitará heredar de nada ya que no se adjuntará a un nodo, ni se heredará Nuestra clase clave necesita un nombre de clase y tendrá una variable que describa sus dientes. La implementación de esta clase no es relevante, pero podemos pretender que es una clave. De vuelta en el script del casillero, podemos almacenar una instancia de nuestra clave en una variable. Vamos a llamarlo clave uno de tipo key asignándolo al nombre de clase de clave Nunu crea una nueva clave, que se asigna a nuestra variable Ahora podemos usar esta clave para crear una entrada en el diccionario. También podemos crear más claves para crear más entradas. Como cada clave que creamos se considera única. La salida ahora muestra las claves como arrecife contadas seguidas de un número largo. Los nombres que hemos usado en otras clases fueron heredados del nodo. Pero como la clave no hereda del nodo, no tiene nombre Ref count es la abreviatura de objeto contado de referencia, y es la clase base para el script GD Si escribimos alguna clase que no herede nada, heredará del arrecife contado y se le asignará un número largo aleatorio Podemos ignorar esto y simplemente entender que nuestras claves son objetos contados de referencia, lo que significa que Gadot está realizando un seguimiento automático de cada instancia única de cada objeto que creamos Pero, ¿qué queremos guardar en los casilleros? Al igual que las matrices pueden contener otras matrices, diccionarios también pueden contener otros diccionarios. Cotejando la forma en que se imprimen los diccionarios, podemos crear nuestros propios diccionarios sobre la marcha usando llaves Cada entrada comienza con una clave seguida dos puntos y luego el valor que coincide con esa clave. uso común de los diccionarios no es crear nada como este escenario de casillero, sino crear algo más como una clase, aunque una sin ninguna función, solo variables. Digamos que este casillero contiene un peluche, que representaremos con un diccionario. Y este peluche pertenece a un conjunto de peluches coleccionables que son similares pero variados a su manera Cada uno de los peluches es un tipo diferente de animal con un color y un nombre. Cada uno de estos pueden ser claves en el diccionario. Digamos que este casillero contiene a Bruno el oso pardo. Y el siguiente casillero contiene a Arthur el Cabra Blanca. Podemos ver nuestro diccionario peluches dentro del diccionario de casilleros. Se da la circunstancia de que el color también es una clase ya definida en Gadot Entonces, en lugar de almacenar nuestros colores como cadenas, se pueden almacenar como colores usando el color del nombre de la clase. Como puede ver, hay muchos colores predefinidos para que los usemos, y podemos decir por cómo se nombran en mayúscula serpiente, que estas son constantes de la clase de color Incluso podríamos fracasar esto y pretender que los peluches contienen una etiqueta NFC o de comunicación de campo cercano, convirtiéndolos en la llave para acceder al casillero. Y podemos poner lo que queramos dentro de la taquilla igual que antes, incluyendo otra felpa Hagamos otro peluche para guardarlo dentro del casillero, que se desbloquea usando Arthur como llave. Esta vez, es cutie, el elefante gris. Así que al imaginar este escenario, hay un lector NFC cerca de los casilleros, y estamos sosteniendo un plushe con una etiqueta NFC adentro, algo así como lo que podrías encontrar en una sala de escape Si sostenemos el peluche contra el lector, debemos verificar qué casillero coincide con el peluche y desbloquearlo, si algún casillero coincide. Pero si tratamos de acceder a una clave en un diccionario al que no se le ha asignado un valor, causaremos un error. la misma manera que lo haríamos si intentáramos acceder a un índice de matriz fuera de rango. Podemos verificar si un diccionario contiene una entrada que coincide con una clave específica usando la función tiene, luego pasando la clave como parámetro. Esto nos permite verificar si existe una entrada de diccionario antes de intentar acceder a su valor, evitando el error. Si el diccionario no tiene la clave, imprimiré un mensaje diferente. En lugar de definir el mismo diccionario dos veces, sería mejor almacenar en una variable y usar la variable dos veces. En la siguiente lección, exploraremos algunas técnicas diferentes que puedes usar cuando te quedes atascado o necesites más información. Te veré en la siguiente lección. 13. 0-12 Debug: Hola, amigos. Hoy repasaremos algunas estrategias diferentes que puedes usar para ayudarte cuando inevitablemente te quedes atascado. Ya adjunté un script al nodo raíz de la escena llamado debug. Probablemente hayas notado la función de autocompletar que está disponible si especificas el tipo de tus variables Esto no solo le permite ver todas las propiedades y funciones de la clase, sino que después de seleccionar una función, también puede ver los tipos de todos los parámetros de funciones para que pueda proporcionar argumentos coincidentes. A, cuando conoces los tipos de todas tus variables, esto hace que los errores de desajuste sean claramente evidentes, y se te avisará del error sin tener que ejecutarlo. Sin tipos estrictos, el motor no sabe qué es lo que no coincide hasta intentar ejecutar la línea Si quieres navegar a través de una clase incorporada como color, podemos acceder fácilmente a la información haciendo clic en cualquiera de los botones en la esquina superior derecha del panel. Online Docs abre una pestaña en tu navegador web predeterminado a la API de GADO que coincide con la versión del editor que estás usando. Aquí encontrarás información básica sobre consejos de Gdo para comenzar, tutoriales detallados sobre los conceptos básicos, enlaces a la comunidad donde puedes encontrar recursos adicionales y una referencia completa de clase Como puedes ver, hay muchas clases. Y seleccionando cualquiera de ellos, podemos ver de qué heredan y qué otras clases son heredadas Cada uno tiene una descripción de lo que hace. Enlaces a tutoriales sobre cómo usarlo, una lista de propiedades y métodos. Cuando hablamos de clases, tendemos a referirnos a las variables como propiedades y a las funciones como métodos. También hay señales, algo que Gadot usa para comunicación automática entre nodos, enumeraciones y constantes como las que hemos usado antes Todos estos tienen sus propias subsecciones y descripciones de cómo utilizarlas. De vuelta en el Editor de GDA, buscar Ayuda abre una ventana en GDA donde se puede ver una lista de cada clase Seleccionando una clase, podemos ver toda la misma información que está disponible el sitio web de GDA en nuestro editor, para que podamos acceder a ella sin conexión Volviendo a nuestro script, incluso podemos acceder a esta información más fácilmente manteniendo presionada la tecla de control o comando que haciendo clic en el nombre de una clase, llevándonos directamente a la información de referencia para esa clase. Lo mismo se puede hacer para funciones y variables específicas. Al hacer clic sobre ellos no solo se abre la página de referencia a la clase, sino que también nos lleva a la función o variable en la que hicimos clic También hay funciones globales que podemos usar mayormente para realizar operaciones matemáticas como clamp, por ejemplo. Si usamos esta función, podemos ver los parámetros que está esperando y podemos usarla para sujetar nuestra variable para que sea 0-1 Sostener la tecla de control o comando y hacer clic en el nombre de la función global nos permitirá acceder a la referencia de esta función, completa con una descripción y cómo usarla. Todos estos están contenidos dentro de la clase de alcance global. Voy a añadir otra variable y otra línea a mi guión. Si ejecutamos nuestra escena, podemos ver el árbol de escenas de la simulación en ejecución a través del panel de escena haciendo clic en el botón remoto. Este no es el mismo árbol de escenas en la pestaña local que construimos para definir la escena como un plano Este árbol de escenas es el que fue construido por el motor para ejecutar la escena. Seleccionando cualquier nodo, podemos ver sus propiedades en el inspector y podemos ver que la función ready ya se ha ejecutado ya que los colores tienen valores diferentes. También podemos cambiar los valores de cualquiera de estas propiedades. También podemos usar print para imprimir siempre que queramos ver lo que nuestras variables tienen en cualquier momento. Y ayuda a ser lo más descriptivo posible con tus estados de cuenta impresos, así que no hay confusión sobre de dónde vienen . Pero si cambiamos las cosas y usamos la función de proceso, simplemente cambiaré el color gradualmente con el tiempo, luego agregaré una declaración de impresión aquí. Dado que esta función de proceso se ejecuta 60 veces por segundo, el valor de las sentencias print como herramienta de depuración se ve muy disminuido ya que el registro de salida simplemente va a repetir el mismo mensaje más rápido de lo que posiblemente podamos leerlo o reaccionar ante Podemos pausar la simulación mientras se está ejecutando, usando el botón de pausa o presionando F seven. Esto nos permite ver el árbol de escenas remoto tal como está en este momento y revisar el contenido del panel de salida con la simulación en pausa Pero esto todavía no es muy útil, ya que se completarán varios fotogramas entre el momento en que comience la simulación y cuando podamos pausar la misma. Si hacemos clic a la izquierda de cualquier línea de código, podemos agregar un punto de interrupción automático indicado con un círculo rojo Cuando ejecutamos la escena actual, la simulación se detendrá cuando llegue a esta línea antes de ejecutarla. Esto es mucho más útil si queremos que nuestra simulación se ejecute un fotograma a la vez. Ahora podemos ver como cada fotograma el color cambia gradualmente de un fotograma al siguiente. Hagamos que nuestra función de proceso llame a otra función para realizar una tarea sencilla. Simplemente voy a cambiar el color gradualmente reduciendo su valor rojo. Entonces ahora deberíamos ver que el color cambia gradualmente cada fotograma volviéndose menos rojo y más azul. Con el punto de interrupción aún en la primera línea de la función de proceso, ejecutaré la escena Aquí se detiene, y podemos ver que la siguiente línea de código a ejecutar se indica con un triángulo amarillo. Si bien la simulación se pausa así, podemos decirle que ejecute solo una sola línea de código a la vez, en lugar de un fotograma completo seleccionando step over del menú Debug o usando el atajo F ten Esto ejecutará solo la línea de código a la que apunta el triángulo amarillo, luego hacer una pausa de nuevo de inmediato. Entonces podemos ver los cambios realizados solo por esa sola línea de código, y podemos ver el triángulo amarillo apuntando a la siguiente línea esperando ser ejecutados. Podemos seguir ejecutando nuestro script línea por línea si seguimos pisando hasta que termine la función de proceso y el frame esté completo, volviendo a la parte superior de la función de proceso para ejecutarse por segunda vez. Ahora podemos ver cada cambio individual al color a medida su valor azul se incrementa por separado de cuando se disminuye el valor rojo, pesar de que ocurren durante el mismo fotograma. En el caso de las llamadas a funciones, hay otra opción para entrar en la función. Si seleccionamos esta opción o usamos el atajo F 11, la flecha amarilla en su lugar entrará en la función que se llama y ejecutará esa línea a la vez hasta su finalización. Cuando se completa la función, la flecha amarilla vuelve a la función original para continuar ejecutándola. Usando estas herramientas, tenemos una visión muy enfocada de lo que están haciendo nuestras clases y cuándo, cómo se comportan y podemos verlas en cámara tan lenta como necesitamos para averiguar qué está yendo mal en qué momento específico en el tiempo Si no puedes resolver un problema tú mismo, la comunidad GDA es muy servicial y siempre dispuesta a echar una mano Hay servidores de Discord para desarrolladores de GDA, incluyendo mi servidor donde mis alumnos se ayudan unos a otros El enlace para unirte está en mi perfil. También hay foros en línea en sitios web como Redit donde también puedes hacer preguntas. Ahora tiene una comprensión básica de la mayor parte de la sintaxis de GDScrip y las herramientas necesarias para explorar estos conceptos más a Cuando estés listo, por favor pídeme un código de descuento para cualquiera de mis cursos de proyecto de juego, y buena suerte. 14. 1 3 Configuración: Oh amigos, bienvenidos a mi curso. Estoy haciendo un juego de plataformas completo de dos píxeles D en Godot. Para comenzar con el motor Cado, primero deberá descargarlo de su sitio web, dirigirse a GodoEngine.org y descargar la última versión estable Para este curso, estaré usando God versión 4.2 Una vez completada la descarga , solo descomprima la carpeta y ejecute el archivo EX Asegúrese de reubicar estos archivos descomprimidos a una ubicación adecuada en su Me gustaría tener el motor anclado a mi barra de tareas para facilitar el acceso No hay instaladores complicados, concentradores o interfaces de almacenamiento para atravesar. Si alguna vez has trabajado con otros motores de juego, probablemente te sorprenderá lo simple y fácil que es usar Good. Por comparación, cuando estés listo, haz clic en el botón Nuevo Proyecto. Dale un nombre a tu proyecto. Esto suele ser lo mismo que el título de tu juego, pero muchas veces los juegos empiezan sin tener todavía un título oficial. Los desarrolladores usarán cosas como Untitled Platform o Untitled Pirate game hasta que se elija un título oficial Selecciona dónde en tu disco duro quieres que se almacene el proyecto . Te recomiendo hacer una subcarpeta en documentos llamados Godot Projects y dar a cada uno de tus proyectos su propia carpeta dedicada dentro de esa carpeta para mantenerlos organizados. Dado que el juego que vamos a hacer utiliza arte simple de dos píxeles D en dos escenas D, podemos usar el renderizador de compatibilidad que admite plataformas de escritorio, móviles y web y es el más rápido en renderizar escenas simples como la nuestra. Por último, Dios optimizará compatibilidad con el control de versiones de Github por defecto, lo cual es muy útil cuando termines, haz clic en Crear y en It para crear el proyecto y abrirlo para editarlo. El proyecto se abre en una escena vacía de tres D, pero estamos haciendo un juego de dos D. Debajo de la pestaña Escena, que se encuentra en la esquina superior izquierda. Por defecto, haga clic en dos escenas D para crear una nueva escena de dos D. Esto cambiará automáticamente nuestra vista del editor a dos modos D. Si alguna vez encuentras que tu editor está en modo tres D, siempre puedes cambiar con los botones en la parte superior de la ventana del editor. Cado. Cada escena se define como un árbol de nodos. La escena misma se define como un nodo dos. Es un nodo dos D, este es el nodo raíz de escenas. Construimos nuestras escenas agregando ramas al árbol de escena. Haga clic en el botón más debajo la pestaña Escena para agregar un nodo al árbol de escenas. Como puede ver, hay muchos tipos de nodos diferentes. Escriba, etiquete en la barra de búsqueda y agregue un nodo de etiqueta a su escena. Seleccione su nuevo nodo Las propiedades de nodos A se pueden editar en la pestaña del inspector, que se encuentra en el lado derecho de la ventana del editor. Por defecto, escribe cualquier mensaje que te guste en el área de texto. Cuando hayas terminado, guarda tu escena seleccionando escena en la barra de menú y luego guarda la escena. También puedes usar el teclado short cart control S, o comando S, dar un nombre a tu escena. La convención de nomenclatura para Godot es usar el caso de serpiente, que es todo minúscula con guiones bajos en lugar Haz clic en el botón Guardar para guardar tu primera escena. Cuando hayas terminado, presiona el botón Ejecutar escena actual en la esquina superior derecha de la ventana del editor. Es el que tiene el icono de play en una tabla de chapaletas. Esta aún no es una escena muy emocionante, pero funciona. Haga clic en el icono de parada para detener la escena. Bajo la pestaña del sistema de archivos, que se encuentra en la esquina inferior izquierda, por defecto, puedes ver una lista de todos los archivos que conforman tu proyecto. Cada nuevo proyecto de Godot tiene solo un archivo de recursos proporcionado por defecto, el logotipo de Godot Haz clic y arrastra el logo a tu escena. Esto agregó un sprite dos nodos D llamado icono al árbol de escena y establecer el icono como la textura de sprites Esto es solo una imagen que se está dibujando en pantalla. Preparémonos para la siguiente sección del curso haciendo un piso sólido para nuestro personaje camine y salte. Para eso necesitaremos agregar colisión. Haga clic derecho en el nodo icono y seleccione agregar nodo hijo. Usando la barra de búsqueda, busque el cuerpo estático dos nodos D. Esto agrega el nuevo nodo como hijo del sprite, pero está mostrando una advertencia Si pasamos el cursor sobre el icono de advertencia , nos dará más información Este nodo no puede chocar con nada porque no sabe qué forma es Para ello, el cuerpo estático dos nodo D necesita otro nodo hijo. Añadiendo otro nodo como antes este tiempo buscar colisión forma dos nodo D, el icono de advertencia en el cuerpo estático Tu T nota ha desaparecido. Pero el recién agregado nodo Tut de forma de colisión tiene otra advertencia Nos pide polo que por favor cree un recurso de forma para ello. Esto se hace en el panel inspector usando el menú desplegable etiquetado Forma Seleccionar nueva forma de rectángulo. Esto ha satisfecho la advertencia. Pero mirando la escena, podemos ver que la forma de colisión no coincide con el icono. Si queremos que la colisión cubra todo el icono, necesitamos ajustarlo. Puede hacer clic y arrastrar sobre los círculos rojos para cambiar el tamaño de la forma de colisión Si desea un control más preciso, puede hacer clic en el recurso de forma rectangular dos D para expandirlo, lo que expone campos de texto donde puede ingresar valores exactos para el tamaño Si la forma de colisión está descéntrica, puede expandir la sección de transformación bajo el nodo dos D para ajustar su posición. También puede ajustar este valor manualmente haciendo clic y arrastrando la Cruz Roja en el centro de la forma de colisión Seleccione el nodo icono y renombrarlo a floor. Como ya no necesitamos hacer ningún ajuste a los nodos secundarios, podemos contraer este nodo haciendo clic en la flecha de colapso. Ahora vamos a convertir esto en un piso real. Ajusta tu vista dentro de la ventana gráfica hasta que puedas ver todo el borde azul superpuesto con el eje x rojo, la parte superior de la caja aparece magenta y aparece el lado izquierdo superpuesto con el eje Y verde. ¿Puede este cuadro azul ser los límites de la pantalla cuando ejecutamos el juego con el nodo de piso seleccionado, ajustar su posición, tamaño y forma para que cubra la parte inferior de la pantalla. Al mantener presionado el botón Alt u Opciones, solo se moverá el nodo seleccionado y sus hijos. Acabamos de crear un piso funcional para nuestro entorno de prueba de juegos de nada más que el ícono de Godot Este tipo de flujo de trabajo es común en el desarrollo de juegos. Usar activos de marcador de posición para crear un proyecto mínimo, que se puede utilizar para crear prototipos y demostrar la mecánica del juego Pero para hacer un juego que se vea bien, necesitaremos activos. He construido este curso usando un paquete de activos gratuito llamado Treasure Hunters, creado por Pixel Frog. A partir de ella, estos activos se liberan bajo una licencia Creative Common Zero. Puede distribuir, remezclar, adaptar y construir sobre el material en cualquier medio o formato, incluso con fines comerciales No se requiere atribución. Puedes descargar el paquete completo de activos de forma gratuita u opcionalmente apoyar al artista pagando cualquier cantidad de dinero que elijas. Una vez completada la descarga, descomprima la carpeta. Importar los activos es tan simple como hacer clic y arrastrarlos a la ventana del proyecto También usaré efectos de sonido y música descargada de Freesound.org La biblioteca de bucles Victory War y Battle Music fue compuesta por Little Robot El pack de sonidos Battle es creado por Luke Sharpals. Estos archivos de sonido y música están bajo licencia de atribución. Todavía son de uso gratuito para cualquier propósito, pero debes darle el crédito apropiado al creador de estos activos y proporcionar un enlace a la licencia. Preste mucha atención a los requisitos de licencia y atribución de los activos que incluya en sus juegos La importación de estos activos funciona igual que la obra de arte. Simplemente haz clic y arrástralos al editor. Sin embargo, estos archivos de audio son mucho más grandes que las imágenes y no vamos a estar usando muchos de ellos. Te recomiendo únicamente importar estos activos a medida que decidas implementar cada uno. Ahora tenemos un piso funcional con colisión y todos los activos artísticos que necesitamos para iniciar la siguiente sección que estará implementando un personaje. Te veré en la siguiente sección. 15. 2 1 personaje: Hola amigos. En la primera sección, iniciamos el proyecto, importamos algunos activos y creamos un piso funcional con colisión. En esta sección, nos centraremos en crear un personaje para que el jugador controle y juegue con él. Para comenzar, primero construiremos la estructura de nodos de un personaje típico en el panel de escena. Haga clic en el botón más para agregar un nuevo nodo al árbol de escenas. Busca un cuerpo de carácter nodo dos D, y créalo. Voy a cambiar el nombre de este nodo por el nombre de mi personaje. Al igual que con el piso, hay una advertencia. Este nodo no tiene forma. Por lo que no puede colisionar o interactuar con otros objetos. Ya sabemos cómo remediar este problema. Simplemente agregue una forma de colisión dos nodos D y defina su forma. La advertencia nos recuerda que debemos crear un recurso shape en el inspector. La mayoría de los personajes en los juegos usan cápsulas como sus formas de colisión porque se ajustan fácilmente para abarcar la forma general de un humanoide y son simples para que el motor funcione Por defecto, se agregan nuevos nodos en el origen de la escena en la esquina superior izquierda. Vamos a acercar los nuevos nodos. También necesitamos poder ver cómo se ve el personaje. Para eso, agregaremos otro nodo hijo al personaje, A sprite, dos D. Vimos en la lección anterior que hay una propiedad de textura en el panel inspector para sprites, pero esta está vacía navegando por el paquete de activos de los cazadores de tesoros Seleccione un sprite de carácter para usar. Por defecto, no quiero que mi personaje esté equipado con la espada por defecto. Seleccionaré de la carpeta sin espada y escogeré una inactiva. Ahora podemos ver al personaje como será dibujado en el juego, pero está borroso Eso se debe a que la configuración predeterminada del proyecto de Godo no está optimizada para pixel art Para arreglar este proyecto seleccione en la barra de menús, luego Configuración del proyecto. Hay muchos ajustes de proyecto y dependiendo de tu versión de Godot, es posible que no estén organizados o nombrados de la misma manera Si tiene problemas para encontrar alguna configuración del proyecto, hay una barra de búsqueda en la parte superior de la ventana etiquetada como configuración de filtro. Necesitamos encontrar la configuración para renderizar dos texturas D, luego cambiar el filtro de textura predeterminado de lineal a más cercano. Esto impedirá que el motor gráfico intente suavizar la textura y simplemente dibujar como está en la pantalla. Con los cambios realizados, podemos cerrar la ventana y ahora el carácter se dibuja en píxeles perfectamente definidos. Cuando se trabaja con pixel art, esta es generalmente la estética preferida. Con los ejes X rojo y Y verde marcando el origen de la escena. Debemos asumir que el origen del personaje estará a sus pies. Arrastremos el spread hacia arriba hasta que el eje X rojo actúe como un piso donde se parará el personaje. Asegúrese de que también estén centrados alrededor del eje Y verde. Para facilitar el ajuste de la forma de colisión, volveré, ordenaré que esté debajo del sprite en el árbol de escena pero aún así la infancia para el personaje Esto también determina en qué orden se dibujan los nodos en pantalla. Con la forma de colisión frente al sprite, es más fácil moverse y ajustar su tamaño para que coincida con el personaje Recuerda que el punto inferior de la cápsula de colisión debe alinearse con los pies del personaje y el eje X rojo para que el personaje se pare limpiamente en el suelo Y también debe estar centrado alrededor del eje Y verde. En dos juegos D como este, generalmente se considera buena práctica hacer que la forma de colisión sea más pequeña que el personaje. Esto evitará que el jugador sea golpeado por ataques que percibirían estar cerca de la señora y le permitirá acercarse al entorno. Antes del siguiente paso, asegúrese de que su panel del sistema de archivos esté enfocado en la carpeta de recursos raíz. crearán nuevos recursos en la última carpeta con la que interactuó En el panel del sistema de archivos, puede contraer cualquier carpeta abierta y hacer clic en el espacio en blanco. Si tu aseguradora con eso hecho bien, da clic en tu personaje Podemos tomar cualquier rama en nuestro árbol de escena y guardarlo como su propia escena. Voy a nombrar esta nueva escena después del personaje que ya está hecho ya que usará el nombre del nodo como el nombre de la nueva escena por defecto. Ahora Roger es su propia escena separada de la escena en la que hemos estado trabajando. nodo de Roger en el árbol de escenas tiene un botón de tablero de chapaleta y los nodos hijos se han ocultado Al hacer clic en la tablilla se abre la escena de Roger. Esto nos permite editar a Roger de forma aislada. Cualquier cambio que hagamos aquí será transferido a todas las escenas que contengan a Roger en la escena principal. Ahora podemos trasladar a Roger desde el origen de la escena hasta el piso donde serán dibujados en pantalla. Si corremos la escena actual, podemos ver a Roger flotando sobre el piso, pero probablemente debería caer al suelo por gravedad Para que Roger se comporte como un personaje, necesitamos agregar un switch de script a la escena de Rogers y seleccionar el nodo raíz Luego haga clic en el desplazamiento con un botón más para agregar un nuevo script. Es una buena práctica escribir comportamientos comunes de la manera más genérica posible Este guión no debería ser Roger. En cambio, nombraré el carácter de script y escribiré el script de una manera que pueda aplicarse a cualquier personaje, no solo Roger Godot ofrece una plantilla predeterminada para scripts adjuntos a ciertos nodos Veremos qué tiene esta plantilla en ella. Por defecto, el script heredará los comportamientos del tipo de nodo al que está unido, en este caso un cuerpo de carácter dos D. Estaremos escribiendo todos nuestros guiones en el idioma nativo de Goido, el guión Godot Haga clic en Crear para crear el nuevo script y adjuntarlo al nodo. El panel principal cambiará automáticamente a la vista de script y abrirá el script para su edición. Como puedes ver, la plantilla ya cuenta con varias características. El personaje tiene una velocidad y una velocidad de salto. Éstas se miden en píxeles por segundo. También hay una fuerza gravitacional que está siendo establecida por los ajustes del proyecto En la función de proceso de física, podemos ver que la gravedad se aplica al personaje si no están en el suelo. Se ha implementado un botón de salto agregando velocidad de salto. Al presionar UI, excepto que es la barra espaciadora, hay un control direccional para direcciones izquierda y derecha que permite que el personaje se mueva y se detenga Mover dentro es una función incorporada que tomará la posición del cuerpo del personaje, la velocidad y las fuerzas externas. Después determine dónde estará el personaje después de que haya transcurrido el tiempo delta Con la configuración predeterminada, este código se ejecutará 60 veces por segundo. Si corremos la escena actual, veremos a Roger caer desde el origen de la escena. Pero esta es la escena de Rogers, no está destinada a ser interpretada Vuelve a la escena principal y cambia la vista a dos D. Al tocar esta escena, podemos ver a Roger caer inmediatamente al suelo. Presionar la barra espaciadora hace que Roger salte. Al presionar las teclas de flecha izquierda y derecha Roger se moverá a izquierda y derecha. Esta implementación de controles no es muy buena, pero sí ofrece un punto de partida a partir del cual podemos construir nuestro juego. Ahora tenemos un personaje básico que se dibuja en pantalla con controles básicos y física. En la siguiente lección, nos centraremos en mejorar los controles de nuestros jugadores. Te veré en la siguiente lección. 16. 2 2 Entrada: Hola amigos. En la lección anterior hemos creado un personaje básico con una física de colisión por pulverización y entrada básica. En esta lección, configuraremos un mejor manejo de entrada para controlar nuestro personaje. Empecemos esta lección con un poco de limpieza. Como puedes imaginar, nuestro juego contendrá muchos recursos diferentes. Y es importante mantenerlos organizados para que podamos encontrar rápida y fácilmente cualquier recurso que necesitemos, ¿verdad? Cocinar en la carpeta raíz o en un espacio en blanco. Cree una nueva carpeta y asígnele el nombre. Scripts y, a continuación, arrastre el guión de caracteres a la carpeta. Después repite el proceso con las escenas. Pero tenemos dos tipos diferentes de escenas. Podemos distinguirlos aún más con una subcarpeta dentro de la carpeta de escenas con el nombre de personajes y colocar a Roger en esta subcarpeta Cuando haya terminado, cambie a la vista de guión. Echando otro vistazo a la plantilla predeterminada proporcionada para el cuerpo del personaje dos secuencias de comandos D realmente no se ajusta a nuestras necesidades. Nombramos a este guión Personaje y planeamos aplicarlo a todos los personajes de nuestro juego, la mayoría de los cuales no serán controlados por el jugador. Es importante aislar y separar la funcionalidad en diferentes scripts para este script, que estamos usando para describir los atributos y comportamientos de los personajes. Deberíamos eliminar cualquier manejo de entrada. Voy a comentar estas líneas presionando el control K o el comando K. aplicación de la entrada de gravedad y movimiento durante el proceso de física sigue siendo útil. Pero agreguemos algunos métodos públicos al guión para describir exactamente lo que puede hacer un personaje. En nuestro juego, un personaje puede mirar a la izquierda o a la derecha. Por ahora, simplemente dejaremos vacío el cuerpo de estos métodos escribiendo, pasando o regresando. Un personaje puede correr lo que requiere una dirección para saber si se mueve hacia la izquierda o hacia la derecha. Podemos representar la dirección como un flotador, que es un número que permite valores decimales. Esto no sólo será útil para conocer la dirección, sino que también permitirá una velocidad variable. Tendremos que almacenar este valor en una variable para que pueda ser utilizado durante el siguiente proceso de física. Definamos una variable local privada en nuestro script llamada dirección de guión bajo, luego establecemos su valor en la función run También podemos editar el proceso de física para usar esta variable en lugar de la que estaba usando antes. Un personaje también puede saltar, pero no necesitamos ningún parámetro para éste. Si el personaje está en el suelo, entonces agrega velocidad de salto a la velocidad y del personaje. Estos serán nuestros métodos públicos que otros guiones pueden usar para controlar a cualquier personaje de nuestro juego. Añadiremos más métodos al script a medida que agreguemos comportamientos adicionales a nuestros personajes. Otros métodos como el proceso de física, que no conciernen a otros scripts, están marcados con un guión bajo anterior, igual que la variable de dirección del guión bajo Estos no están destinados a ser utilizados por otros scripts, son solo para este script. Si otro script quiere controlar la dirección de un personaje, debe llamar al método run en su lugar, porque el método run es público. Esto crea un conjunto universal de comportamientos claramente nombrados para describir cómo actuará un personaje en nuestra ganancia. Una práctica conocida en programación como encapsulación. El contenido de estos métodos, variables y del proceso físico no son importantes para otros guiones. Los otros guiones no necesitan saber cómo salta el personaje, solo necesitan saber que se trata de un personaje y puede saltar escondiéndose. Los detalles de cómo se implementa la funcionalidad se conocen en la programación como abstracción. Estas prácticas harán que tus scripts sean mucho más organizados, fáciles de entender, usar y adaptar para otros fines. Esto está empezando a parecer un mejor guión de personaje, pero hemos cortado la capacidad del jugador para controlar al personaje, porque queremos que eso se haga mediante un cambio de guión separado a la escena principal. Si aún no estás ahí, haz clic derecho sobre tu personaje y agrega un nodo hijo. Este nodo no necesita ningún tipo. Simplemente puede ser un nodo básico y nombrarlo Jugador. Solo lo estamos usando para adjuntar un guión extra al personaje. A continuación, en el panel del sistema de archivos, escribamos haga clic en la carpeta de scripts para crear un nuevo script y llamarlo reproductor. Después adjuntarlo al nuevo nodo. Haga clic en el icono del script para abrir el script para su edición. El propósito del script será recibir entrada y llamar a los métodos apropiados en el script de caracteres como resultado. Lo que significa que necesitaremos hacer referencia al personaje. Si recuerda, adjuntamos este script a un nodo hijo del nodo de carácter. Podemos obtener fácilmente una referencia al nodo de carácter declarando una variable en la parte superior del script Vamos a nombrar este carácter de guión bajo variable, ya que sólo este script debe necesitar acceder a él y asignar su valor para obtener padre Iniciar la declaración con at on ready nos permitirá asignar un valor a esta variable después de que el nodo haya sido creado, ingresado al árbol de escenas y esté listo para comenzar a funcionar. Es decir, que el nodo sabrá quién es su padre en ese momento. Para recibir y procesar insumos, utilizaremos dos métodos diferentes, proceso de subrayado y entrada de subrayado El método de entrada es más eficiente para manejar eventos de prensa y liberación de botones. Este método toma un parámetro, normalmente llamado evento, y su tipo será evento de entrada. Todo lo que tenemos que hacer es verificar el evento para ver si el jugador presionó el botón de salto. Si lo hicieron, entonces le diremos al personaje salte como el proceso de física Underscore Process toma delta como parámetro, que es un tipo float que representa la cantidad de tiempo que ha pasado desde el último proceso Por lo general, una 60 de segundo. Pero como no vamos a estar usando el valor de delta aquí, podemos prefijar su nombre con un guión bajo, dejando que el motor Goodot sepa que no necesitamos este valor en el método de proceso, que ejecutará cada fotograma independientemente de si se dio o no la entrada o se cambió De cualquier manera, podemos verificar el estado de nuestra entrada de movimiento. Esto nos permitirá manejar tanto las pulsaciones de teclas como los ejes de stick analógicos de manera más fácil e intercambiable Llamaremos carácter do run aquí pasando en el argumento de entrada get axis, run left as the negative value and run right as the positive value. Es posible que haya notado que las entradas predeterminadas fueron UI accept, UI left, y UI right. Estos están construidos en asignaciones de entrada destinadas a controlar las interfaces de usuario Como hemos usado diferentes nombres para las asignaciones de entrada, necesitaremos agregarlos a la configuración del proyecto antes de que funcionen Abra la configuración del proyecto y cambie la pestaña al mapa de entrada. Si haces clic en el botón Mostrar acciones integradas, puedes ver las acciones de entrada que se usaron anteriormente. Puede volver a ocultar estas asignaciones con el mismo tipo de alternancia. Corre a la izquierda en el campo de agregar nueva acción y haga clic en el botón Agregar. Después repite para correr a la derecha y salta para mapear cada uno de estos a un botón. Haga clic en el botón más a la derecha. Esto abre una ventana emergente donde puede seleccionar cualquier entrada para teclado, mouse o joypad Puedes usar la barra de búsqueda para filtrar las opciones o usar un campo de escucha para detectarlo automáticamente. Para correr a la izquierda, usaré la tecla A. Después repita el proceso para agregar una clave para correr a la derecha y saltar. También puedes agregar múltiples botones a cada mapeo para que tus juegos funcionen sin problemas. Con un pad de juego, usaré el stick izquierdo para correr y el botón de la cara inferior para saltar. Cuando hayas terminado, intenta ejecutar la escena y probar tus nuevas asignaciones de entrada para controlar al personaje Todo debería funcionar de la misma manera que antes, pero ahora el manejo de entrada y los controles de caracteres están siendo manejados por scripts separados. Usando este método, puedes imaginar cómo el personaje que el jugador está controlando puede volverse intercambiable. El script de manejo de entrada también podría reemplazarse por un script de IA para controlar a otros personajes de tu juego con bastante facilidad. Ahora tenemos un mejor manejo de entrada para controlar a un personaje en tu juego. En la siguiente lección, nos centraremos en mejorar la sensación de la locomoción y la mecánica de salto Te veré en la siguiente lección. 17. 2 3 Locomoción: Hola, amigos. En la lección anterior, mejoramos el manejo de entrada de nuestro personaje aislándolo en su propio guión separado de nuestro personaje. En esta lección hará que los controles de locomoción del personaje se sientan mejor para el jugador Si corres la escena principal y prestas atención a cómo se siente el movimiento izquierdo y derecho, es muy rígido. La velocidad de movimiento es instantánea y constante, que no es como realmente se mueven los humanos o cualquier otro objeto Abre el guión del personaje para simular un movimiento más realista. De hecho, podemos usar variables tomadas de la física del mundo real. En realidad, un objeto se acelerará gradualmente hasta su máxima velocidad y también acelerará. Aquí en la parte superior del guión, Godot ha definido un valor constante para la velocidad de los personajes Agreguemos aquí dos nuevas variables para representar la aceleración y la desaceleración, que estamos midiendo en píxeles por segundo al cuadrado Estos pueden ser privados precedidos de un guión bajo y serán de tipo float Por ahora les daremos valores iniciales. Simplemente usaré el mismo valor que la velocidad y los ajustaré más tarde después de probar cómo se sienten. Ahora el proceso de física necesitará usar estos valores para calcular la velocidad del personaje. Si primero miramos el bloque else, aquí es donde el personaje desacelerará cuando el jugador no esté proporcionando ninguna entrada Todo lo que tenemos que hacer aquí es cambiar la velocidad a la desaceleración. Esta útil función llamada movimiento hacia comenzará en el valor de la velocidad x y se moverá hacia cero una cantidad de desaceleración Esto funciona bien tanto para dirección izquierda como derecha, ya que llegar a un alto significará mover la velocidad hacia cero. Pero si miras arriba, el valor de la gravedad se está multiplicando por delta. Recuerda que este código corre 60 veces por segundo. Y estamos proporcionando nuestra tasa de desaceleración en unidades de píxeles por segundo al cuadrado Podemos multiplicar el valor de desaceleración por delta para ajustar su valor para que coincida con la cantidad de tiempo que ha transcurrido desde el último proceso físico Entonces podemos reescribir el bloque F para usar la misma función y aplicar aceleración Esta vez estamos comenzando a la velocidad x, moviéndonos hacia la dirección de los tiempos de la velocidad a una velocidad de aceleración multiplicada por delta. Recuerda que podemos usar este guión para cada personaje de nuestro juego, y es posible que no queramos que todos los personajes tengan exactamente la misma velocidad constante. Primero, cambiemos la velocidad de una constante a una variable privada y editemos la fórmula de aceleración para que coincida. A continuación, podemos agregar en la exportación al frente de estas declaraciones de variables para hacerlas accesibles a otras partes del motor Godot, es decir, el inspector Si cambiamos a la escena del personaje y seleccionamos el nodo raíz, ahora verás estas variables en el inspector y podrás editar sus valores. De esta manera, cada personaje puede definir sus propios valores de movimiento, velocidad, aceleración y desaceleración No todos necesitan ser los mismos valores constantes. Vuelve a la escena principal e intenta jugar con estos nuevos valores. Se puede ver cómo el personaje acelera hasta acelerar gradualmente y de igual manera desacelera. Dado que usamos el mismo valor la velocidad de los personajes para la aceleración y desaceleración, sabemos que el tiempo que tardará en alcanzar velocidad máxima es exactamente de 1 segundo De igual manera, la cantidad de tiempo que le toma al personaje llegar a una parada completa también es de 1 segundo. Podemos hacer ajustes a estos valores rápida y fácilmente desde el inspector incluso mientras se reproduce la escena. Esto nos permite probar rápidamente y sentir cómo los diferentes valores para nuestras variables afectarán al juego y ver qué valores funcionan mejor. Creo que el personaje debería alcanzar la máxima velocidad en medio de segundo y llegar a parar en un cuarto de segundo. Aumentaremos los valores de aceleración y desaceleración en un factor de 2.4 en consecuencia, probémoslo. Eso me parece mejor si tienes tu tasa de aceleración establecida más baja que tu tasa de desaceleración Sin embargo, si intentas cambiar de dirección mientras te mueves, la redirección se sentirá muy antinatural Esto se debe a que se espera que el personaje desacelere hasta cero, luego acelere en sentido contrario Pero el código tal como está escrito dice que simplemente deberían acelerar de la dirección equivocada a la dirección correcta. Para que esto se sienta mejor, podemos cambiar la sentencia if para verificar primero si la dirección es cero, en cuyo caso el personaje debe desacelerar A continuación, sabiendo que la dirección no es cero, podemos verificar si la velocidad x es cero, es decir, que el personaje está estacionario y decirles que aceleren. También necesitamos la condición si el seno de dirección es el mismo que el seno de velocidad x, es decir, ya se están moviendo y el jugador quiere seguir moviéndose en la misma dirección. Nuestra última posibilidad es si ni la dirección ni la velocidad son cero y sus senos no coinciden, es decir, el jugador quiere moverse en la dirección opuesta al que se mueve el personaje En este caso, podemos movernos hacia la velocidad a un ritmo de desaceleración. Esto se sentirá mucho más natural cuando el jugador intente dar la vuelta mientras se mueve. Vamos a probarlo mucho mejor antes de seguir adelante. mí personalmente no me gusta pensar en términos de píxeles, sobre todo porque estos podrían ser solo activos de marcador ¿Y si decidieras que querías hacer este juego usando un paquete de activos diferente que usa 64 fichas de píxeles en lugar de 32 píxeles? Ahora, todas tus mecánicas no van a funcionar igual, y cada valor debe ajustarse para que coincida con el nuevo tamaño de píxel de tus activos. En cambio, prefiero pensar en mi mecánica en unidades de fichas por segundo, píxeles por segundo. Este sería un valor constante de todo el proyecto, que muchos scripts diferentes necesitarán un acceso rápido y fácil. Para ello, podemos crear una nueva carpeta de script llamada auto loads, luego crear un nuevo script dentro de esa carpeta llamada global. Este script no necesita ejecutar ningún código. Solo se utilizará para mantener variables cuando sean utilizadas por todo el proyecto. Al igual que esta, podemos declarar nuestra variable en este script, PPT, o píxeles por mosaico. Es un entero, un número sin decimales, y su valor será 32. Pero, ¿cómo acceden otros scripts a este valor? Abra la configuración del proyecto y cambie a la pestaña de carga automática. Esta es una lista de scripts que se cargarán automáticamente cuando comience tu juego y permanecerán ahí hasta que se cierre. También se puede acceder a ellos por cualquier otro script por su nombre de nodo. Haga clic en el icono de la carpeta para abrir un navegador y encontrar su script global. El nombre del script se utilizará para generar automáticamente el nombre del nodo. Haga clic en el botón Agregar y agréguelo a la lista de nodos cargados automáticamente en el script de caracteres. Podemos ajustar los valores de nuestras nuevas variables para definirlas en unidades de teselas en lugar de píxeles. Tiene más sentido en mi mente que el personaje se mueva a una velocidad de ocho fichas por segundo, en lugar de 300 píxeles por segundo. Si elijo cambiar a un paquete de activos que usa mosaicos de 64 píxeles, todos mis mecánicos seguirán funcionando igual. Todo lo que necesitaría cambiar es el único valor en el script de carga automática global. Si prefieres usar píxeles como tu unidad principal, no dudes en seguir haciéndolo. Cuando comencemos nuestro juego. Cado ejecutará automáticamente un método en cada nodo cuando esté listo, acertadamente llamado guión bajo En este método, simplemente multiplicamos cada uno de estos valores por punto global para convertirlos en unidades de píxeles. Ahora tenemos nuestro personaje acelerando y corriendo de manera más realista En la siguiente lección, mejoraremos la mecánica de salto y gravedad. Te veré en la siguiente lección. 18. 2 4 Salta: Hola amigos. En la lección anterior, mejoramos la mecánica de locomoción del personaje En esta lección, haremos ajustes similares al salto y la gravedad del personaje. Si corremos la escena principal e intentamos saltar, verás que el personaje salta muy alto y flota en el aire durante mucho tiempo Realmente no se siente bien echando un vistazo al guión del personaje. La velocidad de salto es otro valor constante arbitrario que realmente no se ajusta a nuestras necesidades. En cambio, definamos a nuestros personajes saltan en términos de cuántas fichas de altura deberían poder saltar. Esta será una variable privada exportada denominada altura de salto subrayada con tipo float Y usaré un valor predeterminado de 2.5 aunque no sea exactamente realista. Esto permite al jugador saltar sobre una plataforma por la que también podrían optar por caminar. También necesitamos multiplicar esto por bt global. En el método listo, antes de que comience el juego, necesitaremos calcular la velocidad que necesitará el personaje para alcanzar esa altura de salto. Podemos reemplazar la constante de velocidad de salto con una variable privada para mantener este valor. Ya que se calculará en tiempo de ejecución, no necesita ser exportado. Este cálculo se puede agregar al método ready. Dos, la velocidad de salto se puede calcular usando la raíz cuadrada de altura de salto multiplicada por gravedad multiplicada por dos. No podemos usar raíz cuadrada en un número negativo, tiene que ser positivo. Por suerte, en dos juegos D, el eje y está invertido. La gravedad ya se expresa como un valor positivo. Sin embargo, nuestro resultado para la velocidad de salto también es un número positivo. En consecuencia, necesitamos multiplicar por uno negativo para hacer que el personaje salte hacia arriba, no hacia abajo. Ahora podemos editar el método jump para usar esta nueva variable. Si lo probamos, el personaje saltará exactamente 2.5 fichas de alto cuando presionemos el botón de salto, pero el salto sigue siendo lento y flotante. Para solucionarlo, podemos abrir los ajustes del proyecto y alterar el valor de la gravedad. Ya sea filtrando los ajustes o haciendo clic en física dos D, podemos encontrar el ajuste de gravedad por defecto. Esto se establece en 980 píxeles por segundo al cuadrado. En cambio, voy a escribir cálculo directamente en el campo comenzando con 9.8 que es gravedad en la Tierra, multiplicado por tamaño de mosaico de 32 píxeles, luego multiplicaré por ocho, dándome un valor de 2508 0.8 que es aproximadamente 2.5 veces lo que era originalmente Esto hará que todo en el juego se sienta más pesado y caiga más rápido, lo que le parecerá más realista al jugador. Ahora el salto se siente mucho mejor, pero me gustaría darle al jugador la opción de controlar qué tan alto salta el personaje. Hay muchas formas diferentes en las que los juegos implementan esta característica, como medir cuánto tiempo se mantuvo el botón de salto antes de soltarlo. Agregar una fuerza de salto inicial, una fuerza extra a cada cuadro por un corto tiempo después, etcétera, hecho mal, esto puede llevar a controles frustrantes e insensibles o a los personajes sientan como si estuvieran usando un Mi solución favorita personal a esto es muy simple y se siente muy receptiva al jugador. Simplemente evita que el jugador mueva hacia arriba cuando se suelte el botón de salto en el guión del personaje. Bajo el método de salto, podemos agregar un método de stop jump. Recuerda que el eje y está invertido. En dos juegos D, el valor cero para Y está en la parte superior de la pantalla, y los valores positivos se mueven hacia abajo. Si la velocidad y de los caracteres es menor que cero, lo que significa que se están moviendo hacia arriba, podemos establecerla en cero para evitar que se muevan hacia arriba. Entonces la gravedad comenzará a hacer el movimiento hacia abajo. El jugador percibirá esto como controlar su Ppe de salto al sostener y soltar el botón de salto. Sólo tenemos que llamar a este nuevo método desde el guión del jugador. Cuando el jugador suelta el botón de salto, si el evento se libera acción, salta, luego el personaje deja de saltar. Ahora vamos a probarlo. Podemos controlar fácilmente qué tan alto salta el personaje soltando el botón de salto antes de que alcancen su ápice máximo. Esto es fácil de implementar y efectivo para que el jugador sienta que tiene el control total. Lo último que quiero abordar en esta lección es que el jugador tiene tanto control sobre el movimiento del personaje en el aire como lo hace en el suelo. De manera realista, no habría tal cosa como el control aéreo al saltar Pero en la mayoría de los videojuegos, control aéreo existe para mantener al jugador en control del personaje. Puede ser especialmente útil en juegos de plataformas para permitir al jugador evitar trampas o redirigir atreverse a aterrizar en Algún control aéreo puede ser bueno, pero no debería ser lo mismo que el movimiento en el suelo. Para agregar un control aéreo más específico a nuestro personaje, podemos definir otra variable exportada para él en la parte superior del guión como un tipo float y darle un valor por defecto de 0.5 Todo lo que necesitamos hacer es multiplicar esto por aceleración cuando el jugador no está tocando el piso. Para simplificar el método del proceso de física, dividámoslo en dos métodos separados, la física y la física terrestre. Ambos pueden ser métodos privados en el proceso de física. Si el personaje está en el piso, entonces aplique la física del suelo, lo contrario aplique la física del aire. Después proceda con mover y deslizar. La física terrestre no va a cambiar de lo que ya tenemos en el método de física aérea. Si la dirección no es cero, podemos mover la velocidad x hacia la velocidad tiempos dirección a una tasa de tiempos de aceleración control de aire veces delta. Esto seguirá permitiendo que el jugador tenga algún control en el aire, pero reducido a la mitad. Mantengamos estas variables separadas de las anteriores exportando también categorías para ellas. Estas variables se exportarán a la categoría de salto. Las variables anteriores se exportarán a la categoría de locomoción. Vamos a probarlo. Al igual que con las otras variables, puedes hacer ajustes al valor y ver qué te sienta bien. Ahora tenemos a nuestro personaje saltando y cayendo más realista y con mejor control para el jugador En la siguiente lección, animaremos al personaje para que coincida con su movimiento Te veré en la siguiente lección. 19. 2 5 Animación: Hola amigos. En la lección anterior, mejoramos la sensación general de la mecánica de salto del personaje y le dimos al jugador un mejor control de su altura y trayectoria de salto. En esta lección, agregaremos animaciones a la escena del personaje, abriremos la escena del personaje y obtendremos una buena vista del personaje. Primero, hagamos que el personaje mire hacia la dirección en la que se mueven. Si seleccionas el nodo sprite dos D y buscas en el inspector, expandes la sección offset bajo sprite dos D. La propiedad que queremos cambiar es voltear H. Para horizontal pulsando sobre la casilla de verificación, podemos ver que el sprite Al pasar el mouse sobre el nombre nos indica cómo acceder a esta propiedad En nuestro script, el nombre de la propiedad es flip underscore H, abriendo el guión de caracteres Creamos métodos para cara izquierda y cara derecha, pero aún no los hemos usado. Todo lo que necesitamos hacer es modificar el valor de la propiedad flip H del nodo sprite dos D. Podemos obtener una referencia al nodo sprite dos D en la parte superior del script usando at on ready var, lo nombraremos guión bajo Este será de tipo sprite dos D. Luego asignará el valor de esta variable para que sea signo de dólar sprite dos D. Cualquiera que sea el nodo se adjunte este script de caracteres, buscará a través de los nodos hijos para encontrar uno llamado sprite dos D y asignarlo Tenga en cuenta que para que este script funcione como se pretende, cada carácter que creamos debe tener un nodo hijo llamado sprite dos D. De lo contrario, esta variable no contendrá un valor Ahora en los métodos face left y face right, podemos usar esta referencia al sprite dos D para alterar la propiedad flip H. Si el carácter está orientado hacia la izquierda, entonces la propiedad flip H debería ser verdadera. Si están de cara a la derecha, debería ser falso. Pero estas funciones no se están llamando en ninguna parte. El mejor lugar para llamarlos sería al inicio del proceso de física. No importa si el personaje está en el suelo o en el aire. Después de todo, si el seno de dirección es negativo uno, entonces el personaje debería mirar hacia la izquierda. Si el seno de dirección es uno, entonces el personaje debe mirar hacia la derecha. No necesitamos hacer nada si el seno de dirección es cero. Ahora cuando ejecutemos la escena principal, el personaje se enfrentará a la dirección de la entrada del jugador. Este es un buen comienzo, pero también empecemos a trabajar en animar al personaje Haga clic derecho en el nodo sprite dos D en el árbol de escenas y agrega un nodo hijo El nodo que necesitamos buscar es un nodo reproductor de animación. Este nodo nos permitirá cambiar aspectos del personaje a lo largo del tiempo, particularmente la textura del sprite Al agregar este nodo se abrirá automáticamente el panel de animación en la parte inferior de la ventana del editor. Haga clic en el botón de animación, luego haga clic en Nuevo nombre, el nuevo ídolo de animación. Ahora puedes ver una línea de tiempo en el panel de animación. Cada aspecto del personaje que está siendo cambiado por la animación se enumerará en esta línea de tiempo. Haga clic en el botón más para agregar una nueva propiedad a la animación. La propiedad que necesitamos cambiar es el sprite dos ts textura. Con el fin de marcar las posiciones dentro de la línea de tiempo donde cambiará el sprite Podemos agregar un fotograma clave haciendo clic derecho en la pista de la propiedad y seleccionando insertar clave Una vez que se agrega un fotograma clave a la línea de tiempo, podemos moverlo fácilmente Al hacer clic y arrastrar, si no está en el lugar correcto. Al hacer clic en un fotograma clave podemos establecer su valor en el inspector. El sprite 01 inactivo ya está poblado en el campo de textura Ya que ese es su valor actual, creo que estos activos se ven mejor. Con una velocidad de fotogramas de diez fotogramas por segundo, querré cambiar la textura del sprite cada décima de segundo, lo que significa que la duración total de la animación será de 0.5 segundos. La línea de tiempo está mostrando actualmente 15 segundos, lo que dificulta la edición solo del primer segmento de toda la línea de tiempo. Vamos a acercar usando el control deslizante en la parte inferior derecha hasta que podamos ver fácilmente cada 0.1 segundos en la línea de tiempo. Entonces agreguemos cuatro fotogramas clave más y poblemos cada uno con los sprites restantes En orden, necesitamos reducir la duración de la animación actualmente establecida en 1 segundo a 0.5 segundos. Queremos que esta animación circule. Haga clic en el botón de bucle de animación a la derecha. Podemos previsualizar esta animación haciendo clic en el icono de reproducción en la parte superior del panel de animación. Esto se ve bastante bien. A continuación tenemos que ejecutar animación. Haga clic en el botón de animación y seleccione Duplicar. Después nombra la nueva ejecución de animación. Ampliando la carpeta de activos que contiene la animación de ejecución, podemos ver que contiene seis sprites Tendremos que expandir la duración de la animación a 0.6 segundos y agregar otro fotograma clave. Después, rellena cada fotograma clave con los sprites correctos en orden Cuando hayas terminado, previsualice la animación para asegurarte de que se ve bien Repita el proceso tres veces más para crear las animaciones para saltar, caer y tierra. Prestar atención a la duración de cada animación en función del número de sprites proporcionados en el paquete de activos Sin embargo, estas animaciones no están destinadas a bucle, así que asegúrate de desactivar el bucle para estas. Ahora tenemos nuestras animaciones de personajes todas preparadas. En la siguiente lección, construiremos una máquina de estado para sincronizar las animaciones con lo que está haciendo el personaje Te veré en la siguiente lección. 20. 2 6 Máquina de estados: Hola amigos. En la lección anterior, configuramos animaciones para el movimiento de nuestros personajes. En esta lección, implementaremos esas animaciones y las sincronizaremos con el comportamiento del personaje Pero antes de hacer eso, agreguemos rápidamente otro nodo a la escena principal. Una cámara de dos nodos D. Esto nos ayudará a obtener rápidamente una mejor visión de nuestro personaje ya que podemos reposicionarlo y acercarlo editando sus propiedades en el inspector Ahora cuando probemos a la escena, tendremos una mejor visión de los resultados de estas animaciones. Ahora para implementar las animaciones, abriremos la escena del personaje y agregaremos otro nodo hijo al reproductor de animación. Este nodo se llama árbol de animación. El nodo del árbol de animación nos da una advertencia, no se establece ningún nodo de animación raíz para el gráfico. Al mirar en el panel inspector, hay un campo etiquetado como jugador Anim Al hacer clic donde dice un letrero, podemos seleccionar el reproductor de animación que hicimos en la lección anterior. El propósito de este árbol de animación será controlar qué animación se está reproduciendo en un momento dado. Usando el menú desplegable etiquetado raíz de árbol seleccione nueva máquina de estado de nodo de animación. Esto abrirá la máquina de estado recién creada en el panel del árbol de animación en la parte inferior de la ventana del editor. Antes de comenzar a editar la máquina de estado, sin embargo, echemos un vistazo a la carpeta de activos para nuestro personaje. Las animaciones se dividen en dos carpetas etiquetadas con espada y sin espada. El contenido de cada una de estas carpetas son todas animaciones iguales, excepción del personaje que sostiene una espada. O para evitar esfuerzos redundantes, estaré planeando con anticipación la estructura de este árbol de animación para acomodar características que no se implementarán hasta más adelante en el curso. Para comenzar con nuestra máquina de estado, primero haremos clic derecho en algún espacio vacío en panel del árbol de animación y seleccionaremos Agregar máquina de estado. Entonces nombra esta nueva máquina estatal sin espada. También podemos hacer esto nuevamente y crear otra máquina estatal llamada Con espada. Luego podemos hacer clic en el botón de transición en la esquina superior izquierda y agregar una transición de inicio a sin espada. Ahora, cuando comience el juego por primera vez, el árbol de animación por defecto reproducirá animaciones para nuestro personaje sin la espada. Podemos ignorar la máquina de estado de espada por ahora, volver al modo de selección y hacer clic en el icono de lápiz para abrir la máquina de estado sin espada para su edición. Dentro de la máquina de estado, podemos crear otra máquina de estado llamada movimiento. A continuación, agregue la transición de inicio a movimiento por defecto. Esta capa del árbol se utilizará posteriormente para otro propósito. Abra la máquina de estado de movimiento para editarla una vez más. Crea otra máquina de estado, esta vez llamada locomoción, y crea una transición de inicio a locomoción Después abre la máquina del estado de locomoción para su edición. Finalmente, podemos agregar animaciones a la máquina de estado. Al hacer clic derecho, seleccione agregar animación, luego inactivo y repita para agregar ejecución. Crea una transición de inicio a inactivo, convirtiéndola en la animación predeterminada. A continuación, agregue una transición de inactivo a ejecutar y de ejecutar de nuevo a inactivo. El propósito de esta máquina de estado será cambiar la animación entre estos dos estados. Podemos establecer las condiciones bajo las cuales ocurrirán estas transiciones haciendo clic sobre ellas, luego editándolas en el inspector con la transición de inactivo a ejecutar seleccionado, expandir la sección de avance y seleccionar el área de texto de expresión. La expresión introducida en esta área de texto debe producir un valor booleano, ya sea verdadero o falso La condición bajo la cual queremos que el personaje cambie de inactivo a correr es si la velocidad no es cero. De igual manera, la condición para pasar de correr a ralentí será si la velocidad x es igual a cero También necesitamos decirle al árbol de animación qué nodo está controlando estas expresiones avanzadas. Seleccionar el árbol en el árbol de escena. Después mirando en el panel inspector, podemos cambiar el campo base de expresión avanzada al nodo raíz del personaje. Ahora podemos correr la escena principal y ver el trabajo del árbol de animación. Cambiar la animación del personaje entre inactivo y correr en función de la velocidad x del personaje. Para incorporar el resto de las animaciones. Regrese al panel del árbol de animación y navegue hasta la capa de movimiento de la máquina de estado Haga clic derecho para agregar las animaciones de salto, caída y tierra crean transiciones de locomoción a salto, salto a caída, caída al suelo, suelo a locomoción y locomoción Entonces podemos establecer las condiciones para cada una de estas transiciones. La animación de los personajes debe cambiar para saltar si su velocidad y es menor que cero, luego cambiar a caer si su velocidad llega a ser mayor o igual a cero seguido de tierra si está en piso. Dado que este es un método incorporado del cuerpo del personaje dos nodos, podemos acceder a él y devuelve un valor booleano No hay condición para pasar de tierra a locomoción En su lugar, expanda la sección del interruptor y seleccione al final del menú desplegable. Esto permitirá que la animación terrestre complete antes de pasar a la locomoción, pero no impondrá otras condiciones Por último, si el jugador sale de una repisa, queremos que la animación pase de la locomoción a la caída Eso será cierto si no está en piso. Pero las transiciones de la locomoción a saltar y caer serán ambas ciertas en cualquier momento que el jugador salte Podemos darle prioridad al salto cambiando su prioridad 1-0 Volviendo a la escena principal y ejecutando la escena actual. Ahora podemos ver el árbol de animación en funcionamiento, ya que automáticamente hará la transición del personaje entre los distintos estados. Ahora tenemos animados los movimientos básicos del personaje. En la siguiente lección, agregaremos polvo y efectos de sonido a algunas de estas animaciones. Te veré en la siguiente lección. 21. 2 7 efectos: Hola amigos. En la lección anterior, utilizamos una máquina de estado para sincronizar la animación de los personajes con su comportamiento En esta lección, agregaremos algunos efectos de sonido y visuales para agregar pulido a las animaciones. Comenzando en la escena del personaje, agreguemos un nuevo nodo, un sprite animado dos D, y renombrémoslo a partículas de polvo Una advertencia nos dice que necesitamos crear un recurso de tramas de sprite para que este nodo funcione con el nuevo nodo seleccionado Mirando en el inspector, expanda la sección de animación. Al hacer clic en el menú desplegable etiquetado como marcos de sprite, selecciona nuevos marcos de sprite, luego haz clic en el recurso de marcos de sprite para abrirlo para editarlo, que aparecerá en la parte inferior de la ventana del Aquí podemos ver una animación de fotogramas de sprite recién creada llamada Default, con una velocidad de fotogramas de cinco fotogramas por segundo En el panel del sistema de archivos, busque en el paquete de activos para encontrar el grupo de carpetas de partículas de polvo, seleccione los sprites de caída y arrástralos al área de fotogramas de animación Presionando play para previsualizar la animación, podemos ver cómo se verá. No queremos que esta animación circule, apague el bucle cocinando el botón de bucle de animación Expandir la sección de desplazamiento y ajustar el desplazamiento y hasta que esté nivelado con el eje x rojo, que será nuestro terreno. Es importante usar el campo de desplazamiento y no la posición de las transformadas para que las partículas aparezcan en el suelo. También cambiaré la velocidad de fotogramas para que coincida con las animaciones de mis personajes, que tenían una velocidad de fotogramas de diez fotogramas por segundo. Ahora cuando pulsamos play, la animación se reproducirá solo una vez. Y podemos ver cómo se verá en el juego en relación con el personaje. El propósito de esta animación será jugar una vez cuando el personaje aterrice en el suelo y desaparecer cuando se termine. Este tipo de efectos se ven mejor cuando existen independientemente del personaje, como si el polvo fuera parte del mundo y no debiera seguir al personaje alrededor. Hagamos clic derecho en el nodo de partículas de polvo y guardemos esta rama como escena propia. Esto no pertenece realmente a ninguna de nuestras carpetas existentes. Hagamos una nueva carpeta para ello llamada polvo. Nombra esta escena en particular, polvo de caída cocinando en el tablero de la chapeta, icono en el árbol de escena Podemos abrir la escena del polvo de caída para hacer desaparecer las partículas. Después de que se complete la animación, tendremos que adjuntar un script al nodo raíz, haciendo clic en el botón del script del anuncio nombre el nuevo polvo de script. No necesitamos usar ninguna de las plantillas predeterminadas. Desmarque la casilla de verificación de la plantilla y asegúrese de que el script esté guardado en la carpeta de scripts Esto iniciará el guión con nada más que extiende sprite animado dos líneas D en la parte superior Pero antes de que realmente escribamos cualquier código con el sprite animado dos nodos D seleccionados, mira el panel inspector y cambia al panel de nodos Las señales deben seleccionarse por defecto. Esta es una lista de señales que el nodo puede usar para activar comportamientos ya sea en su propio script o en otros scripts. Podemos usar la señal de animación terminada para saber cuándo se termina la animación. Y ejecutar un método en nuestro script. Haga clic derecho sobre la animación terminada. Conéctese para abrir una nueva ventana. Asegúrese de que las partículas de polvo estén seleccionadas como el receptor de la señal. Luego haz clic en Conectar. Notarás que Do ha generado automáticamente un método en el script que se activará cuando termine la animación. Hay un icono de conexión verde a la izquierda de la declaración del método para hacernos saber que este método está siendo activado por una señal. También en el árbol de escenas, el icono de señal se muestra junto al nodo de partículas de polvo para hacernos saber que este nodo tiene una conexión de señal. Lo único que tenemos que hacer en el script cuando termine la animación, es decirle al motor que hemos terminado con este nodo y se puede quitar. Esto se hace usando un método incorporado llamado free. También queremos decirle al guión que reproduzca automáticamente la animación cuando se agregue a la escena. Anulando el método de guión bajo listo, podemos simplemente llamar cuando este nodo se agrega al árbol, se reproducirá una vez y se eliminará cuando esté terminado Ahora podemos duplicar esta escena para crear las escenas de partículas de polvo similares para saltar y correr partículas en estas nuevas escenas, reemplazar los sprites en la animación con los sprites correctos del paquete de activos Ahora tenemos tres efectos de partículas de polvo diferentes que queremos generar bajo diferentes condiciones para nuestro personaje, pero todos pueden usar un solo método. Volviendo a la escena del personaje, ahora podemos eliminar el nodo de partículas de polvo ya que no está destinado a ser parte de la escena. Luego cambie a la vista de guión y abra el guión de caracteres. Agreguemos una nueva función privada llamada spawn dust, que tomará un parámetro llamado dust El tipo de este parámetro será una escena empaquetada que nos permitirá usar las escenas que acabamos de crear como argumento para el método. Primero, necesitamos instanciar la escena, luego cambiar su posición para que esté en la misma ubicación que el A continuación, agréguelo al árbol de escenas obteniendo primero el nodo padre del personaje y luego agregando el polvo como nodo hijo. Al hacer del polvo un hermano del personaje, existirá en el mundo independiente del personaje y no seguirlos. Tan pronto como se agregue al árbol de escenas, el sprite animado reproducirá su animación predeterminada, luego Q misma para ser eliminada cuando la animación se termine solo una fracción de segundo después Para activar las partículas de polvo de salto, podemos llamar a este método directamente desde el método de salto, pasando en polvo de salto como argumento. Entonces declara lo que es el polvo de salto en la parte superior del guión como una variable exportada de tipo escena empacada. Seleccionar el nodo raíz del personaje y volver al panel inspector. Luego podemos poblarlo en el inspector haciendo clic y arrastrando la escena al campo exportado Las partículas de corrida y caída no tienen un lugar sencillo en nuestro script donde puedan ser engendradas Sin embargo, lo que podemos hacer en cambio es seleccionar el jugador de animación de nuestro personaje, abrir la animación del terreno y agregar una nueva pista. Esta vez una pista de método de llamada. Entonces podemos acceder al nodo raíz del personaje y llamar al método de partículas de desove al inicio de la animación Añadiendo un fotograma clave. Seleccionar el fotograma clave nos permitirá pasar argumentos al método que luego podremos poblar. Al hacer clic y arrastrar el polvo de caída. Podemos hacer lo mismo con las partículas de polvo de ejecución, añadiéndolas a la animación de ejecución. Recuerda que la animación de ejecución hará un bucle, por lo que nuevas partículas generarán cada vez que la animación haga bucles Para las partículas de caída y salto, realmente no importa a qué dirección se enfrente el personaje. Pero para las partículas de carrera, es importante que parezcan moverse detrás del personaje. Podemos configurar la propiedad animada de Steph para que coincida con la del personaje en el momento de su creación Vamos a probarlo. El funcionamiento crea polvo cada 0.6 segundos de funcionamiento continuo. Saltar y aterrizar también crean sus propias nubes de polvo únicas. Para otro poco de pulido, también podemos agregar sonidos a nuestras pistas de animación, Volver a la escena del personaje y agregar un nuevo nodo al árbol de escenas, un reproductor de flujo de audio dos nodos D. Con este nodo en el árbol, ahora podemos abrir la animación de salto y agregar una nueva pista de reproducción de audio. Seleccionar el nodo reproductor de flujo de audio para que sea el objetivo. Colocar un fotograma clave al inicio de la animación. Entonces podemos poblar este fotograma clave con una transmisión de audio. Navegar por los sonidos proporcionados en los sonidos de batalla llenos por Luke Sharps. Hay algunos sonidos apropiados para elegir que se ajustan muy bien a este personaje. Importa los sonidos que te gusten y colócalos en una carpeta de efectos de sonido designada para mantener tu proyecto organizado. Luego, rellena tu fotograma clave de animación en consecuencia. Para obtener la animación de carrera en bucle sobre sonidos de zapatos. Asegúrese de modificar el desfase inicial y el desfase final para seleccionar una muestra que sea más corta que la animación. Vamos a probarlo ya. El personaje hace un gruñido mientras saltan, Un sonido de impacto cuando aterrizan, y ruidos de pisadas A lo largo de esta primera sección del curso, hemos creado un personaje completamente animado con efectos tanto de audio como visuales y divertidas mecánicas de plataformas En la siguiente sección, comenzaremos a trabajar en construir niveles para nuestro juego. Te veremos en la siguiente sección. 22. Tilemap 2-1: Hola amigos. En la última sección, creamos un personaje completamente animado con mecánica de plataformas Si has completado la tarea, ahora deberías tener un elenco completo de cuatro personajes. Y ya habremos descubierto que puedes duplicar el nodo jugador para controlar más de un personaje simultáneamente. Si pudiste completar el desafío intermedio, también tendrás algunos scripts de IA controlan uno o más de los personajes. Con el desafío más avanzado, probablemente tendrás todos los nodos de personaje, hijo al nodo jugador, con el personaje controlado, capaz de ser cambiado con la pulsación de botón. En esta sección, construiremos un nivel para nuestro juego. Nuestra primera lección, comenzaremos con la construcción del terreno nivelado. Agrega otro nodo a la escena principal. El nodo que estamos buscando esta vez es mapa de teselas. Un mapa de teselas nos permitirá agregar y modificar rápidamente sprites en nuestro nivel, cuales se organizarán en mosaicos de un tamaño específico Para que un mapa de teselas funcione, necesita un conjunto de teselas. Como puede ver en el inspector desde el menú desplegable, Label tile set, seleccione nuevo conjunto de mosaicos, luego haga clic en el recurso del conjunto de mosaicos para expandirlo, exponiendo algunos campos que necesitaremos para editar nuestros mosaicos son cuadrados. Pero puedes ver que hay una serie de otras opciones para hacer que trabajar con otras formas de baldosas sea igual de fácil. Lo primero que tenemos que cambiar es el tamaño de la baldosa. El tamaño de mosaico del paquete de activos que estoy usando es de 32 píxeles tanto en ancho como en alto. Es importante que establezca esta propiedad antes de agregar cualquier mosaico al conjunto de mosaicos. Debido a que estamos usando este mapa de teselas para el terreno, también necesitaremos agregar una capa de física para colisiones. Un conjunto de terrenos hará que la edición del terreno sea mucho más fácil. El conjunto de terrenos puede contener múltiples terrenos. Necesitamos agregar un terreno al conjunto de terrenos. Se puede pensar en cada terreno como un bioma o material de construcción diferente Nombremos esta primera isla de terreno. Cada tipo de terreno puede asignarse a un color diferente para distinguirlos entre sí. Como solo vamos a usar un tipo de terreno por ahora, solo podemos usar el color predeterminado. Este color no se utilizará en el juego solo mientras estemos editando el terreno. Es sólo para nuestro beneficio como desarrollador. Con esos cambios realizados, podemos dirigir nuestra atención a la parte inferior de la ventana del editor donde se ha abierto una nueva pestaña para el mapa de teselas. El mensaje nos dice que necesitamos configurar un conjunto de mosaicos primero cambiar a la pestaña de conjunto de mosaicos en la parte inferior. Aquí podemos agregar los mosaicos proporcionados en el paquete de activos a este conjunto de mosaicos. Ya sea haciendo clic en el botón más o haciendo clic y arrastrando el archivo de imagen desde el sistema de archivos El código de tabulador ofrecerá crear automáticamente mosaicos para nosotros. Seleccione Sí. Si estás seguro de que has establecido correctamente el tamaño del mosaico , de lo contrario selecciona no. Las baldosas ahora deberían ser más ligeras y tener un borde naranja. Seleccionar la herramienta de borrador le permitirá eliminar mosaicos del conjunto de mosaicos haciendo clic en ellos. De igual manera, al apagar la herramienta de borrador se le permitirá agregar mosaicos al conjunto de mosaicos haciendo clic en ellos. Volviendo a la pestaña de mapa de teselas, ahora podemos seleccionar y dibujar cualquier mosaico del conjunto de mosaicos a la vista de dos D haciendo clic en Goode proporciona una cuadrícula naranja que coincide con el tamaño de mosaico para que sea más fácil El editor de mapas de teselas también proporciona todas las herramientas habituales para seleccionar líneas de pintura, rectángulos, llenado de cubetas También puede colocar los ojos, seleccionar, borrar, rotar, voltear y aleatorizar mosaicos Haz un piso básico, coloca tu personaje sobre él y coloca la cámara para ver los resultados. Después toca la escena. Notarás que el terreno aún no tiene colisión. Vuelva a la pestaña del conjunto de mosaicos. Cambie al modo de selección y grupo seleccione todas las teselas haciendo clic y arrastrando sobre ellas. Primero agreguemos colisión a nuestras fichas expandiendo la sección de física. Después la física capa cero. Esta herramienta te permitirá crear formas complejas de colisión para cada baldosa, pero solo necesitamos cuadrados básicos. Al hacer clic en el icono de elipse, seleccione Restablecer a la forma de mosaico predeterminada o, alternativamente, presione la tecla para simplemente hacer que la forma de colisión coincida con la forma de las baldosas cuadradas Ahora todos nuestros mosaicos tendrán colisión, al igual que el icono de Codell que estábamos usando como piso de escena Esto es genial, pero construir niveles poblando teselas individuales en el mapa de teselas será extremadamente tedioso Afortunadamente, Godel proporciona un editor de terreno muy fácil de usar Cambia al modo de pintura. Esto nos permite pintar propiedades sobre las baldosas. La propiedad que queremos pintar es la propiedad del terreno. Particularmente en terreno a cero, el terreno isleño. Es posible que desee expandir el panel o acercar el área de mosaico. Para esta parte, cada baldosa se divide en nueve cuadrados más pequeños los cuales podemos pintar al color del terreno haciendo clic o borrar haciendo clic derecho. Cada baldosa que forma parte de este terreno debe tener su cuadrado medio rellenado. Para que el editor de terrenos funcione según lo previsto, necesitamos pintar los bordes de cada baldosa que se pretende dibujar junto a otra baldosa. Cuando hayas terminado, no debería haber ningún duplicado en este conjunto de mosaicos Cada baldosa debe tener un patrón único. Vuelva a la pestaña de mapa de teselas. Cambia a la pestaña de terrenos en la parte superior. Y nuestro terreno insular debe aparecer como una opción seleccionando que verá cada mosaico del conjunto de mosaicos listado, junto con dos opciones adicionales, modo continuo y modo de ruta. Seleccione el modo continuo, luego dibuje el terreno libremente en las dos vistas D haciendo clic y borrado haciendo clic derecho Cada baldosa se conectará automáticamente correctamente a sus mosaicos adyacentes. Deberías poder dibujar el terreno de cualquier forma que puedas imaginar y automáticamente se seleccionarán las fichas adecuadas para cada posición de mosaico. Si hay alguna inconsistencia, verifique dos veces la pintura de su propiedad del terreno en busca Con esta herramienta, podemos generar rápida y fácilmente el terreno para cada nivel de nuestro juego. Ahora tenemos terreno básico en nuestro juego que podemos usar para construir la base de nuestros niveles. En la siguiente lección, agregaremos algo de vegetación decorativa para que el ambiente se sienta más vivo. Te veré en la siguiente lección. 23. 2-2 decoraciones: Hola amigos. En la última lección, configuramos terrenos básicos con colisiones y edición de terrenos En esta lección agregaremos algunas decoraciones a nuestro terreno para hacerlo más interesante. Al igual que el mapa de teselas, cambie a la pestaña de conjunto de mosaicos en la parte inferior de la ventana del editor. Hay otro gráfico de conjunto de azulejos en el paquete de activos que pertenece a este conjunto de azulejos llamado front, palm, bottom y grass. Agreguemos eso al atlas. Estos elementos decorativos realmente no necesitan ninguna física o edición del terreno. La hierba simplemente se puede dibujar sobre áreas al azar sobre tu nivel donde crees que se verá bien. Las raíces, sin embargo, están destinadas a ser dibujadas sobre baldosas del terreno. Pero si tratamos de hacer eso, reemplazará el terreno en su lugar. Para lograr esto, necesitamos agregar otra capa a nuestro mapa de teselas para estas raíces. Seleccionando el mapa de teselas en el árbol de escenas, podemos contraer el recurso del conjunto de teselas y expandir la sección de capas. Aquí tenemos una capa que no tiene nombre. Nombremos este terreno de capa, luego hagamos clic en el botón Agregar elemento, Agregar otra capa y nombrar a esta raíz Para hacer esta capa dibujada frente al terreno, podemos editar el índice z, aumentándolo a uno. Dado que el terreno está en la capa cero, las raíces de la capa uno siempre se dibujarán sobre la parte superior. El menú desplegable en la parte superior derecha de la pestaña del mapa de teselas ahora contiene nuestras dos capas diferentes. Esto nos permite agregar baldosas de raíz a la capa raíz, que luego podemos pintar sobre las baldosas del terreno en la capa del terreno. Cuando se está editando cada capa, aparecerá a todo color, mientras que todas las demás capas se desvanecerán Pero estas raíces también necesitan árboles. Construyamos también los árboles. Si quieres que los árboles tengan colisión y sean un objeto inamovible que actúe como terreno, el tipo de nodo más apropiado para usar sería un cuerpo estático dos D, que llamaremos Palmera Este es el mismo tipo de nodo que originalmente usamos para el icono de Godot Este nodo en particular aún puede tener colisiones, pero no se moverá por colisiones con otros objetos Permanecerá estático. Este árbol tendrá una animación. Entonces agreguemos un sprite animado, dos D como nodo hijo de la palmera Crea un recurso de fotogramas de sprite para el sprite animado. Después abre el recurso para editarlo. Haga clic y arrastre las imágenes de la palmera a la animación. Cambia la velocidad de fotogramas y presiona play para previsualizar la animación. Esto se ve bien. Asegurémonos de que esta animación se reproduce automáticamente por defecto haciendo clic en el botón Reproducción automática en la parte superior del panel Guardemos el nodo Palmera como su propia escena y lo clasifiquemos en una nueva carpeta de escenas para decoraciones. Ahora la palmera se puede editar de forma aislada, y todos los cambios realizados en la escena de la palmera se aplicarán a todas las copias de la palmera Con el nodo de palmera seleccionado, Haga clic y arrástrelo para moverlo por el nivel y colocarlo sobre las raíces. Podemos hacer esto mucho más fácil al activar el ajuste de cuadrícula con el botón en la parte superior de las dos vistas D. También podemos configurar las opciones de ajuste haciendo clic en el icono de elipse Asegurémonos de que los objetos se ajusten a múltiplos de 32 píxeles para que coincidan con el tamaño del mosaico Pero la palmera no quiere alinearse porque el origen del árbol está en su centro. Para que el árbol se alinee con los mosaicos, el origen debe estar en la esquina seleccionando el sprite animado, dos nodos D. Ajusta el desplazamiento para que el sprite dibuje 16 píxeles, o la mitad de un mosaico hacia abajo a la derecha del origen Ahora la palmera se puede mover fácilmente para que coincida con las baldosas del terreno. El cuerpo estático necesita una forma de colisión. Para chocar con cualquier cosa, necesitamos agregar otro nodo hijo, una forma de colisión, dos D. Para que esta palmera sea más interesante Hagamos también que funcione como una plataforma para que el jugador salte. Establecer la forma de colisión para que sea una forma de segmento dos D, esto es solo una línea que podemos editar moviendo los dos puntos. Haz que el segmento de línea se alinee con la parte superior de la palmera. Vamos a probarlo. Funciona como una plataforma, pero sería bueno poder saltar por el fondo en lugar de chocar con ella Me gustaría que el jugador no flotara tan lejos del borde antes de caer Ajuste de la configuración de alineación de cuadrícula a ocho píxeles o cuartos de teselas Voy a hacer que el segmento de línea sólo cubra la mitad de la longitud completa de la baldosa. Si quieres que el jugador pueda pasar por la parte inferior de la plataforma y aterrizar encima de ella. Hay una implementación simple incorporada para ese comportamiento. En Godot, simplemente marque la casilla de verificación de colisión unidireccional en la forma de colisión dos propiedades D. Esto dibuja una flecha en el editor nos muestra en qué dirección se aplicará la colisión. Eso es mucho mejor. Ahora puedo saltar por el fondo de la plataforma de la palmera y deslizarme el borde en lugar de pararme sobre una barrera invisible. Algo que podría ser molesto para algunos jugadores a los que les gusta el estilo de arte pixelado en particular es que el jugador no está siendo dibujado exactamente en los mismos desplazamientos de píxeles que el Si coloco al personaje junto a alguna hierba, se puede ver que los píxeles de mi personaje no siempre se alinean con los píxeles de la hierba en la configuración del proyecto. Podemos ajustar estos ajustes de renderizado para forzar que todas las imágenes que se dibujan en la pantalla se dibujen en coordenadas exactas de píxeles, que es lo que preferirían los fanáticos del pixel art. Estos ajustes están ocultos por defecto. Haga clic en el botón de configuración avanzada debajo de Renderizado. Se revela una nueva opción para dos D. Aquí tenemos opciones para ajustar transformaciones y vértices a píxeles. Esto podría hacer que el jugador pase un píxel por encima del piso Si ese es el caso, ajuste su colisionador para que se paren limpiamente en el piso. Ahora cuando pulsamos play, el personaje y todo lo demás en nuestro juego siempre se dibujarán ajustadas a coordenadas de píxeles Ahora tenemos pasto y palmeras animadas decorando nuestra isla pixel perfect. En la siguiente lección, agregaremos un guión a nuestra cámara, que seguirá al jugador permitiéndonos hacer niveles que son más grandes que una pantalla. Te veré en la siguiente lección. 24. 2-3 cámaras: Oh amigos. En la lección anterior, decoramos nuestra isla con vegetación. En esta lección, haremos que la cámara siga al jugador alrededor del nivel. La forma más fácil de lograr esto sería simplemente hijo de la cámara para el jugador. Pero este enfoque es muy restrictivo y puede provocar mareo por movimiento. movimiento de la cámara debería ser más sutil y mostrar al jugador lo que está por delante de su personaje, teniendo al personaje del jugador en la cámara como hermanos, necesitaremos que la cámara reaccione a las acciones del jugador y tenga su propio comportamiento guionado en respuesta Empecemos por crear un nuevo guión para la cámara. Podemos simplemente llamarlo cámara y asegurarnos de que esté guardado en la carpeta de scripts. Esta cámara necesitará saber qué es lo que sigue. Exportemos una variable privada a la que llamaremos underscore subject El tipo de esto no necesita ser un cuerpo de personaje dos D. En cambio puede ser algo más genérico como un nodo dos D. Si miras en el árbol de escenas, notarás que los nodos tienen diferentes colores, la mayoría de los cuales son azules. Estos nodos azules son todos D de nodo dos, pero son tipos más específicos de nodos dos D, incluyendo la propia cámara. Hay dos personajes D, dos cuerpos estáticos D, dos sprites animados D, etcétera. Al seleccionar cualquiera de ellos, verá en el inspector que tienen las propiedades etiquetadas como nodo dos D así como la propiedad transform que contiene su posición, rotación, escala y sesgo Al establecer el tipo de nuestro sujeto al nodo dos D, la cámara podrá seguir cualquier cosa en nuestra escena que califique como nodo dos D. Ya que solo necesitamos saber que tiene una posición para que la cámara la siga, haga clic y arrastre el personaje del jugador al haga clic y arrastre el personaje del jugador campo exportado para nuestro sujeto de cámara En el método de proceso, que se ejecutará 60 veces por segundo, simplemente podemos establecer la posición de la cámara a la posición del sujeto. Estos serán los mismos comportamientos cuando la cámara era infancia para el personaje sin el movimiento vertical, reduciendo severamente el mareo por movimiento. sería más útil si el personaje Sin embargo, sería más útil si el personaje no estuviera centrado en la vista de la cámara. Pero en cambio, debería mirar por delante del personaje y ligeramente hacia arriba para que el jugador pueda ver partes más relevantes del nivel. Al igual que con los sprites animados, podemos agregar un offset a nuestro script de cámara para cambiarlo de su posición original Vamos a hacer de esta una variable privada exportada, guión bajo offset con el tipo de vector dos Un vector dos contiene dos flotadores, un valor x y un valor y Se utiliza para definir cualquier cosa en dos dimensiones, incluyendo las variables de posición con las que hemos estado trabajando. Ahora el método de proceso puede simplemente agregar la porción x del desplazamiento a la posición X de la cámara. Si posicionamos al personaje exactamente en el origen de la escena, podemos mover la cámara para darnos una idea de dónde creemos que quedará bien. Luego use la posición actual de la cámara como valor de desplazamiento. Alternativamente, podrías definir el desplazamiento en mosaicos y multiplicarlo por Google Ppt en el método ready. Ahora la cámara seguirá el movimiento horizontal del jugador mientras mira hacia adelante a la derecha. Pero, ¿y si no queremos que nuestros niveles sean tan lineales? ¿Y si el jugador quiere ir a la izquierda? La cámara también debería mirar a la izquierda del personaje. La cámara tendrá que reaccionar ante una acción realizada por el personaje. Tenemos dos funciones en nuestro guión de personajes, que se llaman cada vez que el jugador mira hacia la izquierda o hacia la derecha, pero estas se llaman constantemente con cada entrada. Solo llamemos a estas funciones cuando el personaje realmente cambia de dirección. Para ello, podemos exportar una variable privada para almacenar si el carácter se encuentra actualmente orientado hacia la izquierda o no . Como booleano. Los métodos face left y face right establecerán este valor como verdadero o falso en consecuencia. Entonces al inicio del proceso de física, podemos agregar condiciones para llamar solo a la cara izquierda si el personaje no está ya mirando a la izquierda, si están mirando hacia la izquierda. Ahora tenemos nuestros métodos de cara izquierda y cara derecha solo siendo llamados cuando el jugador elige cambiar su dirección. También debemos llamar a los métodos adecuados de cara izquierda o cara derecha durante el método ready basado en el valor de la variable exportada. Esto también tiene el beneficio de hacer que esta función funcione con los personajes cuyos sprites están orientados hacia la izquierda Por defecto, el script de la cámara ahora puede reaccionar al carácter cambiando de dirección usando señales. En la parte superior del guión del personaje, podemos crear una señal personalizada a la que llamaremos Dirección cambiada, y agregar un parámetro que indique a la cámara si el personaje está actualmente orientado hacia la izquierda. Ahora los métodos de cara izquierda y cara derecha pueden decirle a esta señal que emita pasando si el personaje ahora está mirando hacia la izquierda o no como argumento. Con las notas del personaje seleccionadas en el árbol de escenas. Cambie al panel de nodos, haga clic con el botón derecho sobre nuestra nueva señal y seleccione Conectar. Después selecciona la Cámara. Nota de la lista. La cámara escuchará esta señal. Podemos renombrar el método que se llamará como resultado. Para ponerlo en términos que sean más fáciles de entender dentro del contexto de la cámara, pongámoslo en Asunto cambiado de dirección. El método se agrega al script de la cámara automáticamente. Ahora podemos cambiar el desplazamiento de las cámaras para que se vean a la izquierda o a la derecha. Ya que sabemos a qué dirección está orientado el personaje Para preservar el valor de desplazamiento, vamos a crear otra variable privada llamada mirar hacia adelante distancia. Que comienza como una copia del desplazamiento X del guión bajo establecido durante la fase de listo con en listo Entonces podemos establecer la distancia de mirada hacia adelante para que sea el desplazamiento X, pero multiplicado por uno negativo si el sujeto está mirando hacia izquierda o uno positivo si no lo están. Luego use la distancia de mirar hacia adelante en la función de proceso para establecer la posición de la cámara. Ahora la cámara mirará por delante del personaje sin importar en qué dirección estén mirando. Pero, ¿y si queremos que nuestros niveles suban y bajen también? Podemos usar un método similar para que la cámara reaccione ante el sujeto emitiendo una señal. Esta vez moviendo la cámara cuando el personaje aterriza al final de su salto, ajustando la cámara a una nueva altura en el guión del personaje. Agreguemos otra señal llamada aterrizado y pasemos un parámetro llamado altura del piso, que será un flotador. ¿Cómo sabemos cuándo aterriza el personaje? Bueno, tenemos el método práctico es en piso. Si almacenamos este valor en una variable privada, lo llamaremos fue en piso como booleano Lo grabaremos aquí. Arriba muévete y deslízate. Entonces después de mover en diapositiva, podemos verificar si el personaje no estaba en el piso y ahora está en el piso, lo que significa que este es el momento exacto en que aterrizaron. Llamemos a un nuevo método privado aquí llamado guión bajo aterrizado escribir una definición para este método, realmente no necesitamos hacer nada más aquí en este momento, además de emitir la señal aterrizado pasando en nuestra posición Y como la nueva altura del piso. Decirle a la cámara que escuche la señal, la cámara puede entonces llamar a un nuevo método llamado en sujeto aterrizado. Todo lo que necesitamos hacer es ajustar el valor de la posición Y de la cámara para que sea la nueva altura del piso más el desplazamiento Y. Ahora tenemos la cámara siguiendo al jugador, lo que nos permite hacer niveles que son más grandes de lo que podemos caber en una sola pantalla, pero los movimientos son jarry En la siguiente lección, haremos que la cámara se mueva suavemente entre estas posiciones usando preadolescentes Te veré en la siguiente lección. 25. 3 4 Tween: Hola, amigos. En la última lección, movemos la cámara alrededor, siguiendo al jugador a medida que se mueve a la derecha, a la izquierda, arriba y abajo. En esta lección, haremos que la cámara barre suavemente entre estas posiciones. La forma más sencilla de ajustar gradualmente los valores a lo largo del tiempo es usar una preadolescentes Declaremos dos nuevas variables privadas. En la parte superior de nuestro guión de cámara, tenemos dos señales diferentes que desencadenan dos comportamientos diferentes en nuestro script de cámara Queremos que estos se mantengan separados unos de otros. La primera variable se llamará mirar hacia adelante tween, la segunda altura del piso tween Ambos son de tipo tween. Comenzando con la preadolescentes de mirar hacia adelante, cuando nuestro sujeto cambia de dirección, podemos establecer el valor de mirar hacia adelante tween para crear Este es un método incorporado que podemos usar para crear nuestro comportamiento de tweening rápida y fácilmente Luego le decimos a esta mirada adelante tween para interponer una propiedad comenzando con qué nodo pertenece la propiedad cuál es en sí Después designamos entre comillas el nombre del inmueble. Vamos a entretejar el valor de la distancia de mirar hacia adelante para convertirnos en este valor que ya calculamos a lo largo de un período de tiempo Por ahora diremos 1 segundo. Esto se ve mejor. Pero si el jugador cambia dirección mientras la cámara jadea, no deberíamos tener dos preadolescentes creados al mismo tiempo compitiendo por el control de la No parece estar causando ningún problema. Pero podemos eliminar la posibilidad comprobando primero si la preadolescentes ya existe y se está ejecutando Si esto es cierto, entonces deberíamos matarlo antes de comenzar otro. Esta tween es actualmente lineal y tiene una duración de 1 segundo Pero podemos personalizarlo fácilmente para crear una amplia variedad de efectos. Primero, vamos a exportar una variable flotante llamada underscore duration y darle un valor predeterminado de uno Luego conecta esta variable en la llamada al método Tween. Ahora podemos ajustar la velocidad a la que la cámara desplazará simplemente cambiando el valor de esta variable en el inspector. Recuerda que no necesitas detener el juego para ajustar valores en el inspector. Creo que esto debería ser un poco más lento en caso de que el jugador le dé la espalda a un enemigo, pero no quiere que se los retire inmediatamente de la vista. Por ejemplo, para cambiar la forma en que se mueve la cámara a lo largo del tiempo, podemos agregar tipos de flexibilización y transición a la preadolescentes, haciendo que se mueva más lento o más rápido al principio o al Incluso rebotar o ir más allá de los límites definidos. Exportemos una nueva variable privada llamada tipo trans. El tipo de esta variable será el tipo de transición de Tween. Entonces cuando creamos la tween, también podemos llamar a otro método, establecer trans pass nuestro tipo de transición como argumento a este método Podemos hacer esto porque tanto el método create tween como el set trans devuelven el tween Como resultado, el método create tween crea la tween y la devuelve, que luego se usa para llamar al conjunto trans y devuelve nuevamente la tween, que luego se asigna a nuestra variable, seleccionando la cámara en el árbol de escenas y mirando al inspector, verás que el tipo de transición por defecto es lineal, lo que significa que el valor progresa uniformemente sobre el crea la tween y la devuelve, que luego se usa para llamar al conjunto trans y devuelve nuevamente la tween, que luego se asigna a nuestra variable, seleccionando la cámara en el árbol de escenas y mirando al inspector, verás que el tipo de transición por defecto es lineal, lo que significa que el valor progresa uniformemente sobre el duración desde el menú desplegable. Hay una variedad de opciones para alterar cómo cambiará el valor con el tiempo. También podemos agregar otra variable llamada tipo de flexibilización, de manera similar tipo de facilidad de tween Esto alterará la transición para afectar sólo el inicio del fin de la preadolescentes o ambos Al igual que con el tipo de transición, también podemos establecer el tipo de flexibilización en la misma línea de código Cuando creamos la preadolescentes, intente experimentar con diferentes duraciones, transiciones y tipos de flexibilización para ver cómo se sienten Podemos usar la misma técnica para ajustar gradualmente altura actual del piso de la cámara a lo largo tiempo después de que el sujeto aterrice. En lugar de usar un corte duro, primero necesitamos almacenar la altura actual del piso en una variable privada. Luego, cuando el sujeto aterrice, podemos copiar la mayor parte del mismo código desde que cambian de dirección, solo cambiando la variable de preadolescentes de mirar hacia adelante a la altura del piso y también cambiando el nombre de la propiedad que estamos interpelando el valor Vamos a interpelar dos es lo mismo que el parámetro método. Luego podemos editar el método de proceso para establecer las cámaras y posición para que sean la altura del piso más el desplazamiento y Ahora la cámara se desplazará suavemente hacia arriba o hacia abajo después de que el sujeto aterrice ajustándose a una nueva altura del piso. Si quieres que estos dos comportamientos tengan diferentes duraciones, transición o tipos de flexibilización, eso es tan sencillo como exportar más variables para Me gustaría que la pintura horizontal fuera más lenta y más suave, pero la vertical para ser más rápida y reactiva. Voy a tener una mayor duración para la horizontal, pero también tener el tipo de facilidad para estar tanto dentro como fuera. Para vertical, voy a tener una duración más corta y sólo la facilidad de salida. La cámara se mueve más rápido al principio y más despacio después de nosotros. Dependiendo de la versión de do que estés usando, puede haber un problema con mover tanto la cámara como el personaje al mismo tiempo, creando un efecto de jittering Para solucionar esto, intente abrir la configuración del proyecto. Mirando debajo de la ventana de la pantalla para V sync en la parte inferior y desactivar la configuración. Ahora tenemos nuestra cámara, mostrando al jugador exactamente lo que necesita para ver de una manera suave y gentil. En la siguiente lección, agregaremos un fondo animado a nuestra escena. Te veré en la siguiente lección. 26. 2-5 Fondo: Hola amigos. En la lección anterior, terminamos el guión de comportamiento de nuestra cámara, por lo que sigue al personaje del jugador. En esta lección, agregaremos un fondo animado a nuestro nivel. El fondo de nivel necesita dar la impresión de que está muy lejos. De lo contrario, el entorno le aparecerá muy plano y bidimensional al jugador, podemos crear una ilusión de profundidad agregando un nodo hijo a la cámara. Un nodo dos D, tendrá un valor de posición así como un índice Z, un fondo de nombre. Luego expanda la sección de pedidos debajo del elemento canvas y establece el índice Z de este nodo para que sea un valor negativo. El terreno nivelado está utilizando el índice Z predeterminado de cero. dibujará un número negativo detrás dependiendo de cuántas capas de profundidad desee en su entorno. Es posible que desee poner el índice z de fondo más atrás que solo uno negativo. Voy a poner el fondo en negativo diez, dejando negativo uno a negativo nueve disponible para cualquier cosa que necesite estar entre el fondo y el terreno. A pesar de que no estoy planeando hacer eso, es mejor dejar ahí la posibilidad. Ahora, cada nodo hijo que agreguemos a este nodo seguirá automáticamente a la cámara y se dibujará detrás de todo lo demás en el nivel. El paquete de activos contiene varios sprites que podemos usar para ensamblar un entorno de fondo Simplemente podemos hacer clic y arrastrar las imágenes para el fondo a nuestra escena. Y Godot automáticamente los convertirá en sprite dos nodos D grupo seleccionando todos los nuevos Hazlos todos hijos del nodo de fondo. Al arrastrarlos a él, simplemente estiraré el atardecer, el cielo y las imágenes del agua para que cubran toda la ventana gráfica de la cámara Hagamos del fondo su propia escena para que pueda editarse de forma aislada y guardarlo en la carpeta de escenas. Después da clic en el icono de la tabla de chapaletas para abrirla. En la misma carpeta, hay algunas animaciones de sprites para hacer que el agua brille. Agreguemos tres sprites animados dos D en nuestra costura. Luego podemos poblar cada uno de estos con un recurso de marcos de sprite Y poblar los fotogramas de sprites con cada una de las tres animaciones de sprites Además, asegúrate de que reproducen automáticamente sus animaciones en bucle con la velocidad de fotogramas correcta, luego coloca cada una en el agua donde se verán bien Cuando termines, puedes guardar tu trabajo y ver cómo se verá ejecutando la escena principal. A continuación, agreguemos algunas nubes al cielo. Estos no están animados, así que podemos simplemente arrastrarlos a la vista de dos D para hacer sprite dos nodos D. Si quieres ajustar cómo se acoplan los sprites, en lugar de ajustar el valor del índice Z de cada sprite, también podemos usar el árbol de escenas para reordenar los nodos Los nodos con el mismo índice Z se dibujarán desde la parte superior del árbol de escenas hasta la parte inferior. Simplemente organizar la lista de nubes por su tamaño también será un ordenar su orden y poner la nube más pequeña en la parte posterior y la nube más grande en el frente. Guau, guau. Esta nube más grande también ya es más grande que la ventana gráfica de la cámara y tiene estos bordes duros Está diseñado de esta manera para ser enrollado sobre sí mismo usando una técnica llamada desplazamiento de paralaje, duplicando Podemos colocar dos de ellos en nuestra escena y moverlos gradualmente hacia un lado. Entonces cuando uno se mueve fuera de la pantalla, podemos reposicionarlo hacia el otro lado, haciendo que circule infinitamente en el fondo Esto se sumará aún más a la ilusión de profundidad de que el fondo está muy lejos, pero también creará la ilusión de que hay viento. Agreguemos un script al nodo raíz de esta escena, que creará el efecto de desplazamiento de paralaje Primero, necesitaremos obtener una referencia a los nodos hijos que queremos mover, podemos usar at y listos para almacenarlos en variables, asegurándonos de poner los nombres exactos de los nodos después del signo de dólar en sus asignaciones. También exportemos una variable para la velocidad de desplazamiento, que es un flotador basado en la animación de la palmera Se da a entender que el viento va a soplar hacia la izquierda. Usemos un valor predeterminado de negativo 100 en el método de proceso. Después podemos agregar una velocidad de desplazamiento multiplicada por delta a la exposición de las nubes, haciendo que se muevan hacia la izquierda a una velocidad constante Pero vamos a hacer esto a cinco nubes distintas. Entonces sería mejor hacer este método tomando un nodo dos D como parámetro junto con la distancia que se está desplazando como flotador Entonces sólo podemos sumar la distancia a su posición. Ahora el método de proceso puede llamar a este método, pasando en cada nube junto con la velocidad de desplazamiento multiplicada por delta. Para calcular la distancia por fotograma, podemos mejorar aún más la ilusión de profundidad que las nubes se muevan a diferentes velocidades, con las nubes más grandes más cercanas al jugador moviéndose más rápido y las nubes más pequeñas más alejadas con las nubes más grandes más cercanas al jugador moviéndose moviéndose más lentamente. Pero evite usar multiplicadores de velocidad que son múltiplos entre sí Esto formará un patrón muy obvio y romperá la ilusión si una velocidad de nube es exactamente la mitad de otra. Por ejemplo, el jugador notará que ayuda usar números primos para. Lo último que tenemos que hacer es verificar si alguna de nuestras nubes se ha movido completamente fuera de cámara, luego moverlas hacia el otro lado. Si colocamos una gran nube en el medio, la otra está ahora donde estará cuando queramos que dé vueltas, que también es el ancho de píxel de la imagen. Hagamos este valor de ancho exportado variable tipo float con un valor por defecto de 448. Comprobando si la posición x de una nube es menor que con tiempos negativos uno. Entonces podemos moverlo hacia la derecha por ancho multiplicado por dos para ponerlo al otro lado de la segunda gran nube. Esto también hará que las otras nubes circulen periódicamente por sus propias dos. Veamos cómo se ve eso hermoso. Sin embargo, tan pronto como tu jugador cambia el tamaño de la ventana del juego, la ilusión se rompe Al abrir la configuración del proyecto en la ventana de visualización, podemos establecer una resolución deseada para nuestro juego. Más importante aún, podemos cambiar el modo stretch a stretch canvas items, que es todo en nuestro juego de dos D. Definitivamente queremos mantener nuestra relación de aspecto igual incluso si el reproductor cambia el tamaño de la ventana, Una nueva característica recientemente agregada También podemos restringir el estiramiento a solo escala por cantidades enteras. Esto puede impedir que nuestros píxeles se dibujen en tamaños inconsistentes. Una vez que haya decidido una configuración de resolución, asegúrese de que su fondo se ajuste a la nueva configuración, y debería ser imposible verlo fuera de su fondo. Ahora tenemos un agradable atardecer nublado en el fondo de nuestro nivel. En la siguiente lección, agregaremos agua al primer plano. Te veré en la siguiente lección. 27. 2-6 agua: Hola, amigos. En la lección anterior, agregamos un fondo animado a nuestra escena. En esta lección, agregaremos agua al primer plano. Para esta lección, he descargado y modificado otro efecto de sonido para salpicaduras de agua Este efecto de sonido fue creado por Yin Yang Jake 007 en FreeSound.org Al igual que el fondo, podemos comenzar creando un nodo raíz para Esta vez usando un área dos nodo D y nombrarlo agua. Luego establece en el índice z a un número positivo, por lo que siempre se dibujará al frente, dejando espacio para capas adicionales en el medio. Los activos para el agua en el paquete de activos tienen una animación para las olas y un cuadrado plano para todo lo demás. Vamos a añadir un sprite animado dos nodos D para la superficie del agua Crear un nuevo recurso de marcos de sprite. Agregue el bucle de reproducción automática de fotogramas de sprite y luego establezca la velocidad de fotogramas, agregue un desplazamiento o mueva la transformada de sprites animados para que el origen del agua esté en la esquina superior izquierda Esto hará que sea más fácil alinearse con el mapa de teselas y también proporcionará el valor Y de cero siendo la superficie del agua. Después también agrega el sprite inferior como un nodo sprite dos D. Si bien el fondo se puede estirar fácilmente para llenar cualquier área, la superficie deberá duplicarse y repetirse para mantener organizado el árbol de escena. Deberíamos crear otro nodo dos D, para actuar como una carpeta plegable contiene estos sprites animados El área dos D necesita una forma para definir cómo funcionará su colisión. La física del agua necesita dos comportamientos diferentes. Cuando algo está en la superficie del agua y cuando está debajo del agua, podemos usar un segmento de línea dibujado sobre la superficie del agua, ya que eso nos dirá si algo está tocando la superficie o no. Para facilitar las cosas, asegúrese de que el origen del objeto agua esté en línea con el colisionador de superficie También dupliquemos rápidamente una de nuestras escenas de partículas de polvo para crear una escena de salpicadura. Después borra los fotogramas de sprite en esta escena y reemplázalos con los sprites splash one del asset pack Para que el agua reaccione ante las colisiones, tendremos que crear un guión de agua Este guión tendrá que reaccionar ante dos señales cuando un cuerpo entre en él y un cuerpo salga de él. Simplemente podemos conectar estas señales al propio script usando los nombres predeterminados. Los parámetros del cuerpo de estos métodos son de tipo nodo dos D, como se puede ver en la lista de señales. Pero para definir cómo se comportarán nuestros personajes en relación con el agua, necesitamos saber si este nodo dos D llamado cuerpo es un personaje o si es otra cosa. Tendremos que darle a nuestro guión de caracteres un nombre de clase antes de que la palabra se extienda. En la primera línea, agregue nombre de clase, carácter. Esta es ahora una palabra que otros scripts pueden usar para referirse a este script como un tipo general. De vuelta en el guión del agua, cuando un cuerpo entra al agua, ahora podemos comprobar si el cuerpo es un personaje, Luego llamar a un método que aún no hemos definido, que nombraremos entrar al agua y pasar en la posición y del agua, que es la superficie del agua en el cuerpo. Método de salida. Podemos realizar la misma comprobación para ver si el cuerpo es un personaje. Nuevamente, cuando un personaje sale, es decir, que ya no está tocando el segmento lineal que cubre la superficie del agua, podría estar sucediendo una de dos cosas. O ahora están por encima de la superficie del agua o están por debajo de la superficie. Como sabemos que la posición Y de este nodo es la superficie del agua, el cuerpo también tiene una posición Y. Podemos comparar los dos valores para determinar en qué caso se trata este. Pero también agregando PPT global dividido por dos o dos mosaicos. Si la posición del cuerpo es menor o igual a la superficie del agua, eso significa que el cuerpo ha dejado hacer contacto con la superficie del agua y está completamente por encima de la superficie del agua. Dado que los píxeles por mosaico se definen como un entero, pero la posición y se define como un flotador, Godel nos advertirá que los valores decimales serán ignorados Podemos remediar esto echando el valor entero en un valor flotante aquí y el personaje está saliendo del agua De lo contrario, el personaje se encuentra debajo de la superficie del agua. Y deberíamos llamar a un método diferente, que voy a nombrar buceo. Cambiando al script de caracteres, podemos agregar estas tres definiciones de método a nuestros métodos públicos. Ingresa agua, que toma como parámetro un valor de flotación que representa la superficie del agua. También, buceo y salida de agua. El propósito de estos métodos públicos es dejar que el proceso de física y los métodos de salto sepan dónde está el personaje y cómo deben comportarse. Tendremos que añadir algunas nuevas variables privadas. La altura de la superficie del agua como flotador, y dos booleanos que nos dicen si el personaje está en el agua y si están por debajo de la Cada uno de nuestros nuevos métodos ahora puede establecer estas variables de manera apropiada. Entrar conjuntos de agua la altura de la superficie del agua nos dice que estamos en el agua pero no por debajo de la salida superficial. El agua se fijará está en el agua a las caídas. La inmersión simplemente se colocará debajo de la superficie. Para ser cierto para la física, debemos considerar si el personaje flotará o hundirá, así como cuánto estar en agua restringe su movimiento Podemos agregar una nueva categoría de variables exportadas a nuestro script llamado Swim. En aras de la simplicidad, el valor que determina si un carácter flota o no, podemos llamar densidad y darle un valor por defecto de negativo 0.1 Este valor será en comparación con la densidad del agua Un valor de cero tendrá una flotabilidad perfecta, menos de cero flotará, mayor que cero se hundirá para restringir También podemos definir un valor para el arrastre, que se multiplicará por fuerzas para reducir su efectividad. Y usar un valor por defecto de 0.5 Para empezar, cuando un objeto alcanza por primera vez la superficie del agua, hay una fuerza de impacto que reduce su velocidad En el método enter water. Si nuestra velocidad y es más de cero, podemos multiplicarla por arrastre Para simular esta fuerza de impacto, igual que hicimos con el suelo en física aérea, primero podemos verificar en el proceso de física, si el personaje está en el agua, luego aplicar física del agua, asegurándonos de pasar delta, cambiando si a else en la siguiente línea, comprobando si están en el piso. movimiento horizontal en el agua se comportará muy igual que en el suelo, pero con la desaceleración y aceleración también multiplicada por arrastre para reducir su efectividad Ya que copié esta línea desde arriba, necesito cambiar la desaceleración a aceleración El movimiento vertical dependerá de si el carácter se encuentra por debajo de la superficie del agua o si su densidad es mayor a cero. En cualquiera de estos casos, necesitaremos mover su velocidad Y hacia la flotabilidad, que es la gravedad multiplicada por la densidad, y también aplicar arrastre para ralentizar La tasa de cambio se calcula usando gravedad tiempos de arrastre delta. Si el personaje está tocando la superficie del agua, entonces queremos hacerlos sacudir arriba y abajo. Que se puede dividir en dos situaciones con otra declaración if. Si el centro de flotabilidad de los caracteres está por encima o por debajo de la superficie del agua, entonces ajuste la velocidad y para moverse hacia arriba o hacia abajo Podemos simplificar esto para que sea si la posición y del carácter menos un cuarto de una teja es menor que la altura superficial del agua. Por simplicidad, podemos simplemente copiar la fórmula desde arriba multiplicada por una negativa si están por debajo la superficie del agua para movernos en sentido contrario. Lo último que tenemos que hacer es alterar cómo funciona el salto mientras estamos en el agua. Si el personaje está en el agua y debajo de la superficie, entonces la velocidad de salto debería verse afectada por el arrastre. Si el personaje no está debajo de la superficie, entonces deberían tener toda la fuerza de salto para que puedan saltar fácilmente a tierra. También podemos emitir la señal aterrizado aquí para ajustar la cámara. También cuando ingresan al agua también el método de stop jump debe ser deshabilitado mientras están en el agua. Si bien tenemos el script de caracteres abierto, copiemos el método de polvo de generación y utilicémoslo para crear un método de splash En el guión del agua, necesitaremos una referencia a la escena empaquetada, que contiene el splash. Renombrando nuestras variables y métodos en consecuencia. Como el agua está creando el chapoteo y el agua no se mueve, el chapoteo puede ser chilled al agua, no hay problema La posición de las salpicaduras y por defecto será cero, que ya es la superficie del agua Y su posición global x se puede establecer al valor pasado al método como argumento. Esta será la posición del cuerpo que ingresó al agua para crear el chapoteo. Podemos establecer la posición X de salpicadura para que coincida exactamente con esto. El agua también necesita un reproductor de flujo de audio dos D para generar el efecto de sonido splash. Poblado con el archivo modificado que descargué de FreeSound.org El script puede obtener una referencia a este nodo hijo durante la fase de listo, luego decirle al efecto de sonido Podemos generar un chapoteo cada vez que un cuerpo ingresa al agua pasando por la posición del cuerpo. Y también cuando un cuerpo de personaje elige salir del agua, posicionando el agua donde el jugador pueda acceder a ella y recordando poblar la escena repleta de salpicaduras en el inspector, podemos darle una prueba rápida y hacer cualquier ajuste que deseemos al arrastre de densidad del personaje o los cálculos de flotabilidad o el reventón en la superficie hasta que Con el agua completamente funcional, hagamos que abarque todo el primer plano del nivel, estirar la parte inferior, duplicar la superficie y editar la forma de colisión para que coincida con el piso que creamos en la primera lección, y editar la forma de colisión para que coincida con el piso que creamos en puede que también esté en tu camino Ahora tenemos el agua en primer plano de nuestro nivel y los personajes pueden nadar en ella En la siguiente lección, estructuraremos nuestro nivel y agregaremos límites. Te veré en la siguiente lección. 28. 2-7 límites: Hola amigos. En la lección anterior, agregamos agua al primer plano de nuestra escena En esta lección, estableceremos la estructura para nuestros niveles y nuestros límites. Primero, el mapa de teselas está activando actualmente el ruido de salpicadura Cuando ejecutamos nuestra escena, agregar una condición al método de cuerpo ingresado puede regresar si el cuerpo es un mapa de teselas, evitando que este código se ejecute En este caso también, posible que algunas de las animaciones acuáticas no se hayan sincronizado al ejecutar la escena, lo cual es sólo un problema temporal causado por tener las animaciones reproducidas en el editor. Si estás viendo una costura en las nubes de desplazamiento, también puedes reducir la propiedad width en un píxel También debemos ajustar los colisionadores de caracteres restantes para que puedan pararse limpiamente en el suelo. Nuestro árbol de escenas ahora está lleno de muchos componentes diferentes. Los nodos de etiqueta y piso ya no son relevantes. Eliminémoslos. Deberíamos separar todos los nodos que se usarán para construir diferentes niveles en una sola rama, convirtiendo todas nuestras decoraciones en hijos de un nodo dos D. Estos se vuelven más fáciles de organizar, hacen lo mismo con nuestros enemigos, haciéndolos todos hijos de un nodo dos D para mantenerlos organizados. Dado que estos son todos componentes de nuestro nivel de juegos, podemos crear una nueva área dos D para mantenerlos y nombrarlo nivel. Después hacer las decoraciones del mapa de azulejos, enemigos e hijos de agua del nodo de nivel. En aras de la simplicidad, establecemos temporalmente el origen del nivel para que sea la ubicación inicial del jugador y movamos al jugador al origen de la escena. Después ajusta todos los nodos hijos del nivel para que coincidan con guardar el nivel como su propia escena, que pertenece a una nueva carpeta llamada levels. Podemos nombrar a este nivel uno, uno. El personaje del jugador Cámara y fondo se utilizará para cada nivel ya que el asset pack no contiene ningún otro activo para fondos, dependiendo de cómo planees diseñar tu juego, el fondo también puede ser parte del nivel. Ya podemos abrir la escena de nivel uno. Ya que hicimos el nodo raíz de nuestro nivel en un área dos D, eso significa que podemos darle forma. Definamos nuestro nivel como un rectángulo. Y ajustar el tamaño y la posición del rectángulo para definir límites a los que quedarán confinados el jugador y la cámara. Y ajusta el color del error D de esta zona de colisión para que sea más transparente. No afecta nuestra visión de todo lo demás. Al crear un nuevo script para el nivel, podemos obtener una referencia al nodo D de la forma de colisión dos durante la fase de preparación. El propósito de este rectángulo es que el jugador y la cámara sepan dónde parar. Tendremos que obtener los valores mínimos y máximos permitidos dentro de los confines de este rectángulo Vamos a escribir dos métodos, obtener min y obtener max, que será público y devolverá un vector dos. El valor mínimo será la posición de las formas de colisión menos la mitad de su tamaño. Pero para acceder al tamaño, primero necesitamos acceder a su forma, luego al rectángulo, luego al tamaño, y repetir para obtener el valor máximo. Para evitar repetir este código varias veces, también debemos definir esto como una variable, nombrarlo medio tamaño. Regresando a la escena principal. El propósito de esta escena es facilitar la comunicación entre el personaje del jugador, la cámara y el nivel actual, permitiéndonos cambiar fácilmente el nivel por uno nuevo según sea necesario. Se puede renombrar esta escena y su nodo raíz para reflejar este propósito. En un juego sencillo como este, puedes llamar a esto la escena principal, o la escena del juego. Si tu ciclo de juego incluye otro juego además de plataformas, es posible que quieras nombrar la escena de plataformas para distinguirla de otras escenas de juego Para gestionar las reglas de cómo funcionará esta escena de juego , debemos darle un guión. El nombre del guión suele ser el nombre de la escena seguido del gestor de palabras. El trabajo de este gerente es asegurarse de que todas las notas infantiles tengan toda la información que necesitan para hacer cada uno de sus trabajos únicos. Para evitar que el personaje jugador o la cámara salgan de los límites del nivel, necesitan saber cuáles son esos límites. Dado que esta escena será capaz de correr cualquier nivel, necesitará solicitar la información sobre los límites del nivel desde el guión de nivel y pasar esa información al guión del personaje del jugador así como a la cámara. En la parte superior del guión del gerente. Primero consigamos referencias al nivel, al jugador y a la cámara dentro del método ready. Entonces podemos obtener los límites desde el nivel y establecer los límites para el jugador y la cámara. Ahora tanto el personaje como los guiones de la cámara necesitarán métodos públicos para establecer estos límites, luego también hacer cumplir estos límites sobre sí mismos. Comenzando con el carácter, podemos simplemente crear dos nuevas variables de tipo vector dos y almacenar los valores mínimo y máximo. Escribe un método de límites establecidos que toma dos vectores dos y establece los valores de las variables privadas Entonces en la parte inferior del proceso de física, podemos restringir la posición del personaje para que quede contenida dentro de estos límites utilizando el método clamp, proporcionando al valor actual un mínimo y un máximo. Depende de ti si quieres imponer estas restricciones a todos los personajes de tu juego o solo al personaje del jugador. Pero creo que los enemigos deberían ser libres dejar los límites de nivel en mi juego. Haré que este último paso supedite si estos límites se han establecido o no, agregando también una variable booleana llamada is bound Cuando se llama al método set bounds en el personaje del jugador, también establecerá esta variable en true, pero otros personajes permanecerán desvinculados La cámara será un poco más complicada ya que la propia cámara también tiene forma. Copiar las mismas variables y establecer el método en el script de la cámara. Podemos editar los valores de min y max para acomodar el tamaño de la vista de la cámara. Podemos recuperar este valor usando get Viewport destrozado tamaño dividido por zoom y reducido Después sumar este valor al mínimo y restarlo del máximo Casi siempre es mejor almacenar cualquier valor calculado en una variable en lugar de calcularlo más de una vez. Entonces podemos sujetar la posición de la cámara de la misma manera que hicimos con los personajes. Vamos a probarlo. La vista de las cámaras está contenida dentro del límite de nivel como es el origen del personaje, y funciona en todos los lados. Podemos mantener a todo Roger en pantalla aplicando la misma lógica, usando el tamaño del sprite Pero debido a que el sprite no está centrado en el origen del personaje, necesitamos calcular los valores x e y de manera diferente Ahora a Roger sólo se le permitirá donde todo el sprite permanecerá en pantalla A lo largo de esta sección, hemos desarrollado muchas de las características que se utilizarán para generar niveles para nuestro juego. En la siguiente sección, agregaremos tesoros coleccionables y una interfaz de usuario a nuestra escena principal Te veré en la siguiente sección. 29. Datos 3-1: Hola amigos. En la sección anterior, construimos muchos de los componentes estructurales que necesitamos para construir niveles de nuestro juego. En esta sección, crearemos tesoros coleccionables para el jugador los recoja y los disperse a través de nuestros niveles Si completaste la tarea, deberías tener dos niveles básicos construidos con diferentes terrenos, decoraciones y límites A medida que completaste esta tarea, probablemente también hiciste ajustes para que encajaras o sintieras mejor para tu juego. Por ejemplo, disminuí la velocidad de desplazamiento de las nubes a 32 píxeles negativos por segundo porque no me gustó cómo se veían cuando la cámara se pinzaba con pinzas Al dar la vuelta de la cámara, reduje la gravedad aproximadamente a la mitad de lo que era antes y alteré los valores para todos los personajes, locomoción y natación También hice una pequeña corrección al efecto de sonido splash en la escritura de agua. Dado que el reproductor de audio dos nodos D reduce el volumen en función de la proximidad a la cámara, el sonido se volverá más silencioso cuanto más lejos estuvieras desde el inicio del nivel. Para arreglar esto, configuré la exposición global del nodo reproductor de flujo de audio a la exposición pasada al método el sonido se originará desde la misma ubicación que el splash a todo volumen Si bien los tutoriales siempre deben ser lo último que construyas para tu juego, me gustaría aprovechar para repasar algunos principios de diseño de niveles para el aprendizaje intuitivo. Para el primer nivel de isla, inicié al jugador con un obstáculo inmediato que deben saltar por encima, seguido de un obstáculo superior y uno aún más alto. Después de eso, esto debería ser suficiente para que el jugador entienda que puede mantener presionado el botón de salto para llegar a la cima del segundo, pero no al tercer obstáculo. Introduje el árbol como una plataforma de un solo sentido en un ambiente seguro, y requiero que el jugador aprenda a usarlo antes de llegar a la siguiente sección del nivel. Aquí están disponibles los mismos árboles, con un poco más de riesgo de ser introducidos, tener que saltar de árbol en árbol, y potencialmente caer en el agua. Si fallan, el riesgo no es real, aunque sólo percibido por el jugador. He creado tres caminos diferentes a partir de esta parte, siendo el más fácil el camino a seguir, y los otros dos potencialmente conducen a recompensas. Todos son claramente visibles, enseñando al jugador que debería estar buscando más caminos ramificados como este en el futuro, la próxima vez que golpee algo como esto, el jugador verá primero la recompensa, pero se le exigirá que se dé jugador verá primero la recompensa, la vuelta para volver a obtenerla, enseñándole al jugador lo que debería estar buscando Esta es la primera vez que utilicé un árbol de fondo. Porque no quería que el jugador pensara que podían saltar sobre este árbol, fallar y aprender falsamente que todos los árboles no son plataformas En este punto, el jugador tiene experiencia utilizando árboles de primer plano como plataformas Este árbol se posiciona para ser saltado desde el árbol a la izquierda o desde el suelo. Esto le enseña al jugador que solo los árboles de fondo no son plataformas para proceder, deben ignorar el árbol de fondo y saltar desde la repisa En cambio, en caso de que el primer árbol no funcionara, lo seguí con un segundo árbol destinado a atraer al jugador para que intentara saltar sobre él. Y en cambio, siguiendo. Aquí hay otra cueva secreta. Pero esta vez el jugador no puede verlo. Si han aprendido de las partes anteriores del nivel que deben explorar en el agua, serán recompensados. Todas estas entradas al agua están claramente marcadas con rayos de luz, dos, que ayudan a captar la atención del jugador y hacer que el agua se vea atractiva He colocado árboles de primer plano y de fondo juntos para poner a prueba la capacidad del jugador para saltar hasta el árbol más alto Los árboles se distinguen aún más por su coloración y capas delante o detrás del jugador uso de colores o iluminación consistentes para atraer la atención del jugador se llama usando lenguaje visual o posibilidades para decirle al jugador que puede o debe hacer algo en ese lugar o usar ese objeto Muchos juegos utilizan estas técnicas para indicar repisas escalables, objetos rompibles, NBC interactuables O para decirte cuándo debes usar un arma o habilidad específica. Mover el primer nivel fuera del camino, reemplazarlo por un nivel de barco y renombrar los nodos Entonces puedo jugar al otro nivel en su lugar. cuando el jugador alcance este nivel, tendrá una buena comprensión de la mecánica de plataformas y no necesitará ser enseñado En cambio, me concentro en crear la apariencia general de un barco pirata, dando forma a todo el nivel para representar un casco. Y agregó un alicatado extra para ocultar el fondo hasta que el jugador alcance por encima del nivel del agua Decoré habitaciones específicas y callejones sin salida con barriles y botellas, Y posicioné escaleras de manera temática e impidió que el jugador saliera alguna vez del barco Antes de que el jugador pueda recoger algún tesoro, necesitaremos crear un guión para saber cuánto tesoro tiene. Podemos poner este script en la carpeta Autolodes y nombrarlo Pero en lugar de extender el nodo, esta vez necesitamos extender. Podemos quitar la plantilla. El propósito del guión será contener toda la información sobre el progreso de un jugador en el juego. Para comenzar, solo agreguemos un entero, que será el número de monedas que el jugador haya recogido, y otro entero para representar el número de vidas que le quedan al jugador. Exportar estas variables nos permitirá verlas en el inspector mientras se ejecuta el juego. Si es necesario, el valor predeterminado para un entero es cero, lo cual está bien para las monedas de un jugador como valor inicial, pero no tan agradable para sus vidas al comienzo del juego. Deberíamos definir exactamente qué contendrá este recurso cuando se cree por primera vez. Subrayar en ella, podemos establecer los valores iniciales para cada variable, así como realizar cualquier otra lógica que queramos Como parte de la inicialización de recursos, me gustaría que los jugadores iniciaran mi juego con cero monedas y tres vidas Para hacer referencia a este recurso por su tipo, necesitamos darle un nombre de clase. Vamos a llamarlo Datos con una D. mayúscula A medida que nuestro juego se vuelve más complicado, este recurso de datos contendrá muchas más variables de diferentes tipos para rastrear el progreso de los jugadores. Ahora tenemos un lugar para almacenar esta información, pero necesitamos los guiones en nuestro juego para poder acceder a ella libremente. Como hicimos con la carga automática global, podemos crear otra carga automática cuya responsabilidad es acceder y administrar los datos. Vamos a nombrar este archivo contendrá una variable llamada data con una minúscula de tipo data con una mayúscula D. La finalidad del script será dar acceso al resto del juego al archivo de datos actual, pero también administrar el archivo de datos Aquí tendremos que escribir métodos para iniciar un nuevo juego guardando y cargando dos. Realmente solo nos interesa crear un nuevo recurso de datos. Deberíamos establecer el valor de los datos para que sean datos, nuevos datos nuevos crearán un nuevo recurso de datos y activarán automáticamente el método init que acabamos de escribir, estableciendo las vidas en tres en lugar de cero Por ahora, podemos simplemente llamar al nuevo método de juego cuando este nodo esté listo. Al abrir la configuración del proyecto, cambiar a la pestaña de carga automática, luego agrega el nuevo script de archivo a la lista de cargas autos. El nombre de nodo predeterminado funcionará bien si ejecutamos esta escena. Podemos cambiar de nuevo a Dios mientras se ejecuta el juego. Luego cambia de local a remoto en la pestaña de escena. Esto nos mostrará el árbol de escenas para el juego que actualmente se está ejecutando. Seleccionando el archivo auto cargado nodo, y mirando en el inspector, podemos ver que tiene un recurso de datos. El nombre del recurso de datos es ID de objeto, seguido de un número largo. Al hacer clic en el recurso, podemos ver y editar su contenido. Cualquiera de nuestros scripts puede acceder a esta información fácilmente. Para demostrarlo, abramos el guión del manager del juego. Y después de hacer estas cosas habituales con los límites de nivel, simplemente imprime el valor de vidas archivadas Corriendo la escena, podemos ver el número tres impreso en el panel de salida. Ahora tenemos un recurso personalizado configurado para almacenar la información de nuestros jugadores a la que podemos acceder en cualquier momento. En la siguiente lección, crearemos monedas que el jugador podrá recoger. Te veré en la siguiente lección. 30. Monedas 3-2: Hola amigos. En la lección anterior, creamos un recurso personalizado para rastrear el progreso y los datos del jugador. En esta lección, crearemos monedas coleccionables. Podemos dispersarnos a lo largo nuestros niveles para que el jugador los recoja. Para esta lección, he importado un juego de sonidos de clics de monedas de FreeSound.org hechos por Val Inspire con licencia Creative Commons Empecemos abriendo nuestro primer nivel y creando una nueva carpeta nodo dos D para tesoro. Las monedas son objetos físicos que existen en el mundo. Tendremos que detectar colisiones. También podemos querer que se vean afectados por la gravedad. El nodo que mejor defina estos comportamientos será un nodo D de cuerpo rígido dos. Cambiémosle el nombre a moneda de plata para poder ver nuestra moneda. Primero le agreguemos un sprite animado. Crear un nuevo recurso de marcos de sprite. Encuentra los sprites de monedas de plata en el paquete de activos y rellena la animación predeterminada Establezca esta animación predeterminada en reproducción automática, bucle y establezca los fotogramas por segundo. También podemos agregar una segunda animación a este sprite animado haciendo clic en el nombre del botón agregar animación Este efecto de animación, luego llénalo con los sprites de efecto de moneda del paquete de activos Esta animación no debe ser en bucle. Esta es la animación que debe reproducirse cuando se recoge la moneda antes de que desaparezca. Vuelve a la animación predeterminada. Así podemos ver claramente el tamaño y la forma de la moneda en el editor. Ahora que podemos ver nuestra moneda, como con todos los objetos físicos de estas colisiones, tendremos que darle una forma de colisión, creando un recurso de forma de círculo Podemos cambiar su tamaño para que se ajuste al tamaño de la moneda que pueda necesitar para desactivar el ajuste de grado Las colisiones con monedas también suelen generar efectos de sonido debemos agregarle un reproductor de flujo de audio al nodo y poblarlo con el efecto de sonido de moneda Cl Guardemos la rama de la moneda de plata como escena propia y pongamos esto en una nueva carpeta de escenas llamada tesoro. Como todo lo demás, las monedas necesitarán un guión para controlar cómo se comportan. Deberíamos comenzar a organizar nuestros guiones en carpetas designadas. Voy a crear una carpeta de desnudos para guiones del tesoro. Podemos iniciar nuestro guión agarrando referencias a los nodos sprite y reproductor de audio durante la fase de listo Con el nodo raíz de monedas seleccionado, conecta la señal ingresada del cuerpo a sí mismo para que la moneda pueda reaccionar ante colisiones con Cuando un cuerpo entra en el colisionador de monedas, primero debemos tocar el efecto de sonido Entonces queremos comprobar si con lo que colisionó la moneda es algo además de un personaje, y si no es un personaje, regresa por lo que se ignora Si este es efectivamente un personaje, podemos decirle al sprite animado que reproduzca la animación de efectos Entonces este nodo para ser removido de la escena. Con un libre, este código se ejecutará todo en un solo fotograma. No vamos a llegar a ver cómo se desarrolla la animación. Podemos usar un nuevo comando aquí llamado un weight para pausar este código hasta que algo suceda. Lo que queremos esperar será cuando la animación de sprites termine la animación de sprites con el nodo raíz de monedas seleccionado Tendremos que cambiar algunos de los ajustes predeterminados para el nodo de cuerpo rígido. Por defecto, la señal ingresada en el cuerpo solo ocurrirá cuando los colisionadores se superpongan Pero como la física se está aplicando tanto al personaje como a la moneda, esto no va a suceder. El colisionador de personajes empujará al colisionador de monedas Podemos cambiar estos ajustes para permitir que la señal ocurra cuando los colisionadores hacen contacto Al establecer el monitor de contactos a verdaderos contactos máximos reportados a cualquier valor mayor que cero, pero realmente solo deberíamos necesitar uno siguiente. Amplíe la sección de desactivación. La mayoría de la gente no querría que el píxel rotara, así que podemos bloquear la rotación de las monedas haciendo clic en esta casilla monedas coleccionables en la mayoría de los juegos se encuentran en una de dos categorías Los que flotan en el aire y los que son arrojados por ahí después de romper una caja o derrotar a Podemos hacer la primera opción estableciendo la propiedad freeze en true y cambiando el modo de congelación a Kinematic Ahora la moneda no se verá afectada por la física, incluida la gravedad, sino que seguirá colisionando con otros objetos Si queremos encender la gravedad o que la moneda se arroje, simplemente ponemos freeze a false y le aplicamos las fuerzas que queramos También queremos asegurarnos de que nuestras monedas solo sean recolectadas por el personaje del jugador, no por los enemigos ni por cualquier otro personaje. La forma más sencilla de lograrlo es usar capas de colisión. Hasta ahora todo en nuestro juego ha estado usando la capa de colisión predeterminada, la capa uno. Usando diferentes capas de colisión, podemos controlar fácilmente qué objetos reaccionan o ignoran otros objetos. Dejemos que la capa por defecto, la capa uno, represente el terreno. Dado que la mayoría, si no todos, los objetos necesitarán chocar con eso, por defecto, posible que queramos tener diferentes tipos de entornos con diferentes tipos de colisiones en el futuro, dejemos que el mundo use las primeras ocho capas de colisión abriendo la escena de Rogers Podemos cambiar su capa de colisión a la capa nueve y dejar que el segundo bloque represente nuestras capas de colisión de jugadores. De igual manera, podemos poner a los personajes enemigos en la capa 17. Y que el tercer bloque represente nuestras capas de colisión enemiga. Por último, las monedas pueden estar en la capa 25, con el cuarto bloque representando el tesoro. La sección de máscara de las capas de colisión es con lo que colisionará este objeto Lo único con lo que queremos que choque la moneda será con el medio ambiente Y el jugador que hemos establecido en las capas uno y nueve monedas ahora ignorará las colisiones con los enemigos así como con otros tesoros Haré que el personaje del jugador choque con los enemigos, los enemigos choquen con el jugador así como con otros También debemos abrir la configuración del proyecto y dar nombres a cada una de estas capas de colisión para que podamos recordar fácilmente para qué las hemos reservado. Los nombres se mostrarán como una punta de herramienta al pasar el cursor sobre la capa de colisión en el inspector Hay un segundo conjunto de sprites de monedas en el paquete de activos para una moneda de oro dos Duplicemos nuestra escena de monedas de plata y renombrémosla a moneda de oro. Y reemplazar los sprites de monedas de plata por sprites monedas de oro si queremos que diferentes monedas tengan diferentes También podemos agregar un valor entero exportado a nuestro script y darle un valor predeterminado de uno para mi juego. Voy a hacer que las monedas de oro tengan un valor de diez monedas de plata. Si bien es poco probable, es posible que después de que el jugador choca con la moneda, puedan chocar con la misma moneda por segunda vez antes de que Para evitar esto, debemos poner cero la máscara de colisión de la moneda, eliminando cualquier posibilidad de que colisione con cualquier cosa después de que haya sido recolectada Colocando una de cada moneda en nuestro nivel, el jugador ahora puede recogerlas. También podemos colocar agua en una capa separada del terreno y hacer que choque con ambos personajes y tesoros, y nombrar la capa en la configuración del proyecto Ahora tenemos monedas coleccionables de valor variable que el jugador estará motivado a recoger a lo largo de nuestro juego En la siguiente lección, crearemos una interfaz de usuario con un contador para mostrar al jugador cuántas monedas tiene. Te veré en la siguiente lección. 31. Interfaz de usuario 3-3: Hola amigos. En la lección anterior, creamos monedas de diferente valor para que el jugador las recoja. En esta lección, mostraremos cuántas monedas tiene el jugador en la interfaz de usuario. En la escena max de la plataforma principal, podemos agregar una interfaz de usuario para mostrar todo tipo de información importante que el jugador necesita. Esta información debe ser independiente de la cámara y siempre mostrarse frente a todo lo demás. ¿Podrías tener la tentación de hacer de esto un hijo de la cámara como lo hicimos con el fondo hay ningún tipo para crear esto más fácil llamado capa de lienzo. Cada dos nodos n arsenio tiene un orden de sorteo basado en su índice de conjunto y su posición en el árbol de escena Pero después de que todo ha sido procesado por la cámara en una sola imagen, todo eso se convierte en la capa predeterminada, capa cero. Por defecto, una capa de lienzo dibujará una imagen completamente nueva sobre la capa uno. Por encima de eso, las capas de lienzo se rellenan con un nuevo tipo de nodo. De hecho, usamos uno en la primera lección. Estos se denominan nodos de control y están marcados en verde. Para mostrar números en la pantalla, podríamos usar un nodo de etiqueta, que puede mostrar cualquier texto que queramos, pero realmente no encajaría con nuestra estética de pixel art. Y nuestro paquete de activos viene con buenos sprites de números, así que usemos esos en su lugar Podemos agregar nodos de control a la capa de lienzo llamada textura Rets para mostrar estos sprites por nosotros, agreguemos una textura para un dígito, otra para el dígito de diez, y poblemos ambos De forma predeterminada, deberá establecer un límite en la cantidad de dígitos que desea mostrar en la pantalla. Siguiendo las convenciones de juegos como Mario y Donkey Kong, limitaré el número de monedas al 99 y le daré al jugador una recompensa extra por cada 100 recaudados También debemos agregar una textura de icono para decirle al jugador qué significa este número y poblado con la imagen de una moneda para evitar reorganizar manualmente los nodos de control individuales En la capa canvas, también hay nodos proporcionados por Godot, cuyo propósito es organizar sus nodos hijos para nosotros. Agreguemos una caja horizontal al lienzo, le pongamos un contador de monedas y pongamos nuestros otros nodos como hijos de la caja. Se reorganizan automáticamente para que quepan horizontalmente dentro de la caja. Voy a posicionar este contador 32 pixeles lejos de la esquina. Y aumenta escalado dos, es mucho más fácil de notar y leer Luego podemos editar la configuración de los controles individuales para determinar cómo se dibujarán en relación con su contenedor padre. Me gustaría que se mostrara el icono, ajustando proporcionalmente a su ancho Y escale para que se ajuste al tamaño del contenedor padre. Los dígitos, me gustaría duplicar su tamaño para que sean más fáciles de leer. Sabiendo que hay cinco píxeles de ancho, estableceré su ancho mínimo personalizado en diez píxeles. Encajarlos proporcionalmente a su altura. Y mantener su relación de aspecto al mismo tiempo que los mantiene centrados en el padre. Observe cómo se están dibujando los controles del lienzo aquí en el agua. Pero si pulsamos play, se muestran en la esquina superior izquierda de la ventana. Si recuerdas de la primera lección, la imagen que se dibuja en pantalla por defecto es este rectángulo azul. Si ayuda, puedes ocultar el nivel, el personaje y la cámara mientras trabajas en el lienzo haciendo clic en los iconos. Recuerda mostrarlos cuando estés listo para probar tu juego Intenta experimentar con cómo se muestra tu contador en la pantalla y comprueba cómo se ve mientras juegas Para que el mostrador funcione, necesitaremos escribir un guión para ello. Pondré esto en una nueva carpeta de scripts para UI y la nombraré Counter. Dado que la naturaleza de un contador de monedas no tiene nada que con la organización de una caja horizontal, voy a hacer que extienda el tipo de control más genérico. En cambio, necesitaremos referencias a cada una de nuestras recs de textura que deseamos cambiar de conjunto durante la fase lista También necesitaremos una lista de texturas para intercambiarlas, representando cada uno de nuestros números 0-9 Podemos almacenarlos en una matriz exportada de textura dos D's llamados dígitos de subrayado Una matriz es similar a una lista, en este caso una lista de dos texturas D, o imágenes de números que buscan en el inspector. Podemos dar click sobre esta matriz exportada para expandirla y darle un tamaño de diez. Los elementos de la matriz están convenientemente numerados del cero al nueve. Estos son los índices que utilizamos para acceder a los elementos individuales de la matriz. Rellena cada índice de matriz con el dígito coincidente del paquete de activos. Este script necesita una función a la que podamos llamar para establecer el número que se está mostrando. Lo llamaré valor establecido y tomaré un entero como parámetro. Sabiendo que este contador sólo está destinado a mostrar un número 0-99 Primero vamos a hacer cumplir esta regla Al sujetar el valor entre estos números. Podemos establecer la textura que se muestra por las texturas k, para que sean dígitos en un índice. ¿Cuál es el índice? Es lo mismo que el dígito mismo. Pero, ¿cómo extraemos el dígito? Podemos utilizar un operador común en la programación llamado módulo, representado por el signo de porcentaje, que devuelve el resto de un valor de división. Diez devolverá el dígito, que es el índice de matriz de la textura que queremos mostrar. Entonces también podemos establecer el dígito de las decenas realizando división en lugar de módulo. Ahora necesitamos que el jugador colisione con nuestras monedas para actualizar de alguna manera nuestra interfaz de usuario Pero estos existen en diferentes escenas, haciendo que las señales o llamadas a métodos sean algo difíciles. Para cerrar esta brecha, podemos delegar esta responsabilidad al gestor del juego ya que es fácilmente accesible como nodo raíz y tiene acceso a todos los niños. Abriendo el guión de la moneda. Cuando se recoge la moneda, podemos obtener una referencia a la raíz de escena usando la raíz signo de dólar seguida del juego que es el nombre del nodo raíz de escenas. Entonces llama a un método en el guión del manager del juego que aún no hemos escrito. Recogeremos la moneda y pasaremos el valor de la moneda que se está recolectando. Al cambiar al guión del administrador del juego, necesitaremos una referencia al contador de monedas durante la fase de preparación. El tipo de esto no necesita ser una caja horizontal. Como no estamos accediendo a nada específico de ese tipo de nodo, realmente solo nos importa que esta sea alguna forma de nodo de control. Primero, podemos darle a este método de definición de monedas colectadas, tomando como parámetro el valor entero de la moneda. A continuación, agregaremos el valor de la moneda a los datos del archivo. Luego actualice el contador en la interfaz de usuario, estableciendo su valor al nuevo valor de moneda de los datos del archivo. Además, esta actualización del contador debería ocurrir cuando la costura se carga por primera vez también. Probemos también el contador estableciendo su valor en algo aleatorio como 77. Al correr la escena, podemos ver que efectivamente se fijó en 77. Y cuando chocamos con una moneda de plata, el contador sube por una Recoger la moneda de oro la incrementa en diez también. Siéntase libre de probar la configuración del contador en cualquier número aleatorio, un número negativo o algo superior a 99. Pero recuerda eliminar esta línea. Cuando termines, Dios nos avisa de que estamos dividiendo por un entero. Al hacer clic en la advertencia nos lleva al script de la moneda, donde de hecho estamos dividiendo por un entero, y los valores decimales están siendo ignorados. Como esto es a propósito, podemos agregar una línea extra aquí en la división entera. Para ignorar esta advertencia, ahora tenemos la interfaz de usuario que muestra cuántas monedas ha recogido el jugador. En la siguiente lección, agregaremos un objeto de vida coleccionable y también haremos un seguimiento de eso Te veré en la siguiente lección. 32. 3-4 vidas: Hola amigos. En la lección anterior, creamos un contador de monedas para mostrarlo en la interfaz de usuario. En esta lección, agregaremos un vida coleccionable a nuestro juego Empecemos por nuestra escena de primer nivel. El activo que me gustaría representar, la vida del jugador en mi juego es una calavera dorada. Y no creo que quedaría bien tenerlo afectado por fuerzas como la gravedad. A diferencia de las monedas, quiero que parezca más ominosa y misteriosa Siempre será algo que flote hasta que se recoja Usaremos un nodo D del área dos para definir sus propiedades básicas y cambiarle el nombre a Calavera Dorada. Después agrega un sprite animado. Dos D, crear un recurso de marcos de sprites y poblarlo con los activos de sprite de calavera dorada Reproducción automática de bucle y establecer los fotogramas por segundo. Después, al igual que la moneda, agrega una segunda animación llamada Efecto y llévala con los sprites de efecto cráneo Volviendo al cráneo y obteniendo una buena vista de ella en el editor, podemos agregarle una forma de colisión , que será un círculo. Ajustaré el sprite un píxel a la izquierda y bit de manzana para que esté mejor centrado Y ajusta el planeador Circle para que quepa. Agregar un reproductor de flujo de audio dos nodos D. El efecto de sonido que he seleccionado para el cráneo será hud, abierto, hecho por una sopa new age Pero lo recorté ligeramente en un editor de audio, aún es más largo que la animación, así que tendré que agregar uno o dos fotogramas vacíos al final de la animación para que el sonido pueda terminar. Luego guarda la rama del cráneo como su propia posición de escena, el cráneo donde se puede recolectar durante nuestra prueba, abre la escena del cráneo y agrega un guión al nodo raíz. Muchos de los comportamientos del cráneo serán muy similares al guión de monedas que escribimos anteriormente. Empecemos copiando y pegando el guión de la moneda en el guión del cráneo Mi guión de calavera no necesita un valor, ya que cada cráneo representará una vida. Pero seguirá teniendo un sprite y un efecto de sonido cuando ocurra una colisión Todavía podemos hacer toda la misma lógica excepto la parte en la que le decimos al gerente del juego que el jugador recogió una moneda. Separemos eso en un método privado separado llamado underscore collect y llamemos al método desde el mismo lugar Cambiando al script de la moneda, podemos hacer los mismos cambios en el formato. Ahora todo en estos dos scripts es casi idéntico excepto el contenido de este método collect y se extienden diferentes tipos de nodos. Si seleccionamos la moneda y el cráneo, podemos ver que ambos tienen propiedades de un objeto de colisión dos D. No queremos escribir exactamente este mismo guión Cada vez que creamos un nuevo tipo de tesoro para agregar a nuestro juego, podemos definir un guión más abstracto llamado tesoro y extender el objeto de colisión dos D. Aquí podemos escribir todos los comportamientos comunes de la varios tipos de tesoros para nuestro juego, copiando todos los contenidos en el nuevo guión del tesoro. El comportamiento por defecto del método de recolección puede estar vacío ya que tesoro es un concepto demasiado abstracto para saber qué debemos hacer con él cuando se recolecta. El propósito de este método es simplemente decirle a Godot que todo lo que es tesoro puede ser recogido Dale a este guión el nombre de la clase tesoro. Dado que tanto las monedas como los cráneos son diferentes tipos de objetos de colisión, podemos hacer que extiendan el tesoro y obtengan todos los beneficios útiles que ponemos dentro del guión del tesoro Ahora en nuestro script de monedas tenemos cosas específicas de monedas como valor. Podemos anular el comportamiento de ser recolectados en lugar de no hacer nada para decirle administrador del juego que se recolectó una moneda, un método que está anulando otro método se indica con esta flecha azul Es posible que hayas notado que esta flecha aparece cada vez que hemos anulado el método ready De igual manera, cuando se recoja el cráneo, le dirá al encargado del juego que se le colectó una calavera. Ahora bien, no importa qué tipo de tesoro se recoja, estos mismos comportamientos sucederán automáticamente para todos ellos. Pero debemos tener cuidado y asegurarnos de que todos los tesoros tengan estos nodos hijos, y el sprite animado debe tener una animación de efecto Tratar diferentes tipos de objetos como todos teniendo un conjunto similar de comportamientos se llama polimorfismo Todas las monedas y calaveras pueden ser tratadas como un tesoro. La única diferencia será lo que hagan cuando sean recolectados. Cualquier nuevo tipo de tesoro que agreguemos también puede seguir este patrón. Cambiando al guión del administrador del juego, simplemente podemos agregar un método de coleccionar cráneo, aumentando la vida del jugador en uno. Cuando esto sucede, duplicando la referencia del contador de monedas, podemos agregar una referencia de contador de vidas, luego también actualizar la interfaz de usuario cuando se agrega una vida Dado que el método ready es hacer dos tareas distintas no relacionadas, debemos separarlas en diferentes métodos para mantenerlas organizadas. Escribamos límites de nit privados y métodos It UI que realizan cada una de estas tareas de forma aislada y son llamados por el método ready Seguiré las convenciones establecidas por Mario y Donkey Kong, otorgando al jugador una vida extra después de que haya recogido 100 monedas Cuando las monedas archivadas son mayores o iguales a 100, restar 100 monedas, y sumar una vida, y también actualizar el contador de vidas A continuación, podemos duplicar el nodo del contador de monedas en la capa de lienzo y cambiarle el nombre a Contador de vidas. Para poner esto en la esquina superior derecha, voy a cambiar la propiedad de dirección de diseño de derecha a izquierda. Ya que mi contador de monedas estaba 32 pixeles del lado izquierdo de la pantalla. Puedo reflejar esto restando 64 píxeles para agregar el mismo relleno en el lado derecho invertir la dirección de diseño también se invirtió el orden de los nodos hijos. Me gusta que el icono esté del lado derecho, pero los dígitos uno y diez están invertidos. Los arrastraré a la posición correcta. He editado el perro cero uno para que se ajuste mejor a la interfaz de usuario eliminando las partículas sobre la imagen del cráneo para crear este cero cero punto Png para usar como la textura del icono. Por último, en los casos en que la moneda no esté congelada, quiero que permanezca estacionaria mientras se está recolectando. Actualmente, la colisión de Rogers con la moneda agrega fuerza al cuerpo rígido de la moneda haciendo que se mueva mientras la animación del efecto se reproduce en el guión de la moneda En el método collect, queremos acceder a las propiedades del modo de congelación y congelación del cuerpo rígido dos D. Pero estos son inaccesibles para este script ya que está extendiendo el objeto de colisión dos D y a Godot no le gusta que cambiemos configuración de colisión mientras ocurre una colisión Podemos resolver ambos problemas mediante el uso de un método incorporado llamado llamada diferida El método de llamada diferida le dirá a Godot que ejecute esto después de que termine la colisión El procesamiento de llamada diferida toma un argumento de cadena del nombre del método al que queremos llamar En este caso set free habilitó el valor al que queremos establecerlo, que es true. Entonces también necesito establecer el modo de congelación a un valor que se define dentro del cuerpo rígido. Modo congelado de dos clases D, estático. Un cuerpo rígido estático no se moverá ni de fuerzas ni colisiones, que es lo que me gustaría Esto impedirá que la moneda se mueva después de que se recoja con el nodo raíz de cráneos seleccionado Establece la capa de colisión la capa del tesoro y la máscara de colisión en la capa del jugador. También conecte la señal ingresada del cuerpo a los cráneos en el método de cuerpo ingresado Ahora tenemos un contador de vidas y el jugador puede ganar más vidas recolectando cráneos o monedas En la siguiente lección, crearemos un cofre del tesoro lleno de botín pirata. Te veré en la siguiente lección. 33. Pecho 3-5: Hola amigos. En la lección anterior, agregamos un tesoro de calavera coleccionable a nuestro juego En esta lección, crearemos un cofre lleno de tesoros que el jugador podrá abrir. Voy a tener un cofre del tesoro ser un objeto estacionario que parece estar en el fondo para que el jugador pueda caminar frente a él. Cuando lo hagan, el cofre se abrirá y arrojará alguna cantidad de monedas al aire. A partir de la escena de nivel, agreguemos un nodo de área dos a la carpeta del tesoro. Tener comportamientos más complicados que otros elementos del juego. Un sprite animado no será suficiente. Al igual que nuestros personajes, necesitaremos usar un nodo sprite dos D, luego usar un reproductor de animación para controlarlo y un árbol de animación para controlar al jugador Primero vamos a establecer el sprite predeterminado para el nodo sprite dos D. Estoy usando los sprites de cofre de la carpeta del barco mercante, no el de la carpeta Palm Tree Island Quiero uno donde el cofre no esté bloqueado, solo cerrado dentro de la carpeta desbloqueada. Voy a elegir el sprite número tres. También podemos agregar una forma de colisión, que debe ser un rectángulo y estirarla para cubrir todo el cofre. Y un reproductor de flujo de audio para agregar algunos efectos de sonido. Renombra el cofre del nodo de rama y guárdalo como su propia escena en la carpeta del tesoro. Nuestra prueba necesitará un script para controlarlo, que también debería estar en la carpeta de scripts del tesoro. El cofre tendrá una variable exportada para saber si está abierto o no. Dado que el valor predeterminado para un lingote es falso, el cofre no está abierto El cofre también necesitará saber qué hay dentro de él. Agreguemos una variable entera para especificar el valor total de todas las monedas dentro del cofre y darle un valor predeterminado de uno. No tendría sentido permitir que este número sea un número negativo o algún número ridículamente alto Podemos restringir el rango de valores de la variable exportada agregando rango de subrayado y especificando tanto un valor mínimo como un valor máximo Ahora bien, este número no se puede establecer nada negativo o demasiado alto. También podemos agregar una variable llamada botín de subrayado como una matriz de tesoros para representar los nodos de monedas reales dentro del cofre del tesoro Para poder hacer estas monedas, necesitaremos escenas llenas tanto de la moneda de plata como de la de oro. Dentro del método ready, entonces podemos escribir un algoritmo simple para instanciar las monedas necesarias para sumar el valor total Si bien el valor total es mayor a diez, podemos reducir el valor total diez e instanciar una moneda de oro Esta moneda recién instanciada se puede agregar a la matriz de botín con push back Esto se repetirá hasta que el valor total sea inferior a diez o se omita por completo Si ya eran menos de diez, entonces repita el proceso. Siempre y cuando el valor total sea superior a cero, podemos reducirlo en uno e instanciar una moneda de plata, luego empujarla hacia la parte posterior de la matriz Al final de este proceso, el valor total será cero, y el cofre tendrá un montón de monedas que representan esa cantidad listas para desovar Cuando el jugador abre el cofre, entonces podemos pasar por la matriz de botín un elemento a la vez usando un bucle for, establecer la posición global de cada elemento la misma posición global que el cofre, pero también se mueve hacia arriba una ficha. Girar la propiedad de congelación a la física falsa se aplicará a la moneda. Podemos aplicar un poco de fuerza al azar a cada moneda para que dispersen en el aire cuando se abra el cofre. Para ello, necesitaremos crear una variable generadora de números aleatorios e inicializarla con un generador de números aleatorios nuevo durante la fase lista Después agrega un impulso al ítem. La dirección del impulso debe ser hacia arriba un mosaico multiplicado por un número aleatorio. Estableceré mi rango aleatorio 5-10 Luego agregaré también el vector dos, un mosaico derecho, y multiplicaré por un número aleatorio entre uno negativo y uno positivo. Los números negativos harán que vaya a la izquierda en lugar de a la derecha. Esto debería producir una fuente satisfactoria de monedas. Cuando necesitemos agregar el artículo al árbol de escenas, preferiría convertirlo en un hermano del cofre, no un niño conseguiré el padre del cofre Primero conseguiré el padre del cofre y luego agregaré la moneda cuando era niño de eso. Cuando esto se hace, podemos despejar la matriz ya que el cofre ahora está vacío. Seleccionando el reproductor de animación, podemos comenzar haciendo una animación ociosa cerrada, que solo necesita una pista para el sprite dos D, enviando su textura al mismo sprite que ya tiene Después, reduce la duración de la animación a 0.1 segundos. Duplica la animación de inactividad cerrada y crea una animación ideal abierta. Y cambiar el sprite al número ocho. Luego podemos hacer una animación cerrada cambiando el sprite, contando 8-4 por lo que la duración de la animación será de 0.5 segundos También podemos agregar una pista de audio a estas animaciones y cerrar la reproducción del cofre. Sonido Los sonidos que estoy usando para abrir y cerrar el cofre fueron creados por el frisbee Si pieza en Freesound.org duplicando Podemos hacer una animación abierta simplemente invirtiendo los sprites y cambiando el efecto de sonido Pero en la animación abierta, también podemos agregar un método call track a la animación. agregar un fotograma clave durante el fotograma cuando la tapa está abierta, podemos llamar al método de saqueo para generar las monedas, cambiar el árbol de animación, establecer el nodo base de expresión avanzada para que sea el nodo raíz de cofres y la propiedad anim player al reproductor Luego crea una nueva máquina de estado para el árbol de animación. Podemos agregar las cuatro animaciones a la máquina de estado y conectarlas con un ciclo de transiciones. La transición de inactivo cerrado a abierto se activará por está abierto, luego abierto para abrir inactivo al final de la animación. De igual manera, abrir inactivo para cerrar ocurre cuando nada está abierto, cerrar para cerrar inactivo al final de la animación Esta estructura nos permite inicializar el cofre como abierto o cerrado cuando comienza la escena en base al valor de también está abierto Al hacer más de una transición desde el inicio y establecer sus condiciones, seleccione el nodo raíz y llene las escenas empaquetadas con monedas arrastrándolas desde el sistema de archivos al inspector También necesitamos establecer la capa de colisión para poner el cofre en la capa del tesoro y hacer que busque colisiones en la capa del jugador Y establecer el índice Z del cofre para estar detrás del jugador. Cambia al panel de nodos y conecta la señal ingresada del cuerpo al propio cofre. Añadiendo un método en el cuerpo ingresado, si este cuerpo es un personaje, entonces deberíamos establecer está abierto a true, lo que desencadena la animación abierta, que a su vez desencadena el método de saqueo generando el tesoro Coloca un cofre del tesoro en algún lugar de tu nivel. Intenta hacer clic en el botón Está abierto para abrir y cerrar el cofre y editar el valor total de las monedas que se generarán. Cuando se abre el cofre, juega a la cadera e intenta abrir el cofre y recoge tus monedas duramente ganadas. Ahora tenemos un cofre del tesoro que genera una ráfaga de monedas para que el jugador las recoja La siguiente lección agregará un candado al cofre del tesoro y una llave que el jugador puede usar para desbloquearlo. Te veré en la siguiente lección. 34. 3-6 cerraduras y llaves: Hola amigos. En la lección anterior, creamos un cofre del tesoro que genera una fuente de monedas cuando se abre En esta lección, cerraremos el cofre y esconderemos una llave en algún lugar del nivel que lo abra. Empecemos duplicando la escena de la moneda de plata para hacer una escena clave Abre la nueva escena clave, selecciona el sprite animado e intercambia los sprites de la moneda por los sprites clave Y la clave tiene su propia animación de efectos también. Simplemente voy a cambiar el efecto de sonido de las teclas a una moneda diferente. Sonido La clave necesitará un nuevo script heredado del tesoro guardado en la carpeta de scripts del tesoro Todo lo que tenemos que hacer es decirle al script del administrador del juego cuando se recoge la clave. El guión del tesoro se encargará de todo lo demás. Reemplazar el script en el nodo raíz con este nuevo script clave es tan simple como hacer clic y arrastrarlo al nodo Como sigue siendo un guión del tesoro, el comportamiento de la señal sigue conectado al cambio a la escena del juego. Solo tendré una clave por nivel en mi juego. En lugar de contar las teclas como lo hemos hecho con las monedas, solo usaré una sola textura para indicar si el jugador tiene o no la llave. Añadiré una textura destrozada a la interfaz de usuario, rellenaré con la clave predeterminada Espadín, duplicado en escala para ser más visible y posicionarlo debajo de la moneda Después haga clic en el icono para ocultarlo, ya que el jugador no inicia con la clave en el guión del manager del juego, podemos establecer una referencia a esta textura en la fase de listo cuando el jugador recoge la clave. Podemos establecer una variable en los datos del archivo que el jugador tiene una clave para true. También establezca la propiedad visible del icono de clave en true. También debemos crear otro método para cuando el jugador utilice la clave para establecer filet tiene clave para false y ocultar el icono en la interfaz Cambiando al script de datos, podemos agregar la variable has key y establecer su valor predeterminado en el método init Coloca una llave en algún lugar cerca del nivel e intenta recogerla. Para bloquear el cofre, necesitaremos agregar otra variable de bulling para que el cofre sepa si actualmente está bloqueado o no Entonces podemos alterar la lógica en el código de colisión. Si el cofre está bloqueado y el jugador tiene la llave, entonces set se bloquea a false y decirle al manager del juego que el jugador ha usado la llave. Si el cofre no está bloqueado, set está abierto a true. No estoy usando ElseF aquí porque quiero que el cofre se desbloquee y se abra en un evento de colisión Seleccionando el reproductor de animación, necesitaremos agregar más animaciones. Comencemos duplicando la animación de inactividad cerrada para hacer una animación inactiva bloqueada Y cambiar el sprite por el sprite inactivo. Después duplica la animación de cierre para crear una animación de bloqueo. Cambiar el sprite 3-2 a uno, acortar la duración de la animación a 0.3 segundos y reproducir un Esta vez estoy usando key twist in lock hecho por Karen Keegan en Freesound.org Luego podemos duplicar esta animación para crear también una animación desbloqueada invirtiendo Cambiando al árbol de animación, podemos agregar estas nuevas animaciones a la máquina de estado. Y conéctelos. Con un bucle similar de transiciones como lo hicimos con open and close. El cofre pasará de ídolo cerrado a candado. Cuando está bloqueado se establece en true, luego de bloque a inactivo bloqueado al final de la animación. De igual manera, cambiará de ídolo bloqueado a desbloquear cuando está bloqueado se establece en falso, luego a ídolo cerrado al final de la animación desbloqueada. Entonces también podemos iniciar el cofre en el estado inactivo bloqueado si está bloqueado es cierto, pero las condiciones para iniciar el cofre como cerrado y bloqueado pueden ser ambas ciertas. Añadiremos la condición para inactivo cerrado, que el cofre no debe estar abierto y no encerrado en la escena nivelada. Ahora podemos alterar el estado de bloqueo del pecho haciendo clic en la palanca. Ten en cuenta que un cofre cerrado debe desbloquearse antes de que pueda abrirse. Se debe cerrar un cofre abierto antes de que pueda bloquearse. Esto funciona, pero eso no me gusta. El candado simplemente desaparece. El paquete de activos tiene un candado desbloqueado como activo separado, así que usémoslo. Duplicar la escena clave Para crear una escena de candado, cambie el tipo del nodo sprite animado dos D a un nodo sprite dos D, ya que el candado no tiene animaciones, ya que el candado no tiene animaciones, renombra los nodos en consecuencia y llena el sprite con el activo Cambia la forma de la colisión a un rectángulo y cambia su tamaño para que se ajuste a la forma de la cerradura Retira su colisión con el jugador, y reduce el índice Z del candado para que coincida con el cofre. También haré que el ajuste por defecto de la propiedad de frase sea falso, ya que siempre quiero que el candado se vea afectado por la física Y quita el guión haciendo clic en el botón del script con una X roja sobre él. El candado no es tesoro y no debe ser recogido por el jugador abrir el guión del cofre, podemos agregar una escena empacada exportada para el candado, tal como hicimos con el método del saqueo Podemos definir otro método para tirar el candado. Dado que el método del saqueo podría estar tratando con bastantes monedas, las instanciamos durante el Entonces cuando el jugador abre el cofre, las monedas ya existen en la memoria y simplemente se están agregando al árbol de escenas. Esta es una forma más responsable de crear instancias de grandes cantidades de nodos Pero como el candado es una sola cosa, no necesitamos preocuparnos instanciarlo en el momento Dentro del método del candado de tiro, podemos definir una nueva variable para el candado instanciado Luego realiza la misma lógica que las monedas reposicionando la cerradura para que coincida con la ubicación del cofre Aplicando una fuerza de impulso y añadiéndola al árbol de escenas, eliminaré la aleatorización de la fuerza ascendente Simplemente se arroja un poco a un lado. Cambiando a dos vistas D, agregaré rápidamente la imagen del candado a la escena para poder reposicionarla donde quiero que comience, luego miraré sus valores transformados para obtener las posiciones x e y Después de anotar el cuatro negativo y el siete negativo, puedo eliminar el nodo sprite, volver a la vista de guión y establecer la posición inicial de los candados para que sea la posición del pecho más el vector dos, negativo cuatro, negativo Ahora el candado aparecerá en la posición exacta donde parece que coincide con el sprite bloqueado y será arrojado Recuerde poblar la escena empaquetada arrastrando el candado desde el panel del sistema de archivos al inspector, seleccione el reproductor de animación, seleccione el reproductor de animación, cambie a la animación desbloqueada y agregue una pista de llamada al método durante el fotograma cuando el candado haya desaparecido, podemos llamar al Ahora, cuando el jugador recoge la llave y toca el cofre del tesoro, el candado se tira a un lado, el cofre se abre y el jugador es bañado con monedas Ahora tenemos una llave que puede desbloquear nuestro cofre del tesoro. En la siguiente lección, agregaremos un objetivo final a nuestros niveles. Te veré en la siguiente lección. 35. Mapa 3-7: Hola, amigos. En la lección anterior, cerramos el cofre del tesoro y agregamos una llave para desbloquearlo. En esta lección vamos a crear un objetivo final para nuestros niveles. Utilizaré los mapas pequeños como meta para mis niveles, ya que esto implicará fácilmente al jugador que Roger está siguiendo cada segmento de mapa para encontrar el siguiente para armar un mapa del tesoro completo. Es un concepto bastante simple que no voy a necesitar explicarlo. Y también proporciona un marco para la estructura de niveles. Empecemos duplicando la escena del cráneo para crear un pequeño mapa Una escena renombra el nodo raíz. Selecciona el sprite animado e intercambia los sprites de calavera Para el mapa pequeño, uno sprites. Usaré los sprites de entrada y salida juntos para crear la animación de efectos Luego cambia la forma de colisión a rectángulo y redimensiona para que se ajuste al sprite Usaré el sonido de papel hecho por brevceps como efecto de sonido Al igual que con todos los demás tesoros, podemos darle un guión del tesoro llamado Mapa pequeño Heredando del tesoro Todo lo que tenemos que hacer es decirle al administrador del juego que se recopiló el mapa. Cambie el script en el nodo raíz por el nuevo script de mapa pequeño. Después duplica esta escena tres veces para crear un pequeño mapa. Dos, tres y cuatro. Intercambiar los sprites en la animación predeterminada por los sprites coincidentes del paquete de activos por el mapa pequeño cuatro No obstante, voy a cambiar la animación del efecto ya que cuando el jugador recoja esta pieza, han completado todo el mapa. Después de que se reproduzca el efecto in, jugaré la animación desplegada del mapa grande seguida de la animación inactiva, la animación plegable y luego el efecto out Esto le permitirá al jugador saber que los mapas pequeños se han combinado para formar un mapa más grande y que su objetivo está cerca. Cuando el jugador recoge el pequeño mapa, el nivel ha terminado. Y me gustaría premiar al jugador con una breve fanfarria seguida la pantalla se desvanezca a negro antes de regresar a un menú de selección de niveles Cambiemos a la escena del juego en dos vistas D. Podemos cubrir la pantalla en negro con un nodo llamado Color Destrozado y nombrarlo, desvanecerse en el inspector, cambiar el color a negro Luego expanda la sección de diseño y selecciona completamente destrozado de los anclajes Desplegable preestablecido para asegurarse de que esto siempre esté al frente, ya sea asegúrese de que esté colocado en la parte inferior de la rama de la interfaz de usuario o déle un valor de índice Z más alto que todo lo demás No queremos que esto bloquee las entradas del mouse en los controles de la interfaz de usuario. Detrás de él, aunque, También expanda la sección del mouse y dígale al naufragio de color que ignore la entrada del mouse Ahora toda la pantalla será negra, que es idealmente como debería comenzar cada escena de nuestro juego. Está en nuestro camino a medida que desarrollamos esta escena. Tengámoslo oculto por defecto para que sea más fácil copiarlo en otras escenas. Vamos a guardarlo como su propia escena, luego abrirlo para que este rectángulo negro se desvanezca, necesitará un script que pertenezca a necesitará un script que la carpeta de scripts de la interfaz de usuario. Al igual que usamos tweens para mover la cámara, también podemos usar tweens para ajustar otras propiedades a lo largo del tiempo, como Primero, definamos dos colores en la parte superior del guión, uno para el negro y otro para el claro. El negro tiene valores de rojo, verde y azul de cero y un valor alfa de uno. Si bien claro tiene un alfa de cero, alfa es una medida de transparencia. También necesitaremos una variable privada para la mezcla de color. Empecemos por desvanecerse para borrar ya que el rectángulo es actualmente negro Al igual que con la cámara, es una buena idea comprobar primero si la preadolescente ya existe y está funcionando, y si es así, matarla Luego crea la preadolescente. Aquí no hay necesidad de molestarse con transiciones o easings, lineal está bien Luego se interponen una propiedad en este nodo mismo, la propiedad color, con el valor objetivo de clear a lo largo de una duración de 1 segundo Vamos a querer saber cuando este comportamiento esté completo, así podremos devolver una señal de este método para avisarnos cuando termine la tween de color Especificar un tipo de retorno para una declaración de método en Gudo script se realiza después de los parámetros indicados con una flecha Dado que el desvanecimiento a negro será idéntico a excepción de cambiar el color, cambiemos el nombre de este método para se desvanezca y tome un color como parámetro, luego use ese color como valor objetivo Entonces podemos escribir fade to clear, para simplemente llamar fade passing in clear como argumento. De igual manera, escribe fade to black. Llamando a fade, pasando al negro como argumento. Ambos métodos pueden devolver las mismas señales devueltas por fade. Al cambiar al guión del administrador del juego, tendremos que establecer una referencia al desvanecimiento durante la fase roja. Lo primero que debemos hacer cuando se carga la escena es establecer la propiedad visible del fade en true, por lo que el jugador no verá nada más que negro. Entonces, cuando se complete toda la inicialización y el juego esté listo para que el jugador comience a jugar, podemos decirle al fade que se desvanezca para despejar y esperar la señal para cuando esté completa En ese punto, debemos darle al jugador la posibilidad de comenzar a jugar el juego. Establezcamos una referencia al nodo jugador durante la fase de preparación y llamemos a un método que aún no hayamos definido. Establecer habilitado pasando verdadero como argumento. Al cambiar al guión de los jugadores, podemos agregar una variable booleana privada llamada guión bajo está habilitada También define el método set enabled, Tomando un parámetro booleano que establece la variable privada Luego verifique este valor antes de procesar cualquier entrada que devuelva. Si el jugador no está habilitado nuevo en el administrador del juego cuando el jugador recoge el mapa, entonces podemos eliminar el control del jugador configurando habilitado a false. A mí también me gustaría jugar una fanfarria de victoria aquí. Entonces agregaré un nodo reproductor de flujo de audio llamado Fanfare y lo llenaré con una pista de música corta La fanfarria que he seleccionado es Game Success Fanfare Short de L Boss en Freesound.org Después de que el jugador haya sido desactivado, podemos jugar la podemos Espera a que termine la fanfarria. Espera a que el desvanecimiento se desvanezca a negro. Después cambia de escena. Coloca un gol al final de tu nivel. Golpea Play. La escena se carga con una pantalla negra y se desvanece El jugador no puede moverse hasta que se complete el fade in. Recolectar el tesoro al final del nivel elimina el control del jugador, desencadena la fanfarria y se desvanece a negro Ahora tenemos una manera de terminar nuestros niveles y una agradable transición de pantalla suave. En la siguiente sección, le daremos salud al jugador y le dejaremos recibir daño. Te veré en la siguiente sección. 36. 4-1 daño: Hola amigos. En la sección anterior, creamos un montón de tesoros diferentes para que el jugador los recoja. En esta sección se dará salud al jugador, lo que le permitirá recibir daño y morir. Si completaste la tarea, deberías tener tus niveles poblados con tesoros para que el jugador los recoja y se coloquen estratégicamente para manipular su comportamiento si completaste los desafíos También puede tener una variedad exportada de escenas empaquetadas en el guión de su cofre que agrega objetos de tesoro adicionales a la matriz de botín y genera artículos de tesoro adicionales O tener un valor mínimo y máximo de moneda, con el cofre generando un entero aleatorio entre ellos. Después instanciando monedas que equivalen a ese valor aleatorio. Es posible que todos se hayan apoderado de los diamantes de color para crear nuevo tesoro y les hayan dado un propósito único para que su juego le dé algo de salud a los personajes. Empecemos en el script de caracteres, donde podemos agregar una nueva variable exportada para establecer la salud máxima de los caracteres. Esto debe restringirse a que sólo sea un número natural. Algo 1-100 debería estar bien. Probablemente solo voy a tener un trato fiscal, un daño a la vez, 100 serán mucho, y estableceré el valor predeterminado en cinco. Entonces también podemos declarar una segunda variable que representa su salud actual. Para que las cosas sean simples, asumiré que cuando los personajes se cargan en escena, están en plena salud, estableciendo su salud actual igual a su salud máxima Durante la fase de preparación, entonces podemos escribir un método público que inflija daño al personaje, tomando como parámetro la cantidad de daño. Por ahora, solo reduciremos la salud actual por la cantidad de daño, luego imprimiremos la salud actual para que podamos ver el resultado. La mayoría de los juegos como este incluyen un breve período de invencibilidad después de recibir daños La forma más sencilla de lograrlo sería apagar las colisiones durante ese tiempo Pero el colisionador del personaje no solo está recibiendo daños, también está colisionando con el entorno Podemos separar estas responsabilidades agregando otro nodo hijo a nuestros personajes, un área dos D, llamada caja Rt. La única responsabilidad de la caja Rt es ser detectada por fuentes de daño y ser encendida o apagada sin afectar otros aspectos del personaje. También necesitará una colisión de dos nodos hijo D para determinar su forma. Para diferenciarlo de las colisiones normales del personaje, podemos cambiar el color de la caja Rt a otra cosa como el verde No necesariamente tiene que ser idéntica a la cápsula del personaje, pero es un buen lugar para comenzar con el nodo hip box seleccionado. Cambia la capa de colisión para que sea la capa diez, haciendo de esta la capa de daño al jugador. Cualquier cosa que queramos lastimar, el jugador debe enmascarar la capa diez para buscar la caja lastimada del jugador. Para probar esto, necesitaremos algo sencillo a nuestro nivel que pueda lastimar al personaje. Crearemos una nueva escena repleta usando el activo de picos. Este será un cuerpo estático dos nodos D, ya que no se moverá ni se verá afectado por la física. Agrega un nodo sprite dos D y llénalo con un activo de sprite Añádele una forma de colisión y conviértela en un rectángulo. Esta será una superficie sólida transitable que el colisionador de personajes tratará como si fuera parte del terreno Debe abarcar todo el ancho de la baldosa, pero solo llegar hasta aproximadamente una cuarta parte de la altura de las baldosas. Esto también evitará que el jugador salga lastimado si toca los pinchos desde el costado en lugar de la parte superior. Esto es parte del nivel pero no del terreno ni del agua. Hagámosla capa tres, una nueva capa para peligros. Luego podemos agregar otro nodo de colisión para infligir daño, que será un área dos D y vamos a cambiarle el nombre a hip box. Dependiendo de lo preciso que le gustaría ser con su caja de cadera, es posible que desee usar una forma personalizada aquí. Vamos a agregar un polígono de colisión dos nodos D como un hijo de la caja de cadera en el inspector Podemos ver que el polígono es una matriz de dos vectores empaquetados. Al hacer clic sobre él para expandirlo, la matriz tiene un tamaño de cero que actualmente está vacía. Simplemente podemos hacer clic en cualquier parte del editor para agregar un vértice al polígono Voy a añadir una en cada punta de lanza y otra cerca del borde derecho para darle algo de volumen Después haga clic en el vértice inicial para cerrar el polígono. Esta es ahora una forma de colisión personalizada que si el personaje toca, se lastimarán. Pero fíjate en cómo se divide en dos formas más pequeñas, rojo y morado. Eso se debe a que la detección de colisiones en los videojuegos es compleja y requiere mucho cálculo, es mucho más fácil detectar colisiones dentro de un polígono convexo que en un polígono cóncavo Los polígonos cóncavos serán divididos en polígonos convexos por Godot Al hacer que el polígono de colisión coincida con la altura de este tercer pico, hemos duplicado la cantidad de cómputos requeridos para detectar colisiones con estos picos, ya que el motor necesita verificar si el personaje está tocando el polígono rojo o el polígono púrpura Para simplificar esto, eliminemos el vértice del tercer pico, que en nuestro array es el elemento número dos El polígono es ahora convexo y completamente coloreado en rojo. Y podemos simplificar esto aún más eliminando el último vértice Esta caja de cadera necesita buscar al jugador herido capa capa diez si quieres que los enemigos reciban daño de los picos dos, también capa 18, Guarda la rama de picos como su propia escena. Podrías optar por poner esto en su propia carpeta etiquetada como trampas o peligros, pero como no hay otros activos que caigan en esas categorías, solo lo guardaré como decoración. Sin embargo, haré una nueva carpeta de scripts llamada environment, luego moveré cosas como el nivel de la cámara, el paralaje y el agua antes agregar un nuevo script llamado Hazard A continuación, adjunte este script al nodo raíz de los picos. El propósito del guión será reaccionar ante la caja herida de un personaje colisionando con los picos Hit box, seleccionando el interruptor de caja de golpe al panel de nodos y conecte la señal de área ingresada conectándola al nodo raíz del pico. Esto cambiará el nombre del método para que esté en el área de hit box ingresada, lo cual es un poco más descriptivo de lo que está sucediendo. Conseguir al padre de la zona nos da el personaje, entonces debemos decirle a ese personaje que tome daños. Dado que este script podría usarse para cualquier número de peligros o es posible que desee ajustar su daño sobre la marcha, hagamos que la cantidad de daño infligido en una variable exportada y valor por defecto de uno debería estar bien. Dale un rango para que no se pueda establecer en algo negativo o cero. Abre la configuración del proyecto y nombra las capas de colisión, Hazard, jugador herido y enemigo herido. Coloca picos en algún lugar tu nivel e intenta saltar sobre ellos. Se puede ver en el panel de salida que Roger ahora tiene cuatro de salud restantes con cada colisión, el número se reduce en uno. Además, el jugador y otros personajes se pueden configurar para caminar encima de los picos o a través de ellos en función su enmascaramiento de colisión con la capa tres, ahora tenemos un peligro de pico que daña al jugador. En la siguiente lección, haremos que el personaje reaccione ante recibir daño. Te veré en la siguiente lección. 37. 4-2 Reacción: Oh amigos. En la lección anterior creamos picos que dañan al jugador. En esta lección hará que el personaje reaccione ante recibir daños. Probablemente hayas notado cuando estamos haciendo personajes que hay animaciones de éxito en el asset pack. Vamos a ponerlas en práctica ahora. En la escena del personaje con el reproductor de animación seleccionado, agrega una nueva animación llamada hit. Rellenar la animación de golpe a partir de los picos de la carpeta sin espada También agrega un efecto de sonido si te gusta seleccionar el árbol de animación. Edita la máquina de estado sin espada. Podemos agregar la animación hit aquí y hacer la transición a ella. Si el personaje es golpeado entonces la transición de nuevo cuando no son golpeados abriendo el guión del personaje tendrá que crear la variable is hit de tipo booleano, luego establecerla en true cuando el personaje recibe daño El valor debe establecerse de nuevo en falso para hacer la transición del personaje de la animación de golpe de nuevo al movimiento. La animación en sí puede realizar esta función. Pero para que la animación pueda acceder a ella, se debe exportar la variable. Hagamos una nueva categoría para esto en salud llamada Combate. Luego podemos agregar una pista de propiedad a la animación de golpe para establecer el valor de is hit back en false al final de la animación, el personaje ahora reproducirá la animación de golpe una vez cuando recibe daño. Esto interrumpirá cualquier animación de movimiento que estuviera sucediendo porque está en transición fuera de la capa de movimiento de la máquina de estado Vamos a probarlo. Será agradable si el personaje sigue recibiendo daños sin que sea necesario que salgan del colisionador de cajas de impacto y vuelvan a entrar en él Si se quedan en los picos, seguirán recibiendo daños. Además, debe haber una breve ventana después de recibir daño cuando el jugador es invencible Podemos resolver ambos problemas con una sola solución. Apagar la caja de daño del jugador y volverla a encenderla, seleccionando el nodo de caja de daño. Las propiedades en la parte superior del panel inspector etiquetadas como Monitoreo y Monitorable se pueden usar para determinar si las colisiones ocurren Ya que esta es una caja lastimada, es pasiva y no busca nada. El monitoreo se puede establecer en false. Su propósito es ser encontrado por cajas de impacto. Debe ser monitoreable. Girar monitoreable a falso evitará que las cajas de impacto choquen con esta caja lastimada y volverla a ser verdadera desencadenará una nueva colisión con los picos que tienen una Entonces podemos hacer lo contrario. Confíjelo para monitorear las capas pert pero no monitoreable Hay un tipo de nodo simple en Godot para propósitos de sincronización, un temporizador, que podemos agregar a nuestro personaje y llamarlo Invencible El tiempo predeterminado es de 1 segundo, lo cual está bien, y queremos que esto solo cuente una vez a la vez. Marque la casilla de verificación de un solo disparo. Durante la fase de listo, podemos establecer una referencia a la caja del personaje y al temporizador cuando el personaje recibe daños. Podemos establecer monitorable en false, Iniciar el temporizador, esperar la señal de tiempo de espera , y establecer monitorable Pero Godot no nos dejará apagar el colisionador durante una colisión, usaremos set deferred para decirle a Godot que establezca monitoreable en falso después establezca monitoreable en falso el colisionador durante una colisión, usaremos set deferred para decirle a Godot que establezca monitoreable en falso después de que se complete esta colisión. Si quieres tener otras cosas en tu juego que hagan invencible al personaje por un tiempo establecido, también podemos convertirlo en un método público tomando como parámetro un tiempo de flotación Después pasa esto al método de inicio de temporizadores. Ahora el método take damage puede llamar al método become invencible, pasando 1 segundo como parámetro Pero no quiero que los enemigos se vuelvan invencibles, solo el jugador Agregaré una variable de combate exportada por la cantidad de tiempo que el personaje es invencible después de recibir daño restringido a no ser negativo con un defecto de cero en el método de cero en el método toma de daño Luego comprobaré si este valor no es cero antes de llamar al método become invencible, usando este tiempo como parámetro Si los enemigos no van a usar este nodo temporizador, no deberían tenerlo en su árbol de escenas. En lugar de establecer la referencia al temporizador usando ready, en su lugar usaré el método ready. Consulta el valor de duración invencible. Y si no es cero, entonces establece la referencia al temporizador. Ahora solo el personaje jugador necesita tener el nodo temporizador y tendrá un valor de duración invencible establecido superior Pero los personajes enemigos aún necesitan que se les agreguen cajas Rt. De lo contrario, sus scripts intentarán establecer referencias durante la fase de listo y provocarán un error porque no existen. Sus cajas de rebaño también pertenecerán a la capa 18 en lugar de diez Entonces dale a Roger una duración de invencibilidad superior a 0 segundos Al probarlo, el personaje parado sobre los picos seguirá recibiendo un daño cada segundo ya que lo vemos contando regresiva en el panel de salida. Por último, me gustaría que el personaje fuera derribado de la fuente del daño. Modifiquemos el método de toma de daño para aceptar también la dirección de la fuerza como vector dos. Luego establece la velocidad del personaje para que sea esta dirección multiplicada por cinco fichas. El guión de peligro necesitará entonces calcular esta dirección y enviársela al personaje cuando los lastime Esta puede ser simplemente la posición global de los personajes menos la posición global de peligros. Para que el peligro conozca su posición global, no debe extender dos D. Pero no queremos que la distancia sea un factor aquí, solo la dirección. Poniendo esto entre paréntesis, podemos llamar al método normalizado. Normalizado, Tomaremos el vector y lo haremos más largo o más corto para que tenga una longitud de uno. Vamos a probarlo. El personaje que golpea los picos es golpeado con una fuerza hacia atrás, tiene una animación de golpe, y se vuelve invencible por 1 segundo antes de ser golpeado Ahora tenemos personajes que reaccionan al ser golpeados. En la siguiente lección, agregaremos la salud del jugador a la interfaz de usuario y le daremos un objeto de poción para recuperar la salud Te veré en la siguiente lección. 38. Recuperación 4-3: Hola, amigos. En la lección anterior, hicimos que nuestro personaje reaccionara al recibir daños. En esta lección, agregaremos salud del jugador a la interfaz de usuario y crearemos pociones de salud Primero, hagamos un medidor de salud. Los activos en el paquete de activos se dividen en tres imágenes separadas para el calibre y un color rojo plano para el relleno. El medidor de salud en sí solo será un nodo de control básico con dos hijos, uno para el fondo y otro para el relleno. El nodo de fondo puede ser una caja horizontal Clasificando automáticamente las tres imágenes de fondo para nosotros, que son todos restos de texturas, Rellene las texturas con los activos del paquete de activos Puedes esconder las otras ramas de ahí a tu manera. Seleccionando el cuadro horizontal de fondo, expanda la sección de anulación de tema en el inspector y establezca separación a cero píxeles que las imágenes se dibujen sin huecos. El relleno es solo otro textuecto con este color rojo plano que podemos redimensionar manualmente y encajar en Selección del nodo raíz de los medidores de salud. Vamos a escalarlo cuatro veces para que sea más visible. Creo que quedaría bien en la esquina inferior izquierda, voy a configurar los presets de anclaje para que sean abajo a la izquierda Y ajustar el desplazamiento del pivote y para que esté en la parte inferior del medidor, que es de 40 píxeles. Luego establece la posición x del medidor 32 píxeles para agregar el mismo relleno que la moneda arriba solo para diseñar y ver looks mientras juegas el juego. Acercar el nuevo indicador de salud. Seleccione la Textura de Relleno. Para usar el relleno, podemos establecer el modo de expansión para ignorar el tamaño, lo que nos permite establecer manualmente el tamaño a lo que queramos. Haga clic y mantenga presionado el valor de tamaño X y mueva el mouse hacia la izquierda, reduciendo el valor X, que podemos ver, también hace que el medidor parezca que se está agotando Cuando el valor X es cero, el calibre está vacío, y cuando el valor x es 75, el calibre está lleno. Podemos usar esto para mostrar cualquier cantidad de salud que tenga el jugador convirtiéndola en un porcentaje de 75 píxeles. Crear un guión para el indicador de salud. Lo llamaremos Gauge y lo guardaremos en la carpeta de scripts de UI. Podemos obtener una referencia al llenado durante la fase de preparación. Al igual que los contadores, un medidor realmente solo necesita un método para establecer el valor que se muestra. Lo mejor sería tomar este valor como un porcentaje con un tipo float. Todo lo que necesitamos hacer para mostrar este porcentaje es establecer el tamaño del relleno en 75 multiplicado por porcentaje. Un porcentaje en programación suele representarse como un número 0-1 a diferencia las matemáticas donde es 0-100 Esto simplifica nuestros cálculos para ser Si queremos que este script sea más flexible, podemos exportar el valor de 75 píxeles como una variable llamada max pixels y establecer 75 como el valor predeterminado. Cambiando al guión del personaje, podemos crear una nueva señal para cuando cambia el valor de salud del personaje y darle un parámetro que es el porcentaje de la salud restante del personaje. Entonces cuando el personaje recibe daño, podemos emitir esa señal. Para calcular el porcentaje de la salud restante del personaje, simplemente divida la salud actual por la salud máxima, Pero ambos valores se definen como enteros, lo que significa que el resultado siempre será cero o uno Si cambiamos uno de sus tipos a flotar, el resultado será entonces un flotador dos. Luego podemos conectar la señal de cambio de salud del personaje del jugador al medidor de salud. Pero no queremos llamar a un nuevo método. Al hacer clic en el botón de selección, presentaremos una lista de los métodos de medidores de salud que queremos llamar valor establecido Para ello, tanto la señal el método deben tener los mismos parámetros. En nuestro caso, a flote, Recuerda mostrar las otras ramas Cuando estés listo para probar, probémoslo. El medidor comienza lleno, pero saltar sobre los picos reduce el calibre en una quinta parte cada vez. Recuerda colocar el fade en la parte inferior de la rama UI si quieres que se dibuje sobre todo lo demás. Ahora ayudemos al jugador con una poción de salud para recuperar esa salud perdida Como hicimos a través de la última sección, simplemente podemos agregar un nuevo objeto del tesoro usando los activos de la poción roja y crear un nuevo guión para ello heredando del tesoro, copiando uno de los otros Renomíbrala poción roja y ábrela. Cambiar el nombre del nodo raíz para que coincida reemplaza los sprites de animación con el potente rojo y los sprites de efecto con el efecto de poción Centraré el sprite y cambiaré el colisionador a una cápsula para que se ajuste mejor a la imagen. Estoy usando mi grabación de trago hecha por Miley Joe Moss, 1,996 para el efecto sonoro de la poción Los diferentes colores de las pociones probablemente no solo estarán ajustando una variable, sino que tendrán una función completamente diferente Y necesitaremos sus propios guiones únicos. En lugar de tener un script de poción genérico, nombraré esta poción roja hereda del tesoro, luego intercambiaré el script que se adjunta al nodo raíz Podemos exportar una variable entera por la cantidad de salud que la poción recupera como un Voy a poner el mío para que tenga un valor de tres. No quiero molestar al manager del juego con transmitir esta información de la poción al personaje ya que el personaje chocó con la En cambio, voy a hacer un pequeño cambio en el guión del tesoro, almacenando el personaje que colisionó con este tesoro en una variable Después, después de verificar que el cuerpo es un carácter, guarda el cuerpo como la variable de carácter. Ahora el guión de la poción puede comunicarse directamente con el personaje cuando se recoge Al ser recolectada, la poción roja llamará a un método de recuperación de salud al personaje pasando la cantidad recuperada Cambiando al guión del personaje, podemos agregar este método de recuperación de salud a los métodos públicos, tomando como parámetro una cantidad de salud para recuperar, agregando la cantidad de salud recuperada a la salud actual. También debemos tapar la salud actual a la salud máxima usando la función min, luego emitir la señal de salud cambiada para actualizar el medidor de salud en la Y. Podemos combinar estas dos líneas y realizarlas en una sola declaración. Coloca una poción de salud en tu nivel, intenta recibir daño de los picos, luego recoge la poción para recuperar la salud perdida Ahora tenemos una forma para que el jugador sepa cuánta salud le queda, y un ítem para ayudarlo a recuperar la salud perdida. En la siguiente lección, agregaremos un punto de control al nivel. Te veré en la siguiente lección. 39. Punto de control 4-4: Hola amigos. En la lección anterior agregamos un medidor de salud a la interfaz de usuario y una porción para ayudar al jugador a recuperar la salud perdida. En esta lección, estableceremos ubicaciones donde el jugador debe responder después de morir. Voy a borrar el otro nivel de la escena del juego. Ahora, ya que estaremos editando la estructura de niveles y todos los niveles requerirán esta nueva estructura para funcionar correctamente, habrá que editar otros niveles para. Hasta ahora hemos estado usando el origen de la escena como la ubicación donde comenzará el jugador, luego esperando que lleguen hasta el final sin morir. su lugar, es posible que desee que sus niveles sean más largos y le den al jugador puntos de control donde pueda responder en lugar de comenzar de nuevo al principio cada vez Vamos a agregar otra carpeta a los niveles vistos jerarquía llamada puntos de control Luego podemos agregar un nodo básico vacío dos D a esta carpeta llamada start posicionarlo donde queremos que el jugador inicie el nivel. Si lo prefieres. También puede querer que el disparador de nivel esté en esta carpeta y cambiarle el nombre a algo así como fin para hacer un punto de control También crearemos un nodo D de área dos en esta carpeta llamada middle. Dale a este punto de control un nodo de sprite animado. Voy a usar los activos de bandera para mi punto de control ya que el punto de origen de los puntos de control es la ubicación donde se establecerá el origen del personaje y el origen del personaje está a sus pies El origen de los puntos de control debe estar en el suelo donde se colocarán los pies del personaje Con eso en mente, colocaré la bandera para que la base del asta de bandera esté en el origen Al agregar una forma de colisión, solo usaré un segmento de línea que cubra el asta de la bandera para que el jugador deba realmente hacer contacto con el asta de bandera para activarlo. También agregaré un reproductor de flujo de audio a de node, que jugará Game Reward by a Yen Ba en Freesound.org Guarde la rama checkpoint como Pondré el mío en la carpeta de escenas raíz ya que se incluirá en todos los niveles de mi juego. abrir la nueva escena de punto de control, voy a editar el índice z de mi bandera para que se dibuje detrás del personaje a la vez que muy similar al comportamiento de un objeto del tesoro No pensaría lógicamente en esto como un tesoro y no quiero refactorizar el guión del tesoro para encajar esto en él Voy a crear un nuevo script desde cero y ponerlo en la carpeta de scripts de entorno. Toma una referencia al reproductor de flujo de audio dos nodos D durante la fase de listo y conecta la señal ingresada en el cuerpo para reaccionar ante el jugador colisionando con la bandera Reproduce el efecto de sonido y luego establece la máscara de colisión en cero para evitar que ocurran más colisiones Entonces queremos establecer una variable en los datos del archivo para saber que el jugador ha llegado al punto de control Quizás quieras que esto sea booleano si solo quieres tener un punto de control, como un típico juego de Mario, o un entero si quieres tener múltiples puntos de control, más como un juego country de Donkey Kong, un entero es más flexible y también se puede usar para De manera que cada punto de control necesitará entonces un entero único para identificarlo, que el manager del juego utilizará para saber dónde responder al jugador Definamos una variable como un entero para contener este número. A continuación, establezca el valor de punto de control archivado para que sea este número de identificación Cuando el jugador toca el punto de control, podríamos exportar la variable para establecer cada una manualmente, pero eso sería propenso al error y más trabajo para nosotros a la larga En cambio, me gustaría delegar esta responsabilidad en el guión de nivel. Primero, tenemos que asegurarnos de que la máscara de colisión del punto de control esté establecida para colisionar con el jugador Y dale a este script un nombre de clase para que pueda ser identificado por el script de nivel. Cambiando al script de nivel, si podemos asumir con seguridad que todos los niveles tendrán esta carpeta de puntos de control, entonces podemos usar eso para establecer una variable no en la carpeta de puntos de control en sí, sino a una matriz de nodos Podemos establecer el valor para ser carpeta de puntos de control, dándonos una lista de cada nodo en la carpeta de puntos de control Luego usando un bucle de cuatro, podemos contar desde cero hasta el tamaño de esta matriz. Si la nota es un punto de control, establezca su ID de punto de control en su posición en esa lista El nivel ahora contiene una lista de todos los puntos de control donde se podría generar el personaje del jugador y cada punto de control conoce su posición en Será responsabilidad del administrador del juego cargar el nivel y mover al jugador al punto de control apropiado antes de que comience el juego También agreguemos un método al script de nivel para que el administrador del juego pueda solicitar esta información llamada get checkpoint position Tomando el ID de punto de control como un parámetro entero y devolviendo una posición de vector dos Comenzaré con un caso a prueba de fallas de solo devolver el vector dos cero. Antes de usar un argumento para indexar una matriz, debemos verificar que es un índice de matriz válido, que sea tanto mayor o igual a cero como menor que el tamaño de la matriz. Entonces simplemente devolvemos el índice de matriz de punto de control en el ID de punto de control y obtenemos su posición global Cambiando al guión del administrador del juego. Después de que se haya manejado toda la inicialización, pero antes de desvanecerse, deberíamos engendrar Ahora podemos establecer la posición global de los personajes del jugador preguntando al nivel la ubicación del puesto de control, pasando el punto de control archivado como argumento Por último, necesitamos agregar la variable checkpoint al recurso de datos con el valor predeterminado de cero El jugador comenzará en el nodo hijo superior de la carpeta de puntos de control, que es el nodo de inicio vacío Como no estamos usando el parámetro body pasado a la colisión de los puntos de control Godot preferiría que se marcara como opcional precediéndola con un guión bajo Coloque el punto de control en algún lugar alrededor de la mitad de su nivel mientras se asegura de que el inicio de nivel sea el nodo superior en la carpeta de puntos de control Al golpear Play, nada habrá cambiado, pero ahora podemos mover la ubicación de inicio del jugador más fácilmente. Además, si editamos el valor predeterminado de checkpoint en el script de datos, podemos generar al jugador en la bandera en su Ahora tenemos un sistema de puntos de control para que el manager del juego sepa dónde engendrar al jugador En la siguiente lección, agregaremos la muerte del jugador y haremos que el jugador reaparezca en el último puesto de control tocado Te veré en la siguiente lección. 40. 4-5 Muerte: Hola amigos. En la lección anterior creamos un sistema de puntos de control para que el manager del juego pueda generar al jugador en diferentes posiciones En esta lección, agregaremos muerte del personaje y reapareceremos al jugador cuando muera Comenzando en el guión del personaje. Al igual que tapamos la salud al máximo de salud usando Min cuando el jugador se recupera También necesitamos detener la salud actual en cero cuando reciben daño, estableciendo la salud actual al máximo de la salud actual menos la cantidad de daño o cero. Entonces podemos emitir la señal de salud cambiada y establecer la velocidad de retroceso. El resto de este método dependerá de que este daño los haya matado o no. Tenemos que verificar si la salud actual es cero. Si se llama un nuevo método, muere. Si el personaje no está muerto, entonces la variable is hit se establecerá true y pueden volverse invencibles Antes de escribir el método die, debemos declarar una variable booleana para saber si el carácter está muerto o También crea una señal para emitir cuando el personaje muere para que el manager del juego pueda reaccionar ante él. En el método die, podemos establecer la nueva variable booleana es muerta a verdad que podemos usar en el animador Como hicimos con es hit y emitir una señal de que el personaje También sería una buena idea apagar la caja del rebaño del personaje para que dejen de recibir daños. Pero esto sigue siendo algo que probablemente está sucediendo durante una colisión. Tendremos que diferir esto hasta el final del marco actual Establecer la capa de colisión del personaje en cero y la máscara de colisión uno evitará futuras colisiones con cualquier cosa que no sea el terreno Un personaje muerto no recogerá tesoros ni activará un puesto de control Por último, establecer la dirección a cero cancelará cualquier entrada de movimiento que se haya dado al momento de la muerte. Para poder responder al jugador, también necesitamos un método público para revivirlos de estar muertos, el ajuste está muerto, de vuelta a falsa salud actual a la salud máxima. Luego necesitamos restaurar la colisión del personaje estableciendo la propiedad monitoreable de la caja Rt Esto no se desencadena por una colisión, más probablemente la lógica del manager del juego. Está bien simplemente configurarlo directamente. Podemos almacenar los valores de la capa de colisión y la máscara de colisión en variables durante la fase de listo, luego restaurarlos a sus valores originales al revivir el personaje Ya que estaremos reviviendo al personaje del jugador después de reposicionarlo de nuevo en el punto de control, también sería una buena idea omitir aquí la señal aterrizado, que posicionará correctamente Cambiamos la del personaje, también deberíamos omitir la señal de salud cambiada a Tampoco queremos que el personaje pueda hacer nada mientras esté muerto Comenzando con el método face left, primero debemos verificar si el personaje está muerto y de ser así regresar evitando que esto suceda. Y haz esto por cualquier método que no deba ejecutarse mientras el personaje está muerto, incluyendo cara derecha, run jump, y stop jump. También me gustaría hacer una adición al guión del manager del juego. Al desovar al jugador, estamos estableciendo su posición probablemente en el suelo o cerca del suelo en una ubicación en el nivel Te puedes imaginar que existe la posibilidad de que el personaje jugador muera y caiga desde una gran altura. En el momento en que este método de reaparición reposiciona al personaje, el personaje tendría una velocidad muy alta Para evitar que la velocidad persista y potencialmente rompa la colisión de lluvia, debemos establecer su velocidad en cero en este momento Cambiando al reproductor de animación, podemos agregar las animaciones dead hit y dead ground. Recuerda usar los activos de la carpeta sin censura. golpe muerto debería tener un grito de dolor por parte del personaje mientras Dead Ground coloca un sonido de impacto al golpear el suelo. Con la alta probabilidad de que estos sonidos se superpongan, sería una buena idea separar los sonidos vocales de los efectos sonoros generales. Añadiendo un segundo reproductor de flujo de audio de dos nodos D, podemos nombrar una voz y el otro efectos de sonido. Entonces podemos mantener los sonidos vocales restringidos a solo poder tocar uno a la vez, al tiempo que permitimos que los efectos de sonido se reproduzcan simultáneamente sin interrupciones Establecer la propiedad de polifonía máxima de los efectos de sonido a un valor mayor que uno también permitirá que múltiples efectos de sonido se reproduzcan juntos dos Este formato también nos permite ajustar los ajustes de volumen de voces y efectos de sonido independientemente seleccionando el árbol de animación. Agrega estas nuevas animaciones a la máquina de estado sin espada. En primer lugar, reproducir la animación de golpe muerto seguido de tierra muerta. Dead hit se juega cuando el personaje está muerto. Entonces se jugará tierra muerta después de que haya finalizado el golpe muerto, solo si el personaje está en el piso. Para revivir al jugador, necesitamos que estas animaciones vuelvan también al movimiento. Cuando está muerto se vuelve falso en la escena del juego, selecciona el nodo del personaje del jugador y conecta la señal Did al administrador del juego. Vamos a nombrar este método en el jugador Did. Cuando el jugador muere, podría pasar una de dos cosas. O responden en su último puesto de control o se han quedado sin vidas y han golpeado el juego sobre el estado Primero, verificar si la vida de los datos del archivo es igual a cero. Entonces llamaremos a un método de juego sobre, dando juego sobre una definición. Por ahora, solo podemos imprimir el juego terminado. Si vidas no es cero, entonces podemos reducirlo en uno, Actualizar la interfaz de usuario, luego llamar a un método diferente. Regreso al último punto de control. Para regresar al último puesto de control, debemos esperar, desvanecerse, desvanecerse a negro Genera al personaje en el último puesto de control alcanzado, revivirlos, luego esperar descolorido para despejar. En ambos casos, me gustaría tocar un jingle corto como con la fanfarria de la victoria Agreguemos tres variables exportadas al script del administrador del juego de tipo audio stream, que se denominará Victory, Death y Game Over. Estoy usando la música de final de escena para la muerte y el cambio de escena triste, o aterrador. Música para game over, ambas hechas por Dominic Trace de Freesound.org Luego podemos decirle al nodo fanfarria que reproduzca el sonido apropiado para reproduzca el sonido apropiado Jugando el tema de la victoria cuando el jugador recoge el mapa al final del nivel. Jugando el tema de la muerte cuando mueren y el juego sobre tema cuando se les acaba la vida. También sería prudente desactivar la entrada del jugador al inicio del retorno al último punto de control y habilitar la entrada del jugador al He puesto a los jugadores comenzando vidas a uno y la salud de Mac a uno. Para esta demostración, tenemos ahora tenemos al personaje jugador capaz de morir y responder en el último punto de control al que llegaron En la siguiente lección, daremos a los enemigos ataques para lastimar al jugador. Te veré en la siguiente lección. 41. 4-6 enemigos: Hola amigos. En la lección anterior, le dimos al personaje del jugador una animación de muerte y los hicimos reaparecer después En esta lección, agregaremos ataques a los personajes enemigos que pueden lastimar al jugador. Voy a usar Diente Fierce como ejemplo para esta lección. Pero todos los personajes necesitarán tener sus estructuras de nodos editadas para que coincidan antes de ejecutar cualquier prueba. Seleccionando el nodo del jugador de animación, podemos comenzar agregando las mismas animaciones de hit, dead hit y dead ground para los enemigos que hicimos con Roger. Después agregar también anticipación y atacar también. En la máquina de estado de árboles de animación, podemos recrear las mismas animaciones de hit y muerte que hicimos con Roger Estructuración de la máquina de estado en capas. Así permite que el enemigo que sale herido o muerto interrumpa sus ataques. Editando la capa de ataque, luego podemos agregar las animaciones de anticipación y ataque Aquí se agrega una transición del movimiento a la anticipación, la anticipación al ataque y el ataque al La transición de la anticipación al ataque ocurrirá al final, al igual que la transición del ataque al movimiento Pero la transición del movimiento a la anticipación, que pone en marcha la cadena de animaciones, sucederá cuando el personaje quiera atacar en el guión del personaje Agreguemos los deseos de atacar a bolin a las variables de combate Luego agrega un método público llamado attack que establece su valor en true. Cada vez que se llame a este método, el enemigo querrá atacar una vez como la variable is hit necesaria para volver a ser falsa, de lo contrario la animación se repetiría. También necesitamos establecer la variable wants to attack de nuevo en false durante la animación. La variable quiere atacar tendrá que ser exportada para que el reproductor de animación pueda acceder a ella. Volviendo al reproductor de animación durante la animación de anticipación, podemos establecer el valor de wants to attack back en false Esto es suficiente para activar la secuencia de animación para que este enemigo ataque. Pero al igual que los picos, también tiene que haber un hit box buscando la caja herida del jugador. Seleccione la animación de ataque con el primer fotograma seleccionado. Que esto es lo que se está mostrando en el editor con una buena visión del personaje. Vamos a agregar otra área al nodo D al árbol de escena llamado hit box y darle una forma de colisión. Para distinguir este colisionador del colisionador de ambiente azul y el cuadro Rt verde, podemos darle al hit box otro color como el Selecciona una forma que creas que se ajuste mejor al área a la que apunta el ataque. Usaré una cápsula, luego cambiaré tamaño para que se ajuste al tamaño y la forma del área objetivo Asegúrate de dejar la caja de cadera centrada en el personaje y solo mover la forma de colisión fuera del centro. También hay una animación de efectos. Agreguemos un nodo de animación de sprites como hijo de la caja de cadera Crea un recurso de marcos de sprite y llénalo con los sprites de efectos de ataque A diferencia de otras animaciones de efectos, no queremos que esto se reproduzca de forma automática Y también la frecuencia de fotogramas habitual de diez fotogramas por segundo, tampoco debería bucle. También agrega un fotograma vacío al final, reposiciona el nodo sprite para que parezca que el efecto está emanando del ataque Cuando termines, establece el fotograma predeterminado para que sea el último fotograma vacío, modo que inicialmente se cargará en la escena ya que no muestra nada. Pero luego cuando le decimos que juegue, reproducirá la animación una vez y volverá a desaparecer. Podemos establecer la capa de colisión de cajas de golpe para que sea la capa 19, que será la capa de golpe enemigo, y hacer que enmascara al jugador herido capa capa diez. Al ser una entidad activa, está monitoreando cajas dañadas. Nada busca cajas de aciertos. Por lo general, no son monitoreables. obstante, no queremos que esto esté monitoreando hasta que el enemigo realmente ataca. El valor predeterminado de monitoreo también será falso. En el guión del personaje. Sería una buena idea agarrar una referencia al hip box durante la fase lista. Necesitamos agregar un nodo hit box a cada carácter para satisfacer los requisitos de scripts de caracteres antes probar y establecer la propiedad de monitoreo en false. si acaso de nuevo en la animación de ataque, podemos agregar la propiedad de monitoreo de cajas de golpe a la animación, estableciendo su valor en true durante el primer fotograma, back a false durante el segundo fotograma. Después agrega también una pista de método de llamada para la animación del efecto, diciéndole que se reproduzca durante el primer fotograma del ataque. Si bien las animaciones se dividen en anticipación y ataque, realidad hay tres fases para un ataque, un contacto y recuperación cuando se trata de enemigos La fase de anticipación es como el enemigo telegrafía que van a atacar, dando tiempo al jugador para reaccionar Seguido del contacto, que es el momento exacto se enciende el colisionador y el enemigo realmente lastima al jugador Por último, la recuperación, que le da tiempo al jugador para reaccionar ante ser golpeado o tomar represalias. Conéctese al área ingresada señal del hit box al guión del personaje. El único área que vamos a permitir para chocar con un hit box es un cuadro Rt Gracias a las capas de colisión, todo lo que tenemos que hacer es pedirle al área de la caja Rt su padre, que será un personaje, y decirle a ese personaje que sufra daños Por ahora, solo inflige un daño en la dirección de la posición global del jugador menos la posición global de este enemigo. Después normalizado, deberíamos exportar la cantidad de daño como una variable de combate para que pueda ser modificada para cada personaje en la escena de nivel. Encuentra a tu enemigo y conecta un nodo temporizador a él. Y ajusta el temporizador a algo un poco más largo, como dos o 3 segundos. Y ponlo a autos, empieza. Conecta la señal de tiempo de espera de este temporizador al método de ataque del enemigo Ahora este enemigo recibirá instrucciones de atacar una vez cada vez que el temporizador llegue a cero, y se repetirá indefinidamente Cuando estés listo, pulsa play para ver al personaje atacando auto e intenta dejar que te golpee. El esto funciona siempre y cuando el personaje enemigo no se dé la vuelta. Vamos a establecer los nodos sprite flip H propiedad en true para simular al enemigo de cara a la derecha Ahora la animación de ataque se enfrentará a la derecha, pero la caja de cadera y la animación del efecto siguen mirando hacia la izquierda. Seleccionando la caja de cadera en la sección de transformación, haga clic en el icono de la cadena para desvincular los valores x e y para que puedan editarse por separado Luego haz clic y arrastra desde la propiedad scale x, moviendo el mouse hacia la izquierda. A medida que el valor se acerca a cero, la caja de cadera es tan delgada que desaparece. Pero a medida que se vuelve negativo, se ve reflejada alrededor del eje y Podemos usar esto en el guión del personaje para voltear la caja de cadera. Al mismo tiempo volteamos el sprite en el método face left Establece la escala de caja cadera x a uno si el sprite naturalmente mira a la izquierda, l negativo uno y viceversa. En el método de cara derecha, podemos voltear la dirección inicial de nuestro enemigo con la variable exportada. Para probar esto, ahora tenemos a nuestros personajes enemigos atacando al jugador. En la siguiente lección, agregaremos una sobrepantalla de juego. Te veré en la siguiente lección. 42. Terminado el juego 4-7: Hola amigos. En la lección anterior, dimos los ataques del enemigo para lastimar al jugador. En esta lección, agregaremos un juego sobre pantalla. Esta será una nota de control sobre el lienzo de la interfaz de usuario, probablemente dibujada sobre todo lo demás, pero aún debajo del fade, llamado Game Over Menu. Usaré una caja vertical para ordenar todo fácilmente, comenzando con una etiqueta que diga Game Over para que el jugador entienda rápidamente lo que sucede cuando el jugador se queda sin vidas. Solo les voy a presentar tres opciones reintentar desde el inicio del nivel, volver al menú de selección de nivel o salir del juego Voy a añadir tres botones para cada una de mis tres opciones, Seleccionar y salir. Escalaré todo cuatro veces y lo reposicionaré para que esté en el centro de la pantalla. Usando anclas, seleccionando cada uno de los botones, conecta la señal presionada al script del administrador del juego, creando tres nuevos métodos que se llamarán cuando el jugador presione los botones Primero, necesitaremos una referencia al juego sobre menú establecido durante la fase de listo. Y establecer su propiedad visible en caídas para ocultarla. Entonces, cuando se alcanza el juego sobre el estado, podemos establecer su propiedad visible en true. Luego, al presionar cualquiera de estos botones, se debe ocultar el menú de la pantalla de gameover configurando su propiedad visible de nuevo en false Si al jugador le gustaría comenzar de nuevo desde el inicio del nivel, tendremos que restablecer un montón de variables, responder a todos los tesoros enemigos, y puntos de control, etcétera Podemos simplificar esto simplemente descargando y recargando el mismo nivel La descarga es fácil ya que tenemos una referencia al nodo de nivel. Solo podemos llamar a nivel de subrayado gratuito. Para recargar el nivel. No obstante, necesitaremos saber qué nivel se cargó. Al abrir el script de datos, podemos agregar dos nuevas variables, una para mundo y otra para nivel, ambas con un valor inicial de una. Si no quieres organizar tus niveles en mundos, puedes ignorar esa variable mientras estemos aquí. También tendremos que restablecer estos otros valores cuando el jugador comience nuevo desde el inicio del nivel agregando un método de reintento público, podemos establecer monedas a cero, vidas a tres, punto de control a cero y tiene clave para false De vuelta en el script del administrador del juego, podemos llamar a los datos del archivo para restablecer el progreso de los jugadores. Entonces podemos establecer el valor de level a ser load, que toma un argumento string que representa la ruta del archivo al recurso que queremos cargar. Buscando a través de la pestaña del sistema de archivos, encuentra tu nivel, haz clic derecho y selecciona copiar ruta. Después pega esta ruta entre comillas. Y siga la llamada de carga que devuelve un recurso con instanciate para convertir ese recurso en un nodo Luego agrega ese nodo al árbol de escenas con add child, pero esto solo cargará el nivel uno. Podemos reemplazar las que están en el nombre del archivo con las variables de nuestros datos de archivo, pero las variables son números enteros. Y esta es una cadena de conversión de los enteros a cadenas usando el corchete STR Siempre y cuando cada nivel esté dentro de la carpeta levels y se nombra en el mismo formato, se cargará simplemente configurando las variables world y level en los datos del archivo. Luego podremos engendrar al jugador, apagar los controles del jugador y revivirlos. Pero no queremos que el jugador vea nada de esto sucediendo. Deberíamos comenzar por desvanecernos a negro. Después al final, esperan desvanecerse para despejar y volver a encender los controles del jugador. El jugador estará en el inicio del nivel el cual ha sido completamente recargado de nuevo y volverá a intentarlo con tres Por ahora, si el reproductor quiere volver al menú de selección de niveles, solo podemos desvanecernos a negro y restablecer los datos de sus archivos, ya que aún no hemos construido esa escena. Pero deja aquí un comentario o una declaración de impresión para que sepamos en el futuro implementar esta característica Si presionan el botón ex It, podemos esperar, se desvanecen a negro. Entonces llama a get tree quit para cerrar el juego. Alternativamente, es posible que desee que este regreso a la pantalla de título del juego cuando tengamos uno. Para fines de prueba, solo tendré visible la sobrepantalla del juego Por defecto el botón Salir funciona. El botón de selección de nivel aún no hace mucho, pero eso es intencional. El botón de reintento también funciona. Pero este menú se ve mal y no encaja con la estética del juego. Usemos el paquete de activos para mejorarlo. Comenzaré cambiando la etiqueta a un nodo de control básico llamado Banner y lo llenaré con restos de textura, poblándolos con las imágenes de letras para deletrear juego y ordenarlos usando dos cajas horizontales Restablecer el tamaño y cambiar la separación a dos píxeles entre cada letra Agregaré cinco Ts de textura más y usaré las imágenes del pequeño banner para armar un banner, reordenándolos para que encajen centrados sobre el punto de origen del banner y tengan las palabras escritas en el banner Entonces le diré al banner que se centre dentro del cuadro vertical padre, seleccionando el juego sobre el nodo de menú. Expande la sección del tema y selecciona Nuevo tema en el menú desplegable. Luego haga clic en el recurso temático para abrirlo en el panel inferior. Esta pantalla nos muestra varios elementos diferentes de la interfaz de usuario y cómo se verán usando este recurso temático, que podemos editar. Vamos a agregar botón al tema. Debajo de la pestaña de cuadro de estilo, hay cinco opciones para diferentes estados de botón. Añadiéndolos todos al tema. Entonces podemos cambiar cómo se ve el botón en cada estado. Comenzando con normal, agrega una nueva textura de cuadro de estilo, da clic en el cuadro de estilo para abrirlo, luego llénalo con el botón verde Una imagen. Los botones de la vista previa son ahora verdes, igual que los botones de nuestro juego. Pero están estiradas y feas. Luego expanda la sección de margen de textura, agregando algunos píxeles de espacio de margen. La imagen ahora se ve mejor. Las imágenes de este paquete de activos tienen un margen inferior mayor que los otros lados. Dado que el juego sobre el menú está utilizando este recurso temático. Todos sus hijos también tienen el mismo tema aplicado al pasar el mouse o enfocarse en un botón Cambiaré su textura con el botón amarillo. Podemos ver cómo se comporta esto al pasar el cursor y hacer clic en los botones en la vista previa Cuando se desactiva, usaré la misma textura de botón verde, pero modularé el color, multiplicando los valores RGB y alfa todos por la mitad para que se vuelva más gris Cuando se presiona, usaré la misma textura de botón amarillo, pero haré lo mismo, modulando con valores RGB grises. Pero deja alfa a plena opacidad, quitando el texto de los botones En su lugar, los reemplazaré con íconos. Luego, coloque cada botón una caja horizontal emparejada con otra caja horizontal para que actúe como etiqueta del botón. Cada caja horizontal de etiqueta tendrá múltiples Recs de textura por cada letra de la palabra que quiero deletrear, diciéndole a la caja horizontal encoja y centre verticalmente Para la selección de nivel, solo usaré un texto vacío directo como espacio. Quisiera más espacio entre los botones y sus etiquetas. Entonces agruparé seleccionaré los cuadros horizontales y editaré sus valores de separación para que sean de 14 píxeles. Entonces pondré los tres botones en otra caja vertical y colocaré eso dentro de un nodo contenedor de panel llamado madera. Y también agregar un nodo de panel al contenedor del panel llamado papel, Reabriendo el tema En el panel inferior, podemos hacer más cambios en paneles y contenedores de paneles. Añadiendo el contenedor del panel al tema, también podemos darle una caja de estilo, usando prefabs Tres como imagen Quiero márgenes más amplios en este panel para que los botones no se vean tan abarrotados cerca de los bordes. Los nodos de contenedor cambian de tamaño automáticamente para adaptarse a su contenido También agreguemos el panel al tema. Los paneles son similares a una textura destrozada, pero también tienen márgenes de textura como los botones Y voy a usar prefab nine como su textura. Esto tiene márgenes bastante amplios a 20 píxeles. Y a diferencia de las imágenes de botones donde el interior era solo de un color plano, el papel y la madera tienen textura que se está estirando. Ampliando la sección de estiramiento del eje, podemos establecer las texturas para mosaico en lugar de estirar para espaciar más las cosas, le daré al panel de madera un ancho mínimo de 160 píxeles y al papel un tamaño personalizado de 120 por 100 píxeles. Posicionando el papel en el lado derecho de la madera y los botones centrados verticalmente. Las palabras parecen estar escritas en el papel. Y quitar la altura mínima personalizada de la pancarta. Ahora tenemos un juego temático sobre pantalla. En la siguiente sección, le daremos una espada al jugador para que pueda contraatacar. Te veré en la siguiente sección. 43. Espada 5-1: Hola amigos. En la sección anterior, permitimos que el personaje jugador sufriera daños y muriera. En esta sección, le daremos al jugador una espada y ataques propios para que pueda contraatacar si completaste la tarea. Todos tus niveles ahora tendrán la carpeta de puntos de control. Y todos tus enemigos habrán golpeado animaciones de muerte y ataque. Todos tus enemigos podrán atacar, El jugador recibe daño y muere si completaste los desafíos. También puedes tener tu interfaz de usuario y juego sobre menú tweening desde fuera de la pantalla. Así como pociones verdes y azules que afectan al personaje de maneras únicas Empecemos con un poco de limpieza. Me gustaría ordenar los guiones de personajes y jugadores en una nueva carpeta de guiones llamada personajes. Esta escena principal del juego se utilizará para todos los niveles, no solo para el primer nivel. Así podremos eliminar el nodo de nivel en el script del gestor de juegos. No vamos a establecer el valor del nivel usando en on ready. En el método listo. Después de configurar el fade para que sea visible, entonces debemos cargar el nivel actual. Escribir un nuevo método privado. Nivel de carga podemos usar el mismo código que escribimos en el método del botón de reintento presionado para cargar el nivel y reemplazarlo con una llamada al método Luego también muévalo límites y la interfaz de usuario al nivel de carga. Se actualizarán para que coincidan con los nuevos valores. También agregue una línea a la interfaz de usuario de nit para establecer la propiedad visible del icono de clave para saber si el jugador tiene o no la clave Ahora sea cual sea el mundo que se establezca un nivel en los datos del archivo, ese nivel se cargará cuando comience el juego. Si se vuelve a cargar o cambiar el nivel, los límites y la interfaz de usuario se actualizarán para que coincidan Hasta ahora todo lo que hemos hecho en nuestro guión de personajes ha sido aplicable, o al menos lo suficientemente flexible, para ser aplicado a cualquier personaje. No obstante, la manada de activos solo tiene al humano portando la espada. Para separar estos comportamientos del guión del personaje, podemos crear un nuevo guión que herede del personaje, que contendrá comportamientos que solo se pueden aplicar al héroe de nuestro juego guardado en la nueva carpeta de scripts de personajes, y reemplazando el guión del personaje en la nota raíz de Roger Este script necesitará una variable booleana exportada para decirnos si el héroe actualmente sostiene una espada o no actualmente sostiene una espada También podemos darle a este script un nombre de clase para que otros scripts puedan verificar fácilmente si algo es un personaje o un héroe. También voy a tener una referencia privada a la espada que está equipada. Después agrega un nuevo método público que otros guiones puedan usar para decirle a Roger que equipe una espada. Tomando la espada como parámetro, estableciendo la variable privada local y poniendo su espada a otro método público, diciéndole a nuestro héroe que suelte la espada. Si no tienen una espada para soltar, podemos ignorar y regresar. De lo contrario, el engaste tiene espada a caídas, diciéndole a la espada que se caiga. Pasando como argumento la posición global del héroe, la espada sabe dónde debería estar. Como el héroe ya no tiene espada, la variable espada será nula, lo que significa vacía. Cuando el héroe muera, anularemos el comportamiento del personaje de morir para verificar si el héroe tiene una espada y si es así la soltaremos, entonces todavía queremos que el resto del código de die se ejecute también. En lugar de copiar y pegar, podemos usar super die para llamar a la definición heredada de morir Siguiendo el mismo proceso que hemos utilizado para crear todos nuestros tesoros coleccionables Hagamos una espada equívoca para el personaje jugador. Quiero que mi espada tenga aplicada la física. A veces lo haré un cuerpo rígido dos D como las monedas, pero mi espada será más compleja que objetos típicos del tesoro con múltiples estados y más cosas que cambiar que solo el sprite, más como el cofre del tesoro Dándole un sprite dos nodos D. Pondré su sprite predeterminado para que sea espada, ocioso, cero uno. Añadiendo un reproductor de animación y el árbol de animación, puedo crear la animación ociosa para que la espada gire. Luego agrega una forma de colisión a la rama, dándole un tamaño de forma de cápsula para que se ajuste al sprite de espadas Pondré esto en la capa 26 para mantenerla separada de otros artículos y que solo choque con el tren o con el jugador como las monedas Lo tendré incapaz de rotar congelado por defecto, con su modo de congelación establecido en Kinematic para que no se mueva, pero aún pueda tener Y reportar colisiones al contacto con hasta dos a la vez seleccionando el tratamiento de animación Configuraré la propiedad Anim player para que sea este reproductor de animación y crearé una nueva máquina de estado por ahora Esto solo tendrá la animación inactiva reproduciendo por defecto. Y también agregar un reproductor de flujo de audio al nodo, que voy a poblar con el efecto de sonido desenvainado, guardando esta rama como Quizás quieras poner esto en una carpeta de armas o equipo, pero como no hay otros activos como este, solo lo guardaré en la carpeta Escenas. Saqué la espada del origen de la escena, así que restableceré su transferencia y propiedad para volver a introducirla Ahora necesitamos crear un guión para la espada. Si bien esto se comporta de manera similar al tesoro, es lo suficientemente diferente como para preferir no refactorizar el código y en su lugar simplemente heredar el cuerpo rígido dos D, conectar la señal ingresada del cuerpo al Gracias a las capas de colisión, es bastante seguro asumir que lo único que puede cidar con la espada es Roger. Pero voy a comprobar sólo para estar seguro si el cuerpo es un héroe y puede equipar la espada. Tendremos que definir este método y hacer que devuelva un valor booleano Entonces podemos decirle al héroe que equipe esta espada, pasándose a sí misma como argumento, y que se vuelva invisible para que el jugador ya no pueda ver la espada. Ya que el sprite del personaje dibujará para facilitar la física de soltar la espada También descongelaré el cuerpo de la cresta con juego diferido. Agarrando una referencia al reproductor de flujo de audio dos lo hacen durante la fase de preparación También podemos tocar el efecto de sonido. Cuando esto sucede en el guión del héroe, necesitamos escribir el método de la espada equipada devolviendo un booleano Sólo tenemos que decir si el héroe no tiene espada y no está muerto. Bajo estas condiciones, el héroe debería poder equipar la espada. Entonces cuando el héroe deja caer la espada, llaman método caído. Escribiendo esa definición, podemos tomar la posición de donde se cayó la espada como parámetro de tipo vector dos. Voy a necesitar un generador de números aleatorios iniciado durante la fase lista para dar un flotador aleatorio entre uno negativo y uno positivo. Voy a establecer la posición global de la espada para que sea esa posición más la mitad de un azulejo arriba. Aplica una fuerza de impulso de hasta ocho fichas más derecha multiplicada por un número aleatorio similar al efecto de las monedas. Y finalmente establecer visible a verdadero para que el jugador pueda verlo. Ahora podemos duplicar nuestras animaciones para crear otras nuevas donde el héroe esté sosteniendo la espada, comenzando por idol, luego correr, saltar, caer tierra y golpear. Ahora podemos conectar a nuestros héroes sin máquina de estado de espada a la máquina de estado de espada de ancho basado en el valor de tiene espada abriendo el ancho almacenado máquina de estado. Esta capa superior contendrá la máquina de estado de ataque conectada a la animación de espada golpeada, ya que cuando el jugador muera, dejará caer la espada dentro de la máquina de estado de ataque. Por ahora, solo agrega la máquina de estado de movimiento y conéctalo desde el principio, agregando las animaciones de salto, caída y tierra, así como la máquina de estado de locomoción, conectándolos la misma manera que todo lo demás Y por último, completando la locomoción máquina estatal dos, colocando la espada en algún lugar de tu nivel El héroe ahora podrá recogerlo y todas las animaciones seguirán funcionando igual, solo que con la espada equipada. Y cuando mueren, se deja caer la espada. Ahora tenemos un objeto de espada que el jugador puede recoger y equipar. En la siguiente lección, agregaremos ataques con espada. Te veré en la siguiente lección. 44. Ataque 5-2: Hola amigos. En la lección anterior añadimos una espada que el jugador puede equipar y soltar. En esta lección, agregaremos un botón de ataque y las animaciones de ataque para el jugador. Comencemos abriendo la configuración del proyecto , la pestaña del mapa de entrada, y agregando un botón de ataque. Voy a usar el botón izquierdo del ratón clic J en el teclado y el botón de la cara izquierda para gamepad Acomodar una variedad de estilos de juego en dos nombres de capas de física. También agregaré nombres de golpe de jugador, golpe enemigo y capa de espada. Después en el guión del jugador, durante el evento de entrada, si se presiona el botón de ataque, entonces deberíamos decirle al personaje del jugador que ataque. El guión del personaje ya se ha configurado para procesar esta configuración de entrada quiere atacar a true, pero los jugadores pueden y machacarán botones incluso cuando la acción deseada sea imposible. Setting quiere atacar a true desencadenará un ataque cuando sea posible gracias al árbol de animación. Pero esto sucederá aunque pase una cantidad significativa de tiempo desde que se presionó el botón. Deberíamos establecer un límite de tiempo sobre cuánto tiempo se considera válida la entrada de ataque antes de ignorarla si el personaje no puede realizar el ataque durante ese tiempo, agreguemos un nodo temporizador al hit box llamado buffer de entrada y fijemos su tiempo a medio segundo y un disparo a true Después en el guión de héroe, podemos agarrar una referencia a este nodo durante la fase de listo. Anulando la definición de ataque, podemos establecer quiere atacar a true, iniciar el temporizador de búfer de entrada, esperar su señal de tiempo de espera Entonces set quiere atacar de nuevo a falso. Si no se activó ningún ataque dentro de medio segundo después de presionar el botón, entonces la pulsación del botón será ignorada. La duración del tiempo se puede ajustar fácilmente en las propiedades de los nodos del temporizador. Al atacar, me gustaría evitar que los personajes tomen otras acciones en el guión de los personajes. Voy a necesitar otra variable de lingotes para saber si el personaje actualmente está atacando o no Lo cual configuraré durante las animaciones y estableceré su valor en false cuando la escena se cargue por primera vez, por si acaso, como hicimos con el monitoreo del hit box. Entonces de la misma manera compruebo si el personaje está muerto antes de realizar otras acciones, también agregaré la condición que no deben estar atacando. No obstante, voy a cambiar de carrera para que si están muertos o atacando, en vez de simplemente regresar, pondré el valor de dirección a cero. De lo contrario, comportarse normalmente. Los personajes tendrán que terminar sus ataques antes de tomar cualquier otra acción. También agregaré la condición a la colisión de caja de impacto de que este personaje no debe estar muerto y debe estar atacando para poder infligir daño En la vista Rogers dos D, no le he dado una forma a Rogers hip box nodo todavía conectado la señal o establecer la capa de colisión y máscara Podemos conectar fácilmente la señal de nodo de área ingresada al método que ya estamos definidos en el script de caracteres. Luego configura esta caja de cadera para que se apague por defecto en el jugador golpee la capa de colisión 11 y enmascarando la capa T enemiga capa 18. Seleccionando el jugador de animación Rogers, podemos agregar un ataque a una animación poblada con los sprites apropiados y estableciendo su configuración de longitud quiere atacar a falso durante el primer fotograma, necesitamos establecer el valor de es atacando a true mientras se reproduce la animación . Luego volvamos a falso. Una vez hecho esto, el personaje sabe no moverse ni saltar. Luego establezca la propiedad de monitoreo de la caja de cadera en true durante el segundo frame y false durante el tercero. Detectando la colisión que lastimará a los enemigos. Usando el segundo fotograma de la animación como guía visual, crea una nueva forma para la colisión. Usaré una cápsula y pondré su color en rojo para que coincida con mis otras cajas de cadera. Luego establezca su forma, posición y rotación para que se ajuste al área afectada del ataque. Agregar pistas a la animación para la colisión. Forma nodos, forma, posición y rotación. Podemos agregar fotogramas clave para cada uno durante el primer fotograma de la animación. Agrega un modo animado a la caja de cadera para crear las animaciones de efectos. Y crea una animación para cada uno de los tres efectos de ataque con un fotograma vacío al final como valor predeterminado. Al igual que hicimos con los ataques enemigos. Posicionar el nodo delante del personaje para que la animación de sprite parezca que se alineará con el ataque de nuevo en la animación de ataque uno, podemos agregar una pista que reproduzca la animación de efecto, pasando ataque uno como primer argumento en el método de reproducción Llame al inspector. Y también una pista de reproducción de audio para reproducir un efecto de sonido swipe, duplicando la animación attack one Podemos crear las animaciones de ataque dos y atacar tres, intercambiando las texturas de sprite, cambiando el pase de argumento al sprite animado y poblando la reproducción de audio con un Luego crea una nueva forma de colisión para las diferentes animaciones de ataque. Reajustando su rotación posicional y forma para que coincida con el área afectada de los ataques Dependiendo de la versión de Godot que estés usando. Es posible que el editor no muestre correctamente el colisionador mientras haces esto, pero aún puedes ingresar valores manualmente en el inspector y repetir todo el proceso para hacer que el ataque sea tres Asegúrese de crear un nuevo recurso en forma de colisión para cada animación. Ah, seleccionando el árbol de animación. Buceando hacia abajo en la capa de espada de ancho , capa de ataque, Queremos agregar nuestras tres animaciones de ataque. Me gustaría hacer la transición a través estas tres animaciones de ataque en orden siempre y cuando el jugador siga presionando el botón de ataque, pero vuelva al movimiento de cualquiera de ellas si deja de presionar el botón de ataque. Primero haciendo la transición fuera de movimiento para atacar a uno, si el personaje quiere atacar y está en el suelo Después siguiendo las mismas condiciones a través de los otros dos ataques, solo cambiando al final de la animación anterior. Los ataques dos y tres volverán al movimiento al finalizar su animación. Pero la transición del ataque dos al ataque tres tendrá prioridad. Si se cumplen sus condiciones, ataque uno hará la transición de nuevo al movimiento si o bien el personaje no quiere atacar o si ya no están en el suelo. Antes de probar, sería útil poder ver el colisionador animando en el menú de depuración Seleccione Formas de colisión visibles para renderizar formas de colisión mientras se juega el juego. Ahora bien, si recogemos la espada en nuestro juego, el jugador podrá realizar ataques combinados con ella, cada uno con diferentes animaciones, formas de colisión y efectos de sonido. Y los ataques lastimarán y matarán a los enemigos también. Ahora tenemos al personaje jugador capaz de realizar un ataque combinado de tres golpes con una espada para luchar contra sus enemigos. En la siguiente lección, agregaremos dos ataques aéreos. Te veré en la siguiente lección. 45. Ataque aéreo 5-3: Hola amigos. En la lección anterior, agregamos animaciones de ataque para el jugador. En esta lección, agregaremos más ataques que el jugador pueda usar al saltar. Comenzando en la escena de Rogers, seleccionando el nodo jugador de animación de Roger Podemos duplicar la animación de ataque uno para crear uno de ataque aéreo e intercambiar los sprites por esa animación Cambiando el efecto de sonido de deslizamiento por uno diferente. También necesitamos crear una nueva forma de colisión para esta animación. Ajustar su forma, posición y rotación para que coincida con el área afectada. Al ajustar estas formas de colisión con una animación, ayuda a crear un nuevo nodo en forma de colisión y ajustarlo en su lugar. A continuación, copie los valores en los fotogramas clave de animación y elimine el nuevo nodo. Cuando hayas terminado, cambiemos el nombre del nodo sprite animado dos para atacar los efectos Después duplicarlo para crear efectos de ataque aéreo. Asegúrate de crear un nuevo recurso de fotogramas de sprite para este nuevo nodo y crear las dos animaciones de efecto de ataque aéreo Los efectos de ataque aéreo no están posicionados de la misma manera que los efectos de ataque terrestre. Así que tendremos que reposicionar el nodo, eliminando la pista para el efecto de ataque Podemos agregar una nueva pista para los efectos de ataque aéreo en su lugar, luego duplicando esta animación Para crear el ataque aéreo dos, podemos repetir el proceso, intercambiando los sprites, cambiando el argumento pasado a la animación del efecto y cambiando el efecto de sonido Después ajustando la forma de colisión para que coincida con el ataque. Agregando estas dos nuevas animaciones al árbol de animación, se comportarán muy de la misma manera que los ataques terrestres, solo con la condición de que el personaje no debe estar en el piso haciendo la transición del ataque aéreo uno al ataque aéreo dos al final de la animación, bajo las mismas condiciones Y de vuelta al movimiento al final del segundo ataque, haciendo la transición fuera del ataque aéreo uno, de vuelta al movimiento Si el jugador ya no quiere atacar o está en el suelo, me gustaría crear la sensación de suspenderse en el aire mientras el jugador realiza estos ataques aéreos Anularemos la definición de física aérea en el guión del héroe. Si el héroe está atacando y su velocidad y es mayor que cero, lo que significa que están cayendo, entonces estableceré su velocidad y en cero, lugar de mantenerlos en el aire mientras dure su ataque. De lo contrario, podemos usar delta de física súper aérea para realizar los comportamientos heredados del guión del personaje. Pero como el jugador puede optar seguir atacando infinitamente, también puede optar por permanecer en el aire para siempre. Podemos rectificar esto con otra mecánica de juego, un temporizador Cool down. Agregar otro nodo temporizador a la caja de cadera llamado Enfriar. Dejaré su ajuste de tiempo en el valor predeterminado de 1 segundo, pero pondré un tiro a true. Agarrando una referencia a este nodo durante la fase de listo en el guión de héroe para que podamos referenciarlo en el árbol de animación Posteriormente en las animaciones de ataque, podemos agregar una pista de llamada al método a cada una iniciando el temporizador de enfriamiento al final de cada animación. Inicio de llamadas en el temporizador de enfriamiento. Nuevamente, con cada ataque simplemente restablecerá su valor de tiempo de nuevo a 1 segundo y comenzará a contar atrás de nuevo. En el árbol de animación, no permitiremos la transición al primer ataque de la secuencia a menos que se detenga el temporizador de enfriamiento. De esa manera el jugador se verá obligado a dejar de atacar después un máximo de tres ataques en el suelo o dos ataques en el aire. La duración del enfriamiento se puede ajustar fácilmente en las propiedades de los nodos del temporizador. También me gustaría atacar un enemigo desde arriba para hacer rebotar al jugador. Agregar una anulación al guión de héroe del método ingresado en el área de caja de golpe. Primero tendré que verificar si este héroe está muerto o no atacando y luego regresar si no están en el piso. Y la posición y global del área golpeada por el ataque es mayor que la posición y global del héroe, lo que el enemigo que está siendo golpeado está por debajo. Entonces estableceré su velocidad y para que sea fuerza de salto dividida por dos, creando un rebote que será menor que un salto completo. Y por último, llamar a la definición heredada para infligir daño. Bueno, al crear las animaciones de ataque de los jugadores, agregué la nueva variable para es atacar, pero esa variable no se incluyó en las animaciones de ataque enemigo. Entonces agreguemos eso en. Mientras que el aligeramiento de la máquina de estado del árbol de animación ayuda a mantener las cosas organizadas También introduce la posibilidad las animaciones se interrumpan, dejando las variables establecidas en formas que no deberían ser. Por ejemplo, si Roger ataca su variable de ataque y el monitoreo de caja de cadera están ambos establecidos en true. Pero luego lo golpean antes de que se complete la animación y esas variables no se vuelven a poner en falso. Roger ahora no puede moverse y cualquier enemigo que se le acerque será dañado por cajas fantasma de cadera. Podemos restablecer estas variables cuando el personaje recibe daño o muere. Para evitar que esto suceda, vamos a crear un método de interrupción de ataque. Restablecer el valor de ataque y monitoreo de caja de cadera ambos de nuevo a falso, y llamar a este método cuando el personaje recibe daño si estaba atacando Ahora tenemos al personaje jugador capaz de realizar ataques en el aire, suspendiendo la gravedad y generando una fuerza de rebote al impactar. En la siguiente lección, agregaremos guiones de IA para tener la patrulla del enemigo en el área. Te veré en la siguiente lección. 46. Patrulla 5-4: Hola, amigos. En la lección anterior, agregamos ataques aéreos para el jugador. En esta lección, escribiremos un guión de IA para hacer que los enemigos patrullen un área. He movido a los otros enemigos y posicioné diente feroz entre dos obstáculos en mi nivel. Y deshabilitó el temporizador de ataque automático para el comportamiento enemigo más básico. Me gustaría que simplemente caminaran hacia adelante hasta que choquen contra una pared y se den la vuelta. Al igual que creamos el nodo jugador para controlar al personaje del jugador, podemos crear un nodo hijo para que los enemigos controlen su comportamiento. Con IA, este nodo requerirá dos posiciones D. Entonces lo haré un nodo dos D y lo llamaré Patrulla. Darle a este nodo un nombre de script para patrullar. Lo pondré en la carpeta de scripts de caracteres y usaré la plantilla predeterminada para un nodo dos D. Durante la fase de listo, tomaré una referencia al nodo padre, que es el carácter que se está controlando. También declaremos una variable para que sepamos qué dirección queremos movernos como tipo flotante. En el método ready, podemos inicializar el valor de direction en función de si el carácter padre está orientado hacia la izquierda o no Pero la variable está orientada hacia la izquierda se marcó como privada. Deberíamos agregar un método público que devuelva su valor al script de caracteres, que podamos acceder indebidamente a él Entonces podemos establecer el valor de la dirección del guión bajo en función del valor de retorno de los caracteres principales Public is facing left method, Esto nos permite leer el valor de está mirando hacia la izquierda pero no cambiarlo. En el método de proceso, no necesitamos delta. Deberíamos poner un guión bajo delante de él para que el motor pueda ignorarlo. El comportamiento predeterminado será simplemente decirle al personaje que corra en la dirección deseada. Pero antes de hacer eso, debemos verificar si el personaje ha chocado contra una pared, que está convenientemente incluida en el cuerpo del personaje dos de node para nosotros. Si el personaje está en una pared, entonces debemos cambiar el valor de dirección. Podemos obtener el vector normal de las paredes, que es un vector que es perpendicular y que apunta lejos de la superficie de las paredes. Sólo nos interesa la porción x de este vector para saber si la pared está orientada hacia la izquierda o hacia la derecha. También podemos aplicar signo a esto. El retorno será uno negativo o positivo. Esto no importará en mi juego, ya que cada pared es perfectamente plana. Sus vectores normales serán exactamente a la izquierda o a la derecha de todos modos. Pero este código funcionará con paredes anguladas. Ahora dos, vamos a probarlo. Ahora Fierce Tooth camina de lado a otro entre los dos obstáculos. Incluso detectan al jugador como un obstáculo. Dos, cualquier cosa con la que colisione el cuerpo del personaje al nodo D que impida el movimiento horizontal será detectado por el método is on wall ¿Y si posicionamos el diente feroz en la parte superior de la plataforma? Simplemente correrán por el costado y repetirán el mismo comportamiento que antes. Si bien puede que quiera este comportamiento a veces, probablemente no quiero que esto suceda todo el tiempo y puede querer que los enemigos se den la vuelta si ven presuntos. Esto es un poco más complicado ya que no se nos proporciona la detección de repisas Agregar un nodo hijo al nodo de patrulla. Podemos utilizar un rayo fundido dos nodos D para detectar la presencia o ausencia de terreno frente a un personaje. Colocaré el rayo para que esté en el espacio vacío frente al personaje y apuntando hacia abajo al suelo. Queremos que el comportamiento de este enemigo cambie en función de si esta flecha está o no golpeando el suelo. Cuando se dan la vuelta, reposiciona la flecha hacia el otro lado De vuelta en el guión de patrulla, podemos tomar una referencia al elenco durante la fase de listo y llamarlo Floor Re luego establecer su posición para que quede la mitad de una baldosa por delante del personaje en el método ready. Alternativamente, podrías exportar una variable si tus enemigos tienen diferentes tamaños y necesitan posicionar el rayo de manera diferente. Esta es una división entera, pero lo estoy haciendo a propósito, así que ignoraré la advertencia. En el método de proceso. Cada vez que el personaje está en el suelo y el rayo no choca con nada, eso significaría que el personaje está frente a una repisa Entonces podemos llamar a un método repisa detectada. Si se detecta una repisa, podemos intercambiar fácilmente el valor de dirección entre uno negativo y uno positivo multiplicándolo por uno multiplicándolo por Después reinicia la posición del rayo para estar frente a la nueva dirección del personaje. En lugar de duplicar el código, podemos convertir el código del método ready en un nuevo método y llamarlo en cualquier momento que queramos que cambien de dirección Ahora Fierce Tooth caminará de un lado a otro sin salirse de los bordes de la plataforma. Activar formas de colisión visibles en el menú de depuración también nos permitirá ver el rayo de piso en el trabajo mientras esto sucede. Pero, ¿y si quiero hacer una excepción y que algunos enemigos salgan de las repisas Podemos agregar un nuevo tipo de variable a nuestro script, Una enumeración a menudo acortada a enum, que es solo una Denle el nombre, comportamiento de repisa, y luego llene esta lista con todas nuestras opciones que queremos tener Sólo voy a añadir dos opciones. El valor predeterminado en la parte superior de la lista será dar la vuelta, pero también quiero tener la opción salir de las repisas dos También podrías querer tener cosas como parar o saltar, etcétera La convención para las enumeraciones es usar mayúsculas y minúsculas. Tal vez recuerde haber usado una enumeración ya la cual se definió en el nodo D del cuerpo rígido dos, al establecer su propiedad de modo congelado Con la enumeración definida, podemos exportar una variable usando la enumeración como su tipo Entonces cuando se detecta una repisa, podemos hacer coincidir el valor de esta variable y proporcionar un bloque de código para ejecutar para cada Si el supuesto comportamiento está configurado para dar la vuelta, deberíamos ejecutar el mismo código desde antes. Pero si está listo para marcharnos, entonces simplemente podemos pasar o regresar. Fuera de este método, se puede imaginar cómo se puede utilizar este formato para proporcionar cualquier número de comportamientos alternativos. Seleccionando el nodo de patrulla. El inspector ahora contiene un desplegable etiquetado comportamiento de repisa a partir del cual podemos seleccionar el comportamiento que queremos describir en términos que son fáciles de entender para cualquiera También voy a mover la posición de inicio de los jugadores para obtener una mejor vista. Digamos a Fierce Tooth que se salga de las repisas y veamos qué pasa Guarda el nodo patrulla como escena propia en la carpeta del personaje. Ahora podemos aplicar el mismo script de comportamiento a todos los enemigos básicos de nuestro juego. Ajustando la forma en que reaccionan a los diferentes obstáculos del terreno, usando casting y enumeraciones. En la siguiente lección, le daremos a la detección del jugador enemigo un comportamiento agresivo. Te veré en la siguiente lección. 47. Agresión 5-5: Hola amigos. En la lección anterior, creamos un script de IA que puede ser utilizado para hacer cualquier enemigo de nuestro juego patrulle en el área e incluso cambiar su comportamiento. En esta lección, escribiremos otro guión que permitirá a los enemigos percibir al jugador e intentar atacarlo. Empecemos en escena de dientes feroces. El primer paso será saber si un enemigo puede o no ver al jugador. Este será un comportamiento único solo para aquellos personajes que queremos que sean enemigos. Deberíamos crear un nuevo guión para los enemigos que heredan del personaje Luego podemos reemplazar el guión del personaje por el guión enemigo en el nodo raíz de Fierce Tooth. Agreguemos una variable booleana para saber si el enemigo puede ver al jugador o Pero, ¿cómo sabemos si el enemigo puede ver al jugador? Al igual que hicimos con el ataque, podemos agregar otra área al nodo para representar la visión del enemigo. Y darle forma de colisión. A utilizar un color neutro, como el blanco para la visión. Y que sea una gran área circular que cubra varios azulejos frente a ellos y ligeramente alrededor de ellos por todos los lados. Esto representa todo su campo de visión. Necesitamos saber si el personaje jugador entra en esta área. Ajustemos las capas de colisión. Poniendo esto en la capa 20, una nueva capa para la visión enemiga y enmascarando la capa nueve, para que solo puedan ver al jugador. Esta área será monitoreada, pero no monitoreable. Y siempre encendido por defecto. Pero puede haber obstáculos en el camino bloqueando su visión. También podemos usar un nodo de fundición para verificar su línea de visión. No importa dónde esté el objetivo ahora mismo, solo lo pondré en el medio. Pero el punto de origen del Raycast debería ser de los ojos del enemigo Podemos distinguir estos dos nodos renombrándolos para Clarity División de Campo sólo estará buscando al jugador. La línea de visión estará enmascarada por el terreno y el jugador así como cualquier otra cosa que le gustaría oscurecer su A continuación, podemos conectar las señales de entrada y salida del cuerpo del nodo D de la zona dos al guión enemigo Estos son muy bien llamados para nosotros a la visión cuerpo entró y salió. Almacenemos al héroe en una variable medida que entra y sale del campo de visión del enemigo. Gracias a las capas de colisión, solo el héroe debería estar activando este método Pero siempre es más seguro verificar primero, almacenar una referencia al héroe a medida que ingresa al campo de visión y estableciendo esa referencia nula a medida que salen del campo de visión. Para verificar la línea de visión, necesitaremos una referencia a los nodos de línea de visión establecidos durante la fase de listo. Entonces, durante el método de proceso, no necesitamos delta. Si el héroe está dentro de nuestro campo de visión, haremos algunas matemáticas, pero si no están en nuestra división de campo, entonces no podemos ver al jugador poniéndolo en falso Podemos establecer la posición objetivo de la línea de visión para que sea la diferencia entre la posición del héroe y la posición del enemigo apuntando la línea de visión directamente al personaje del jugador. Si la línea de visión es golpear algo y ese algo es el héroe, entonces podemos ver al jugador. De lo contrario, debe estar golpeando nada o algo más, como terreno o un obstáculo. No podemos ver al jugador activando formas de colisión visibles en el menú de depuración y presionando play. Después volviendo al editor, podemos cambiar al árbol de escenas remoto y seleccionar Diente Fierce para observar sus variables en el inspector en tiempo real. Ahora podemos ver que a medida que el jugador entra al campo de visión, la línea de visión comienza a rastrear su posición. La variable can C player se establece en true solo cuando están dentro del campo de visión y no obstruidos por el terreno desde la línea de También necesitamos que el campo de visión se voltee como todo lo demás cuando el enemigo se enfrenta a izquierda o derecha. Agarrando una referencia al nodo de visión durante la fase de listo y anulando las definiciones de cara izquierda y cara Podemos comenzar llamando a sus súper métodos. Luego agrega el ajuste de la escala X de visión a una cuando mira hacia la izquierda o una negativa cuando mira hacia la derecha. Ya que los enemigos están todos enfrentando a la izquierda por defecto. Dado que los moldes no utilizan la propiedad de escala, necesitaremos agregar una condición adicional al calcular la posición objetivo. Si el personaje enemigo no está mirando hacia la izquierda, entonces multiplique la X de la posición objetivo por una negativa para reflejarla. Una vez que el enemigo haya visto al jugador, queremos pausar su comportamiento de patrullaje y hacer que persigan al jugador en su lugar En el script de patrulla, podemos agregar una variable booleana privada para controlar si este personaje está patrullando o no Y establecer su valor en true por defecto. Entonces proporcionar métodos públicos para pausar y retomar este comportamiento. Establecer el valor de es patrullar en cada caso cuando se detiene También llame a la ejecución de caracteres cero para obligarlos a dejar de ejecutarse en el método de proceso Si este personaje no está patrullando, entonces deberíamos regresar y no ejecutar ninguno de este código En el script enemigo, podemos obtener una referencia al nodo patrulla durante la fase de listo aunque pueda o no existir usando un método llamado get node o null passing en el nombre del nodo que estamos buscando como argumento. Entonces reemplaza cada una de estas tres líneas con una llamada de método, diciéndole a este enemigo si puede o no ver al héroe escribiendo este nuevo héroe de método privado. Se necesitará un parámetro booleano de si ahora pueden o no ver héroe si el enemigo no puede ver al héroe, es decir, que el valor hasta este momento ha sido falso, pero ahora pueden ver al Este es el momento exacto en que el jugador ingresó tanto a su campo de visión como a su línea de visión. Entonces deberíamos establecer puede ver héroe a verdad. Si la nota de patrulla existe, entonces dígale que detenga su comportamiento. Inversamente, si el enemigo pudiera ver al héroe pero ahora no puede, entonces podemos decir que el comportamiento de patrullaje se reanude en caso de que el héroe esté detrás del También podemos obligar al enemigo a enfrentar la dirección del jugador en este momento comparando sus posiciones globales y el método de proceso del enemigo. Si podemos ver al héroe, entonces deberíamos correr hacia ellos usando la diferencia de la exposición global del héroe y la exposición global del enemigo para conocer la dirección y aplicarle señal Por lo que solo es uno negativo o uno positivo o cero si están directamente por encima o por debajo. De vuelta a la vista, podemos agregar otra área más al nodo para ahorrar tiempo. Vamos a convertirlo en un hijo del nodo hip box y ponerle un nombre a este objetivo. Lo haré amarillo para indicar peligro y hacer de esta forma lo que creas que tenga sentido, pero probablemente similar o solo un poco más grande que el hit box rojo. Coloca esto en otra nueva capa de colisión, capa 21, la capa de objetivo enemigo y la máscara. Para el cuadro Rt del jugador capa diez. Esto será de monitoreo y no monitoreable. Podemos conectarnos al área ingresada señal al guión del enemigo. No necesitamos el área dos D, así podemos marcarla con un guión bajo Entonces, cuando la caja T del jugador entre en el área objetivo del enemigo, el enemigo atacará. Vamos a probarlo. Cuando Fierce Tooth ve a Roger, dan persecución. Y si no pueden ver a Roger, volverán a sus comportamientos normales de patrullaje Si atrapan a Roger, atacarán. Nuestros enemigos ahora pueden ver y perseguir y atacar agresivamente al jugador En la siguiente lección, crearemos un enemigo que pueda disparar proyectiles Te veré en la siguiente lección. 48. 5-6 Proyectil: Hola amigos. En la lección anterior, permitimos que nuestros enemigos percibieran al personaje del jugador y lo atacaran. En esta lección se creará un nuevo enemigo con ataques a distancia. Ya empecé a crear un nuevo enemigo para esta lección, la concha marina. Hasta el momento, la estructura del árbol de nodos es la misma. La raíz es un cuerpo de personaje, dos D en la capa de colisión enemiga, enmascarando la capa de terreno con el sprite dos D, reproductor de animación y árbol de animación Un nodo en forma de colisión con un recurso en forma de cápsula, una caja de Rt a juego, caja de cadera, caja de destino y visión. Asegúrese de que cada uno esté configurado la capa de colisión apropiada, enmascarando las capas correctas y sean monitoreables o monitoreables Comenzaré agregando un nodo dos D llamado al origen del proyectil, que marcará la ubicación exacta desde donde se dispararán los proyectiles Y un nodo temporizador, que le dirá a este enemigo que dispare. Un proyectil configurado para autos arranca y disparará cada 3 segundos. Todas las animaciones han sido pobladas con los sprites apropiados Inactiva, golpeada, fuego y destruida. Destruido es solo un fotograma. Luego, el segundo fotograma establece la propiedad visible del sprite en caídas para ocultarlo, la máquina de estado del árbol de animación tiene las animaciones golpeadas y destruidas en la capa superior haciendo una transición basada en el hit y es variables muertas del script de caracteres dentro de la máquina de estado de ataque El Seashell por defecto es inactivo, luego pasa a disparar cuando quieren volver a disparar a inactivo al final de la animación y no quieren Creemos una nueva carpeta de scripts de personajes para los enemigos y pongamos guiones de enemigo y patrulla dentro de ella. Al igual que creamos el guión enemigo heredando del personaje, podemos darle al guión enemigo un nombre de clase enemigo, luego crear un nuevo guión llamado So Heredating Ahora bien, este script tiene todos los comportamientos y atributos de un personaje, un enemigo, y lo que sea que pongamos en el guión de los tiradores para generar un proyectil, igual que lo hicimos con monedas de desove, podemos exportar una variable de escena empaquetada, luego también exportar variables para describir el comportamiento de los proyectiles, como su velocidad, que me gustaría y atributos de un personaje, un enemigo, y lo que sea que pongamos en el guión de los tiradores para generar un proyectil, al igual que lo hicimos con monedas de desove, podemos exportar una variable de escena empaquetada, luego también exportar variables para describir el comportamiento de los proyectiles, como su velocidad, que me gustaría describir en azulejos por segundo. Lo estableceré en diez por defecto. También el daño que hará el proyectil cuando golpee al jugador, un entero que va de 1-100 con un defecto de uno La duración máxima, voy a permitir que el proyectil exista antes de destruirse a sí mismo como un flotador, con el defecto de 10 segundos. Durante listo. Después de realizar todos los métodos ready heredados, multiplicaré mi velocidad medida en teselas por segundo por Cobolpt para cambiarla a píxeles por También agarra una referencia al nodo de origen del proyectil. Usando en on ready, podemos escribir un método para generar el proyectil que será llamado por animación de fuego del enemigo tirador durante el fotograma exacto en el que debería aparecer el proyectil Crear una variable temporal para sostener el proyectil recién instanciado. Podemos posicionarlo en su punto de origen y agregarlo al árbol de escena como hermano del enemigo Si el enemigo puede moverse, el proyectil no se verá afectado por el movimiento del padre Existirá como una entidad independiente del mundo. Entonces podemos decirle al proyectil que dispare, dándole la información que necesita para hacer su dirección de trabajo, velocidad, daño y duración Este enemigo solo disparará proyectiles a la izquierda o a la derecha, dependiendo de en qué dirección estén enfrentados para activar la animación de fuego Al igual que con las animaciones de ataque, tendremos una variable booleana quiere disparar que se establece en true por un método público fuego en el reproductor de animación de conchas marinas Durante la animación de fuego que podemos establecer, quiere volver a disparar falso generar el proyectil durante el fotograma cuando se vea más correcto Para hacerlo en la escena de la concha también crearé el proyectil que será un nodo D del área dos No quiero que la física se aplique a mis proyectiles y preferiría calcular sus comportamientos Si quieres que tus proyectiles usen la física, deberían usar un cuerpo rígido dos D como nodo raíz El proyectil que está siendo disparado por el enemigo de concha marina es una perla y lo pone sobre la capa de golpe enemigo, enmascarando el terreno y la capa t del jugador Ya que estas son las únicas cosas que quiero que el proyectil pueda golpear Y necesitará un sprite para dibujar. Y una forma de colisión, que es el círculo. Voy a colorear rojo. Posicionar el proyectil donde debe originarse dentro de la concha marina Es posible que desee reposicionar el nodo de origen del proyectil en función de cómo debería verse en relación con el enemigo tirador También agregaré un nodo temporizador, que se utilizará principalmente para limitar la duración que pueda existir este proyectil Voy a poner que es una oportunidad a verdad cuando la perla golpea algo que quería romper. Voy a añadir un nodo dos D llamado escombros. Ocultaré el sprite de concha marina en forma de colisión para una mejor vista mientras hago los escombros de perlas usando escombros como carpeta luego puedo agregar nodos hijos por cada pieza de perla rota como cuerpo rígido dos nodos D. Desde ahora me gustaría aplicar la física. Las piezas de escombros tendrán sus propios sprites y formas de colisión. Colocaré la mitad superior de la perla donde coincida con el sprite de perla original y le daré una forma de colisión a juego Póngalos en una nueva capa, capa cuatro para escombros y enmascarar solo el terreno, tenerlo incapaz de rotar y congelado con el modo de congelación establecido en Kinematic Luego duplicarlo para crear el fondo intercambiando sprite y reposicionándolo para que coincida con el fondo de la perla intacta Tanto los escombros superior como inferior estarán ocultos por defecto. Con la estructura de nodos completa, podemos guardar la rama del proyectil como escena propia en una nueva carpeta Proyectiles y abrirla para editarla. Ahora podemos eliminar la perla de la escena de la concha marina y restablecer su posición para que esté centrada sobre el origen A continuación, agrega un script al nodo raíz de la perla llamado Proyectil, guardado en la carpeta de scripts enemigos Durante la fase lista, voy a agarrar referencias a los nodos hijos. Sé que voy a necesitar acceder como el sprite, escombros y temporizador Habiendo escrito ya la llamada al método de fuego en el guión del tirador, podemos darle una definición a eso. Aceptando una dirección como vector, dos velocidades como flotador, daño como un entero y duración como flotador. Tendremos que almacenar todos estos valores en variables locales privadas, excepto la duración. La duración simplemente podemos usar para configurar el temporizador. Si la duración dada fuera algo más que cero, el valor menor o igual a cero se consideraría duración ilimitada. También necesitaré una variable local privada para saber si este proyectil ha sido destruido o no En el método de proceso, si este proyectil no ha sido destruido, entonces agregue a su posición dirección tiempos velocidad por delta Esto hará que el proyectil se mueva en línea recta a una velocidad constante Cuál es el comportamiento esperado de los proyectiles en la mayoría de los videojuegos Conectando el área ingresada en el cuerpo ingresó señales al guión. El único cuerpo con el que debe encajar este proyectil es Si esto sucede, le dirá al proyectil que se rompa si entra en un área que debería ser la caja lastimada del jugador Primero intentaré obtener el padre del área, que debería ser el personaje del jugador. Después de verificar que este es el héroe, les diré que tomen daño, pasando la cantidad de daño y dirección normalizada como argumentos, luego rompan el proyectil Añadiendo en el método break, lo conectaré a la señal de tiempo de espera del temporizador Se llamará automáticamente 10 segundos después de que el proyectil sea disparado Si no golpeó nada cuando se rompe el proyectil, me gustaría que con el tiempo sucedieran algunas cosas diferentes , lo que podría hacerse con un reproductor de animación, pero prefiero hacerlo con código relativamente simple Primero, agregaré una variable exportada para la textura dos D, que muestra el proyectil siendo destruido Y cambiar el sprake por éste D se destruye variable a true El proyectil deja de moverse y es máscara de colisión a cero, por lo que no disparará más colisiones Entonces quiero reutilizar el nodo temporizador, que actualmente se está utilizando para activar el método de interrupción en la señal de tiempo de espera Al ser éste el método de rotura, el proyectil ha impactado algo y ese comportamiento ya no es necesario Obtendré la señal de tiempo de espera del temporizador y la desconectaré del método break Luego reinicia el temporizador con un nuevo tiempo, 0.1 segundos, que es la velocidad de fotogramas que he estado usando para todas mis animaciones. A la espera de que la señal de tiempo de espera sea 0.1 segundos después, estableceré la propiedad visible de sprites en false, luego diré a los escombros Entonces espera diez segundos más antes de decirle al motor que este proyectil ya no es relevante y se puede quitar del árbol de escenas Ahora podemos crear un nuevo script para dispersar los escombros adjuntándolo al nodo de escombros, que voy a poner en la carpeta de entorno. Este script solo necesita una variable, una matriz de nodos que son sus hijos. Cuando se nos dice que se dispersen, podemos iterar a través de esta matriz con un bucle for siguiendo el formato de cómo lo escribirían otros lenguajes Para cada bucle, podemos referirnos a cada miembro de la matriz de piezas como una pieza, luego decirle que se haga visible, descongele y le aplique una fuerza de impulso Dado que las piezas de escombros ya están distribuidas a sus posiciones originales en relación con el agujero ininterrumpido, simplemente podemos usar su posición como dirección de la fuerza de impulso, luego multiplicarla por una baldosa Por supuesto, se puede experimentar con diferentes cantidades de fuerza que se aplican para dispersar los escombros. Puede estar normalizando la dirección, por lo que su distancia al origen no es un factor Cuando se destruye la concha marina, podemos hacer lo mismo que con la perla creando los escombros. Nodo dos D, esta vez con cuatro hijos. Para cada uno de los cuatro sprites de shell rotos copiando y pegando los nodos, ya tendrán la configuración correcta Posicionando cada uno en la ubicación exacta donde coincidirá con el sprite de caparazón ininterrumpido y también ajustará sus formas de colisión A continuación, adjunte el script de escombros al nodo de escombros. Finalmente, conecte la señal de tiempo de espera de los temporizadores para decirle al proyectil marino que dispare cada 3 segundos. Seleccionando el nodo raíz de conchas marinas, necesitamos poblar la escena empaquetada que contiene el proyectil y establecer las caras de sprite a la izquierda y está mirando hacia la izquierda para Sí. A continuación, agregue una pista de llamada al método a la animación destruida para que los escombros se dispersen. En el mismo momento en que el sprite de conchas marinas se vuelve invisible, probémoslo. El proyectil dispara perlas cada 3 segundos que chocan con el terreno y rompen generando escombros, los cuales se eliminan automáticamente Después de 10 segundos, estas perlas pueden golpear y dañar al jugador. Y el jugador también puede destruir el caparazón del mar atacándolo con la espada. Ahora tenemos un enemigo que puede disparar proyectiles al jugador En la siguiente lección, agregaremos un jefe enemigo a nuestro juego. Te veré en la siguiente lección. 49. Jefe 5-7: Hola, amigos. En la lección anterior, agregamos un nuevo tipo de enemigo que puede disparar proyectiles En esta lección, agregaremos un encuentro de jefe enemigo a nuestro juego. He seguido adelante y he creado un nuevo nivel para el encuentro con jefes, que es un hoyo en el que una vez que el jugador salta, no podrá salir del nivel. Checkpoint está justo antes que el jefe y la espada está ahí, así que ya lo habrán hecho El tótem está formado por tres enemigos tirador, que son casi exactamente cubetas de la concha marina de la lección anterior Excepto que enmascaran la capa de colisión enemiga para fines de apilamiento. El tótem azul tiene un polígono de colisión personalizado que dificulta que el jugador se pare encima de él, pero aún capaz de saltar sobre En su proyectil se encuentra una espiga de madera que es un duplicado de la perla con sólo los sprites y formas de colisión alteradas A diferencia de los sprites perlados, la espiga de madera no es simétrica en la escritura del proyectil Vamos a agregar una nueva variable exportada, voltear con dirección. Entonces al disparar el proyectil, si voltear con dirección y dirección x es mayor que cero, debemos establecer la escala x dos negativo uno para voltear el sprite, forma de colisión y escombros y establecer el valor de los picos de madera de esta variable en true, dejando las perlas falsas Desafortunadamente, estos sprites tótem no están centrados. Para que los tótems individuales puedan mirar hacia la izquierda o hacia la derecha mientras permanecen centrados dentro del tótem, necesitarán un sprite Luego anulando las definiciones de cara izquierda y cara derecha, estableceré el desplazamiento de sprites para que sea este número multiplicado por uno si hay sprites face left else negative one y viceversa para Entonces estableceré el valor de esta variable durante ready, antes de super ready. Ya que súper listo le dirá al personaje que mire a izquierda o derecha, descubrí un problema con establecer la posición de los proyectiles antes de agregarlo al árbol de escenas Entonces podemos arreglarlo agregándolo primero al árbol. Además, no quiero que a este enemigo se le agregue ninguna velocidad de knocback al recibir daño En el script de caracteres, podemos agregar otra variable de combate llamada stagger como flotador con un valor predeterminado de cinco Los demás enemigos seguirán teniendo el mismo comportamiento que antes. Entonces cuando un personaje recibe daño, podemos multiplicar la velocidad de retroceso por esta nueva variable y establecer su valor en cero para el jefe, eliminando el efecto ¿Cómo creamos un encuentro con jefes? Empecemos por agregar un nodo de toting de área a este nivel, que cuando el jugador ingrese, comenzaremos el encuentro con el jefe, luego lo configuraremos para que esté monitoreando para la capa del jugador Le voy a dar forma de rectángulo y hacer que llene toda la arena. Me gustaría que la cámara se quedara quieta y al centro durante la pelea de jefes. Entonces voy a añadir un nuevo nodo tipo A marcador dos nodo D y nombrarlo Cámara Un marcador dos nodo D es casi exactamente lo mismo que un nodo dos D, excepto que dibuja un gizmo de cruz en el editor para que podamos ver fácilmente dónde Si queremos que la cámara permanezca bloqueada en su lugar durante el bosphte, necesitaremos poder anular su comportamiento predeterminado en una variable booleana que está siguiendo sujeto con el valor predeterminado de true en el método de true Si la cámara no está siguiendo al sujeto, entonces podemos regresar para evitar cambiar la posición de la cámara. Vamos a crear una nueva variable de panorámica para realizar este comportamiento de panoramización usando una preadolescentes. Después un nuevo método público, pan to marker, que tomará como parámetro un marcador dos D y también la duración del pan con un valor predeterminado de 1 segundo. Si la sartén existe y está funcionando, deberíamos matarla. Luego crea una nueva y dile que desplace la posición de la cámara a la posición global de los marcadores. Al llamar a este método, queremos anular el siguiente comportamiento predeterminado configurando es el siguiente sujeto a false. Entonces podemos agregar otro método para reanudar siguiendo el ajuste de sujeto que está siguiendo sujeto a true. Pero si lo dejamos así , la cámara va a cortar duro a la posición del sujeto. Primero, debemos verificar si la cámara está actualmente panning y acabar con ese comportamiento Si lo es, entonces podemos revertir los cálculos de la posición de la cámara desde el método de proceso para calcular en su lugar cuáles los valores de distancia de mirada hacia adelante y altura del piso serían los valores de distancia de mirada hacia adelante y altura del piso en la posición actual de la cámara. Luego emitirá tanto la dirección cambiada como las señales aterrizadas, que entretendrán la cámara suavemente de regreso al sujeto De vuelta en la escena de nivel, también podemos agregar una capa de lienzo al nivel. A diferencia de la capa de lienzo en la escena del juego, que se dibujará en todos los niveles, esta capa de lienzo solo se dibujará en niveles con el jefe copiando el indicador de salud del jugador. Podemos pegarlo en el lienzo de encuentros con jefe, luego reposicionarlo para que esté en la parte superior central de la pantalla Y reemplazar el corazón por el cráneo, teniéndolo oculto. Por defecto, me aseguraré de mostrarlo solo durante la batalla. Después de que termine la batalla, quiero que el tesoro final de nivel se revele. Tendré el tesoro posicionado en un área imposible de alcanzar e invisible en el guión del tesoro. Voy a añadir un método público simple llamado To Reveal, que tomará una nueva posición como un parámetro vector dos. Este método moverá el tesoro a la posición deseada, Hazlo visible. Reproduce la animación del efecto hacia atrás. Espera a que termine la animación. Después reproduce la animación por defecto, seleccionando el nodo de encuentro de jefe. Vamos a crear el script de encuentro con jefes, guardándolo en la carpeta de guiones del enemigo. Este script necesitará una referencia al marcador de cámara y los nodos del medidor de salud establecidos durante la fase de preparación. Pero también una referencia a la propia cámara, que podemos llegar iniciando nuestro camino desde el nodo raíz. También tomaré una referencia al tesoro de nivel accediendo primero al padre de este nodo, que será el nivel. Después consigue los puntos de control de nodo. Alternativamente, podría exportar esto como una variable que conecta la señal ingresada del cuerpo al script. Esto será desencadenado por el jugador que ingresa al área de la arena del jefe. Aquí es cuando debemos comenzar el encuentro con el jefe. Almacenemos también una referencia al héroe en una variable local. Cuando esto sucede para facilitar el seguimiento de la posición y el comportamiento Para iniciar el encuentro, primero desplazaré la cámara hacia el marcador de la cámara y luego mostraré el medidor de salud en el lienzo de la interfaz de usuario. Inversamente, para terminar el encuentro, debemos decirle a la cámara reanude siguiendo al jugador y oculte el indicador de salud Finalizar el encuentro podría ocurrir si el jugador muere o si el jefe es derrotado Si el jefe es derrotado, el encuentro debería terminar pero también revelar la recompensa. Reutilizar el marcador de cámara como ubicación de recompensa. Podemos activar el método de encuentro final automáticamente conectando la señal de salida del cuerpo a él. Dado que el jugador responderá fuera de la arena, este guión necesitará saber cuál es el jefe enemigo. En este ejemplo que estoy usando, el encuentro con el jefe es en realidad tres enemigos. Exportaré una serie de enemigos. Solo quiero tener un medidor de salud rastree la salud combinada de los tres enemigos. Haré que el script boss encounter maneje la lógica extra, creando dos nuevas variables para la salud actual y máxima. Entonces en el método listo, puedo iterar a través de mi variedad de enemigos jefes, sumando su salud máxima para obtener un total combinado Luego configurando la corriente para que sea igual al máx. También escribiré aquí un nuevo método que actualice el medidor de salud. Comenzando el estado actual en cero e iterando a través de la matriz Sumando la salud actual de todos los jefes enemigos. Para obtener un total combinado, entonces podemos calcular el porcentaje de salud total restante de la corriente de lanzamiento a un flotador y dividirlo por el máximo. Luego establezca el valor de los medidores de salud usando este porcentaje combinado Si el total combinado de salud es cero, entonces el jefe ha sido derrotado. Podemos usar la señal de salud cambiada que emite el script de caracteres para llamar a este método. Pero la señal de salud cambiada pasa un argumento float con ella, agregando eso como parámetro a nuestro método. Podemos ignorarlo precediéndolo con un guión bajo y conectar las señales durante el método ready cuando calculamos la salud máxima. Una mecánica común en los juegos es que el comportamiento del jefe cambie a ciertos porcentajes de salud. Si el jefe aún no está muerto, llamemos a un método de verificación de fase, pasando el porcentaje como argumento. Dado que este comportamiento variará de jefe a bos, deje el cuerpo en blanco junto con otro método vacío. Decidir el siguiente ataque. Ahora tenemos todas las estructuras genéricas de encuentro con jefes en su lugar. Vamos a darle a este script un nombre de clase para que pueda ser heredado para proporcionar comportamientos específicos de encuentro. Eliminando el script de encuentro de jefe del nodo. En cambio, podemos reemplazarlo con un guión heredado, describiendo específicamente los comportamientos del tótem En este guión, podemos definir cómo decide sus próximos ataques, así como cómo y cuándo cambia entre fases de batalla. Voy a mantener las cosas simples con solo tener una nota de temporizador adjunta al encuentro con el jefe, que voy a tomar una referencia con listo. Comience cuando comience el encuentro con el jefe y deténgase cuando termine el encuentro con el jefe. Después conecta su señal de tiempo de espera para decidir el siguiente ataque. El tótem decidirá qué hacer cada 1 segundo. Agregar un generador de números aleatorios y un entero para almacenar un entero aleatorio. Primero voy a iterar a través de cada jefe en la matriz del jefe, luego generando un número aleatorio 0-2 puedo igualar los resultados Ignoraré a cero, es decir, que el enemigo no hará nada. Si es uno, entonces se enfrentarán a la izquierda y dispararán. O si es un dos, van a enfrentar a la derecha y disparar. Para aumentar la dificultad. A medida que la salud del jefe se vuelve más lenta, comprobaré cuando el porcentaje llegue a menos de un tercio y menos de dos tercios cuando se crucen estos umbrales Voy a configurar el tiempo de espera de los temporizadores para que sean un poco más cortos para que los tótems ataquen con más frecuencia Pero me aseguraré de que el tiempo quede más largo que la animación, permitiéndote terminar y volver al ralentí entre cada ataque. No me olvidaré de poblar la matriz del jefe con los enemigos jefe. Vamos a probarlo. El encuentro con el jefe se activa cuando el jugador entra a la arena. La cámara se desplaza y se bloquea en su lugar, y se muestra el indicador de salud del jefe, que rastrea la salud combinada de los tres enemigos. Si el jugador muere, es responder en el punto de control y el encuentro con el jefe se detiene hasta que el jugador re entra a la arena Cuando todos los enemigos están muertos, el indicador de salud desaparece, la cámara reanuda siguiendo al jugador y se revela la recompensa Ahora tenemos un jefe enemigo que sería apropiado para envolver un mundo de niveles en nuestro juego. En la siguiente sección, nos centraremos en los menús y la progresión. Te veré en la siguiente sección. 50. Pausa 6-1: Hola amigos. En la sección anterior, agregamos combate a nuestro juego. En esta sección, agregaremos menús y progresión si completaste la tarea, ahora todos tus enemigos tendrán comportamientos únicos. Permitirles patrullar un área de tu nivel, buscar al jugador, luego perseguirlo y atacar. También debes tener un cañón capaz de disparar una bala de cañón que explota Si completaste los desafíos, tus enemigos también pueden estar arrojando tesoros al ser derrotados. El cañón puede ser operado ya sea por el jugador o por un enemigo, y la concha también tiene un ataque de mordida En esta lección permitirá al jugador pausar el juego y abrir un menú de pausa. Comencemos abriendo la configuración del proyecto y agregando un botón de pausa al mapa de entrada. Voy a usar la llave de escape, el botón de inicio en mi pad de juego. Todo nuestro manejo de entrada está siendo procesado actualmente por el guión de los jugadores. Pero hacer una pausa en el juego no tiene nada que ver con controlar a un personaje Cualquier nodo en nuestro árbol de escenas puede anular el método de entrada. Pausar el juego debe ser responsabilidad del manager del juego En el script Game Manager, podemos agregar un método de entrada que toma un evento de entrada como parámetro. Si se presionó el botón de pausa, deberíamos pausar el juego. El método de pausa puede tomar un parámetro de bulling, lo llamaré, debería pausarse de esta manera Se puede usar para hacer una pausa si el argumento es verdadero o para hacer una pausa si el argumento es falso La pausa se ve en Godot es muy simple, solo que el valor de get tree paused, o en este caso dos, debe ser Entonces cuando se presiona el botón de pausa, podemos pasar el valor de get tree pause con un operador de nudo para cambiar su valor como argumento. Pero si hacemos una pausa en todo el árbol de escenas, incluido el administrador del juego, entonces el administrador del juego no podrá hacer nada, incluso recibir entrada y deshacer la pausa del Selección del nodo raíz de escenas. Mirando en el inspector. Bajo nodo, podemos ampliar la sección de proceso y establecer su modo de proceso para siempre, incluso cuando el juego está en pausa, el manager del juego seguirá funcionando Cualquier cosa que quieras pausar en tu juego, selecciona el nodo y establece su propiedad de modo de proceso para apilar. El valor predeterminado de inherit le dirá a todos los nodos secundarios que hereden el modo de proceso de sus nodos padres haciendo una pausa en el nodo Rogers también hará una pausa en el nodo también hará una pausa Pausar nodos de nivel hará una pausa todos los tesoros de sus enemigos y todo lo que hay en ellos. Los controles de la interfaz de usuario como botones, seguirán funcionando mientras el juego está en pausa Pero si estás usando Tweens para mostrarlos u ocultarlos, entonces deberán establecerse para procesar siempre dos. Vamos a probarlo. Cuando se presiona el botón de pausa, el juego se detiene. Cuando se vuelve a presionar el botón de pausa, se deshace, esto es funcional, pero me gustaría presentarle al reproductor un menú de pausa y algunas Podemos comenzar duplicando el juego sobre el menú y renombrándolo Menú Pausa, agarrando una referencia al Durante la fase de preparación, podemos establecer su propiedad visible al hacer una pausa o no hacer una pausa en el Rápidamente editaré el banner en la parte superior del menú de pausa para decir pausa en lugar de terminar el juego. Después cambia el botón de reintento para reanudar. Ya no quiero que el botón de reanudación llame al método de reintento presionado Voy a editar la conexión de la señal. De hecho, podemos tener esta llamada al método de pausa directamente. Pero el método de pausa toma un parámetro clic en el avanzado a objetivo para agregar argumentos de llamada adicionales. El argumento que necesitamos pasar al método de pausa es un booleano Podemos agregarlo a la lista y su valor predeterminado es false, que es exactamente lo que queremos. Al hacer clic en conectar el botón Reanudar ahora se le indicará al juego que se deshaga. Los botones de selección de nivel y salida pueden permanecer exactamente los mismos que estaban en el juego sobre el menú. Pero me gustaría agregar otra opción para reiniciar este nivel desde el principio, duplicando el botón reanudado Cambiaré este para que sea Reiniciar y editar la etiqueta del botón para que este encaje mejor en la pantalla. Con un botón extra, editaré el cuadro de estilo del panel en el editor de temas. Esta imagen en papel tiene un tamaño de 128 píxeles, pero tiene un borde vacío alrededor de 12 píxeles en todos los lados. Puedo decirle a Godot que solo use la subregión de esta imagen, configurando las coordenadas x e y iniciales, el ancho y alto de la subregión a usar Entonces tendré que ajustar los menús individuales para que las palabras aparezcan en el papel. El botón de reintento del menú de juego sobre y este botón de reinicio son muy similares en comportamiento Intentemos combinarlos en un solo método. El único cambio real que quiero hacer aquí es no restablecer la vida y las monedas del jugador Podemos renombrar esto al reintentar el método presionado para reiniciar y hacer que tome un parámetro booleano de si esto es o no un juego terminado con un valor predeterminado Luego pasa esto al método de reintento de datos de archivo, que voy a cambiar para que se llame reset El nivel se descargará, se volverá a cargar y el jugador regresará cargar y el jugador al inicio del Todo de la misma manera que antes. Pero si el jugador ha pulsado el botón de reinicio del menú de pausa, también necesitamos despausar el juego Podemos hacer esto al cargar el nivel en el script de datos. Podemos editar el método retry, renombrarlo reset, y tomando el juego sobre el parámetro booleano Ahora, solo si esto se está llamando desde un juego sobre el estado se deben restablecer las vidas y las monedas. En el menú de pausa, el botón de reinicio se puede conectar al método de reinicio. Como el parámetro tiene un valor predeterminado de false, no necesitamos especificar un argumento aquí. Pero en el menú de juego sobre, el botón de reintento se puede conectar al mismo método de reinicio Esta vez especificando true como argumento. Ahora, todos los mismos comportamientos serán utilizados por estos dos botones, con la única diferencia siendo restablecer vidas de los jugadores y las monedas si se les han quedado sin vidas. Vamos a probarlo. Ahora. Cuando el juego está en pausa, se muestra el menú de pausa y al presionar Reanudar se oculta el menú de pausa haciendo una pausa en el El botón de reinicio devolverá al jugador al inicio del nivel, restableciendo todos los componentes del nivel a sus estados originales El botón de selección de nivel aún no está haciendo nada, ya que aún no tenemos un menú de selección de nivel y el botón de salida sale del juego. Ahora podemos pausar nuestro juego y darle al jugador un menú de opciones mientras el juego está en pausa En la siguiente lección, agregaremos una pantalla de título para comenzar nuestro juego. Te veré en la siguiente lección. 51. 6-2 Title: Hola amigos. En la lección anterior, agregamos un botón de pausa y un menú de pausa a nuestro juego. En esta lección, agregaremos una escena de título y un menú principal. Empecemos por crear una nueva escena de dos D llamada title guardada en la carpeta Escenas. Podemos copiar muchos de los componentes de otras escenas para ponerlos en la escena del título. Al igual que el fondo, estableceré la propiedad de escala del nodo raíz de escenas de título en tres, haciendo coincidir el zoom de las escenas del juego. cámara luego reposiciona el fondo, llena la pantalla y toma los sprites animados de la superficie del agua de mi escena nivelada Agregar un nodo dos D para mantenerlos como un grupo. También voy a añadir en un nuevo sprite animado dos nodo D que contiene el buque mercante Relleno de cada uno con los sprites del paquete de activos. Podemos configurar sus animaciones para reproduzca de forma automática a la velocidad de fotogramas deseada Voy a poner el barco detrás del agua reordenando sus nodos, Otro para la vela y uno para Roger. Para luego agregar también un nodo sprite dos D para el ancla Añadiendo en un nodo de capa de lienzo, podemos agregar notas de control a la escena del título. Usaré una caja vertical para sostener el título y otra para sostener los botones. El cuadro de título contendrá dos cuadros horizontales, uno por cada palabra, Jolly y Roger, poblando cada uno con cinco direcciones de texto Usaré las letras grandes del paquete de activos para el título que deletrea Jolly Roger. Quiero que las letras mantengan siempre sus relaciones de aspecto. Voy a escalar ocho veces el tamaño del título, así que domina la escena Después duplique y repita para hacer la otra palabra. Voy a mover el pivote para estar en el centro del título. Luego usa anclajes personalizados para hacerlo centrado horizontalmente en la pantalla y un tercio desde la parte superior de la pantalla Por ahora, voy a tener mi pantalla de título solo tengo dos botones, Nuevo Juego y Continuar. Me gustaría que estos botones se vieran igual que los de mi otra escena. Usando el mismo tema, pero el tema que creamos es local a la escena del juego. Cambiando a la escena del juego, selecciona cualquier nodo que tenga el tema aplicado. Como el juego sobre menú. Ampliando el menú desplegable, podemos guardar el tema como un archivo de recursos, haciéndolo disponible para todo el proyecto. Lo guardaré en la carpeta raíz, nombrándolo madera y papel en la escena del título, seleccionando el nodo de control de botones El tema del papel de madera ya está disponible en el menú de carga rápida y sus hijos heredan el tema Escalaré los botones cuatro veces y los volveré a colocar en la esquina inferior izquierda Luego rellenaré cada botón con cajas horizontales llenas de textura Recs para deletrear sus etiquetas, manteniendo la relación de aspecto de las letras espaciando cada letra dos píxeles Y dar a los botones un tamaño mínimo para que se ajusten a su contenido. Reiniciando el tamaño de la etiqueta, anclaré al centro del botón, luego la duplicaré para hacer la etiqueta continua Reiniciando su ancla. Voy a hacer los botones un poco más grandes y reposicionarlos. Voy a tener el botón de continuar desactivado por defecto ya que no tendría sentido permitir que el jugador lo presione. Si aún no hay un archivo say, también podemos arrastrar y soltar el fade, ya que lo guardamos como su escena de zona. Veamos cómo se ve bien en el script del archivo. Agreguemos un nuevo método para verificar si existe el archivo seguro. Regresando un toro. Por ahora sólo puede devolver falso. Al igual que el nodo raíz de escenas del juego tiene un script de administrador de juegos. Esta escena de título también necesitará un guión de administrador de títulos. Este guión comenzará haciendo visible el fade. Voy a tomar una referencia al botón de continuar usando en on ready. Luego pregunte al archivo auto load si existe un archivo say para cargarse. Si existe un archivo say, entonces deberíamos establecer la propiedad disabled del botón continuada en false, permitiendo que el reproductor lo presione. Entonces dile al fade que se desvanezca para comenzar el juego. Conectando las señales de botón presionado al administrador de títulos. Podemos agregar métodos para manejar ambos botones. Si el jugador presiona el botón de nuevo juego, le diré al archivo de carga automática para crear un nuevo recurso de datos. Después de aguardar fade, fade to black, cargaré la escena del juego, que cargará el primer nivel de mi juego usando get tree change scene to file, que toma un argumento string representa la ruta del archivo a la escena que queremos cargar. Explorando el sistema de archivos, podemos encontrar la escena del juego click derecho y copiar su ruta. Después pégalo entre comillas. Si presionan el botón continuar, le diré al archivo que se cargue. Para cargar el recurso de datos. Entonces me gustaría desvanecerme a negro y cambiar de escena igual que el nuevo botón de juego, pero cargar la escena de selección de nivel en su lugar. Hagamos el cambio de escenas en un método separado. Cambiar escena, tomando un parámetro de cadena de la ruta del archivo de escenas. Entonces tanto las pulsaciones de botón de juego nuevo como de continuar pueden llamar al cambio de escena, pero cambiar a diferentes escenas. estas alturas probablemente hayas pulsado el botón Ejecutar proyecto por accidente en lugar del botón Ejecutar escena actual al menos una vez y se te haya pedido que establezca una escena predeterminada para tu proyecto. Si aún no has establecido una escena principal, puedes hacer clic en Seleccionar Actual para establecer esta escena del título como escena principal. Alternativamente, puede abrir la configuración del proyecto y buscar debajo la sección de la aplicación y configurar la escena principal aquí usando el navegador de archivos. Si miramos bajo Entorno de renderizado, podemos cambiar el color predeterminado que se muestra cuando Cade no tiene nada más que renderizar, configurándolo en negro para cubrir cualquier hueco entre el desvanecimiento y el desvanecimiento Ahora bien, si presionamos el botón Ejecutar proyecto, la escena del título se desvanece de negro Como no existe ningún archivo say, El botón de continuación permanece deshabilitado, pero podemos hacer clic en el botón de nuevo juego. Esto se desvanece a negro y carga el primer nivel, permitiendo que el jugador comience a jugar un nuevo juego Nuestro juego ahora tiene una escena de título que accede a la escena predeterminada para nuestro proyecto. En la siguiente lección, agregaremos en la escena de selección de niveles. Te veré en la siguiente lección. 52. Selección de niveles 6-3: Hola amigos. En la lección anterior, agregamos una pantalla de título y un menú principal a nuestro juego. En esta lección, agregaremos una escena de selección de niveles. He seguido adelante y he creado una escena básica, muy parecida a la escena del título con solo un fondo de sprites animados de Roger y el timón del barco, una capa de lienzo y el fade Como hicimos con el recurso temático, podemos abrir cualquier nivel, seleccionar el nodo de mapa de mosaico y guardar el conjunto de mosaicos como recurso para que pueda ser compartido por todo el proyecto. En la escena de selección de nivel, agregaré un nodo de mapa de mosaico y lo cargaré con el recurso de conjunto de mosaicos. Luego usa el mapa de azulejos para dibujar la cubierta de popa de un barco con Roger al timón. implica al jugador que entre cada nivel, Roger está navegando su barco entre islas Veamos cómo se ve esto hasta el momento. Agradable para mostrar los niveles. Voy a agregar un contenedor de panel al lienzo. Escalarlo para que coincida con todo lo demás, y establezca su tema en madera y papel. Este contenedor contendrá una caja vertical, cual contendrá una caja horizontal para el título. Pondré cuatro Ts de textura en el cuadro horizontal para deletrear los mapas de palabras, asegurándome de que conserven sus relaciones de aspecto y permanezcan centrados. También centraré el título en su conjunto y reduciré la separación entre letras. Debajo del título, agregaré un contenedor de cuadrícula. Esto funciona de manera muy parecida a una caja vertical u horizontal, pero organiza su contenido en una simple cuadrícula. Dado que los mapas son cada uno de un cuarto, voy a hacer que sea una cuadrícula de dos por dos columnas configurando a dos. Cada celda de cuadrícula contendrá otra caja vertical que contiene un botón y un panel, cuyo tema se ha configurado para que parezca papel. Voy a establecer su tamaño mínimo en 36 por 32 píxeles, así que es lo suficientemente grande como para contener el nombre del nivel. Usando otro cuadro horizontal para escribir un guión, uno, me aseguraré de que la etiqueta esté anclada al centro del papel Siéntete libre de nombrar tus niveles lo que quieras para los botones. No quiero usar el botón verde. Puedo eliminarlo haciendo clic en el toggle plano. En lugar de usar estos botones verdes y amarillos, estableceré la propiedad del icono de botones para que sea el mapa pequeño, una textura. Me aseguraré de que el botón permanezca centrado dentro de su celda de cuadrícula. Bajo tema anula la ampliación de la sección de estilo. También estableceré el estilo de enfoque para que sea una caja de estilo vacía para que el botón permanezca invisible. Duplicaré el nivel 113 veces para hacer los otros botones de la cuadrícula, Cambiando las etiquetas de nombre de cada una para que coincidan con los niveles. Puedes diseñar esta interfaz para que luzca como quieras, acomodando por muchos mundos los niveles que quieras tener en tu juego. Pero esto es suficiente por ahora configurar el pivote de los contenedores del panel para que quede en su centro. Voy a anclarlo para que sea dos tercios del lado izquierdo de la pantalla y uno, dos desde arriba. Y cambia los iconos de los botones para que coincidan con los diferentes segmentos del mapa. Para que estos iconos de botón se animen, podemos seleccionar una nueva textura animada en el menú desplegable. Como hay ocho imágenes en la animación de mapa pequeño, agregaré ocho fotogramas a esta textura animada, luego configuraré cada fotograma en consecuencia. Los valores predeterminados indican a esta animación que reproduzca un fotograma por segundo. Podemos cambiar las longitudes de fotogramas individuales a 0.1 segundos o establecer la escala de velocidad general de toda la textura en diez. El botón no está renderizando, así que voy a cambiar una propiedad para obligarla a actualizarla. Repitiendo este proceso, configuraré cada uno de los cuatro segmentos del mapa para que sean texturas animadas para los respectivos iconos de botón. Eliminaré el exceso de espacio en la parte inferior del contenedor del panel restableciendo su tamaño y le daré al título más espacio con un tamaño mínimo personalizado Crear un nuevo script para el gestor de selección de nivel. Primero voy a tomar una referencia al fade usando at on. Listo. Durante listo, configuraré el fade para que sea visible, luego le diré que se desvanezca para despejar. Escribiré un método personalizado para conectar los botones a En el nivel seleccionado, que tomará el mundo y el nivel como parámetros, ambos representados por enteros Conecte la señal de botón presionado desde el botón de nivel uno al administrador de selección de nivel y elija este nuevo método. Luego expandiendo avanzado, podemos agregar dos argumentos enteros a la conexión de señal, el mundo y el nivel, ambos con un valor de uno. Establecer los valores de los datos de punto de archivo, mundo de puntos y nivel para que sean sus nuevos valores. Entonces podemos esperar, desvanecerse a negro, y cargar la escena del juego. La escena del juego manejará automáticamente la carga del nivel correcto en función de los datos del archivo. Recuerda que para un nivel se cargue usando este método, debe estar en la carpeta de escenas de nivel y nombrado usando el formato correcto para ser detectado. Entonces podemos conectar el resto de botones al mismo método, cambiando los valores de los argumentos para que coincidan con el mundo y el nivel que se cargará, asegurándonos de que el destino se dibuje sobre todo lo demás. Al posicionarlo en la parte inferior de la lista de nodos, voy a reducir la separación de las cajas verticales para que ocupen menos espacio. Después restablece el tamaño y la posición del menú por última vez. Vamos a probarlo ejecutando la escena actual. Después de que la escena se desvanece, hacer clic en el nivel uno, un botón se desvanece y carga el primer Si lo hacemos de nuevo, al hacer clic en un botón diferente se cargará un nivel diferente. Nuestro juego ahora tiene una escena de selección de niveles, lo que permite al jugador cargar cualquier nivel en nuestro juego. En la siguiente lección, permitiremos que el juego guarde y cargue los datos del jugador. Te veré en la siguiente lección. 53. 6-4 Guardado: Hola amigos. En la lección anterior, agregamos una escena de selección de niveles que puede cargar cualquier nivel en nuestro juego. En esta lección, haremos que los datos de progresión de los jugadores guarden y carguen en el script del archivo, ya configuramos muchos de los métodos que necesitaremos completar para esta lección. En otros motores y cuando se trata del ahorro de consolas, carga es algo difícil de aprender. Pero para los propósitos de nuestro juego, el Godot Engine proporciona formas sencillas de lograr exactamente lo que necesitamos Primero, necesitamos saber dónde almacenar el archivo. Vamos a declarar una variable llamada path de tipo string. Comenzando la ruta con el usuario colon Godot encontrará automáticamente el lugar apropiado para almacenar nuestro archivo say, En la mayoría de las plataformas podemos darle un nombre al archivo. Vamos a llamarlo guardado automático. La extensión de nuestro recurso de texto es RS. Dado que este es un valor que nunca se debe cambiar, declararé la constante en lugar de una variable. Esta es una forma más eficiente de almacenar valores que sabes que no cambiarán. A diferencia de las variables que están diseñadas para cambiar, el propósito principal es reutilizar el mismo valor en múltiples lugares a lo largo de su guión sin reescribirlo cada vez La T significa texto, lo que significa que el archivo que se crea se puede abrir, leer e incluso editar en cualquier editor de texto que no sea muy seguro. Pero el cifrado es muy ineficaz y generalmente no vale la pena el esfuerzo extra sin importar cuántas medidas tomes. Si alguien quiere hacer trampa, lo hará. Solo recomendaría molestarse con la seguridad para los juegos multijugador en línea Para verificar si este archivo existe, todo lo que necesitamos hacer es llamar al método exists del cargador de recursos pasando en el argumento de cadena path. Para guardar el juego, solo necesitamos llamar al método save del ahorrador de recursos pasando los datos a guardar y la ruta para su ubicación. Cada vez que llamamos guardar, sobrescribirá los datos de guardado existentes De igual manera, la carga solo necesita establecer el valor de los datos para que sea carga del cargador de recursos, dándole la misma ruta al archivo. Esta es una implementación simple de un solo archivo autoguardado Podrías vincular fácilmente los comandos de guardar y cargar a los botones del menú. E incluso crear múltiples archivos say usando el mismo proceso. El administrador de títulos ya está configurado para cargar los datos de los jugadores cuando se presiona el botón de continuar. La pregunta es, ¿cuándo debemos guardarlo? Podemos comenzar guardando los datos al mismo tiempo que se crean. Ten en cuenta que este sistema de guardado automático solo almacena un, digamos, archivo Al iniciar un nuevo juego se sobrescribirá cualquier archivo seguro existente Entonces, cuando se presiona el nuevo botón de juego, si no existe un archivo seguro existente, podemos llamar a un nuevo método para iniciar un nuevo juego, crear el nuevo archivo guardado, guardarlo y hacer la transición a la escena del juego Si existe un archivo say, deberíamos pedirle consentimiento al jugador antes de sobrescribir su archivo say existente Rápidamente armaré un contenedor básico con la pregunta sobrescribir, guardar archivo y dos botones para sí y no Y set is visible property defaults by default, agarrando una referencia a la confirmación usando add on ready Lo haré visible cuando el jugador presione el nuevo botón de juego, pero ya existe un archivo seguro. Después conecta las pulsaciones de botón sí y no al guión. Todo lo que N tiene que hacer es ocultar esta confirmación mientras que sí comenzaremos un nuevo juego. Por el formato de mi juego, realmente no me importa lo que suceda durante un nivel en particular. Para poder seguir la progresión del jugador a través de mi juego, solo necesito saber cuándo completan o salen de un nivel. Para que las cosas sean simples, puedo guardar automáticamente el juego cada vez que el jugador entre en la escena de selección de niveles. En el guión del gestor de juegos, tenemos algunos botones en el menú de pausa que aún no funcionan. Agreguemos las transiciones del menú de pausa del juego a la escena de selección de niveles. Cuando presionan exit, regresan a la escena del título. Se accede a estos métodos desde el menú de pausa. El árbol de escenas se detiene cuando ocurren estas transiciones, cuando se carga una nueva escena, el árbol permanece en pausa Tendremos que poner en pausa el árbol de escenas cuando las otras escenas se carguen usando los métodos listos de su manager Dado que el menú de pausa ahora solo regresa a la escena del título, la escena del título debe tener un botón de salida para cerrar el juego. Voy a poner eso en la esquina superior derecha. Conecta su señal presionada al script manager y haz que esperes fade to black antes de llamar Get copy the exit button node, podemos pegarlo en la escena de selección de nivel y editar su señal para conectarlo al script manager de selección de nivel. Y que esperen desvanecerse a negro antes de cambiar a la escena del título. Vamos a probarlo. Después de recoger una moneda, puedo salir del nivel Volviendo a la escena de selección de nivel, donde el progreso se ha guardado automáticamente, cerrando el juego y ejecutándolo nuevamente. El botón de continuación está habilitado porque el archivo de guardado existe para cargarse. Al presionar continuar nos lleva a la escena de selección de niveles, cargando cualquier nivel. Podemos ver que el contador de monedas se guardó y cargó entre sesiones, cerrando el juego y ejecutándolo de nuevo. Podemos intentar sobrescribir el archivo guardado y que se nos presente una confirmación antes de comenzar un nuevo juego con cero monedas Nuestro juego ahora guarda y carga los datos del jugador cada vez que el jugador sale o completa un nivel. En la siguiente lección, bloquearemos el acceso a los niveles y los desbloquearemos cuando el jugador complete un nivel. Te veré en la siguiente lección. 54. Desbloqueo 6-5: Hola amigos. En la lección anterior guardamos y cargamos la progresión del jugador. En esta lección bloquearemos acceso a niveles hasta que el jugador complete el nivel anterior para desbloquearlo en nuestro recurso de datos, vamos a querer rastrear información sobre cada nivel en nuestro juego, los cuales están organizados en mundos. Podemos declarar una variable llamada Progress como una matriz de mundos que contienen una matriz de niveles, una matriz bidimensional, una navaja vacía. Por defecto, necesitaremos inicializarlo para que sea el tamaño correcto para nuestras necesidades y llenarlo con valores iniciales Necesitaremos una matriz para cada mundo y un valor para cada nivel en cada mundo. Si tuviera dos mundos, la matriz se vería así, pero solo tengo uno. Voy a quitar la segunda submatriz. Queremos que se desbloquee el primer nivel del juego. Por defecto, cambiaré el valor 0-1 dependiendo de cuántos marcadores de progreso diferentes quieras realizar un seguimiento por nivel Recordar sus códigos numéricos puede ser problemático. Podemos definir una enumeración para describir los diferentes marcadores de progreso, comenzando con el nivel bloqueado, luego desbloqueado, luego completado Después inicializar el primer nivel para que se desbloquee el progreso. Agregar en un método público para establecer un marcador de progreso. Podemos tomar el marcador de progreso como parámetro junto con un ID de mundo y un ID de nivel. Después establece el valor de progreso indexado en mundo menos uno, nivel menos uno Dado que las matrices comienzan en cero, pero nuestros números mundiales y de nivel comienzan en uno usando el operador R iguala con el marcador de progreso, pero nuestros números mundiales y de nivel comienzan en uno usando el operador R iguala con el marcador de progreso, dándoles un valor predeterminado. Suponiendo que la mayoría de los marcadores de progreso se establecerán para el nivel que el jugador esté jugando actualmente. Pero aún así permitiéndonos establecer marcadores para otros niveles si queremos. Dado que estos números se están utilizando para indexar array, debemos validarlos para evitar bloqueos. Para que estos números se consideren índices de matriz válidos, deben ser mayores que cero y menores que son iguales al tamaño de la matriz. Ya que estamos restando uno de estos números. Si los índices de matriz no son válidos, deberíamos regresar. Pero también podemos emitir un mensaje para decirnos a nosotros o a cualquier otro desarrollador sobre este error, con una advertencia que indica que el índice de marcador de progreso no era válido y mostrar el mundo de los ID de nivel que se utilizaron. Esta es una operación de bit, es decir, que no está tratando este número como un entero, sino como una serie de bits, unos y ceros Si consideramos que cada bit es un marcador de progreso, entonces el primer marcador de progreso, el primer bit, bloquea el nivel, si es cero, y desbloquea el nivel si es uno El siguiente bit nos dice si el nivel se ha completado, comenzando con cero, es decir, que no se ha completado, pero luego cambiando a uno para quedar terminado. Si el nivel comienza con un valor de 0000, desbloquearlo se convierte en 0001, luego marcarlo como completo lo hará 0011 Dado que está desbloqueado y completado, podemos cambiar bits individuales usando operadores de bits, lo que nos permite codificar una gran cantidad de información en una sola variable. Este u operador establecerá el valor del bit marcado por el marcador de progreso en uno. También podemos establecer el bit a cero usando e igual con el marcador de progreso invertido con el operador agregando un parámetro adicional a la definición del método. Podemos activar o desactivar el marcador de progreso. Tendré el comportamiento predeterminado para establecer el bit en uno o encendido, ya que no planeo bloquear nunca nada que haya sido desbloqueado por el jugador en mi juego. Dado que una sola variable contiene 32 bits, podemos rastrear hasta 32 bits diferentes de información por nivel. De esta manera, agregando marcadores de progreso a la enumeración. Una enumeración es solo una lista numerada. La entrada en la parte superior de la lista tiene un valor predeterminado de cero. El siguiente, después 234, etcétera. Podemos cambiar estas asignaciones numéricas si queremos, Dando bloqueado un valor de cero, desbloqueado uno y completado dos. Pero también quiero rastrear si el jugador abre un cofre del tesoro en mis niveles. El siguiente marcador de progreso, en lugar de ser tres, será cuatro. Podríamos tener hasta 32 valores diferentes en esta enumeración, duplicando cada vez el valor a ocho, 16, etcétera, Si uno en binario es 0012, es 0104, es 100 Cada marcador de progreso será todo ceros, con solo un bit teniendo un valor de uno, que es el bit que se establecerá o desestablecerá por el método set progress marker Deberíamos eliminar bloqueado es igual a cero, ya que la forma correcta de bloquear un nivel sería establecer el marcador de progreso desbloqueado en off. También tendremos que verificar los valores de nuestros marcadores de progreso, aceptando el marcador de progreso, el mundo y los números de identificación de nivel. Igual que el método set, pero devolviendo un booleano, podemos devolver el valor de progreso indexado por el mundo en números de ID de nivel menos uno Después aplique el operador de extremo de bit con el marcador de progreso. También debemos validar que los índices de matriz son válidos antes de usarlos, igual que anteriormente, y aclarar el mensaje de advertencia para que sea más útil. Esto devolverá true si el marcador de progreso está encendido o falso si está desactivado, o si los índices no fueron válidos en la escena de selección de nivel. Podemos controlar fácilmente a qué nivel tiene acceso el jugador al cambiar la visibilidad de los botones de nivel, el contenedor de cuadrícula ordenará automáticamente los contenidos visibles En el script Level Select Manager, podemos obtener una matriz de los contenedores de cuadrícula hijos usando add on ready declarando una nueva variable entera como índice en la matriz de botones de nivel Luego iterando a través de los mundos en la matriz de progreso. Nuevamente, a través de los niveles en cada mundo. Podemos establecer la propiedad visible de cada botón en el contenedor de cuadrícula para que coincida con si ese nivel ha sido desbloqueado o no. Tendremos que agregar uno al mundo y nivel para obtener los números de identificación adecuados de sus índices de matriz e incrementar el índice de botón cada vez En el script de nivel, podemos exportar variables para saber qué nivel se desbloquea completando este nivel y establecer sus valores predeterminados en uno. El comportamiento predeterminado será desbloquear el primer nivel, esencialmente logrando nada más que no causar ningún error Después en el guión del manager del juego, cuando se recoge el mapa, podemos establecer el marcador de progreso del nivel actual como completado. Y también establecer el marcador de progreso desbloqueado del nivel que se va a desbloquear al completar este nivel. Después la transición a la escena de selección de nivel en el primer nivel. Voy a establecer sus valores exportados para desbloquear el segundo nivel. De vuelta en el guión de nivel, podemos rastrear si el jugador ha abierto el cofre, obteniendo una referencia a la llave y cofre si existen. Usando en el nodo listo obtener o nulo. Entonces cuando se cargue por primera vez el nivel , si sí existen y el jugador ha abierto el cofre para este nivel, entonces podremos quitar la llave y decirle al cofre que ya se ha abierto en el guión del cofre. Agreguemos un método público para que ya esté abierto, limpiando la matriz de botín. Entonces la configuración se bloquea a false y se abre a true cuando se saquea el cofre, Establece el marcador de progreso para este nivel que se abrió el cofre Vamos a probarlo. Comenzando un nuevo juego, puedo salir del primer nivel a la escena de selección de nivel, y solo se desbloquea el primer nivel. Volviendo al primer nivel, puedo terminarlo y volveré a la escena de selección de nivel, donde se ha desbloqueado el segundo nivel. Volviendo nuevamente al primer nivel. Esta vez abriré el cofre y volveré a la escena de selección de niveles. Entrando al primer nivel una última vez para ver que la llave no está ahí y el cofre ya está abierto. Ahora tenemos la progresión de los jugadores a través del juego siendo rastreados por el, digamos, archivo, desbloqueando el acceso a nuevos niveles a medida que avanzan En la siguiente lección, agregaremos música de fondo a nuestro juego. Te veré en la siguiente lección. 55. Música 6-6: Hola amigos. En la lección anterior, bloqueamos el acceso a niveles hasta que el nivel anterior había sido completado por el jugador. En esta lección, agregaremos música de fondo. Comencemos en la escena del título y agreguemos un nodo reproductor de flujo de audio a la escena. Podríamos establecer una pista de audio aquí, decirle que se reproduzca de forma automática y establecer el volumen Entonces haz esto para cada escena en nivel. Pero las transiciones de escena cortarían duramente nuestras pistas de música y sonarían bastante discortantes como resultado, igual que tenemos la pantalla desvaneciéndose a negro, música en transición también debería desvanecerse para brindar una mejor Voy a dejar la reproducción automática encendida por ahora y el volumen a lo más bajo irá. Básicamente silenciado. La mayoría de los desarrolladores de juegos que no son también ingenieros de sonido tenderán a pensar en el volumen como un flotador, 0-1 con cero silenciado y uno siendo el volumen completo Pero el volumen en realidad se mide en decibelios, que no escalan La duplicación de decibelios no duplica el volumen. La escala de volumen aquí oscila entre 80 y 24 decibelios negativos Afortunadamente, no necesitamos saber cómo funciona esto para poder usarlo de manera efectiva. Adjuntemos un nuevo guión a este nodo musical. Cuando comience el juego por primera vez, el audio va a reproducir de forma automática la pista con el volumen silenciado Podemos comenzar desvaneciendo suavemente el volumen desde cero hasta el nivel deseado, declarando una variable para almacenar el volumen deseado En términos más simples que son más fáciles de entender, un flotador 0-1 con escalado lineal, la propiedad de volumen de nodos reproductor de flujo de audio se denomina volumen DB para decibelios Entonces podemos declarar otra nueva variable, volumen L, para lineal, para representar el volumen actual en una escala lineal y darle un valor predeterminado de cero o silenciado En el método ready, podemos asegurar que el volumen permanezca silenciado ajustando el volumen de decibelios para que coincida con el volumen lineal Convertirlo con una fórmula de conversión conveniente proporcionada por Gade lineal a decibelios, dándole el volumen lineal como argumento Definir un método privado para desvanecer el volumen. Podemos tomar como parámetro el volumen lineal objetivo. Junto con la duración del efecto destino, con el valor por defecto de 1 segundo. Si bien el volumen lineal no es igual al volumen lineal objetivo, debemos mover el volumen lineal hacia el volumen lineal objetivo en una pequeña cantidad. Para ello, podemos obtener el tiempo delta del proceso y dividirlo por la duración. Luego establece los indecibelios de volumen para que coincidan con el volumen lineal y espera el siguiente fotograma de proceso para hacerlo Cuando todo esto esté hecho, podemos emitir la señal para que cualquiera que lo esté escuchando sepa que el destino del volumen está terminado. La forma en que se escribe este código, es obvio que el valor de duración está destinado a ser un número positivo. Para evitar posibles errores o bucles infinitos, debemos verificar si el valor de duración es algo menor o igual a cero. En ese caso, podemos establecer el volumen, omitir inmediatamente la señal, y regresar Dado que la música probablemente se incluirá en cada escena del juego, sería más fácil convertir esto en un script de carga automática. Mover el script a la carpeta de carga automática. Abrir la pestaña de carga automática de la configuración del proyecto. Podemos agregar esto a la lista de nodos autocargados. Después borra el nodo reproductor de flujo de audio de nuestra escena del título. Para que cualquier gestor de escenas pueda controlar la música de fondo con una sola línea de código, todo lo que tenemos que hacer es definir dos métodos públicos, uno para iniciar una pista y otro para detenerla. Comenzando con stop track, tomaremos un tiempo de desvanecimiento como parámetro, un float, con un valor predeterminado de 1 segundo. Esto puede simplemente llamar fade. El volumen lineal objetivo es cero, silenciado, pasando el tiempo de desvanecimiento es el argumento para la duración Después aguarda el volumen Fade finished signal antes de detener el flujo de audio. Jugador nodo para reproducir una pista, podemos tomar la pista en cuestión como un parámetro junto con el tiempo de desvanecimiento. Establezca la transmisión que se está reproduciendo en esta nueva pista, dígale que reproduzca y luego desvanezca el volumen al volumen deseado para la duración del tiempo de desvanecimiento. Pero, ¿y si ya se está reproduciendo una pista? Podemos agregar un par de cheques extra. Primero para verificar si la música ya se está reproduciendo, luego también verificar si la pista que se está reproduciendo actualmente es la misma que la pista que queremos reproducir. Si este es el caso, no necesitamos hacer nada en absoluto y podemos regresar. También podemos aprovechar esta oportunidad para ignorar pistas nulas. De lo contrario, el nodo de música está reproduciendo actualmente una pista diferente. Deberíamos desvanecer esa pista antes de desvanecernos en la nueva Llamando a fade con un volumen lineal objetivo de cero y esperando la señal de desvanecimiento de volumen terminada, entonces el resto del método puede trabajar el mismo desvanecimiento en la nueva pista, evitando cortes duros en cada uno de los scripts del administrador de escena Podemos exportar una variable para mantener la pista de música de fondo para esa escena. Entonces en el método listo antes de desvanecerse para despejar, podemos decirle a la música que reproduzca la pista de música Yo pueblo esta variable con una pista de música de mi escena de selección de nivel de activos importados También exportaré una variable para la música de fondo y reproduciré la pista durante el método de escritura. Usaré la misma música de fondo que la escena del título para la escena de selección de nivel en el guión del administrador del juego. Al cargar un nivel, solicitaré la pista de música desde el nivel. De esta manera cada nivel puede establecer su propia música de fondo en el guión de nivel, exportando una variable de música y configurando una pista diferente de las otras escenas. Y agregaré pistas de música a mis otros niveles también. Por último, también agregaré música al guión de encuentro con jefes, pero también declararé una segunda variable para almacenar la pista que se estaba reproduciendo desde el nivel cuando comienza el encuentro con jefes. Puedo almacenar los niveles de música de fondo normal en la segunda variable, luego tocar al jefe. Música Cuando termine el encuentro con el jefe, volveré a tocar el nivel normal Música Poblar el encuentro con el jefe fue algo más intenso que el nivel normal Música Al salir del juego, también podemos desvanecer la música de fondo también. hora de importar música de fondo, es importante que esté diseñada para estar bucle dependiendo de dónde obtengas tu música bucle puede estar codificado en los propios archivos y ya ser capaz de bucle para estos archivos Necesito abrir la configuración de importación y establecer su modo de bucle para reenviar. Después haz clic en Re Importar, para que hagan un bucle. Vamos a probarlo. La pantalla de título se desvanece con alguna prensa musical temática pirata y continúa La música sigue sonando a través de la transición de escena ya que la pista de música es la misma para ambas escenas. Al entrar al nivel de jefe, la música se desvanece y se desvanece con una nueva pista entrando a la arena de jefes Los niveles predeterminados de música de fondo se reemplazan por una pista de música más intensa. Cuando el jefe es derrotado, la música vuelve a la normalidad. Al regresar a la escena de selección de nivel, vuelve a cambiar la música y salir del juego desvanece la música antes de cerrar la ventana Nuestro juego ahora reproduce música de fondo única para cada escena y nivel, incluso permitiendo que las pistas se cambien temporalmente. En la siguiente lección, exportaremos el juego para ser jugado y probado. Te veré en la siguiente lección. 56. Exportación: Hola amigos. En la lección anterior, agregamos música de fondo a nuestro juego. En esta lección, exportaremos el juego para distribuirlo y probaremos el juego. Antes de poder exportar Godot tendremos que descargar las plantillas de exportación desde el menú del editor Seleccione Administrar plantillas de exportación. Seleccione un espejo en el menú desplegable y, a continuación, haga clic en Descargar e instalar. Estas plantillas permiten exportar su proyecto Godot a una amplia variedad de formatos para su distribución Una vez completado el proceso, puede cerrar el gestor de plantillas de exportación. En la configuración del proyecto, ya le hemos dado un nombre a nuestro proyecto. También es posible que desee agregar una descripción, un número de versión y un icono para obtener los mejores resultados. Intenta usar una imagen que sea de 256 por 256 píxeles, o al menos que tenga dimensiones cuadradas. Ya fijamos la primera escena para correr. Si trabajas para un estudio o un editor, también puedes agregar una imagen aquí para eso. Es posible que desee realizar ajustes la configuración de visualización para que se ajuste mejor al proyecto exportado, como por defecto a pantalla completa en lugar de ventana Si cambias alguna configuración de pantalla, asegúrate de probar el juego para asegurarte de que tu juego se muestra correctamente antes de exportar. Para cambiar el icono del juego al exportar para Windows, necesitarás descargar un ejecutable de edición RC desde Github. Te recomiendo poner este archivo en la carpeta Gio Projects, ya que probablemente necesitarás usarlo en la mayoría, si no en todos, de tus proyectos. En el menú del editor, abre la configuración del Editor bajo exportar Windows, hay una opción para agregar la ruta a la configuración del ejecutable de edición RC que Cado ahora podrá editar iconos para proyectos de Windows exportados si tienes un certificado de firma de paquetes, esta también es la ubicación para proporcionar esa información también. Con todos los ajustes configurados, ahora podemos ir al Menú Proyecto y hacer clic en Exportar. Da clic en el botón Anuncio y selecciona la plataforma a la que quieres exportar tu proyecto. Dos, elegiré Web First. Aquí no necesitamos hacer mucho para ajustar la configuración. Explorando la ruta de exportación. Deberíamos crear una nueva carpeta llamada Exportar, o compilaciones, si lo prefieres. Después dentro de esa carpeta, cree una nueva carpeta para cada plataforma. En este caso, Web. Lo más importante a la hora de exportar a Web es que el proyecto debe denominarse índice HTML. Este es el nombre de archivo que las plataformas web buscarán al incrustar tu juego Si no está ahí, no va a funcionar. Al hacer clic en Exportar proyecto, desmarque la casilla de verificación Exportar con depuración para eliminar cosas como mensajes de advertencia Luego haz clic en Guardar. Cuando esté hecho, podemos cerrar la ventana. Una vez que el proyecto haya sido exportado, encuéntrelo en su navegador de archivos. Seleccione todos los archivos que fueron creados por Godot y comprimirlos en un archivo zip llamado index zip Este es el archivo que cargarás para incrustar tu juego en plataformas de alojamiento web como Itch en las opciones de inserción de estas plataformas, soporte de búfer de matriz compartida se requiera soporte de búfer de matriz compartida para que el juego se ejecute. Esta es una de las formas más fáciles distribuir compilaciones tempranas de tus juegos. Plataformas como esta también te permiten vender tus juegos también. Pero, ¿y si tu juego es realmente bueno y quieres venderlo profesionalmente en plataformas como Steam? De vuelta en la ventana de exportación del proyecto, podemos agregar otra plataforma, esta vez, Windows. Aquí es posible que desee ajustar algunos de los ajustes, como configurar cómo se cambia el tamaño del icono del juego en un juego de pixel art La escala usando vecino más cercano mantendrá la pixelización Es posible que desee agregar también el nombre de su empresa si tiene un nombre y una descripción. Copyrighter, marcas comerciales, etcétera. Exportaremos esto a una carpeta separada de la exportación web, haciendo una nueva carpeta para Windows y renombrando el ejecutable para que coincida con el nombre del juego Si está distribuyendo esto internamente para pruebas alfa, es posible que desee exportar una compilación de depuración para pruebas beta, acceso anticipado o compilaciones de lanzamiento. Querrás tener la depuración desactivada también bajo la configuración de depuración, eliminando el envoltorio de la consola. Después exporta el proyecto y ahorra. Una vez completado el proceso de exportación, podrás encontrar los archivos exportados creados por Godot y tu Explorador de Archivos, Seleccionar los archivos, comprimirlos en un archivo zip, y subir el zip comprimido a las plataformas de distribución para ser descargados El mismo proceso se puede usar para construir también en plataformas Mac, Linux, IOS y Android. Las plantillas de exportación para otras plataformas como Nintendo o Playstation no se proporcionan por defecto. Debes ser aprobado por la plataforma antes de que te permitan usar su SDK para construir juegos. Nuestro juego ahora es exportado y subido a sitios de distribución como It o Steam para ser jugado por cualquiera. Ahora tienes todas las habilidades necesarias para construir una plataforma y un juego de píxeles completos. Puedes construir más niveles, modificar y ajustar las cosas a tu gusto, e implementar más activos a partir de este paquete de activos También puedes descargar otros paquetes de activos o crear tus propios activos para seguir agregando nuevo contenido. Todo en este proyecto se estructura manera que se edite de manera aislada. Puedes modificar sus escenas y guiones individuales si así lo deseas. Cada implementación es solo una plantilla básica sobre la que puedes construir o recrear la tuya desde cero e integrarla en el juego Alterar cualquier cosa, desde cómo se comporta la cámara hasta cómo se administran los archivos de guardado, debería ser fácil de cambiar Gracias a la estructura que hemos construido, sigue adelante y construye tu juego de la manera que quieras para que sea tuyo. Después compártelo con la clase ya sea subiendo el proyecto o compartiendo un enlace a tu página de Ch Juega los proyectos presentados de tus compañeros y deja comentarios constructivos sobre su trabajo. Gracias por completar el curso y asegúrese de revisar mis otros cursos para continuar aprendiendo.