Transcripciones
1. Introducción: Bienvenidos a mi curso
introductorio sobre
desarrollo de juegos de tres D y Gada. En este curso,
cubriremos todo lo que necesitas saber sobre
el uso del motor Gudo para construir un controlador de
personajes en tercera persona desde lo básico
de trabajar en tres espacios D
hasta e incluyendo controlar un personaje y una
cámara en una escena de tres D. Exploraremos cómo
usar las matemáticas, la física y los vectores para lograr
la
jugabilidad en tercera persona que esperas de la
mayoría de los juegos modernos de tres D, con el stick izquierdo
moviendo y girando al personaje y
el stick derecho girando la cámara alrededor de ellos. Cuando termines,
tendrás una buena comprensión del control de
personajes en tercera persona y una
implementación completamente funcional que es altamente personalizable para
cualquier proyecto de tres D, ya sea una plataforma
o acción o PG, o incluso un acogedor sim de granja. Puedes llevar el proyecto
en cualquier dirección que desees. También aprenderás habilidades útiles para trabajar en el motor de juego
Gada, organizando y diseñando tus proyectos para que
sean más escalables. Estarás
aprendiendo a codificar en script
GD con todo lo
explicado en detalle Nuestros guiones
serán escritos para ser altamente personalizables
y reutilizables. Todos los archivos del proyecto también
estarán disponibles en GT Hub si necesita
revisar el proyecto terminado. Estos videos fueron grabados
usando la versión 4.2 de Gada. Activos descargados de
HO hechos por Kusberg.
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 esto Hola. Los scripts tienen la
extensión de archivo punto gD. 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 calculáramos 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 dividir 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, que sabemos que no
es correcto. Dado que hay un total de siete ocupantes en
dos casas ocupadas, el promedio debe 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 Solo 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. 0-11 diccionarios: 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
uno de los casilleros, 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 guardar 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 Depuración: 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. Fundamentos: Hola, amigos. Nuestro objetivo para la primera sección
de este curso es crear un
personaje de tres D que el jugador pueda controlar en perspectiva en tercera
persona. Nuestra primera lección
será configurar una escena básica de tres D
y un nuevo proyecto. Al abrir Gada por primera
vez, no hay proyectos. Cadeau recomienda explorar proyectos de muestra
oficiales. Presiona cancelar para ignorar
esta recomendación. Estaremos iniciando un nuevo
proyecto desde cero. Haga clic en el botón nuevo
para crear un nuevo proyecto. Tendremos que darle un nombre
al nuevo proyecto. Voy a nombrar a la mía Gada
tres D curso. Y selecciona una carpeta en tu
disco duro para almacenarla. Recomiendo hacer una carpeta para proyectos
de Gada en documentos. Luego haga clic en el botón re
carpeta para crear una nueva carpeta en esta ubicación con el nombre del proyecto. Puedes cambiar la
configuración del renderizador para tu proyecto. Forward es lo mejor
para juegos de
PC o consola de alta fidelidad . O el renderizador móvil
para dispositivos móviles. Me gusta usar el renderizador de
compatibilidad para la mayoría de los proyectos
porque es más compatible con
compilaciones web que se pueden subir a sitios como dot IO Por último, Dios admite la integración con el
control de versiones de GT Tub por defecto. Da click en crear y editar para crear el proyecto y
abrirlo para editarlo. La ventana del editor de Gdo se
divide en varias pestañas. En el centro hay una vista previa de cómo es la
escena actual, así
como varias herramientas
que podemos utilizar para editar cosas. En la parte superior izquierda
se encuentra la pestaña de escena, que contiene una lista de todo lo que hay
en la escena actual. Debajo está la pestaña del sistema de
archivos, que contiene todos los activos importados para nuestro proyecto como modelos, texturas, sonidos y música. Además de todos los archivos, crearemos usando
el editor de Gada, como escenas, guiones
y recursos. Actualmente, el único archivo
aquí es el logotipo de Gada. A la derecha está
la pestaña inspector, donde si seleccionamos
algo en la escena, podremos ver sus propiedades
y editarlas. Todas estas pestañas se
pueden cambiar de tamaño y
reorganizar como mejor le parezca
para adaptarse mejor a
su Nuestra escena es un vasto espacio
vacío de tres D dividido por tres ejes de colores. El eje x rojo representa
a derecha e izquierda. El eje y verde
representa arriba y abajo. El eje Z azul representa
hacia adelante y hacia atrás. Empecemos haciendo clic en el botón de tres escenas D
en la pestaña de escena. Esto ha creado un nodo raíz para nuestra escena en la pestaña de escena, llamado Nodo tres D, que también es el tipo de nodos. Podemos renombrar este nodo
haciendo doble clic sobre él o haciendo clic derecho
y seleccionando renombrar. En muchos juegos, esta
escena será referida como la escena principal
o la escena del juego. También puedes nombrarlo el estilo de juego
que se utilizará, como la escena de plataformas, exploración, combate
o rompecabezas Voy a nombrar el mío juego. Este nodo raíz formará nuestro árbol de escena a medida que le
agreguemos ramas. Haga clic en el
botón más o haga clic derecho en el nodo raíz y seleccione Agregar nodo hijo para agregar una
rama al árbol de escenas. Hay muchos tipos de nodos
diferentes para elegir que sirven para
muchos propósitos diferentes. Los tipos de nodos siguen una
jerarquía de herencia. Así que todos los nodos comparten
el nodo de tipo común. Pero luego están el nodo
tres D, elemento Canvas, nodo dos D, control, cada uno con muchos subtipos
diferentes Si sabes lo
que buscas, puedes escribir el nombre del
nodo en el campo de búsqueda. Vamos a agregar una
instancia de malla tres nodo D. Puede ver que una
instancia de malla tres nodo D está heredando propiedades de una instancia de geometría
tres nodo D, instancia
visual tres nodo D, nodo tres D y nodo Haga clic en el botón Crear para agregar el
nodo D de tres instancias de malla al árbol de escenas. puede ver que el nodo
se agrega al árbol de escenas, pero se le aplica sangría para implicar que es un
hijo del nodo raíz Cualquier nodo con hijos se
puede contraer o expandir para ocultar o
mostrar sus nodos secundarios. Se supone que esta es una imagen de tres D, pero no se muestra nada
en la ventana de vista previa. Eso se debe a que
esta instancia de malla no tiene un recurso de malla que
le diga qué dibujar. Con la instancia de malla
tres nodos D seleccionados. Busque en la pestaña del inspector para ver y editar las propiedades de
los nodos. Las propiedades se dividen en los mismos tipos que vimos
al crear el nodo. Así podemos ver qué
propiedades se heredan de diferentes tipos y cuáles son específicas de nuestra instancia de malla. Podemos ver que el campo
de malla está vacío. Al hacer clic en el menú desplegable, hay varias opciones, incluyendo algunas formas
básicas, caja, cápsula, cilindro, cuádruple,
prisma, esfera y Torus. Hagamos de esta forma un plano. Ahora podemos ver una
forma de tres D dibujada en nuestra vista previa. Al hacer clic en el
recurso mesh se expanden sus propiedades para que podamos
verlas y editarlas también. Aquí podemos establecer el
tamaño del plano tanto
en las dimensiones x como en
y escribiendo un número en el campo o haciendo clic y
arrastrando sobre la etiqueta del campo Las unidades generalmente
se consideran metros o aproximadamente tres pies
en medidas imperiales. Pero no hay ningún requisito
para usar esta relación. En un juego de estrategia, una unidad puede ser de un
kilómetro o milla, o si estás jugando
como un pequeño insecto, entonces una unidad podría ser de un
centímetro o una pulgada. Ahora que tenemos
algo en nuestra escena para darnos un punto de referencia, exploremos un poco más la
escena. Hay una cuadrícula de líneas
grises más claras que dividen el plano x z en unidades con cada octava
línea siendo más clara. Podemos acercar o alejar
usando la rueda del ratón. Alejando, podemos ver que
este patrón continúa
ya que cada octava subdivisión, más grande también
está marcada, con 64 unidades de diferencia, que
es ocho Y nuevamente, cada ocho o 512 unidades ocho
la potencia de tres volver a acercar, el
grado original vuelve a ser visible. Mantener presionada la rueda del mouse y mover el mouse nos
permite rotar el mundo alrededor del eje y y también inclinar nuestra
perspectiva hacia arriba o hacia abajo. Pulsar el botón derecho
del ratón y mover el ratón nos permite
rotar nuestra perspectiva,
mirando a la derecha, a la izquierda, arriba o abajo. Aún manteniendo presionado el botón
derecho del mouse, podemos usar las
teclas WASD para volar por nuestra escena mientras también usamos el mouse para orientar
nuestro punto de vista Si parece que te estás
moviendo despacio o nada en absoluto, probablemente
estés alejada. Esto nos permite
ver
rápida y fácilmente nuestras escenas desde
cualquier posición o ángulo. La malla sólo define la
forma de un objeto de tres D, no su iluminación de color
o cualquier otra cosa. Esos están todos establecidos por material. Ampliando el
desplegable de material etiquetado, seleccione nuevo material estándar
tres D. Luego haga
clic en el recurso
material recién creado para ver y editar sus propiedades. Los materiales tienen
muchas propiedades para controlar cómo
interactúan con la luz. Ampliar la sección albedo. Aquí podemos ajustar
el color o también usar un archivo de imagen dos D para aplicar
textura al material. Intenta arrastrar el logotipo de Gada
al campo de textura. Si hay tanto una
textura como un color, entonces cada color de píxeles se
multiplicará por el
valor de color para producir el resultado. En la esquina superior derecha
hay una serie de botones, uno de los cuales es un tablero de
chapaleta con un icono de play, ejecutar escena actual Al hacer clic en este botón nos
incitará a guardar la escena actual si aún no lo
hemos hecho. De lo contrario, guardará
la escena automáticamente. Esto nos permite ejecutar una simulación de nuestro
juego a partir de esta escena actual que estamos editando. No se muestra nada. Podemos cerrar la ventana
para terminar la simulación. Esto se debe a que
no hay cámara en la escena. Se requiere una cámara para
ver tres escenas D. Una cámara es solo
otro tipo de nodo. Entonces podemos agregarlo
a la escena de la misma manera que agregamos
la instancia de malla. Necesitamos usar una cámara tres
D para ver tres escenas D. La cámara se agrega
en el origen de la escena, que es el centro
del piso, y está mirando en la dirección Z
negativa. Podemos ver en qué dirección está mirando
una cámara
así como el ancho de
su campo de visión basado en el gizmo magenta
con forma de pirámide Y el triángulo nos muestra
qué dirección es también hacia arriba. Con la cámara tres nodos D
seleccionados en el árbol de escenas, hacer clic en el toggle anterior nos
mostrará lo que ve
la cámara. Donde está sentada la cámara ahora mismo, no puede
ver nada. Vuelva a hacer clic en la alternancia previa para regresar. Tenemos que
alejarlo del piso y girarlo para
mirar el piso. Podemos mover la
cámara fácilmente a lo largo un solo eje haciendo clic y arrastrando sobre cualquiera de
las tres flechas, rojas para el eje x, verde para y y azul para Z. También
podemos mover la
cámara a lo largo de un plano haciendo clic y arrastrando
cualquiera de los Esto bloqueará el valor x y o
z
asociado mientras movemos la posición a lo largo de
los otros dos ejes. Mueva la cámara hacia arriba a lo largo del eje verde y
hacia adelante a lo largo del eje Z. Dependiendo de la
perspectiva de tu editor, hacia adelante puede parecer al revés. Pero para mayor claridad, se
usa hacia adelante para referirse a la dirección Z
positiva, que es la dirección de
los puntos de flecha azul. Esto también se puede hacer
bloqueando el eje rojo y moviendo la cámara a lo largo
del plano YZ así. A continuación, necesitamos rotar la cámara para mirar
hacia abajo al piso. Podemos rotar alrededor de
un solo eje haciendo clic y arrastrando cualquiera
de los tres círculos Girar alrededor del eje y verde será como girar la
cabeza hacia la izquierda o hacia la derecha. Girar alrededor del eje z
azul será como inclinar la cabeza hacia ambos lados o incluso boca abajo. Mirar hacia abajo es una rotación alrededor del eje x, que es de color rojo. Haga clic en la vista previa para ver si su cámara puede ver
el piso con claridad. Con la cámara tres nodos
D seleccionados, mira en el inspector en
las propiedades heredadas del nodo tres D.
Expandiendo la transformación, podemos ver que los valores
de posición
y rotación de la cámara han sido editados. Los tres nodos D
heredarán esta propiedad para controlar su posición y
rotación en tres espacios D. Aquí, podemos
editar manualmente los valores, o podemos hacer clic y
arrastrar sobre las etiquetas para ajustarlas con el ratón
como hicimos con el plano. La escala es un multiplicador de
un tamaño de tres objetos D. Por defecto, los
valores X Y y Z están todos vinculados entre sí, por lo que
editar uno editará los tres. camras no tienen tamaño, por lo que cambiar el valor
no afecta a la cámara Pero establecer la escala
en un valor negativo reflejará efectivamente su rotación. Podemos restablecer la escala
a una haciendo clic en el botón de reinicio e
ignorar esta propiedad. Comprobando la vista previa, la
cámara ahora puede ver el piso. Pero si corremos la
escena actual, el piso es negro. Esto se debe a que no hay fuente de
luz en nuestra escena. En el editor, el
piso se ilumina porque hay previsualización de
algo de luz y ambiente, que podemos activar o
desactivar usando estos botones. Al apagarlos del
piso se vuelve negro, que es lo que vemos
cuando corremos la escena. Entonces, para que la cámara
pueda ver el piso, también
necesitamos agregar una
fuente de luz a la escena. Agrega una luz direccional
tres D no a la escena. Al igual que la cámara, se agrega en el origen de la escena mirando hacia el
negativo dicha dirección. Una luz direccional
simula la luz solar, produciendo rayos de
luz paralelos sobre toda la escena Es posición no afecta su comportamiento, sólo su rotación. Podemos moverlo y
colocarlo en cualquier lugar de la escena, preferiblemente en algún lugar donde
podamos ver el artilugio de flecha blanca Esta flecha apunta en la
dirección de los rayos de luz. Gire la fuente de luz, manera que la luz apunte hacia
abajo hacia el suelo, iluminándola para la cámara Ahora bien, si corremos la escena, la cámara puede ver el suelo gracias a la luz
que se refleja en él. Todo juego ejecutable necesita
tener estos tres componentes
básicos, algo para mirar, una cámara con la
que verlo y
una fuente de luz Si necesitas practicar con tres posiciones D y rotaciones, intenta hacer una obra de arte
tridimensional abstracta usando instancias de malla Tenga en cuenta que las luces no
proyectan sombras por defecto. Para habilitar las sombras, haga clic
en el nodo de fuente de luz, expanda la sección de sombra
bajo la luz tres D, y haga clic en el botón de activación. También puede agregar
luces adicionales a la escena, ajustar la energía o color para producir una amplia
variedad de iluminación. Siéntase libre de experimentar
con diferentes propiedades de los materiales y cómo
interactúan con la iluminación también. Cuando termines,
debes tener una buena comprensión de la
relación entre mallas,
materiales, cámaras
y fuentes de luz Cómo se utilizan para
crear una escena tridimensional, cómo mover y rotar objetos en el espacio tridimensional y cómo navegar por tu escena. En la siguiente lección, comenzaremos a recibir aportes del jugador. Te veré en la
siguiente lección. Bien.
15. Guiones: Hola, amigos. En
la lección anterior, configuramos una escena básica de tres
D con mallas,
materiales, una cámara
y una fuente de luz En esta lección, aceptaremos
aportes del jugador. Haga clic en proyecto en la barra de menú y abra
la configuración del proyecto. Cambie a la pestaña de mapa de entrada en la parte superior de la ventana de configuración
del proyecto. Para lograr
nuestro objetivo de controlar un carácter de
tres D, necesitamos aceptar entradas
para las cuatro direcciones de
movimiento, izquierda, derecha, adelante
y atrás. Escriba, mueva a la izquierda en el campo de
agregar nueva acción. Luego haga clic en Agregar para
agregar la acción. El nombre de la acción es
una descripción de para
qué se
utiliza la entrada en nuestro juego, convencionalmente
escrita en minúsculas separadas por guiones bajos Las acciones son desencadenadas por eventos, que podemos agregar haciendo clic
en el botón más. Los eventos pueden ser teclas del teclado, clics
del mouse o movimiento
o entrada desde un pad de alegría. Podemos buscar
las entradas deseadas expandiendo sus categorías, filtrando los resultados de búsqueda o usando el campo de escucha para simplemente presionar el
botón que queramos. Para moverse a la izquierda, la mayoría de los
juegos usan la tecla A o el stick izquierdo de un
joypad inclinado hacia la izquierda Agregar múltiples eventos se acomodará mejor a
diferentes estilos de juego. También necesitamos
poder movernos hacia la derecha, hacia adelante y hacia atrás, agregando
una nueva acción para cada uno. Usaré la tecla D o el
stick izquierdo derecho para derecho. WK o stick izquierdo hacia arriba para adelante, y tecla S o stick izquierdo hacia
abajo para atrás El valor de la zona muerta es
la cantidad mínima de presión o inclinación requerida
para activar esta acción. Ahora el motor escuchará estos eventos de entrada y
activará estas acciones. Cuando hayas terminado,
haz clic en el botón Cerrar para cerrar la configuración del proyecto. Vamos a crear un nuevo
nodo que
reaccione a las
acciones de entrada que creamos. Este nodo no necesita
representar ningún
objeto físico en nuestra escena, por lo que puede ser solo un
nodo básico, y nombre jugador. Cualquier cosa en nuestras
escenas se puede dar comportamientos adjuntando
guiones a ellas. Haga clic derecho en el
nodo del jugador, seleccione Script adjunto. O con el
nodo reproductor seleccionado, haga clic en el
botón de guión adjunto en la pestaña de escena. El lenguaje predeterminado
para los scripts en el motor Goda es GodaScript, que es muy fácil de aprender y bien optimizado para el desarrollo de
juegos Los scripts heredan los comportamientos
del tipo de nodo al que se
adjuntaron En este caso, sólo
un nodo normal. Se proporcionan plantillas para diferentes tipos de nodos para
proporcionar funcionalidad básica. Las
casillas de verificación de la plantilla están activadas por defecto. Echemos un vistazo a lo que tiene en ella
la plantilla predeterminada para un script de nodo. Estamos creando un nuevo script, no usando uno que esté
integrado en el motor. Podemos darle un nombre al script, que será recomendado
por el motor, coincidiendo con el nombre del nodo al
que se está adjuntando. Es convencional
usar snake case al nombrar scripts
como las acciones de entrada Minúsculas separadas
con guiones bajos. Haga clic en el botón crear
para crear el script, y el editor
cambiará automáticamente a la
vista de script para editarlo. Puede volver a la vista de
tres D en cualquier momento haciendo clic en el botón
tres D en la parte superior del editor. De igual manera, cambie a la
vista de script haciendo clic en guión. La línea superior especifica
el tipo de nodo al que se puede
adjuntar
este script, que es nodo. La palabra clave extends,
permite que este script herede las propiedades
y comportamientos de un nodo, para que podamos utilizarlos
en el script Las funciones son comportamientos que el script ejecutará en el
nodo, se adjunta a él. Nuestra plantilla de script
comienza con dos funciones,
listo y proceso. Texto gris, comenzando con
un ctathorp o comentarios. Texto que existe sólo
para nuestro beneficio como desarrollador para explicar el
guión en lenguaje sencillo. Los comentarios nos dicen que
la función ready se llama
automáticamente
cuando el nodo ingresa al árbol de escenas
por primera vez. Esto no es cuando creamos
el nodo en el editor, sino cuando presionamos el botón ejecutar escena
actual. La simulación
construirá el árbol de escenas, y cuando el nodo jugador se agregue al
árbol de escenas y esté listo, entonces llamará a este comportamiento. La función de proceso
se llama cada fotograma, que con la configuración predeterminada
del proyecto es de 60 fotogramas por segundo. Esta función tiene un
parámetro llamado Delta, que es la cantidad
de tiempo que ha transcurrido desde el
fotograma anterior en segundos. Esta variable se representa
como un número de coma flotante, un número con puntos decimales. Podemos especificar el tipo de
cualquier variable con dos puntos, seguido del nombre del tipo. Dado que el script Gudo está
escrito de forma suelta, esto es opcional, pero especificar un
tipo mejorará la eficiencia del motor y
reducirá la frecuencia Por lo que se recomienda especificar
siempre el tipo de sus variables a menos que
necesite permitir múltiples tipos. Bien. Podemos usar el
comando print en nuestros scripts para enviar texto básico a la consola de salida aquí en
la parte inferior de la ventana. El comando print toma
una cadena como argumento, que es una secuencia
de caracteres contenidos
entre comillas. Imprimimos listos durante la función ready y procesemos durante la función de proceso. También podemos usar
el operador plus para agregar cadenas juntas, lo que nos permite agregar el valor
de Delta a la cadena de proceso Pero Delta es un flotador, no una cuerda, lo cual no
está permitido. Podemos lanzar el
tipo de Delta de un float a una cadena
usando el comando STR, pasando Delta como
argumento entre paréntesis. Ejecuta la escena actual y
deténgala después de un breve momento. En la consola de salida,
podemos ver que ready
se imprimió una vez, seguido del proceso 0.016, etcétera muchas veces, que es la velocidad
de fotogramas de una 60 de segundo A veces el número
podría ser mayor porque ese fotograma tardó un poco
más en procesarse. Entonces podemos ver que
estos comportamientos están siendo llamados automáticamente
por el motor. Eliminemos estas declaraciones de
impresión y toda la función ready. En cambio, vamos
a querer verificar si el jugador está dando alguna entrada durante
la función de proceso. Para almacenar esta información, necesitamos declarar una
variable en la parte superior del script usando
la palabra clave VR. Vamos a llamarlo dirección de movimiento. preceder el nombre
de la variable con un guión bajo, la
marca como privada, lo que significa que solo este script necesita preocuparse por ella El tipo de nuestra variable
será un vector dos. Un Vector dos es una estructura para contener dos flotadores
llamados x e y. Ya
hemos estado
trabajando con Vector dos al cambiar
el tamaño de la malla plana y vector tres es cuando se edita la posición o rotación
de cualquier nodo tres D. Durante la función de proceso, podemos establecer el valor de dirección de
movimiento al
estado actual de
las acciones de entrada de movimiento que creamos anteriormente usando el
operador de asignación o signo igual. La dirección de movimiento
es igual al vector de entrada. Input es una clase singleton, un script incorporado al que
podemos hacer referencia por su tipo, ya que siempre
habrá una sola instancia de la misma El periodo accede a
variables o funciones, que en este caso, se denominan métodos porque
pertenecen a una clase. El método que estamos llamando
se llama get vector. Get vector acepta cuatro
cadenas como argumentos, que son los nombres
de las acciones de entrada que se utilizarán para
crear un vector dos, que luego se
almacenará en la variable. Un valor x negativo, que queda se restará
de un valor x positivo, para calcular el valor
de x en el vector De igual manera, un valor
y negativo hacia arriba se
restará de un valor
positivo y hacia abajo para calcular
el valor de y
Esto puede parecer invertido,
pero al mirar las asignaciones de entrada,
la dirección hacia arriba se enumera como
el lado negativo
del eje
y hacia abajo es el positivo. Esto puede parecer invertido, pero al mirar las asignaciones de entrada,
la dirección hacia arriba se enumera como
el lado negativo
del eje
y hacia abajo es el Además, la cámara mira en
la dirección de ajuste negativo. Avanzar desde la perspectiva de la
cámara en realidad significa moverse hacia atrás
a través del espacio tres D. Esto es consistente con los juegos
bidimensionales ya que el origen de la escena está en la parte superior de la pantalla y los valores
positivos
se mueven hacia abajo, no hacia arriba. Por ahora, solo podemos imprimir el valor de nuestra variable
para ver de qué se trata. Vamos a correr la
escena actual y probarla. La consola de salida está
constantemente imprimiendo cero, cero porque no
se está dando ninguna entrada. Si presionamos alguna de las teclas WASD o inclinamos el
stick izquierdo en nuestro joypad, el valor que se está
imprimiendo cambiará Izquierda significa que el valor x
es negativo, positivo. Abajo establece el
valor y en positivo, que es hacia la cámara y arriba negativo
lejos de la cámara. Cerrando la ventana, podemos
ver un mensaje de advertencia. El valor de Delta no está siendo utilizado por nuestra función de
proceso. Podemos agregar un guión bajo
al frente de Delta para marcarlo que el motor sepa que
se puede ignorar ya que
no lo necesitamos Ahora podemos leer la entrada de movimiento
del jugador desde el teclado
o desde el JoyPad En la siguiente lección, usaremos entrada
del jugador para mover
un objeto a través de nuestra escena. Te veré en la siguiente lección.
16. Controles: Hola, amigos. En
la lección anterior, comenzamos a recibir
aportes del jugador. En esta lección, moveremos un objeto de tres D a través de
nuestra escena usando esa entrada. Empecemos quitando todas las mallas de nuestra
escena excepto el piso Y añadiendo un nuevo nodo
a la escena del juego, un cuerpo de personaje tres nodo D. Este nodo viene con alguna funcionalidad incorporada para la física de mover a un personaje pero
en realidad no representa nada que
el jugador pueda ver. Entonces debemos agregar un
nodo hijo al cuerpo del personaje, una instancia de malla tres
D. que podemos poblar con una malla de
cápsula con la intención de reemplazar esto con un
carácter real más adelante El cuerpo del personaje tres D está en el origen de la escena en el suelo, igual que la instancia de malla. Si consideramos que la
posición de los personajes está
entre sus pies, entonces la cápsula debe moverse hacia arriba en relación con
el cuerpo del personaje. Con la instancia de malla
tres nodos D seleccionados, que deben ser chilchilded
al cuerpo del personaje, mueve la cápsula hacia arriba a lo largo del eje y hasta que
esté en el piso, que debe ser una unidad Seleccionando el
cuerpo de carácter tres nodo D, si movemos este nodo, la instancia de malla también
se moverá. Los nodos hijos siguen la posición, rotación y escala
de sus padres. Bien. Hay una advertencia en la pestaña de escena que indica que el cuerpo del personaje necesita
una forma de colisión. Este es otro nodo hijo. Necesitamos agregar al cuerpo del
personaje tres nodos D, una forma de colisión tres nodos D. No es asumido
por el motor Goto que las colisiones ocurrirán
cuando chocan las mallas En cambio, podemos agregar
una forma extra, generalmente una que es mucho
más sencilla de detectar colisiones para que
los cálculos sean más eficientes Al igual que el nodo D de la instancia de malla
tres necesita
un recurso de malla, el nodo D de forma tres de colisión requiere un recurso de forma. Usaremos la misma forma de
cápsula y la moveremos hacia arriba una unidad para estar en la
misma posición que la malla. Bien. Esta es ahora una rama de nodos
que todos se relacionan con nuestro personaje
específicamente y
no tienen nada que ver con la escena
general del juego. Al hacer clic derecho en el cuerpo del
personaje tres nodo D, seleccionar rama segura como escena, y darle un nombre a esta escena. Puedes nombrar a esta
escena el nombre
del personaje o simplemente
dejarla como personaje por ahora. Los nodos hijos en el árbol de
escenas ahora están ocultos, y el nodo de personaje
tiene un icono de tablero de chapaleta Si hacemos clic en el tablero de
chapaleta, la escena del personaje se
abre para su edición Bien. Se abre una nueva pestaña en el editor
para nuestra nueva escena, y podemos cambiar entre
la escena del juego o la escena personaje haciendo
clic en las pestañas. El personaje es ahora
una escena separada de la escena del juego que
podemos editar de forma aislada. Cualquier cambio que hagamos
a esta escena
alterará cualquier instancia de la
misma en otras escenas. Al igual que nuestro nodo jugador
tiene un guión de jugador, el nodo de personaje también necesita un guión de personaje para
decirle cómo comportarse. Adjuntando un nuevo script al nodo
raíz de nuestro personaje, este nuevo script
heredará del cuerpo del personaje
tres D. Podemos usar la plantilla básica
para este tipo de nodo y hacer clic en Crear para
abrir el Nuevo Script Hay algunas diferencias
en esta plantilla. El personaje tiene
una velocidad y una
velocidad de salto almacenadas como constantes. Las constantes son similares
a las variables, pero más eficientes para
valores que nunca cambian Una fuerza gravitacional se
está leyendo desde la configuración del
proyecto Bien. En lugar de la función de
proceso, hay una función de
proceso de física. Por defecto, tanto el
proceso como el proceso de física se ejecutan 60 veces por segundo. Pero en juegos con muchos cuerpos físicos
complejos,
la velocidad de fotogramas del proceso de física se
puede reducir para mejorar la eficiencia sin sacrificar las actualizaciones
gráficas
o el tiempo de respuesta Cualquier cosa que tenga que ver con los cálculos de velocidad
o fuerza se realiza en la
función de proceso de física para mantenerlos separados. Durante la función de
proceso de física, si el personaje
no está en el suelo, entonces los tiempos de gravedad
Delta se están
restando de su velocidad
vertical Si el jugador presiona
la acción de aceptación de interfaz de usuario, una acción de entrada incorporada
asignada a la barra espaciadora, entonces el personaje saltará. Esta plantilla también está usando código
similar para leer la entrada de
movimiento desde
las teclas de flecha. Luego, la entrada se convierte en un vector tres
agregando un cero para el valor y y usando el movimiento vertical y
para el eje zt, convirtiendo
las entradas arriba y abajo en el teclado del controlador en movimiento hacia adelante
o hacia atrás. Esto se multiplica entonces
por la base de nodos, que es una estructura de tres vectores tres apuntando hacia
arriba y hacia adelante Estas son las mismas flechas de tres
colores que se muestran en el editor cuando
seleccionamos cualquiera de tres nodos D. Sin embargo, estas flechas
están en el espacio global. Si giramos el cuerpo del personaje, las flechas siguen siendo las mismas. Los vectores de base de nodos
se muestran si cambiamos al espacio
local haciendo clic en este togle o presionando
la tecla T de método abreviado A medida que el nodo gira, sus vectores base o sus interpretaciones locales de arriba y hacia adelante también
rotarán Estos son los
vectores direccionales que se están utilizando para determinar la dirección en la que
se moverá
el carácter cuando se da la entrada. Luego se normaliza la dirección. Es decir, independientemente
de cualquier rotación o inclinación parcial
del stick izquierdo, la longitud del
vector direccional se convertirá en uno, resultando en que el
personaje se
mueva siempre a una velocidad constante. Esto es una taquigrafía para si
la dirección no es cero. Luego mueve el personaje a lo largo los ejes x y z por dirección
multiplicado por velocidad. Si la dirección es cero, entonces mueva su velocidad hacia
cero a una velocidad. Finalmente,
se llama al método move
in slide para aplicar
su velocidad y fuerzas
externas durante
la duración de Delta para averiguar dónde
debe estar el personaje este fotograma. Si tratamos de ejecutar esta escena, no se dibuja nada porque esta es la escena del personaje que no
tiene cámara ni iluminación. Así que cambia a la escena del juego y ejecuta este cisne
para probar el juego. El personaje
cae inmediatamente por el suelo. Esto se debe a que el piso
no tiene ninguna colisión. Agreguemos un nodo
tres D de cuerpo estático a la escena. Un cuerpo es un término general para cualquier objeto que se vea afectado
por la física o las colisiones Estático significa que es
inmutable, o en este contexto, que no se moverá
ni de la física como la gravedad ni de colisiones con otros cuerpos
como nuestro personaje La instancia de malla de piso
debe ser hijo de este nodo de cuerpo estático ,
ya que es el
componente visual del mismo. Entonces necesitamos agregar una colisión forma de tres nodos D para darle
al piso una forma con que colisionará
con otros cuerpos Esta forma será una caja. Ampliando el recurso de
forma de caja, podemos darle un largo y
ancho coincidente con el piso, -5 metros tanto en largo como en
ancho y una altura de cero. Podemos renombrar los nodos para
reflejar esta nueva disposición, por lo que el cuerpo estático tres nodo
D es el piso, y la instancia de malla tres D es un hijo usando
su nombre por defecto. Ahora, cuando ejecutemos
la escena actual, la
forma de colisión del personaje colisionará con la forma de colisión del piso,
evitando que caigan El piso no reaccionará ante la colisión
porque es estático. cruzar las
teclas de flecha se moverá el cuerpo del personaje tres nodo D y pulsando la barra
espaciadora saltará. De vuelta al guión del personaje, los comentarios nos dicen
que como buena práctica, deberíamos reemplazar las acciones
de interfaz de usuario
integradas acciones de juego personalizadas,
que ya tenemos. Entonces podemos comentar
estas dos líneas, presionando Control
o comando K. Pero la variable dirección
se está declarando aquí dentro de la función de
proceso de física. A esto se le llama el
alcance de la variable. Se declara dentro de
esta función y por lo tanto solo existe
dentro de esta función. Como hicimos con
el guión del jugador, podemos declarar esta
variable de dirección en la
parte superior del guión fuera del proceso de física para ampliar su alcance a todo
el guión. Lo configuraremos para que sea privado
procediendo con un guión bajo y estableceremos su
tipo como vector tres,
una estructura que contiene
tres flotadores para Y también edita el nombre de la variable dentro del proceso de
física para que coincida. Para mover el carácter,
escribamos una nueva función en nuestro
script llamada move, que aceptaremos un parámetro llamado direction of
type vector three. Este parámetro de dirección es diferente a nuestra variable de
dirección, ya que esta no
tiene un guión bajo, y su propósito será almacenar
el valor que se pasó
a esta función de movimiento, asignándolo con el operador de
asignación El nombre de esta función move no tiene guión bajo, marcándolo como
público, lo que significa que está destinado a ser
accesible a otros scripts Bien. Nuestro
guión de jugador llamará este método para
mover al personaje en
función de la dirección de movimiento
que se recibió. Podemos cambiar entre
scripts haciendo clic sobre ellos en la lista de scripts a
la izquierda de la vista de scripts. Cambiando al guión del jugador, podemos agregar una nueva variable para mantener el personaje de
los jugadores controlando. Se trata de un carácter de
subrayado de variable privada de tipo cuerpo de carácter tres D. Añadiendo en
la exportación al frente de la declaración de
variables, permitirá que sea accedido por otras partes
del editor Gda,
es decir, la pestaña inspector En la escena del juego, si
seleccionamos el nodo jugador, la
variable de personaje aparece listada en el inspector y
podemos asignar su valor. Ya que especificamos el tipo de la variable para que sea cuerpo de
carácter tres D, solo se pueden asignar nodos de
ese tipo o nodos que hereden de ese
tipo Asignar el
nodo de personaje para que sea el valor de la variable de personaje en
el script de nodos del jugador, ya sea haciendo clic en un
signo y seleccionándolo de la lista o haciendo clic y arrastrando el
nodo al campo En lugar de imprimir el
valor de la dirección de movimiento, queremos llamar carácter do movimiento y pasar la
dirección de movimiento como argumento. Pero el tipo de
dirección de movimiento es un vector dos, y el tipo del
parámetro esperado por el carácter do
move es un vector tres. Aunque estos fueran
del mismo tipo, esta no sería la dirección correcta
para mover al jugador. Ya que la dirección que
esperamos que se
mueva el personaje depende de
la perspectiva de la cámara. Agreguemos otra
variable exportada para la cámara. Después asigne su valor. Cambiaremos el nombre de la dirección del movimiento
a la dirección de entrada y crearemos otra variable para
la dirección de movimiento del vector de tipo tres. ¿Cómo convertimos la dirección de
entrada bidimensional en
una dirección de
movimiento tridimensional basada en la
perspectiva de la cámara? Multiplicamos la
base de la cámara por la dirección de entrada, similar a la forma en que
se hizo en el código de la plantilla, pero lo haremos un
poco mejor. Primero, tomar la
dirección derecha de la cámara, es flecha roja, que podemos acceder con la
cámara punto base punto X y multiplicarlo por dirección de
entrada punto x Si el jugador presiona a la derecha, se moverá a lo largo de la dirección derecha de la
cámara, y si presionan a la izquierda, entonces la dirección de entrada
x es negativa y derecha multiplicada por
número negativo irá a la izquierda en su lugar. Luego agregue usando el operador
más es igual, la
dirección hacia adelante de las cámaras, es flecha azul, base de punto de la
cámara se multiplica
por la dirección de entrada punto y, convirtiendo la
entrada vertical en movimiento a lo largo de las cámaras direcciones hacia adelante
y hacia atrás. Pero actualmente la cámara está rotada ya que está mirando hacia abajo. Entonces, si el jugador avanza, se moverá ligeramente hacia
abajo en el suelo, moviéndose más lento de lo que lo
haría a
la izquierda o a la derecha, y moviéndose hacia atrás, en realidad
estarán tratando de subir al aire para
acercarse más a la cámara. Multiplicando el
vector base por el vector 3101, eliminará cualquier componente y, aplanándolo sobre Entonces necesitamos normalizar
el vector aplanado tres, por lo que siempre
tendrá una longitud de uno y no afectará la velocidad de movimiento del
jugador Esto eliminará cualquier efecto de la rotación x o z en
estas direcciones, pero la rotación y de la cámara seguirá alterando los controles
del jugador. Ahora cuando ejecutamos
la escena actual, el guión de los jugadores está comprobando
la entrada, cada fotograma. Si damos una
entrada, entonces
verificará las direcciones derecha
y hacia adelante de la cámara, las
aplanará en el plano ed, las
normalizará y le dirá al personaje qué dirección mover en función de la entrada Entonces el proceso de
física del personaje los
moverá en
esa dirección. Mover al personaje usando los vectores de
base aplanados de la cámara permite al jugador
mantener el control del personaje desde
cualquier ángulo de cámara, e incluso mientras la cámara se
mueve o también está siendo
controlada por el jugador al mismo tiempo ya que
la dirección
del movimiento se calcula
dinámicamente cada fotograma Separar las entradas
del jugador del personaje también es una estructura más flexible ya que el personaje del jugador que está controlando se puede cambiar
fácilmente. El guión que le dice al personaje dónde moverse podría
controlarse fácilmente con la lógica del juego
en lugar de la entrada del jugador. Ahora tenemos al jugador capaz de
mover una cápsula a través de nuestra escena, y en la siguiente lección importaremos un modelo de personaje para
reemplazar la cápsula. Te veré en la siguiente lección.
17. Importación: Hola, amigos. En
la lección anterior, solíamos reproducir
tu entrada para mover
una cápsula a través de
una escena de tres D. En esta lección, reemplazaremos la cápsula con un modelo de
personaje. Empecemos descargando
un paquete de activos de Soto. Para este curso, estoy
usando la versión gratuita del Pack de personajes de Kits Aventureros Al hacer clic en descargar ahora, se
le pedirá que pague, pero puede hacer clic en No, gracias. Sólo llévame a las descargas. Opcionalmente elegimos
apoyar al artista dando cualquier cantidad de dinero
que consideres apropiada. También hay versiones pagas de estos paquetes de activos, que
incluyen más contenido. Te recomiendo
probarlos gratis y pagar por las versiones extra
si te gusta su trabajo. Después haga clic en descargar
para descargar los activos. Mientras esperamos que se complete la
descarga, volvamos a la página de
activos y echemos
un vistazo a lo que se incluye
en este paquete de activos. Hay cuatro
personajes todos con una variedad de armas
y accesorios, y cada personaje
está animado con una amplia variedad de animaciones para que las usemos en un formato
consistente. Los modelos son
eficientes para su uso en juegos
móviles y son compatibles
con el motor Cada. Estos activos son gratuitos para uso
personal o comercial bajo licencia creative
common zero. Asegúrese de verificar las
licencias de los activos que descargue antes de
usarlos en sus proyectos. En algunos casos, la atribución
puede ser requerida, o el uso en proyectos comerciales
puede estar totalmente prohibido Cuando se complete la descarga, extraiga el contenido
de la carpeta zipped en
algún lugar de su disco duro Después abre la carpeta
para ver qué hay en ella. Queremos utilizar los
caracteres y los modelos están disponibles
en dos formatos diferentes. Para este curso,
estaré usando los GLTFFiles. Importar los activos
a Coda es tan
simple como hacer clic y
arrastrarlos a la ventana del editor Nuestra carpeta de recursos
está empezando a verse un poco desordenada, así que
organicémosla. Haga clic derecho en la carpeta de recursos
raíz y cree una nueva carpeta. Vamos a nombrar esta carpeta, activos
importados. Después crea otra carpeta dentro de ese uno de los caracteres
nombrados. Seleccione el grupo y arrastre los
activos de caracteres importados a esta nueva carpeta. Bien. También podemos crear una nueva carpeta en la carpeta de recursos
raíz para contener scripts y otra para escenas. Los scripts tienen un icono de diente
y la extensión de GD. Mientras que las escenas tienen el icono del tablero y su extensión es TCN Puedes organizar tus
recursos, sin embargo, tiene
sentido para ti y se
adapta mejor a tu flujo Antes de poder trabajar con
los activos importados, necesitamos editar algunos ajustes de
importación. Seleccione cualquiera de los archivos GLB de
caracteres en la pestaña del sistema de archivos Luego cambia el documento
que actualmente está mostrando la
pestaña de escena a la pestaña de importación. Aquí podemos editar
cómo el editor de Dios interpreta los archivos y
genera los activos importados La mayoría de estos ajustes están
bien para nuestros propósitos. Primero, agreguemos un tipo raíz de cuerpo de carácter tres
D. Por defecto, el carácter habrá
sido importado como un nodo tres D. Pero queremos que nodo
raíz de
nuestro personaje sea un cuerpo de carácter tres D para que sea compatible
con nuestro guión de caracteres. Si cambiamos alguna
de las configuraciones, no se
actualizarán
a menos que volvamos a importar el activo. A continuación, haga clic en el botón
Avanzado. Se abre la ventana de
configuración avanzada de importación, y podemos ver una vista previa de cómo verá
el activo importado. Puede acercar y alejar con
la rueda del mouse o hacer clic y arrastrar para rotar el
modelo y obtener una mejor vista. A la izquierda se encuentra el árbol de escenas que
generará este activo, incluyendo un esqueleto, huesos, mallas y un reproductor de animación
con todas las animaciones Antes de poder trabajar con
este modelo de personajes, necesitamos permitir que ciertas
animaciones se repitan. Empecemos con
la animación inactiva. Con la
animación inactiva seleccionada, podemos previsualizar cómo
se verá con el botón de reproducción en la
parte inferior de la ventana. Pero sólo juega
una vez y luego se detiene, que es exactamente el problema. En el lado derecho, podemos cambiar los ajustes de importación
para la animación, cambiando el modo de bucle a lineal. Ahora cuando pulsamos play, cuando termine
la animación, volverá al
inicio y volverá a jugar. En cambio, el Ping Pong
jugará la animación hacia atrás para volver al inicio y volver a avanzar después de eso. Vamos a establecerlo en
lineal. Luego repita para cualquier animación
en esta lista que contenga la palabra inactivo,
bloqueo o ejecución. Si bien no está cubierto
en este curso, es posible que también desee permitir el
bucle para disparar, girar, bloquear
y lanzar hechizos también. Cuando hayas terminado, haz clic en
el botón de volver a importar para volver a importar los activos con la configuración de animación
actualizada. Deberás repetir
este proceso para que los demás personajes antes de
poder usarlos. Cambia a la escena del personaje. Haga clic y arrastre el recurso del
personaje al nodo raíz de
la escena del personaje para agregarlo al árbol de escenas. Vamos a activar la iluminación de vista previa para que podamos ver
mejor nuestro carácter
importado y eliminar el nodo de instancia
de malla dibujando la malla de cápsula. El nodo bárbaro
es solo un nodo, no el gran árbol de nodos que
vimos en la configuración de importación, y tiene el icono de
clapper board, lo que
implica que esta es una
instancia de Al igual que creamos la
escena del personaje a partir de la escena del juego. Eso lo podemos hacer a la inversa. Dando click derecho sobre el Bárbaro
y seleccionando hacer Local. Esto romperá el
vínculo que este nodo tiene con el activo importado y lo convertirá en una versión
única que solo
existe en esta escena. Y ahora podemos ver todos
sus nodos hijos. Las animaciones están contenidas dentro del nodo
reproductor de animación. Vamos a colapsar el nodo de la plataforma
por ahora para ocultar la mayor parte de él. A continuación, queremos que el Bárbaro sea el
nodo raíz de la escena Podemos hacer clic derecho sobre él nuevamente
y seleccionar make seen root para organizar el árbol de
escenas para que este se convierta en el nuevo nodo raíz de
escena. A continuación, hagamos clic y
arrastremos el nodo D de la forma de colisión tres para volver a padre
al nodo Bárbaro Haciendo de esta la
forma de colisión para el Bárbaro y eliminar el cuerpo del
personaje original tres nodo D ya que ahora es redundante Sin embargo, todavía necesitamos un script de
caracteres adjunto
al nodo raíz. También podemos agregar esto haciendo clic y
arrastrándolo al nodo raíz Nuestro árbol de escena todavía
se ve igual que antes. Solo el nodo D de
instancia de malla tres ahora
se reemplaza con
el equipo de personajes, y hay un nodo de reproductor de
animación. Nuestro personaje
parece estar sosteniendo demasiados artículos
en sus manos. Expanda el nodo de plataforma
para ver sus hijos. Podemos ocultar cualquiera de los
elementos que se mantienen en las
manos del personaje haciendo clic en el icono junto a ellos. También podemos ocultar el sombrero y
p del
personaje para cualquiera de los personajes que no
sean el pícaro El pícaro tiene un modelo completamente
diferente para cuando la capucha está levantada ya que también se
le quita el pelo Dependiendo de la versión de Coda o de los activos que estés usando, puede
haber un ícono de X rojo que
muestra que hay un
problema con este activo Seleccionándolo y buscando
en la configuración de importación, podemos cambiar la versión de
nomenclatura GLTF para hacer 4.1 o anterior y volver a importar
el activo para solucionar este problema Cuando termines, colapsa
la plataforma una vez más. Si guardamos la escena del
personaje desde el menú de escena o pulsando el control S o el comando S. Luego cambiamos a
la escena del juego. Podemos ver que el personaje
de nuestra escena de juego
se ha actualizado corriendo esta escena, podemos mover al personaje
igual que antes, pero se están
moviendo torpemente en los TPs Ahora tenemos el modelo de personaje importado a nuestro proyecto. En la siguiente lección,
animaremos a nuestro personaje caminando. Te veré en la siguiente lección.
18. Caminar: Hola, amigos. En
la lección anterior, importamos
modelos de personajes a Cada. En esta lección, animaremos al personaje para que camine
por nuestra escena Empecemos por mover
la cámara un poco hacia atrás ya que el personaje es
más grande que la cápsula. Los movimientos de los personajes
son muy rígidos. El personaje o bien se mueve a toda velocidad o no se mueve en absoluto. Esto no se siente muy bien y no es como
realmente se mueve nada. Debe haber
aceleración hasta una velocidad máxima y
desaceleración antes de detenerse abrir el guión,
podemos ver que la velocidad del personaje se
declara como una constante. En su lugar, declaremos algunas variables privadas
exportadas para definir cómo se mueve nuestro
personaje. Comenzando con su velocidad de
marcha medida en unidades por segundo, que se
representa mejor como un flotador. Podemos dar a las variables
un valor predeterminado usando el operador de asignación en la misma línea cuando se
declaran. Yo lo pondré en uno. También queremos valores de aceleración
y desaceleración
medidos en unidades
por segundo al cuadrado También tipos de flotación. Considera la rapidez con la que
cambiarías
de estar inactivo a
caminar a toda velocidad. Alrededor de medio segundo
suena razonable, lo que es una aceleración del
doble de la velocidad de marcha. Y también qué tan rápido
llegarías a una parada completa al
caminar a toda velocidad. Esto suele ser más rápido que aceleración, así que
voy a hacer cuatro. Seleccionando el nodo raíz de
Bárbaros, podemos ver las variables
exportadas disponibles para ser editadas
en la pestaña inspector Al editar estos números
se
sobrescribirán los valores predeterminados
proporcionados en el script Pero al presionar el botón de reinicio los
devolverá a
sus valores predeterminados. Esto nos permite
experimentar fácilmente con diferentes
valores y también brinda la posibilidad de diferentes personajes tengan
diferentes velocidades de movimiento. Para facilitar las cosas, podemos separar la velocidad de los
personajes en el plano x z de la
velocidad a lo largo del eje y, que nos permite aislar
los ajustes en velocidad de
movimiento de cosas
como saltar y gravedad. Declaremos otra
variable privada X Z velocidad de tipo vector tres. Al inicio del proceso de
física, podemos establecer el valor de
x speed para que sea un
nuevo vector tres, copiando la
velocidad del personaje en los ejes x y z, mientras establecemos el valor
y en cero. Entonces podemos hacer nuestros
ajustes a la velocidad de los personajes X Z aquí sin preocuparnos por el impacto
de su velocidad y. Luego al final del
proceso de física, antes de la diapositiva de movimiento, podemos establecer la velocidad de los
caracteres para que sean
los valores ajustados para X y Z, pero el
mismo valor que lo fue para y Este método también
tendremos beneficios adicionales más adelante. Bien. A continuación, tendremos que
editar este bloque de código que mueve
al personaje. El enunciado está dividiendo
esto en dos casos. Si el jugador está proporcionando una dirección de
movimiento o no. En lugar de dividir la velocidad en componentes x y z, ya que eliminamos la velocidad y, simplemente
podemos editar la velocidad x
z directamente aquí. Si el jugador está proporcionando
una dirección de movimiento, debemos asignar x z
velocidad para moverse hacia dirección multiplicada por la
velocidad de caminar a una tasa de tiempos de
aceleración Delta. Esto tomará cualquiera que sea su velocidad
actual a lo largo del plano X Z y lo moverá hacia su velocidad de caminata
en
la dirección que el jugador quiera ir a
una velocidad de aceleración. Ya que Delta es la
cantidad de tiempo que ha pasado desde
el último fotograma, generalmente una 60 de segundo Ajustará la aceleración
para que coincida con la velocidad de fotogramas, lo que dará como resultado que el personaje acelere y se mueva
a las velocidades especificadas, independientemente de en qué se establezca la velocidad de fotogramas del
juego. De igual manera, cuando no se da entrada de
movimiento, el personaje debe
desacelerar a una velocidad de cero a una tasa de desaceleración
multiplicada por Delta Podemos eliminar la
constante de velocidad original ahora ya que ya no
se usa. Cambiemos a la escena del juego e intentemos mover al
personaje ahora. Ahora el personaje
acelera hasta una velocidad de caminata y
desacelera de forma más natural. De vuelta en la escena del personaje, podemos cambiar a la vista de
tres D para que podamos
ver al personaje. Seleccione el nodo
del reproductor de animación y la pestaña de animación se abrirá
en la parte inferior de la ventana. La animación que se
está viendo
actualmente es una mano de ataque masculino chop, y el modelo de personaje ha asumido el primer fotograma
de la animación. Podemos presionar el
botón de reproducción en la parte superior de la pestaña de animación para
previsualizar la animación. Ampliando la pestaña de animación y desplazándose por las pistas de
animación, podemos ver que cada hueso es
fotograma clave para producir una animación
resultante Use el control deslizante Zoom para ajustar la cantidad de
tiempo que se muestra en la pestaña de animación y podrá ver cada fotograma clave individual Usando el menú desplegable,
podemos seleccionar cualquiera de las animaciones que se
importaron, incluido el inactivo. Y previsualizando esta animación, ya que configuramos
los ajustes de importación, la animación se bucle Por lo que el nodo reproductor de animación puede reproducir cualquiera de
estas animaciones. Solo tenemos que controlar
qué animación se está reproduciendo. Esto se puede hacer
a través de un script, pero el código será
muy largo y tendrá que
dar cabida a demasiadas posibilidades. La mejor manera de controlar
qué animación se está reproduciendo es usando
otro nodo, podemos agregar a nuestra
escena de personajes, un árbol de animación. El árbol de animación
necesita ser dicho qué reproductor de animación
está controlando. Así que haciendo clic en el
campo asignado junto al jugador Anim, podemos seleccionar el nodo del
reproductor de animación de la lista A continuación, necesitamos proporcionar un
recurso para este nodo tal
como lo hicimos con las instancias de malla y
las formas de colisión. Este recurso se llama máquina
de estado. Creando la
máquina de estado abriremos la pestaña del árbol de
animación en la
parte inferior de la ventana del editor. Podemos desplazar la ventana gráfica de esta ventana arrastrando con
la rueda del ratón presionada La máquina de estado rastreará en
qué estado
se encuentra el personaje y reproducirá la animación correcta
para ese estado o incluso combinará múltiples
animaciones. Simplemente necesitamos decirle a la máquina del estado cuáles son
esos estados y también cómo y cuándo el personaje hará la
transición entre estados. Por ahora,
solo tendremos un estado, que combinará las animaciones ociosas y caminantes juntas. Si el personaje comienza
a caminar de inactivo, no
deben pasar
inmediatamente de ocioso a caminar, ni deben hacer una
transición inmediata de regreso cuando se detienen. Sin mencionar que el
jugador podrá inclinar ligeramente
el stick izquierdo para
moverse más lento si así lo desea. Necesitamos que las animaciones de ralentí y
caminar se
mezclen dependiendo de la velocidad de movimiento del
personaje. Esto se puede lograr
con un espacio de mezcla. Al hacer clic con el botón derecho en el espacio vacío, agregar un
espacio de mezcla unidimensional a la máquina de estado,
y asígnele el nombre locomoción. Después haga clic en la herramienta
Conectar nodos. Haga clic y arrastre desde el
inicio hasta la locomoción. Haciendo de este el estado
por defecto donde el personaje comenzará
cuando ejecutemos el juego. Vuelva a cambiar para seleccionar
y mover nodos. Después haga clic en el lápiz para editar el espacio de mezcla de locomoción Un
espacio de mezcla unidimensional tiene un eje, que se muestra
horizontalmente que va desde uno
negativo hasta
un valor con nombre positivo. Si consideramos que esta es la velocidad de los caracteres, podemos cambiarle el nombre a velocidad y establecer su valor mínimo a cero y su
valor máximo a uno. Una, en este caso,
debe considerarse que es 100% de velocidad, no una velocidad de una
unidad por segundo. Podemos agregar animaciones al espacio
de mezcla con
la herramienta de creación de puntos. Al hacer clic sobre a cero. Podemos agregar la animación inactiva. Uno, la animación de caminar. Haga clic en establecer la
posición de fusión dentro del espacio. Luego haga clic en cualquier lugar a
lo largo del eje para ver cómo
se ve la animación a esa velocidad. También puede hacer clic y
arrastrar para ver cómo cambiar la velocidad a lo largo del tiempo combina
las animaciones. Bien. Ahora, todo lo que necesitamos hacer es tener
el guión del personaje, decirle al árbol de animación
la velocidad del personaje. Los nodos pueden
comunicarse entre sí fácilmente
asignándolos a variables, y podemos hacerlo todo en
una línea de nuestro script usando at on ready al
inicio de la declaración Llamemos a esta variable, subrayemos animación
de tipo árbol de animación y le asignemos de valor Usando el signo de dólar, entonces
podemos especificar una ruta de nodo para acceder a cualquier
nodo en el árbol de escenas, comenzando desde este nodo
al que se adjunta el script. Si el nodo al que estamos tratando acceder es hijo de éste, simplemente
especificamos
el nombre del nodo. seguimiento de una secuencia de
nodos se puede hacer
separando los nombres de los nodos
con una barra diagonal Si el nombre del
nodo contiene espacios, puede poner la
ruta del nodo entre comillas. Si alguna vez no está seguro
de la ruta del nodo, puede hacer clic en cualquier nodo del árbol de escenas y
seleccionar Copiar ruta de nodo Después pegarlo como texto. Nuestro script ahora tiene una referencia al nodo del árbol de animación. Todo lo que tenemos que hacer es establecer la posición del espacio de mezcla después de nuestros cálculos de velocidad XZ. Usando la variable,
podemos acceder
al método set para establecer
cualquier propiedad que queramos. La propiedad que queremos establecer
se define como una cadena, que representa una ruta
a la propiedad, usando el
mismo formato que la ruta del nodo. Podemos usar las sugerencias
para rellenar automáticamente este parámetro, buscando nuestra posición de sangramiento de
estados de locomoción Al igual que con la ruta del nodo, seleccionando el
árbol de animación en el árbol de escenas, podemos expandir parámetros, locomoción y copiar
la ruta de propiedad Después pegarlo como texto. A continuación, especifique el valor en el que
queremos establecer esta propiedad, que será un valor
0-1 que represente el porcentaje de
la velocidad
máxima del personaje a la que se
mueven Dado que la velocidad D
es un vector, podemos usar el
método length para saber exactamente qué tan rápido se
mueve el personaje a lo largo del plano D. Entonces divide esto por
su velocidad de marcha para convertirlo en un número 0-1 Veamos cómo se ve esto
cuando corremos la escena del juego. Ahora el personaje se mezcla entre la animación de ralentí y caminar relación con su velocidad a
lo largo del plano x d, pero no están girando para coincida con la dirección en la
que se mueven. Intenta experimentar
con diferentes valores para la velocidad de
marcha, la
aceleración y la desaceleración del personaje para ver cómo se siente En la siguiente lección,
agregaremos rotaciones y saltos. Te veré en la siguiente lección. Bien.
19. Rotación: Hola, amigos. En
la lección anterior, animamos la locomoción de nuestro
personaje En esta lección, rotaremos el modelo de personaje para mirar en la dirección en la
que están caminando. Comenzando en el guión del
personaje, si el jugador está proporcionando entrada de dirección de
movimiento, entonces simplemente podemos
decirle a este nodo que
mire su posición actual
más la dirección. Esto girará el
cuerpo del personaje tres nodos D para que su vector base
hacia adelante esté apuntando directamente a
estas coordenadas. Dado que hemos restringido la
dirección al plano x dicho, esto dará como resultado
que solo gire el personaje alrededor del eje y para enfrentar la dirección que el
jugador quiere mover. Pero la rotación
será inmediata y apuntará al personaje en
sentido contrario. Dado que Gudo invierte el eje Z, podemos corregir esto simplemente
cambiando la dirección más
a la dirección menos Además, si tenemos algún
nodo infancia al personaje en
la
escena del juego como la cámara, por
ejemplo, entonces también se moverá y
girará,
que no es lo que queremos. La solución no
va a ser suficiente. Bien. En la escena del personaje, podemos ver que todos los componentes
visuales
del personaje son hijos
de un nodo tres D llamado rig. Seleccionando rig en el árbol de escena, podemos editar su transformación, haciendo clic y arrastrando
el control deslizante de rotación y para rotar el
modelo de personaje alrededor del eje y De esta manera, el modelo de
personaje se puede rotar independientemente
del cuerpo del personaje tres D, por lo que no afectará a ningún otro
niño en la escena del juego. En el script de personajes, al
igual que hicimos con
el árbol de animación, podemos usar at on ready para almacenar una referencia al nodo rig
en una variable privada. Entonces, cuando agregamos
velocidad de movimiento al personaje, también
podemos decirle a la plataforma que
mire hacia dónde va. El personaje ahora
mira hacia la dirección en la que se mueven sin
afectar a otros nodos. Pero la rotación inmediata podría no ser lo que
estamos buscando. Entonces hagamos que el personaje gire un poco cada fotograma. Podemos definir la velocidad de
rotación de un personaje como una variable privada exportada
y darle un valor predeterminado. Los motores de juego suelen calcular las rotaciones en radianes,
no Si no estás familiarizado
con los radianes, un círculo completo de 360
grados es Pi por 2 radianes También hay otra constante
matemática llamada T, que es Pi por dos. Pero si consideramos el caso de
uso para este valor, solo
nos preocupa
qué tan rápido rotará
el personaje
hasta 180 grados. De lo contrario, simplemente
rotarían en sentido
contrario. Así podemos definir el valor de
las variables exportadas como
un múltiplo de Pi o cuántas medias rotaciones puede
hacer
el carácter en 1 segundo cual invertido nos
dirá cuánto tiempo tardará el personaje en girar
a mitad de camino Alternativamente, puedes definir velocidad de
rotación de
tu personaje en grados y usar la función grado a resplandor para convertirla
cuando comience el juego Utilizaré el
método Pi y diré que mi personaje debería poder dar vuelta en medio segundo,
haciendo que la velocidad de rotación
Pi sea dos veces. Bien. En el proceso de física, si el personaje está
dando entrada de movimiento, primero
necesitamos averiguar qué ángulo estamos rotando dos. A esto le llamaremos
el ángulo objetivo. Podemos encontrar nuestro
ángulo objetivo usando trigonometría. Si el ángulo objetivo es theta,
que en este caso, representa la rotación y de un objeto orientado
en la dirección, podemos encontrarlo usando la función tangente
inversa A t dos. Esto toma
dos argumentos flotantes, que son valores de punto de dirección x
y punto de dirección z. Ahora el ángulo objetivo
mantiene el valor, queremos
mover gradualmente nuestra rotación y a. A continuación, necesitamos la diferencia
entre estos dos ángulos, expresada como un número entre Pi
negativo y Pi positivo. Diciéndonos hasta qué punto necesitamos
rotar y en qué dirección. Restar nuestra rotación actual
y del ángulo
objetivo proporcionará la diferencia entre
los dos Para asegurar que el
personaje solo
rotará por
el camino más corto, luego envolvemos este resultado
usando la función rap f, asegurándonos de que el
resultado siempre esté entre el valor de
Pi negativo y Pi positivo. Ahora tenemos todos
los números mágicos, necesitamos rotar al personaje,
pero cómo los usamos. Podemos determinar
la dirección de la rotación usando una
función llamada seno, pasando como argumento la
diferencia de ángulo. Esto devuelve uno negativo si el número es negativo, cero, si es cero, y uno
positivo si es
un número positivo. Si multiplicamos esto por el
carácter es la velocidad de rotación, y Delta, entonces
sabemos cuánto pueden girar y en qué
dirección en un solo fotograma. Añadiendo esto a su rotación y, rotaremos al personaje, pero también sobrepasaremos
el ángulo objetivo Entonces agregando una función de abrazadera, podemos restringir el valor de la velocidad de
rotación por Delta para que solo esté entre cero y el valor absoluto de
la diferencia de ángulo El valor absoluto es
con el seno eliminado, por lo que un número negativo se
volverá positivo. Luego se multiplica por el seno para asegurar que el personaje gira
en la dirección correcta. Esto impedirá que el
personaje sobrepase la rotación y se
detenga en el ángulo objetivo Para que esto sea más eficiente, ya que solo estamos
usando el ángulo objetivo una vez en el cálculo
de la diferencia de ángulo, podemos copiar y pegar
su cálculo en la misma línea y
tener una variable menos. Y como este proceso se está
ejecutando 60 veces por segundo, no
debería estar
declarando ninguna variable Entonces moveremos la
declaración de la variable a la
parte superior del script. Por último, necesitamos eliminar la línea de look out a continuación ya
que ya no es relevante. Ahora el personaje gira gradualmente para enfrentar la dirección de entrada del
jugador. Y podemos alterar la rapidez con la
que rotan en el inspector. A continuación, agreguemos un botón de
ejecución que el jugador pueda mantener
presionado para moverse más rápido. Abra la configuración del proyecto y cambie a la pestaña de mapa de entrada. Agregar una acción de ejecución. Usaré la tecla Mayús
o el botón de la cara izquierda. En el guión del jugador, podemos reaccionar a los eventos individuales de pulsación de
botón de
manera más eficiente que lo hicimos
con las entradas de movimiento usando una función diferente, la entrada de
subrayado Esta función
solo se llama durante los fotogramas cuando hay un evento
de entrada sucediendo. En lugar de Delta, el parámetro para entrada es un evento de entrada, que es una estructura que contiene información sobre cuál fue el
evento que sucedió. Dentro de esta función, entonces
podemos verificar esta estructura para ver si se presionó
el botón de ejecución. Si lo fuera, podemos decirle
al personaje que corra. Bien. De igual manera, también podemos verificar si se soltó el
botón de ejecución. Y si es así, dile al
personaje que camine. En el
guión del personaje, podemos agregar una velocidad de carrera para ir junto
con la velocidad de caminar. Luego agregue otra variable
privada no exportada llamada
velocidad de movimiento con un
valor predeterminado de velocidad de caminata. Todo lo que tenemos que hacer
en las funciones de caminar y correr es establecer el valor
de la velocidad de movimiento para que sea
la velocidad de caminar o la velocidad de
carrera en consecuencia. Entonces usa la velocidad de movimiento
en nuestros cálculos de velocidad. Sin embargo, al determinar
la posición de mezcla para las animaciones de
locomoción del personaje, usaremos la velocidad de carrera Seleccionando el árbol de
animación del personaje, podemos editar el espacio de mezcla
de locomoción Ahora bien, si consideramos que
un valor de velocidad de uno es el personaje
corriendo a toda velocidad. Podemos usar la herramienta Seleccionar
y mover puntos para mover nuestra animación de caminata a
algún lugar más cerca de la mitad del eje y agregar otra animación
en el extremo derecho para nuestra animación de carrera, ya sea cambiando
a la herramienta de creación de
puntos o haciendo clic derecho. A cualquier valor de velocidad, el espacio de mezcla
combinará la
animación más cercana a la izquierda y a la derecha
aplicando pesos a la animación
en función de su proximidad. De vuelta a la escena del juego,
antes de probar una carrera, posible que
queramos darle un poco más de espacio a nuestro
personaje. Entonces seleccionando el piso, podemos editar el tamaño
del piso y de todos sus hijos rápidamente
aumentando su escala. Ahora, cuando ejecutamos la escena del juego, el personaje no solo puede
caminar por la escena, sino también correr
manteniendo presionado el botón de correr. Dependiendo de los valores utilizados para la aceleración
versus la desaceleración, puede
parecer que el
personaje se desliza luchando
por
redirigir su impulso Si echamos un vistazo
al proceso de física, la declaración desglosa
esto en si el jugador está proporcionando entrada de
movimiento o no. Podemos desglosar esto aún más
para tener en cuenta también si el jugador quiere moverse en la misma dirección que
el personaje o no. Para comprobar si a qué dirección quiere ir
el jugador es similar a la dirección en la ya se mueve
el personaje. Podemos usar algunas matemáticas vectoriales. Un producto punto es una forma de multiplicar dos vectores
juntos que dará como resultado un número que representa cuán similares o diferentes
son esos vectores El producto de punto de dos vectores, ambos apuntando en la misma
dirección será uno, y direcciones opuestas, uno
negativo. Si los dos vectores
forman un ángulo recto, son perpendiculares, su producto de
punto será cero. Así podremos comprobar
si los resultados
del producto punto son
mayores o iguales a cero para saber si el personaje debería estar acelerando en
la dirección deseada. Ya que el jugador
quiere moverse en más o menos una dirección similar a donde ya
se mueve el personaje, lo contrario, el
producto punto es negativo, que significa que el
jugador está tratando moverse más o menos en
la dirección opuesta. Debemos decirle al personaje que desacelere, no acelere Ahora la
desaceleración del personaje se puede aplicar cuando el jugador cambia
repentinamente de dirección Ahora tenemos al
personaje girando y corriendo por nuestra escena. En la siguiente lección,
agregaremos animaciones de salto. Te veré en la siguiente lección.
20. Salto: Hola, amigos. En
la lección anterior, giramos al personaje
para mirar hacia la dirección en la
que se mueven. En esta lección,
agregaremos animaciones de salto. Empecemos por habilitar las sombras
de nuestras escenas de la luz del sol. Seleccione el nodo D de tres
luces direccionales, expanda la sección de sombra y active la palanca de activación
si aún no está encendida. Esto nos dará un
poco más
de perspectiva de lo alto que está saltando el
personaje. En la escena del personaje, si
seleccionamos el nodo
del reproductor de animación, la pestaña de animación debería abrirse en la parte inferior
de la ventana. También puedes abrirlo manualmente haciendo clic en la animación aquí. Mirando a través de la
lista de animaciones, podemos ver que hay varias animaciones de
salto diferentes. Si seleccionamos alguna de estas
animaciones, no se reproducirán. Esto se debe a que
el árbol de animación tiene el control total en estos momentos. Seleccione el
árbol de animación y haga clic en la palanca activa para
desactivarlo mientras exploramos
las animaciones de salto. Volviendo al reproductor de
animación, abre el salto completo de animación corta o
larga y pulsa play. Estas animaciones
no son muy flexibles. Queremos que nuestros saltos
sean más dinámicos. abrir la animación de
inicio de salto, podemos ver que esta
animación es lo debería suceder cuando el jugador
presiona el botón de salto. Amplíe para que pueda ver
los fotogramas clave de animación. Dado que hay 30
cuadros por segundo, están espaciados 0.033
3 segundos de distancia. Podemos establecer el snap a
este valor para permitirnos fregar
a cada
fotograma individual usando la línea de tiempo. Si cambiamos nuestra vista previa
a la vista ortogonal izquierda o derecha y acercamos los pies del personaje. Tenga en cuenta que los
pies del personaje permanecen en el suelo durante 0.3 segundos completos
de la animación. Esto es importante, ya que
si agregamos velocidad
al personaje al inicio de la animación,
se verá mal. esto le sigue
la animación de salto inactivo, que debe circular hasta que el
personaje toque el suelo. Lo que luego debería llevar
al salto y la animación. Descomponer estas animaciones
de esta manera permite que el salto sea de cualquier duración y aún así se vea bien
para el jugador. También tenga en cuenta que el
fotograma final de la
animación de inicio de salto es idéntico
al primer fotograma de la animación de
salto inactivo. Esto también es cierto sobre
el fotograma final
del salto inactivo y el
primer cuadro de salto de tierra, pero es menos importante
es el
momento en que el personaje aterriza
podría suceder en cualquier momento. Seleccionando el nodo del árbol de
animación, podemos volver a encenderlo en el inspector y luego echar
un vistazo a la máquina de estado. Podemos agregar las tres
animaciones de salto a la máquina de estado. Me gustaría ponerlos por encima
del espacio de mezcla de locomoción, dispuestos en la misma secuencia izquierda a derecha ya
que serán utilizados Agrega una conexión desde el inicio del
salto hasta el salto inactivo. Entonces mira en el panel
inspector. Estas son las propiedades de la transición entre estados. Queremos que estas dos
animaciones se reproduzcan en secuencia
directa ya que el último y el primer
fotograma son idénticos. Cuando se complete la
animación de inicio de salto, simplemente
cambie inmediatamente a saltar inactivo. Ampliando la sección del interruptor, podemos establecer el
modo de conmutación al final. El icono de flecha en la
máquina de estado cambiará para indicar que esta
transición
ocurrirá al final
de la animación. Agregando la transición de
saltar inactivo a saltar tierra. Queremos que esta
transición ocurra inmediatamente cuando el
personaje toque el suelo. decir, no sabremos
exactamente en qué se encuentra el
salto de marco inactivo
cuando esto suceda. Para evitar espasmos incómodos, podemos cruzar el fundido de las dos
animaciones juntas por una breve ventana como
una décima de segundo, solo el tiempo suficiente para que el
cambio no sea inmediato En cuanto a cuándo ocurre el cambio, queremos que sea inmediato, pero bajo una condición específica, cuando el personaje
toque el suelo. Ampliando la sección avanzada, podemos escribir cualquier condición o combinación de
condiciones que queramos en el área de texto de expresión para controlar cuándo ocurrirá esta
transición. Al igual que en el guión del personaje, podemos usar el
cuerpo del personaje tres nodos D construido en método está en el piso para verificar si el personaje
está tocando el suelo. Cuando esto se haga realidad, la transición
iniciará el desvanecimiento cruzado de salto Idle a saltar tierra por
una décima de segundo, luego jugando el
resto de salto tierra Sin embargo, para usar esta característica, necesitamos volver a seleccionar el nodo del árbol de
animación y cambiar su propiedad de nodo
base de expresión avanzada Este es el nodo al que se
llamará la expresión
avanzada, y queremos usar
el cuerpo de carácter tres nodo D para esto para verificar
el valor de is on floor. A continuación, en una transición de tierra de
salto a locomoción. Vamos a querer permitir que
esta animación se reproduzca en su totalidad antes de
regresar a la locomoción Por lo que es el modo switch
debería estar al final. Mientras que el marco final de la tierra de salto es el mismo que
el primer cuadro de ralentí. Si el personaje aterriza
mientras está en movimiento, entonces no queremos
cambiar inmediatamente de tierra de salto
a caminar o correr. Así podemos agregar una cruz triste a esta transición también para
mezclarla más suavemente. Al agregar una transición de
locomoción a salto, esto se activará cuando el
jugador presione un botón Expande la
sección avanzada y cambia el modo avanzado
de automático a habilitado. Esto vuelve
gris la flecha verde en la máquina de estado, ya que la transición ya
no es automática. Esto nos permitirá activar manualmente
esta transición
a través de nuestro guión de
personajes más adelante. Como no sabemos qué está
haciendo el espacio de mezcla de
locomoción en cualquier momento aleatorio cuando el jugador presiona
el botón de salto, agregar un breve desvanecimiento cruzado a esta animación también ayudará a
suavizar la transición Por último, las animaciones de salto inactivo y salto
terrestre también podrían ser útiles para si
el jugador se
sale de una repisa
en lugar de saltar Agregar una transición
directamente de la locomoción al salto inactivo
se acomodará a este caso Podemos establecer la
expresión avanzada para esta transición sea si el personaje
no está en el suelo. Y el desvanecimiento cruzado de la locomoción para saltar inactivo para suavizar
la transición Pero, ¿y si las condiciones para transición de la locomoción al arranque en salto o el salto inactivo
son ciertas al mismo tiempo El personaje ha
salido del suelo y el jugador presionó el botón de
salto este marco. Si desea controlar
qué transición tiene prioridad en este caso, puede seleccionar cada transición y establecer su configuración de prioridad. El consejo de herramienta nos dice
que a números más bajos se les da prioridad cuando son posibles múltiples
transiciones. Voy a dar prioridad
al arranque por salto en este caso estableciendo su prioridad de
transición a cero. Podemos previsualizar cómo se verán estas
animaciones, transiciones y cruces haciendo
clic en el botón de reproducción en cualquier estado para forzar a la
máquina de estado a ese estado Tenga en cuenta que este personaje
está flotando en el espacio
vacío y
por lo tanto no está en el piso. Nuestro script de personaje
sigue usando el código básico de la plantilla para
hacer que el personaje salte. Deberíamos actualizar
esto para que coincida con la forma en que
manejamos los insumos para
caminar y correr. Abra la configuración del proyecto y cambiando a la pestaña de mapa de entrada, podemos agregar una acción para saltar. Usaré la barra espaciadora y botón de la cara
inferior
de mi controlador como eventos para la acción de salto Bien. Cerrando la configuración del proyecto y abriendo el guión del reproductor, podemos agregar otra condición a nuestro estado de cuenta para verificar si se presionó
el botón de salto. Y si es así, dile al
personaje que salte. Cambiando al guión de
caracteres, podemos agregar una función de
salto público. Bien. Antes de que podamos escribir
la función de salto, necesitamos acceso a
la máquina de estado. Añadiendo otra declaración de
variable debajo del árbol de animación. Comenzando con add on ready, obtendremos una referencia a
la reproducción de la máquina de estado. tipo es la reproducción de máquina de
estado de animación y podemos acceder a ella desde el árbol de animación
usando corchetes. Dentro de los corchetes, podemos especificar una ruta a lo que estamos tratando de
acceder como una cadena. A lo que queremos acceder
es a los parámetros de reproducción. Bien. Como antes, si seleccionamos el nodo del árbol de
animación, podemos ver el
recurso de reproducción enumerado aquí. Al pasar el cursor sobre su nombre nos
da la ruta de la propiedad, o podemos hacer clic derecho y copiar su ruta y
pegarla como texto Ahora que podemos acceder a
la máquina del estado cuando
se le dice al personaje que salte. Si el personaje
está en el piso, entonces podemos solicitar que
la máquina estatal viaje al estado Jump start. Asegúrese de que el nombre
del estado coincida exactamente. Luego copia también la
línea desde abajo, que aplica los
caracteres de velocidad de salto, y elimina estas líneas
del proceso de física por completo. Si probamos esto, el
personaje saltará, pero la animación y la
velocidad no están sincronizadas. Añadiendo otra función
privada separada llamada apply jump velocity, podemos establecer la velocidad y del
personaje
a la velocidad de salto, moviendo el
cuerpo del personaje hacia arriba. Y asegúrate de que el guión esté
guardado antes de continuar. Desactiva el
árbol de animación por un momento. Después en la animación de
inicio de salto, frota hasta el fotograma cuando los pies del
personaje
abandonan el suelo. Al hacer clic en más agregar pista. Podemos agregar nuestras propias pistas
a esta animación. El tipo de pista que queremos
agregar es una pista de método de llamada. A continuación, seleccione el nodo al
que queremos llamar a un método, que es el
cuerpo del carácter tres nodo D. Desplácese hacia abajo hasta la parte inferior para
encontrar nuestra pista recién agregada y haga clic derecho en esa pista donde la
línea de fregado la cruza. A continuación, seleccione Insertar clave. Podemos llamar a cualquier método de nuestro script de caracteres o a cualquiera de los métodos heredados
del cuerpo del carácter
tres nodos D en sí. El método que queremos llamar es
aplicar la velocidad de salto
a nuestro personaje. Recuerda reactivar el árbol de
animación antes de probar. Ahora cuando el jugador
presiona el botón de salto, el personaje iniciará la animación de salto
y esperará hasta que sus pies realmente
abandonen el suelo antes de moverse hacia arriba. Bien. En algunos juegos, es posible que quieras que el personaje salte de manera
más responsable En ese caso, es importante
utilizar animaciones donde los pies del personaje
dejan el suelo al inicio de la animación. Ahora tenemos a los personajes
saltando y cayendo animados. En la siguiente lección
mejoraremos cómo se siente
el salto y cómo
es controlado por el jugador. Te veré en la siguiente lección.
21. Gravedad: Hola, amigos. En
la lección anterior, agregamos animaciones de salto
a nuestro personaje. En esta lección, mejoraremos la mecánica de saltos y
caídas. Prueba del salto,
hay algunos problemas. Es lento y flotante. El jugador tiene tanto control sobre el personaje en el aire
como lo hace en el suelo, y no podemos cambiar la altura del
salto de ninguna manera. Si miramos en el guión del
personaje, la velocidad de salto se
define como una constante. También podemos ver
que la fuerza de gravedad se está recuperando
de la configuración del proyecto. Si abrimos los ajustes del proyecto, podemos seguir esta
cadena para encontrar los ajustes de gravedad bajo
Física tres D gravedad hábil La dirección de la gravedad también
es editable aquí. Aumentemos la gravedad para que el personaje se sienta más pesado. Multiplicaré por dos. Tenga en cuenta que este cambio
afectará a todo en todo el proyecto que
esté sujeto a la gravedad. Si solo quieres afectar
la gravedad del personaje, podemos hacerlo
en el guión del personaje. En la escena del juego, cambiar
a tres D V. En mi mente, realmente no tiene sentido
definir una velocidad de salto. En cambio, me gusta pensar en lo alto que quiero
que el personaje pueda saltar. Podemos crear rápida y fácilmente geometría
básica en
nuestra escena usando un tipo de nodo llamado CS G o geometría sólida
constructiva. Agreguemos una caja CSG. Muévelo hacia un lado y
descanse limpiamente en el piso. Agregue colisión a la caja haciendo clic en la
palanca de colisión en el inspector. Podemos cambiar el tamaño del cuadro
ingresando valores en el inspector o haciendo clic y arrastrando los
puntos rojos en la el tamaño de la caja
hasta que represente la altura máxima a la
que te gustaría que
tu personaje
pudiera saltar Podemos ver exactamente qué tan alta es
la caja con su
valor y en el inspector. Pero asegúrate de que el fondo
de la caja esté en el piso. Su posición de transformación y el valor debe ser la mitad de su altura. Duplica esta casilla ya sea haciendo clic
derecho sobre ella y
seleccionando duplicar o usando el atajo
Control D o comando D. Coloca el duplicado
junto a la otra caja. Haz que esta caja sea más alta que
la anterior y haz
que represente una altura a la que el personaje no
debería poder saltar. En el
guión del personaje, como hemos definido un montón de variables para personalizar cómo se mueve el
personaje, podemos hacer lo mismo con
cómo salta el personaje. Exportemos una
variable privada llamada jump height como flotador y
le demos un valor predeterminado en
algún lugar entre
las alturas de
las dos cajas que acabamos de hacer. Esto permitirá que el
personaje salte
a la primera caja,
pero no a la segunda. Luego agregue una variable privada
no exportada para mantener la velocidad de salto real que se requiere para
alcanzar esa altura de salto. Ahora tenemos dos categorías completamente
separadas de variables en nuestro script, una para controlar
cómo se mueve el portador y otra para controlar
cómo salta el portador. Podemos agregar otra línea
por encima de estos para
enfatizar aún más su distinción
en la categoría portuaria. A continuación, proporcione un
nombre de cadena para la categoría. Voy a llamar a estas variables de
locomoción y a las de abajo variables
saltantes Esto no sólo nos proporciona más información
aquí en el guión, sino que también
los separa en el inspector. También moveré la dirección a la categoría de locomoción y la gravedad a la categoría de
salto Lo marco como privado
con un guión bajo. Si quieres que tu
personaje experimente una fuerza de gravedad
diferente a la de otros objetos en tu juego, también
puedes exportar
otra variable. Vamos a llamarlo masa y darle
un valor por defecto de uno. Esto actuará como multiplicador a la gravedad que se le agrega
al personaje. Entonces a 0.5, la gravedad
se reduciría a la mitad, o con una masa de dos, la
gravedad se duplicaría. En la función ready, podemos calcular la
velocidad de salto usando la física. La velocidad de salto requerida para alcanzar la altura de salto deseada es la raíz cuadrada de
altura de salto multiplicada por gravedad, también multiplicada
por masa si la estás usando y multiplicada por dos. Bien. Cambia la velocidad de salto que se agrega a la
velocidad y del personaje para esta nueva variable, y ahora podemos
eliminar la constante ya que
ya no se usa. También necesitamos multiplicar la gráfica por la masa en
el proceso de física Corremos la escena del juego e
intentemos saltar en nuestras cajas. El personaje puede
saltar lo suficientemente alto como para
llegar al primer cuadro,
pero no al segundo. Intenta experimentar
con diferentes valores de altura de salto, gravedad o masa, y mira cómo
cambian la sensación de los
personajes saltando ¿Y si el jugador no
quiere saltar a toda altura? La mayoría de los juegos tendrán
el personaje para hacer un salto más pequeño
tocando el botón, y un salto más alto,
manteniendo presionado el botón. La animación del personaje que tiene
un retraso antes de
saltar realmente puede ser beneficiosa para implementar esta característica. Empecemos por no
definir una altura de salto, sino tanto una altura máxima de salto como una altura
mínima de salto. Lo que significa que también necesitaremos una velocidad de
salto mínima y máxima. Y calcula ambos
valores en la función ready. Bien. Luego necesitamos escalar
la cantidad de
velocidad que se agrega al personaje
en función de la cantidad de tiempo que
se mantuvo presionado el botón. Para medir el tiempo, hay un tipo de nodo
conveniente que podemos agregar a nuestro personaje un nodo temporizador. Vamos a nombrar este saltador. Y agarrar una referencia al nodo temporizador durante
la fase lista, la misma manera que lo hicimos
con los otros nodos. Dado que el nombre del
nodo contiene espacios, la ruta se
enmarca entre comillas. Dividiendo el salto en
dos funciones de servidor, llamemos al primer salto
de inicio. Cuando se presiona el botón de salto,
podemos iniciar el temporizador. Entonces, cuando se suelta el
botón de salto, podemos establecer su
propiedad paused en true Lo que significa que
cuando lo
iniciemos, también tendremos que establecer su propiedad
pausada en false Por lo que tendremos que editar
el guión de los jugadores para
llamar a start jump
cuando se
presiona el botón y completar el salto
cuando se suelta el botón. En el inspector,
podemos ver que el temporizador está configurado para contar
atrás desde 1 segundo, que es más largo que 0.3
segundos, así que está bien. Pero tenemos que verificar
la palanca de un disparo, así que el temporizador
solo contará una vez y no se reiniciará
cada vez que se complete. Cuando la velocidad de salto se agrega realmente
al personaje, podemos pausar el temporizador si no se
ha detenido ya En caso de que el jugador siga
manteniendo pulsado el botón de salto. Podemos comenzar sumando la velocidad
mínima de salto. Después sumar también la
diferencia entre la velocidad máxima y la
mínima. Multiplicado por uno menos el
tiempo restante en el temporizador, dividido por la
cantidad máxima de tiempo posible, que determinamos a partir de la
animación es de 0.3 segundos. Nunca queremos que esto esté
por encima de 0.3 segundos así
podemos aplicar la función min
para taparlo a 0.3. Si el jugador
presiona y suelta el botón dentro de
un solo cuadro, esto estará cerca de cero, y el resultado será la velocidad
mínima de salto. Si el jugador mantiene
pulsado el botón, el mantiene 0.3 segundos, este será el punto cero 3/0 0.3, que es uno, y el resultado será la velocidad máxima de
salto Una cantidad de tiempo
intermedio
escalará linealmente entre
los dos resultados Vamos a probarlo
ejecutando la escena del juego. Al tocar el
botón de salto, el personaje salta hasta una altura
de 1.5 unidades, y manteniendo presionado el botón,
salta hasta 2.5 unidades. Al mantener presionado el botón durante diferentes duraciones, se producen
saltos de diferentes alturas A continuación, agreguemos más variables
exportadas a nuestra categoría de salto. Control de aire y frenos de aire. Se trata de multiplicadores a aceleración y
desaceleración respectivamente, lo que reducirá la cantidad de control que el jugador tiene sobre el personaje en el aire sin
eliminarlo 0.5 es un buen lugar para comenzar
por su valor predeterminado. Tendrás que probar para determinar cómo quieres que sienta
el personaje en tu juego. En el proceso de física,
el primer bloque de código gira la plataforma de caracteres para
orientarse hacia la dirección deseada. En la mayoría de los juegos, esto
sucederá independientemente de si el personaje está
en el suelo o en el aire. A continuación se suma la gravedad, que sólo se aplica cuando el personaje
no está en el suelo. Este bloque está moviendo
al personaje, pero lo está haciendo de una
manera que sólo tiene
sentido cuando el
personaje está en el suelo. Pero aplicándolo en cada marco, independientemente de que estén en el piso o en el aire medio. Entonces se está configurando la posición de
mezcla de animación de locomoción , que nuevamente, solo se aplica cuando el personaje
está en el piso La aplicación de la velocidad D y el método de movimiento y deslizamiento
son universalmente aplicables Así podemos separar las partes
del proceso de física
en física general, física terrestre y física aérea, escribiendo una nueva función para la física
terrestre y aérea, tanto privada como aceptando
un parámetro de flujo para Delta. Luego podemos cortar y
pegar la gravedad en la función física
del aire y los cálculos de movimiento en la función de
física del suelo. Entonces en el proceso de física, si el personaje está en el
piso, llama física terrestre. De lo contrario, llame a la física aérea. Pasando Delta como
argumento a ambos. Nuestro proceso de física es ahora mucho más pequeño y
más fácil de entender, mientras que la física terrestre
y aérea están separadas entre sí y también son
más fáciles de manejar. Entonces, ¿cómo aplicamos el
control de aire y los frenos de aire? Copia y pega los cálculos de
velocidad x de la física del suelo
en la física del aire. Después multiplica cada vez que
el jugador esté tratando
de controlar al personaje en
el aire por control aéreo. Y en cualquier momento no
están tratando de
controlar al personaje en
el aire por frenos de aire. Esto no es lo
mismo que aceleración y desaceleración en este caso, ya que al intentar dar la
vuelta en el aire, el jugador sigue tratando de controlar
al personaje Aplicando la velocidad de salto 0.3 segundos después de que comience la animación de
salto, produciremos una gran cantidad de tiempo de coyote para el personaje Si no quieres esto, puedes requerir que el
personaje aún esté en el suelo antes de agregar la velocidad de salto
con una declaración if. Además, la inicialización de la
velocidad de movimiento debe estar usando add on ready Actualmente, esto está inicializando la velocidad de
movimiento al
valor predeterminado de la velocidad de marcha Pero si tuviéramos que sobrescribir el valor predeterminado
de la velocidad de marcha, no se asignaría
a la velocidad de movimiento Usa bloques de geometría para construir una pequeña carrera de obstáculos
para tu personaje. ¿Qué tan difícil es controlar a
los personajes saltando? Experimenta con diferentes valores hasta que tengas la sensación
que deseas para tu juego. Ahora tenemos a los
personajes saltando y siguiendo la mecánica,
sintiéndose más realistas. Y la siguiente lección,
agregaremos controles de cámara. Te veré en la siguiente lección.
22. Cámara: Bien. Hola, amigos.
En la lección anterior, ajustamos cómo las fuerzas afectan a
nuestro personaje en el aire. En esta lección, agregaremos
controles de cámara a nuestra escena de juego. Como lo hemos hecho en lecciones
anteriores, sería fácil simplemente hijo de la cámara al jugador. La cámara seguirá
al jugador alrededor, pero luego girar la cámara alrededor del jugador
sería complicado. Pero si solo agregamos otra
capa de separación, un no hijo al jugador con la cámara
entonces un nieto, esto se vuelve mucho más sencillo inclinaciones y
rotaciones de la cámara que
esperamos de los juegos
controlados en tercera persona se pueden lograr únicamente alterando los valores de rotación de
este nodo intermediario, ya sea sobre los ejes x o Girando alrededor del eje y girará la cámara
alrededor del personaje, como esperamos de inclinar
el stick derecho horizontalmente Girando alrededor del eje x inclinará la cámara hacia arriba o hacia abajo. ¿Qué esperamos de inclinar
el palo derecho verticalmente? Debido a que la cámara es
hija de este nodo, coincidirá con su rotación y se
mantendrá enfocada en el
personaje también. Podemos ajustar el punto focal de la
cámara, moviéndola desde los pies del
personaje hasta su cabeza moviendo el
nodo hacia arriba a lo largo del eje y. A partir de aquí, también podemos ajustar la propiedad de
desplazamiento horizontal de la cámara para
desplazar aún más la cámara a lo largo del eje x para producir un efecto de cámara de
hombro. Incluso podemos controlar qué tan
lejos está la cámara
del personaje y controlarlo dinámicamente
cambiando el tipo de nodo. Haga clic derecho en el nodo y seleccione cambiar Tipo y buscar muelle
brazo tres D nodo. También podemos editar el nombre
del nodo para reflejar
su nuevo tipo. Con la cámara como
hijo del brazo de resorte, necesitamos restablecer su transformación, que tenga la misma posición y rotación del brazo de resorte. En el inspector, podemos ver la longitud del resorte
se establece en 1 metro. La cámara siempre intentará
reposicionarse para estar a 1 metro de distancia de este
nodo a lo largo de su eje Z. Aumentemos esa distancia a algo más alto
como 5 metros. Bien. Este
nodo de brazo de resorte también tiene colisión. Si hay un
objeto de colisión entre el origen del
brazo de resorte y la cámara, entonces el margen es qué tan
lejos de la colisión se colocará la
cámara. La cámara se colocará lo
más cerca posible de la longitud del
brazo del resorte antes de
que
ocurra una colisión , comprimiendo el resorte. Si se elimina la obstrucción, el resorte se descomprimirá y empujará la distancia completa Esto se hace con un rayo fundido, comprobando un solo punto a lo largo
del eje del conjunto de brazos de resorte. Pero si también especificamos una
forma para el brazo de resorte, podemos darle el volumen de colisión reemplazando el raycast
por un molde de forma Requeriendo que
haya más espacio vacío antes de permitir que la cámara retroceda a toda la distancia. Si hacemos de la forma una caja, podemos definir sus dimensiones, y ahora la caja
se utilizará para detectar
qué tan lejos a lo largo del
brazo de resorte puede llegar la cámara. Para controlar la cámara,
necesitamos agregar más asignaciones de entrada a
la configuración del proyecto Abra la configuración del proyecto y cambie a la pestaña de mapa de entrada. Agrega acciones para izquierda, derecha, arriba y abajo. Usaré
las teclas de flecha y stick tilt para los eventos que
activarán cada una de estas acciones. En el guión del jugador,
ya tenemos una referencia
a la cámara, pero no es la cámara que
en realidad vamos a controlar. Necesitamos obtener una referencia
al nodo del brazo de resorte. Y lo puso en el inspector. En la función de proceso, podemos llamar a una función que
aún no hemos escrito. En un guión que
ni siquiera hemos creado todavía hasta el brazo de resorte para
mirar en una dirección. La dirección a mirar podemos obtener de la entrada como hicimos aquí, vector de
entrada con la izquierda
como la x negativa, derecha como la x positiva. Busque hacia arriba como la y negativa, y hacia abajo como la y positiva. Vamos a crear el script de brazo de
resorte. Heredará del brazo de
resorte tres D. No hay plantilla para los scripts de tres D del brazo de
resorte, y el valor por defecto sin
plantilla no es relevante Desmarquemos el toggle
de plantilla, lo que nos permite comenzar
desde un script en blanco Simplemente nombraré este brazo de resorte y lo guardaré en la carpeta de
scripts. Ya sabemos que necesitamos
escribir una función pública n, que aceptará un parámetro
de
dirección de tipo vector dos del script
del reproductor. Bien. Solo necesitamos entonces
rotar este brazo de resorte alrededor del eje x por dirección y el
eje y por dirección x Pero como todo lo que sucede durante una función de proceso, está sucediendo 60
cuadros por segundo, y queremos que funcione
independientemente de la velocidad de fotogramas, que significa
multiplicarlo por Delta Pero aquí no tenemos
acceso a Delta, ya que esta función no la
tiene como parámetro. Podemos agregarlo a la lista de parámetros y pasarlo
desde el script del jugador. Bien. O
simplemente podemos llamar a un método incorporado, obtener procesado Delta
T para recuperarlo. Ahora el brazo de resorte que sostiene la cámara girará
con la inclinación del stick derecho. Estas rotaciones están ocurriendo a una velocidad de 1 radián/segundo Podemos editar la velocidad de las rotaciones exportando
una variable privada Vamos a llamarlo velocidad de rotación. Entonces multiplica esto por
dirección y Delta. Si desea que estas rotaciones
tengan diferentes velocidades, puede exportar
variables separadas para ellas. Bien. Si bien normalmente
se permite que la rotación y circule sin fin, la rotación x
generalmente tiene límites Los controles se romperán si
permitimos que la cámara se incline todo el camino para mirar
directamente hacia arriba o directamente hacia abajo. Dado que el
eje de las cámaras aplanado sobre el plano x triste
se convertirá en cero o invertido Por lo que necesitamos sujetar la rotación de los brazos del
resorte para que esté entre un valor mínimo
y máximo. Si la cámara siendo plana con el horizonte es una
rotación de 0 radianes, mirar hacia arriba o
hacia abajo es una rotación de Pi sobre 2 radianes en la dirección positiva
o negativa Sólo tenemos
que asegurarnos de que el valor absoluto sea menor que Pi sobre dos. Aplaudir la rotación x entre Pi
negativo y positivo sobre tres es una solución rápida
y fácil que aún ofrece una amplia gama También podemos exportar estos valores y permitir que se ajusten estos
límites. Bien. Podrías ir más allá y usar
dos quintas partes de Pi, o incluso usar la
función
grados a radiancia para convertir 89
grados Siempre y cuando la cámara no pueda ir directamente por encima o por debajo
del personaje, Bien. En el guión del jugador,
necesitamos hacer algunos ajustes en los controles de nuestros
personajes. Como la cámara ahora es
hija del brazo de resorte, la cámara
ya no gira, al
menos no dentro del espacio local. El brazo de resorte está girando y la cámara permanece
estacionaria con relación a él. Podemos obtener las cámaras vectores de base
global, que en lugar de ser
relativos al nodo padre, serán relativos a toda
la escena. Alternativamente, podemos usar los vectores base
del propio brazo de resorte. Bien. Y en este caso, ni siquiera
necesitamos una referencia
a la cámara en absoluto. Ahora tenemos la cámara fácilmente
controlada por el jugador. En la siguiente lección,
importaremos e implementaremos
modelos ambientales en nuestro juego. Te veré en la siguiente lección.
23. Mazmorra: Hola, amigos. En
la lección anterior, agregamos
controles de cámara a nuestro juego. En esta lección,
construiremos una habitación para que nuestro personaje
corra y salte alrededor de él. He seguido adelante y descargué K Hits Dungeon remasterizado
Asset pack Abrir la carpeta de activos. Si miramos en la carpeta G LTF. Hay una gran cantidad
de modelos que podemos importar
fácilmente a
ado para nuestro proyecto. En Go, primero hagamos
una nueva carpeta dentro de
la carpeta de activos
importados llamada Dungeon Con esta nueva carpeta seleccionada, la
importación de los activos los
colocará en esta carpeta. Al igual que con los personajes, tendremos que hacer
algunos ajustes a la configuración
de importación de estos activos. Empecemos con tierra de
piso Grande. Haga doble clic en el activo
o seleccione avanzado en
la pestaña de configuración de importación para abrir la ventana de configuración de
importación avanzada. Si seleccionamos el nodo D de
instancia de malla tres, podemos permitir que Dios genere
una forma de colisión para este activo automáticamente
marcando el toggle de física. Una malla de alambre de la forma de
colisión es visible en la vista previa y se
agrega una nueva sección de física con varias opciones. Dado que el piso es parte
del ambiente, esperamos que tenga colisiones pero no se mueva como resultado de esas colisiones ni se vea afectado por fuerzas externas como Su tipo de cuerpo es estático. Hay algunas
opciones diferentes para elegir para generar
esta forma
de colisión, y podemos ver que
la actual se produjo usando convexo
descompuesto Esto está bien para la mayoría de
los objetos de nuestro juego, pero si inclinamos la vista previa, podemos ver que la forma de
colisión está notablemente muy por encima del
piso en ciertas partes Esto daría como resultado
que los
pies del personaje no tocaran el suelo, lo que no se vería muy bien. Seleccionar convexo simple
del menú desplegable. Esta colisión tiene
menos polígonos que antes y
el mismo problema Los pies del personaje no
tocarían el suelo en algunos lugares. Seleccionando tri mesh, la forma de colisión coincidirá exactamente con
la instancia de malla. Dado que estos activos son de polietileno bajo, esto no es realmente
un problema tanto en términos
de rendimiento como lo sería si esta malla estuviera hecha de miles
de triángulos la forma de colisión del personaje Sin embargo, la forma de colisión del personaje
colisionará con
estas rocas Dependiendo de cómo
quieras que funcione tu juego, eso podría ser algo bueno o
malo. Sólo sé consciente de ello. Si quieres ignorar
las rocas por completo y solo tener una
caja plana para colisión, luego selecciona la casilla para
la forma de colisión. La forma de colisión de caja no se
configurará automáticamente para que coincida con el
tamaño o la forma de la malla. Pero podemos editar
sus dimensiones y posicionamiento aquí en la
parte inferior del panel. Seleccionaré primos
para este piso para
demostrar cómo la forma de
colisión del personaje interactúa
con las rocas Una vez que su baldosa tenga
la forma de colisión, prefiera, haga clic en importar
para volver a importar el activo. A continuación, echemos un vistazo a un objeto que tal vez queramos
que sea más dinámico, como el activo Boxarg Al igual que hicimos con la baldosa del piso, podemos seleccionar la instancia met tres nodo D y agregar física
haciendo clic en el toggle. Como queremos que esto no
sólo tenga colisiones, sino que también se mueva
y se vea afectado por fuerzas externas como la gravedad, su tipo de cuerpo debe ser dinámico Después selecciona una
forma de colisión para ello. Cambiaré esto
a simple convexo. Algunos objetos, es
posible que no quieras
molestarte con colisiones
o física en absoluto, como pancartas u otros
artículos decorativos En esos casos, no
hay necesidad de
molestarse en editar la configuración de
importación. Repite este proceso para cualquier activo al que quieras
que se aplique la física. Hay muchos activos
en este paquete de activos. No hay necesidad de
hacerlas todas ahora mismo. Siempre puedes editar
sus ajustes de importación y agregarlos a tu
juego más tarde si quieres. Queremos construir una habitación
con estos activos, lo que podemos hacer
haciendo clic y arrastrando cualquier activo al
árbol de escenas para agregarlo a la escena Pero posicionar manualmente cada
activo individual es tedioso Sin mencionar que es posible que
queramos que nuestro juego tenga
diferentes salas. Al igual que tenemos al
personaje definido como su propia escena separada, queremos que nuestros niveles
de juegos sean también sus propias escenas
separadas. De esa manera, la
escena del juego puede cargar cualquier nivel en el que el jugador
esté jugando actualmente Eliminemos el
piso y las casillas CSG. En cambio, podemos reemplazarlos con un nuevo nodo tres D para
representar un nivel de nuestro juego. Vamos a llamarlo mazmorra. Dado que la escena del juego está
pensada para jugar cualquier nivel y
los diferentes niveles probablemente
van a tener
diferente iluminación, hagamos de la luz solar un
hijo del nodo de nivel. Al hacer clic derecho sobre
el nodo Dungeon, podemos guardarlo como escena propia Nombrado Dungeon guardado
en la carpeta de escenas. Así que todos los componentes visuales de la escena del juego en realidad están contenidos dentro de otras escenas. Las únicas cosas
en nuestra escena de juego deben ser el controlador de
entrada del jugador, un personaje, un brazo de resorte y una cámara para que el jugador
controle y el nivel Después haga clic en el tablero de chapaleta para abrir la escena de las mazmorras Aquí podemos editar nuestro
calabozo separado de otras cosas en la escena del juego como la cámara o el personaje En la escena de mazmorras,
podemos agregar un nuevo tipo de nodo, un nodo de mapa de cuadrícula,
que
nos permitirá construir
rápidamente el nivel utilizando los activos que importamos Pero el mapa de cuadrícula requiere un recurso llamado
biblioteca de malla, que tenemos que generar primero a
partir de los modelos importados. En el menú principal,
seleccione escena nueva escena para crear una nueva escena en blanco y seleccione tres escenas D
en la pestaña de escena. Esta escena en realidad no
representará nada en el juego, sino que actuará como una colección de tres modelos D para
usar en el mapa de cuadrícula. Coquizar y arrastrar cualquiera de los
tres modelos D que desee en su mapa de cuadrícula al
nodo raíz de escenas, los
agregamos a la colección Todos los modelos estarán
en el origen de la escena ocupando el mismo
espacio, lo cual está bien. Podemos filtrar nuestros
recursos para
facilitar el proceso de selección utilizando este campo. El filtrado para GLTF
mostrará solo los archivos GLTF. Agrupar seleccionando los activos, podrían agregarse a la biblioteca
de malla mucho más rápido. Una vez que todos los modelos que
quieres usar estén en la escena, guarda la escena no en
la carpeta de escenas, sino en la carpeta Dungeon de
activos importados Y llámelo Dungeon
Mesh Library, con la extensión T SCN Siguiente s escena del menú principal, Exportar como biblioteca Mesh. Guardemos esto en
la misma carpeta, llámalo Dungeon Mesh Library Esta vez con la extensión Mb. De vuelta en la escena Dungeon, seleccionando el nodo Grid Map, podemos asignar nuestra nueva
biblioteca de mallas en el inspector Podemos arrastrar el recurso desde
el sistema de archivos tap
al campo o hacer clic en el
menú desplegable y seleccionar Carga rápida Esto presentará una
lista de recursos dentro del proyecto de
un tipo compatible. Seleccionando nuestra biblioteca de mallas recién
creada, podemos ver que las
mallas se han
rellenado en la cuadrícula de
selección Selección del activo de baldosas. Podemos colocar un mosaico de cuatro en
cualquier parte del
mapa de cuadrícula haciendo clic. Posicionando las teselas, se
ajustarán a las coordenadas de la
cuadrícula
a lo largo del plano XD. Ampliando la sección
de la pestaña del inspector, podemos editar los tamaños de celda a los
que
se ajustan las baldosas del piso Como sabemos que estas
baldosas tienen 4 metros de ancho, fijemos el tamaño de
celda XD en cuatro Ahora, podemos colocar fácilmente una rejilla de tres por tres de
baldosas haciendo clic. Y elimínelos haciendo clic
derecho. Todos estos cuatro
mosaicos están encendidos por cero. Esta es la
coordenada de celda en el eje y. Si aumentamos el piso, entonces las baldosas se
colocarán 2 metros arriba y igual manera en piso negativo
uno, 2 metros por debajo. Y podemos editar la diferencia de altura del
piso con el tamaño de celda y valor. Si queremos agregar mallas
a la biblioteca de mallas más tarde, podemos volver a la escena de la biblioteca
de mallas Este último activo de muro
necesita ser
reimportado con una versión anterior de nomenclatura
G LTF Podemos agregar más mallas a
esta escena. Entonces repórtelo. Asegúrese de que la casilla de verificación Fusionar con
existente esté marcada para actualizar la biblioteca de mallas
existente para incluir las nuevas mallas De vuelta en la escena de mazmorras, seleccionando el
mapa de cuadrícula, las nuevas mallas se agregan a la cuadrícula de selección No todas las
mallas son de 4 metros. Muchos miden 2 metros o
incluso 1 metro o menos. Cambiando las
dimensiones de la rejilla a 1 metro, puedo borrar los mosaicos actuales ya que ahora se superponen. En su lugar, seleccione
coordenadas que estén separadas por
unas pocas celdas para
volver a dibujar las cuatro teselas Pero ahora
se puede colocar una malla más pequeña en coordenadas
cada 1 metro en lugar de cada 4 metros. Bien. Al decidir la ubicación para colocar la malla
en el mapa de cuadrícula, las claves WASD también se pueden
usar para rotar la malla Con una rotación
alrededor del eje x, eje
S y y el eje DZ. La Wk se restablecerá de nuevo
a la rotación predeterminada. Crea un escenario dngon básico a
partir de los activos y guárdalo. Si hay algún
objeto que desee
colocar y no en las coordenadas exactas de la
cuadrícula, aún se
pueden agregar
a la escena separados del mapa de cuadrícula y
colocarse manualmente. Después regresa a la escena del juego. En la escena del juego, el piso de la mazmorra está
por encima del personaje Así que vamos a mover al personaje
arriba del piso. Cuando ejecutamos la escena del juego, el personaje puede chocar
con el piso, las paredes y cualquier otro objeto
de la escena, que tenía física generada
por los ajustes de importación Con estas herramientas, podrás construir una amplia variedad de niveles para tu juego de
forma rápida y sencilla, añadiendo, eliminando o
cambiando cosas según sea necesario. Ahora tenemos un controlador de
personajes en
tercera persona completamente funcional , lo que permite al jugador
controlar a un
personaje completamente animado caminando y saltando en un mundo de tres D. Bien.
24. ¿Qué sigue?: Bienvenido a mi curso
sobre lo esencial del desarrollo
de juegos y Gado. Este curso es una continuación de introducción al
desarrollo de juegos de tres D y Gado pero se
puede seguir y aplicar
a cualquier proyecto que contenga un personaje que el jugador pueda controlar para moverse por
múltiples niveles. Te invitamos a unirte a
nuestro servidor de discordia para trabajar en este curso
junto a tus compañeros En este curso,
cubriremos elementos esenciales que son comunes a casi
cualquier juego de cualquier género. Construyendo una escena de título, menús, transición fluida
entre escenas, movimiento de un personaje entre diferentes niveles de tu
juego, música de fondo, ajustes y
persistencia de datos entre escenas, niveles y sesiones de juego Cuando termines,
tendrás una buena estructura
básica de
un juego que
podrás desarrollar aún más en algo de tu propio
diseño de cualquier género. También aprenderás habilidades útiles para trabajar con el motor de juego
Gada, organizando y diseñando tus proyectos para que
sean más escalables. Estarás
aprendiendo a codificar con script
GD con todo lo
explicado en detalle Aplicaremos principios de diseño
orientado a objetos en nuestros scripts, herencia, encapsulación y abstracción,
para mantenerlos organizados, personalizables y reutilizables
para un proyecto de cualquier tamaño Todos los archivos del proyecto
también estarán disponibles en GitHub, si necesitas revisar
el proyecto tal como estaba después de completar
cada lección. Estos videos fueron grabados
usando Gadot versión 4.2 0.2. El proyecto comienza
con activos de
Ka Kits Character y Dungeon remasterizados Packs
hechos por En este curso,
también estaré agregando activos de Basic Guy Bundle
hecho por Penzilla, y música en el pack
Barns Music hecho por Eric el Funny Todos están disponibles
para descargar de forma gratuita en H dot IO.