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.