Transcrições
1. Sejam bem-vindos à masterclass de Godot 3D!: Construir um jogo em três D
pode parecer complexo, mas com a
estrutura certa, torna-se um processo que você pode
enfrentar passo a passo. Bem-vindo ao curso de desenvolvimento de
jogos Godot D. Eu sou Steve Carstensen,
e nesta aula, vamos construir um jogo completo de
três D juntos usando
Godot Você aprenderá como
trabalhar dentro do motor, entender como três cenas
D funcionam
e, gradualmente, dar vida a
um jogo
jogável por meio de um projeto real Começarei
aprendendo a navegar interface
Godot e a trabalhar
com três objetos D básicos A partir daí, você passará para física,
os controles do jogador, a câmera, iluminação, o som, a interface do usuário e a IA, todos os sistemas principais que
fazem um jogo em três D funcionar. Cada capítulo se
baseia no anterior. Você criará tanques,
ambientes, inimigos e sistemas de jogo passo a
passo, aprendendo não apenas o que fazer, mas por que as coisas funcionam da
maneira que funcionam em Deus Este curso foi desenvolvido para alunos
iniciantes a
intermediários. Não precisa de experiência anterior com Godot ou desenvolvimento de
jogos em três D. Começaremos com
os fundamentos e construiremos tudo juntos Ao final do curso, você
terá um jogo de
três D totalmente jogável
e, o mais importante,
uma base sólida que poderá usar para começar a criar
seus próprios projetos Vamos começar.
2. Instalando o Godot: Nesta lição muito curta, vamos baixar e
instalar o motor GDOGame, que é o que vamos
usar no restante
deste Então, abra seu
navegador e acesse G DO engine.org Você também pode obtê-lo no Steam
e, no momento da gravação
deste curso, a versão mais recente era 43. Então, basta clicar
nele e acessar o GdoEngine e você o obterá para
o
sistema operacional relevante Agora, não vamos usar
a versão habilitada para Net, então simplesmente adquira o Gudo Engine
padrão Os binários habilitados para rede
permitirão que você use C SAP, mas como usaremos script
GD ao longo
deste curso,
isso pode tornar as coisas
um pouco confusas porque são duas linguagens totalmente
diferentes No entanto, as chamadas de
código e função do C Sharp na API e todas essas coisas
são, na verdade, muito semelhantes então se você quiser um pouco
de desafio e quiser tentar converter
mentalmente GD Script em C
Sharp em sua cabeça, você pode fazer isso, mas
eu não serei
responsável por nenhuma insanidade que aconteça como
resultado disso Então, vamos pegar GoFurt lá. E o Gadot não requer
nenhum tipo de instalação. Você pode simplesmente baixá-lo e copiar o executável
onde quiser Assim, você pode colocá-lo na sua
área de trabalho ou qualquer outra coisa. Vou continuar
com todas as
minhas outras instalações do Gadot e voltarei
com você em um momento
3. Visão geral do projeto: Batalha de zona: Ao longo
das aulas deste curso, você
aprenderá a recriar
esse jogo de batalha de
tanques em estilo retrô ,
semelhante ao clássico jogo de zona de
batalha publicado pela Atari Começaremos com o básico da
criação de um tanque,
uma arena de três D, movimentação do tanque por meio da entrada do usuário
e, em seguida, da criação de um sistema
configurável de geração de inimigos com inteligência artificial contra os quais
lutar Ok, então com isso resolvido, vamos começar. Ao carregar o Gado pela primeira vez, você verá o gerente do
projeto. E isso lhe dará uma lista de todos os projetos que você tem disponíveis para você e nos quais você
já está trabalhando. Ou se você está apenas
começando com uma nova instalação,
você não terá nada. Então, vou criar um novo projeto. Portanto, você
pode criar um. Você pode importar um
de um local específico, talvez de uma
versão anterior do Gadot
ou de um local diferente que o
Gado não esteja monitorando, ou pode escanear um local
específico em busca de projetos que
já existam atualmente Então, vamos criar e quando você cria um novo projeto, você tem a oportunidade de dar
a ele um nome de projeto. Então, vamos chamar
nossa Zone Battle. E vamos
criar uma pasta para isso. E o que isso fará é ir para a pasta em que
pedimos para colocar nosso projeto e,
em seguida, criar
uma subpasta com o
nome específico do projeto, para
que não precisemos nos
preocupar em
tentar criar acidentalmente um projeto
e uma pasta que
já tenha coisas nela e,
em seguida, criar uma subpasta com o
nome específico do projeto, para que não precisemos nos
preocupar em
tentar criar acidentalmente um projeto
e uma pasta que
já tenha coisas Então, eu vou mudar
isso e vou colocá-lo em outro lugar. Ele vai para
Larngdo three D e vamos
dar a ele uma nova pasta Na verdade, não
precisamos dar a ele uma nova pasta porque
vamos criar uma. Então selecionamos uma nova pasta, que será Larndo
three D e depois Zone Battle, que é o nome
do nosso projeto Então, para o renderizador, isso vai depender
da plataforma que
você está almejando Portanto, compatibilidade significa que ele deve ser
executado em praticamente qualquer coisa. E então, o celular, é claro, é para dispositivos móveis. A renderização,
os vários efeitos e os diferentes recursos
suportados pelo Three D tendem a
ser
reduzidos em dispositivos
móveis
porque não são tão poderosos quanto o hardware do PC Então, basicamente, se você
tem como alvo telefones, especialmente telefones de baixo custo, use o celular, e ele
diz aqui Portanto, ele suporta
desktop e celular. Os três gráficos D
são menos avançados
, menos escaláveis, e
assim por diante Vamos usar o Forward porque vamos
desenvolver em um desktop. E, como um aparte, eu não
recomendaria tentar seguir este
curso se você estiver tentando executar o Gadot
em um dispositivo Android, especialmente se for Você aproveitará ao máximo este curso
trabalhando em um desktop. Então, com isso resolvido, deixamos nossos metadados de
controle de versão com o Git Na verdade, não faremos nada
com
a Virgin Control
neste curso. Mas se você quiser
enviar
suas coisas para o
controle de origem mais tarde para fazer o
backup, os dados já
estarão lá. Então, agora vamos criar
Ed Okay. Agora que criamos e carregamos nosso
projeto, vamos abordar os conceitos básicos
da interface de usuário do
Gadot E para isso, você pode se juntar a
mim na próxima lição, e aprenderemos sobre como
os vários Windows funcionam
e, em seguida, poderemos começar nosso jogo. Te vejo lá?
4. Navegando no Godot: a janela principal, a árvore de cenário e o inspetor: Bem vindo de volta. Agora que você
criou seu arquivo de projeto, precisamos nos familiarizar com o ambiente de
desenvolvimento Godot A janela principal aqui é onde a maior parte do seu desenvolvimento
ocorrerá, e é importante que façamos sua própria lição. Então, na lição seguinte,
discutiremos como
navegar nessa janela. O próximo passo é o sistema de arquivos. A pasta de recursos
no sistema de arquivos representa a pasta raiz
do projeto. E podemos verificar isso clicando com o botão
direito do mouse e
selecionando Abrir Gerenciador de Arquivos. E você verá que isso nos
leva direto para
a pasta Zone Battle que criamos quando
iniciamos nosso projeto. Aqui está o ponto do nosso projeto GadoFle que é o arquivo físico do
projeto, e aqui está o ícone ponto SVG, que aparece Todos os arquivos, recursos,
scripts, cenas, tudo o que você
arrastar ou salvar diretamente nessa pasta, desde que Gadot saiba o que
são e saiba como
importá-los , aparecerão aqui
no seu sistema de arquivos Você pode até mesmo criar
novas pastas aqui e organizar seu
projeto como quiser. A seguir está a árvore de cenas. A árvore de cenas é
onde acompanhamos a hierarquia dos nós que compõem a cena em que
estamos trabalhando atualmente Tudo no GaDo é
representado por cenas, e as cenas são meramente
coleções de nós. nós em si são simplesmente componentes
pequenos ou às vezes não
tão pequenos que fazem várias coisas, e tudo o que você
poderia querer usar em um GadoGame é representado
por algum tipo de nó Então, por exemplo, se quiséssemos apenas um objeto
de três D representado por uma
posição no espaço de três D, aqui poderíamos criar o nó raiz, e isso
nos daria um nó três D, e um nó três D é literalmente apenas uma posição no espaço
de
três D, o que , é claro, ainda não
discutimos, então isso não fará
nenhum sentido. Mas, além disso, podemos adicionar outros nós abaixo dele como
filhos desse nó, porque na base de
cada cena há um nó raiz
e, em seguida, há vários nós conectados
abaixo dele, e todos eles
formarão sua Então, podemos criar
um monte
deles e todos eles são
considerados parte desse arquivo. Definitivamente
, veremos uma maneira mais aprofundada de usar a árvore de cenas em aulas
futuras e lidar com a hierarquia dos nós
e assim por diante Mas, por enquanto, saiba que tudo o que está em
seu GodObject será representado,
armazenado e exibido
nessa árvore específica Finalmente, precisamos falar
sobre o inspetor. O inspetor
permitirá que você modifique todos os dados visíveis
em qualquer um dos seus nós Então, por exemplo, como um nó três D é uma
posição no espaço de três D, podemos alterar sua posição, sua rotação e sua escala. Então, podemos movê-lo
assim e assim por diante, e você verá que o
valor é atualizado aqui. Mas também, se quiséssemos
mudar isso diretamente, poderíamos. E isso vale para
praticamente qualquer tipo de nó
que você possa ter. Então, por exemplo, se quisermos
adicionar algo diferente,
como uma câmera, você pode ver agora que a câmera
tem seu próprio conjunto de dados. Mas como uma câmera
também é um nó três D, ela terá todos os
dados disponíveis para nó três D, além de todos os dados específicos da câmera. Então, novamente, tudo o que você
poderia querer modificar para um nó existente
está disponível nessa janela. E vamos usar essa janela
extensivamente para definir as informações de nossos nós bem
como investigá-las
enquanto estamos depurando Falando em depurar
coisas, na parte inferior, vemos várias guias que não
estão expandidas no momento, mas uma delas é o depurador,
e é extremamente útil, e definitivamente a usaremos quando chegar a hora vemos várias guias que não
estão expandidas no momento,
mas uma delas é o depurador,
e é extremamente útil,
e definitivamente a usaremos quando chegar a hora
. Aqui embaixo, você também tem editores de
animação de áudio e Shader, bem
como o console de saída Qualquer console de saída é
útil se você quiser transmitir coisas para o console
enquanto o jogo está em execução ou se quiser
procurar mensagens de erro ou algo parecido.
Então aí está. Em poucas palavras, esse é o editor de Gado, e todos os
vários recursos do editor que
usaremos para criar nosso jogo, certeza
investigaremos mais profundidade
nas próximas aulas. E na próxima
lição, como prometi, vamos dar uma
olhada na janela do editor. Então, nos vemos lá.
5. Como navegar no Godot: a janela do jogo e navegação básica no espaço 3D: Mamãe. Bem vindo de volta.
Nesta lição, veremos as noções básicas sobre como
navegar pelos três espaços D de Godo, bem
como algumas maneiras
de configurar
as janelas da janela de visualização
e orientar as coisas que você possa ver o
que está fazendo e
como A primeira coisa que
vou mencionar é que a maior parte desses controles, assim
como quaisquer atalhos de
teclado que possamos encontrar
ao longo desta aventura, são basicamente os
mesmos do Blender Uma das maneiras personalizar isso
é se você acessar as configurações do
editor e
acessar Editores, três D
e navegação, não apenas verá todas as várias configurações, mas também há uma opção
chamada
Esquema
de navegação, mas também há uma opção na qual você pode alterá-la de Gdolablender
para Maya ou Modo, para Maya ou Modo, se forem Também existem combinações de teclas
que você também pode alterar, mas não vamos nos
aprofundar muito nisso. O que vamos aprender aqui é suficiente para você
começar
e, em seguida, você pode se aprofundar
nos esquemas de controle à vontade, pois eles
podem se aprofundar bastante. Então, a primeira coisa
que vamos
observar é como
contornar essa janela E a primeira coisa que você pode fazer é manter pressionado
o botão direito do mouse, e isso orientará sua câmera de visualização com base em sua
posição no espaço de três D. Então, se você segurar
o botão do meio do mouse, ele orbitará a câmera. E, finalmente, se precisar mover
a câmera, mantenha pressionada a tecla Shift e
use o botão do meio do mouse, e isso manobrará
sua câmera Portanto, uma combinação dessas
três coisas permitirá que você oriente sua câmera de forma que você possa ver o que
quer que esteja olhando Você também tem esse pequeno dispositivo
no canto superior direito da tela que permite que você
se ajuste
rapidamente a uma
orientação Então, como você pode ver, se eu clicar
no X, no Z ou no Y, ele se encaixará imediatamente de forma que o eixo esteja
apontando diretamente para mim, e então os outros dois serão
orientados da mesma forma Dessa forma, você também pode ver rapidamente qual é a sua
orientação, caso não
se lembre necessariamente das cores
dos eixos Então, o eixo Z é azul, o eixo vermelho é X e o eixo
amarelo esverdeado é Y. Então, olhando rapidamente para isso, posso dizer que Y é reto cima e para baixo, então estou
olhando diretamente E isso é reforçado por esse pequeno
indicador aqui, que é ortogonal superior O que isso significa é que estou em cima de
tudo o que estou
olhando diretamente para baixo porque estou olhando para baixo no eixo Y. E então, se clicarmos
novamente, nada acontecerá. Hum, e agora estamos
no fundo do poço. Então, se eu clicar aqui para
X, isso trará isso de volta. E então, se eu clicar aqui,
que é o oposto de Z, isso vai trazer isso
para o primeiro plano, que significa que estamos
vendo isso de trás Portanto, você também pode alterar essas orientações
em vez de jogar com esse pequeno controle
clicando com o botão esquerdo do mouse no botão três ou nos
três pontos naquele E agora você pode escolher
uma dessas visualizações e também ver as várias combinações
de teclas dessas visualizações, se quiser alternar
para elas rapidamente. Então, se eu quiser ir para a esquerda, posso selecionar isso da esquerda. E se eu quiser ir para trás, posso selecionar isso
na parte traseira e assim por diante. E ao fazer isso, ele muda para o que é chamado de visão
ortogonal, e isso basicamente significa que
você está olhando diretamente e não está levando em consideração nenhum
cálculo de profundidade Então, normalmente, se você
for para a perspectiva, poderá ver
a visão em perspectiva. E isso é basicamente
matemática. Se você não sabe
nada sobre isso, você realmente não
precisa se preocupar com isso. modo geral,
você
trabalhará na
visão em perspectiva nove em
cada dez vezes , porque ela lhe dá a noção mais realista
do que você está vendo. Basicamente, quando você melhorar
o trabalho com três D, você saberá quando
precisa usar a visualização ortogonal e poderá alternar
para ela Se eu tentar lhe dizer
sob quais circunstâncias as visualizações
ortogonais são usadas, você provavelmente não
entenderá Então, não se
preocupe com isso por enquanto. Trabalhe em perspectiva e
tudo ficará ótimo. E também temos a opção de fornecer várias janelas de visualização Então, se eu clicar no
pequeno botão de visualização aqui, tenho a opção de
dividir minha janela em duas, três ou até
quatro janelas de visualização E quando eu colocar uma
câmera no mundo e veremos como isso funciona
na aula sobre câmeras, poderei mudar uma
dessas visualizações para que ela
me mostre o que minha câmera vê. E então, dessa forma, poderei trabalhar e entender o que o
jogador vai ver, como minhas mudanças também se
refletem no jogador. Então, se clicarmos novamente nisso, voltaremos para o Viewport 1 E sim, isso deve nos bastar. Agora que podemos
manobrar em nosso mundo de três D, mostrarei como
realmente manobrar nosso amigo do cubo
em um espaço de três D, mas isso será uma lição mostrarei como
realmente manobrar
nosso amigo do cubo
em um espaço de três D,
mas isso será uma lição
por si só.
Te vejo lá.
6. Primitivos e espaço 3D — rotação, escala, tradução: Bem vindo de volta. Agora estamos no ponto em
que podemos começar a examinar a manipulação de objetos
em um espaço de três D. E, felizmente para
nós, na verdade, não precisamos
criar esses objetos sozinhos. No mínimo,
se não estivermos usando três modelos D que
criamos ou foram
criados em outro lugar, podemos detalhar
as coisas usando o que chamamos de primitivos
para fornecer E é
exatamente isso que vamos
fazer por
enquanto criar nossos objetos
feitos de espaços reservados Portanto, o primeiro espaço reservado que aprenderemos a usar é
a instância de malha E, tecnicamente, a instância de malha não
é um espaço reservado, mas fornece
primitivos de espaço reservado para usarmos Então, podemos criar
uma nova cena de três D com um nó três D em
sua raiz ou podemos ir para outro nó e selecionar
a instância de malha três D, e é isso que
vamos fazer. Então, o que exatamente fizemos aqui? Bem, criamos uma nova cena, e na raiz
dessa cena está uma
instância de malha com três nós D. Agora, o nó D da instância de malha
três, além de ser
difícil dizer, é um nó três D, o que significa que ele tem uma posição e orientação
em um espaço de três D, mas também tem valores
adicionais. E um desses valores
é a propriedade mesh. Então, se expandirmos essa lista suspensa, veremos todas essas
malhas diferentes que podemos criar E o que
queremos é uma nova malha de caixa. Estrondo. Agora temos uma caixa. Se não quiséssemos uma caixa, poderíamos transformá-la em uma
cápsula ou quadriciclo, o que é uma maneira elegante de
dizer um retângulo plano Também temos um prisma, que é um triângulo Então, sim, isso nos
permitirá criar vários tipos diferentes
de poço, existe até um Touro Essa é bacana.
Eu tenho uma rosquinha Vamos fazer alguns tanques de donuts. Isso vai ter uma aparência hilária. Talvez eu crie alguns
inimigos de hovercraft no
final do curso De qualquer forma, vamos
voltar para nossa caixa. Isso nos dá um cubo e
é uma coisa maravilhosa. Agora, se clicarmos
no cubo em si, ele abrirá a malha e nos permitirá mudar
coisas sobre ela E antes de fazermos
isso, precisamos observar que esses objetos de malha, sejam eles de malha
cilíndrica, malha simples, seja o que for, eles são o que
chamamos de recurso. Então, Gadot realmente trabalha com dois tipos diferentes de objetos Um é um nó, e isso é algo que será
colocado em sua árvore de cena, e o outro é um recurso. E um recurso é basicamente
uma coleção sofisticada de dados. E às vezes precisamos de
recursos dentro de nossos nós. Então, por exemplo, uma instância de malha
três D requer uma malha. O que é uma malha? Bem, uma malha é uma coleção de pontos e faces que, quando renderizados pelo motor de jogo Gadot, nos
fazem ver um cubo, e esses dados são mantidos em um arquivo, que são nossos Um pouco mais ou menos confuso
seria icon dot SVG Um arquivo SVG é um arquivo de imagem. E o que é um arquivo de imagem, mas apenas alguns bits
que determinam Bem, no caso do arquivo SVG, na verdade
é arte vetorial Mas se fosse um bitmap, seria uma coleção de dados que indica
as cores,
as posições e alguns outros
valores dentro do Bitmap Portanto, precisaríamos
desse arquivo bitmap para texturas, sprites
ou qualquer outra coisa Então, por exemplo, o
sprite seria o nó e exigiria
um recurso de bitmap Essa é uma maneira elegante de dizer
que a malha requer uma malha, e uma malha é um recurso, e é assim que fazemos Criaremos
recursos posteriormente
no curso, quando trabalharmos em nossas interfaces de usuário
e outras coisas semelhantes. Mas agora temos coisas que podemos mudar como parte
do recurso. Então, se quisermos alterar seu tamanho nas direções X e Z, por exemplo, para
torná-lo maior, podemos. E, novamente, temos nossa
pequena seta circular aqui para fazer as coisas voltarem ao
normal, se quisermos que seja assim. E também temos coisas que podem indicar texturização e várias outras coisas que
veremos mais tarde, mas provavelmente não vamos
alterá-las dentro
da própria malha Vamos
mudar isso em outro lugar. Mas agora que temos um cubo, podemos orientá-lo
e movê-lo E a primeira coisa que
vamos fazer é expandir
a propriedade de transformação da porção D
do nó três dos
dados
das instâncias de malha dentro do expector
e
veremos a posição, a
rotação e a escala Esses três grupos
de números são o que determinam a posição,
rotação e escala dos
cubos no espaço mundial A posição de um objeto
no espaço mundial é indicada em três eixos, que são representados por linhas Então, como você pode ver
aqui, a linha vermelha, o X vai da esquerda
para a direita, a linha Z, que é azul vai em direção ao
horizonte,
e então a linha
esverdeada amarelada,
o eixo Y está para e então a linha
esverdeada amarelada, cima ou para Alterar o valor em um
desses eixos ou em um
desses eixos mudará a posição do
objeto no espaço Então, agora está no que
é conhecido como origem, que é ponto morto, zero, zero, zero,
como você pode ver. Agora, se quiséssemos
mover o objeto para cima, poderíamos mudar seu Y para, por exemplo, um, e
agora ele se moveu. Também podemos mudar sua posição usando
esses controles de seta. Então, agora, o que
vemos na verdade são todos
os controles disponíveis
para esse objeto, então podemos fazer o
que quisermos com ele Mas também podemos limitar os controles com esses
botões aqui em cima. Então, se quisermos apenas
mover nosso objeto, clicaríamos nesse botão
para colocá-lo no modo de movimento, que ocultaria os
outros controles de rotação, que
significa que não
seríamos capazes de girá-lo, apenas
poderíamos
movê-lo ao longo do eixo aqui Portanto, as setas são bastante
autoexplicativas, mas o que é um pouco confuso
são esses pequenos retângulos E esses retângulos são uma forma curta de mover algo ao longo de
um plano específico Então, por exemplo, este aqui, esse azul moverá o objeto em
relação às coordenadas X e Y
ou basicamente ao longo do plano horizontal que
esses dois eixos compõem Então, vamos colocar isso de volta em zero. E se eu começar a
movê-los, você pode ver que meus valores X e Y estão mudando
aqui no inspetor Se eu fizesse o mesmo
com este verde, estaria nos eixos X
e Z e o mesmo vale para o vermelho nos
eixos Y e Z. Portanto, isso fornece uma maneira rápida de mover a coisa em uma orientação
específica. Então, por exemplo, se você
quisesse simplesmente deslizar algo no chão sem
acidentalmente arrastá-lo para o ar, você poderia
movê-lo
assim ou
movê-lo assim, dependendo de para onde
você estava olhando E fica um pouco
mais fácil orientar uma dessas coisas se você
estiver olhando para uma direção
específica, e agora eu posso usar Ds. Portanto, mudar a posição de um
objeto no espaço
físico de três D é conhecido como translação e é representado pela propriedade de posição aqui. Além disso,
vamos
analisá-los um pouco
mais no futuro, mas uma coleção de
vários valores, como X, Y e Z, é conhecida como vetor. E há todo tipo de
matemática que vamos fazer com
vetores para mover coisas e fazer cálculos
físicos e todo
tipo de outras coisas divertidas Mas veremos isso
em uma lição posterior. A etapa é a rotação, e a
rotação pode ser definida com o modo de rotação ou simplesmente
colocá-la de volta no modo de
seleção para que você possa fazer o que puder para
reorientar todas elas. Mas vamos voltar
ao modo de rotação. E o modo de rotação permitirá que você gire o objeto
ao longo dos três Então, se eu quisesse girar em torno do eixo X, eu
usaria esse vermelho E então, se eu quisesse manobrar orientá-lo em torno
do eixo amarelo, eu usaria o amarelo
, e então o azul, é
claro, é o E uma coisa que você também
notará ao passar o mouse sobre
esses botões, verá que
há teclas exibidas que permitem que você obtenha
funcionalidades extras Então, por exemplo, se
mantivéssemos
o controle pressionado e
tentássemos girar essa coisa, ela se encaixaria na grade Então, como você pode ver,
não está girando suavemente. Está pulando de um
ponto a outro. E isso é um pouco mais óbvio se voltássemos ao modo de movimento, porque cada uma dessas interseções da
grade é uma coordenada na Então, se eu segurar o controle
e agora mover isso aqui, você verá que ele
se encaixa no centro
daquele ponto ali, que é 000 menos um, eu acho,
na Sim, bem, zero,
zero, um, na verdade, porque Z positivo
está indo em sua direção e Z negativo está
voltando para o horizonte. Nós. Mas, como você pode ver, está
se ajustando às localizações
individuais da grade aqui, números inteiros E você pode, é claro,
mudar esse estalo. Bem, não está lá,
mas você pode alterar esse encaixe nas
configurações do editor Não é isso. Tudo bem,
vamos voltar. E, finalmente, temos a escala, e a escala é meio estranha porque a escala altera o tamanho de um objeto de uma maneira
específica Então, agora, todos os três
estão trancados. Então, se eu mudar um
deles, ele mudará os outros também, que significa que ele será escalado
uniformemente em
todas as direções Se eu os desvincular
clicando neste botão aqui
, posso alterar cada um
deles individualmente, que significa que posso esticar ou ao longo de qualquer
eixo Agora, o problema aqui é que esses valores modificam os
valores definidos aqui. Então, se eu disser que meu cubo
foi um por um, e então eu o escalo nas direções X, Y e Z de forma que seja dois e dois, Oh,
isso não funcionou E isso é porque
eu deveria ter feito isso antes de me conectar
a eles novamente. O que está acontecendo é que
ele pega isso um
por um e aumenta por esse fator, de modo que
na verdade é dois por dois por dois Agora, se eu mudasse
isso para que X fosse dois, agora funcionalmente
seria quatro S um, dois, três ou um, dois, três, quatro, porque está multiplicando o tamanho base original do
objeto pelo valor da escala E isso fica confuso porque escalar objetos
pode quebrar a física porque os
cálculos da física acham que o objeto tem um tamanho quando
parece que tem Mas, geralmente, você usaria
o dimensionamento para fixar um objeto que não estava definido na escala correta
quando estava sendo criado no Blender ou qualquer modo geral, quando
você cria um objeto, você quer que ele esteja na
escala correta no espaço mundial Então, essas coordenadas do espaço mundial que vemos aqui na posição
e assim por diante, estão todas em metros,
mas são completamente arbitrárias Poderíamos facilmente vê-los como pés ou jardas ou qualquer outra coisa. O computador não se
importa de uma forma ou de outra. Só sabe que
esse valor é um, e isso é tudo o que é. Mas quando criamos os objetos
em nosso software de modelagem, por exemplo, você precisa de
um quadro de referência. Então, por exemplo, um humano tem 1,5 metro de
altura, mais ou menos. Me desculpe. Eu sou dos EUA, então existem esses valores loucos de
métricas
que, você sabe, não estamos
familiarizados com eles. Mas digamos que
um humano tinha 1,6 metros altura e que um jato tinha
cerca de 10 metros de comprimento. Bem, se você estivesse modelando um
humano e um jato no liquidificador, você gostaria de
ter certeza de que o humano tinha 1,6 metros de comprimento, e o jato tinha na verdade 10 metros de comprimento
para
que você pudesse colocar o humano no jato e tudo
estaria do tamanho certo Digamos que, por
qualquer motivo, o modelador criou o
jato em uma escala diferente, talvez fosse uma miniatura ou
algo parecido, e então você precisou
usá-lo como um jato de tamanho real, e então importou os
dois juntos, e a pessoa é infinitamente
maior que o jato, você gostaria de reduzir ou
aumentar o jato, e espero que a física
não quebre, sim, geralmente é por isso
que
você usaria a escala Na maioria das vezes, porém, você deixará a escala em 1 e depois alterará o
tamanho de suas primitivas Pelo menos é isso que
vamos fazer. É o menos
confuso do grupo. Então, respectivamente, aqui
estão nossos botões de rotação, e então também temos
nossos botões de escala,
nosso botão de escala aqui em cima Assim, poderíamos escalar dessa forma, como
estávamos fazendo lá. E então, é claro, os
retângulos funcionam da mesma maneira. É só que, em vez de
movê-lo, ele vai escalá-lo Então, sim, isso é
como manipular
a orientação básica e outros enfeites de um
objeto de três D em um espaço de três E em nossa próxima lição, examinaremos os materiais
e, em seguida,
construiremos um tanque e começaremos a movê-lo usando as coisas que aprendemos aqui. Então eu
vou te ver lá.
7. Materiais: Bem vindo de volta. Nesta lição, vamos
dar uma breve
olhada na funcionalidade básica
de um material de malha O material é um recurso
que basicamente define muitos aspectos diferentes
da aparência do objeto,
desde sua texturização até sua iluminação, sua transparência e várias coisas A massa permitirá vários efeitos diferentes
que normalmente você precisaria usar um
sombreador para criar Mas, devido aos poderes de seus materiais, você não
precisa se preocupar com isso. Então, vamos adicionar um
material ao nosso objeto e podemos simplesmente clicar
na malha para abrir
as propriedades da malha. E mais ou menos na metade, você
verá o material cair, e vamos criar um novo material padrão
três D. Como você pode ver, há três
tipos diferentes de material do sombreador exigirá
que você escreva um sombreador para lidar especificamente com a forma como você deseja que o objeto
seja renderizado, e isso está muito além do escopo do que
faremos aqui Então, vamos usar um material
padrão três D, e agora você pode ver que nosso
bloco mudou um pouco, e isso
se deve às
configurações padrão do material. Então, se clicarmos uma vez
no material,
o menu
suspenso de materiais se expandirá. E uau, tem
muita coisa aqui. Portanto, o primeiro e mais
importante que
devemos examinar é o
albedo ou albedo Eu não sei exatamente
como isso é pronunciado. Mas o Albedo controla tanto a textura quanto
a cor do objeto Portanto, nosso objeto está completamente
sem textura, como você pode ver. E se quisermos
mudar a cor, podemos clicar uma vez na cor. E então, à medida
que mudamos, você pode ver a cor do objeto
mudando em nossa janela. Vamos
redefinir isso. Também podemos adicionar uma textura
ao objeto. Então, vamos pegar nosso ícone de ponto
SVG e jogá-lo lá. E agora você pode ver que
seu objeto é texturizado, embora a escala não
seja particularmente boa porque essa textura
não foi feita para esse
objeto em mente Poderíamos corrigir isso abrindo o UV e alterando a escala. Então, faremos isso só
para ver como funciona. E eu acredito que sim. Parece que é Whoops Parece que vai
ser dois e dois. Talvez não. Experimente
três. Lá vamos nós. Portanto, UV se refere
às coordenadas
da textura conforme ela é vista cima e
projetada no objeto As coordenadas UV começam do zero e depois vão
para uma no canto mais distante
da textura. E dependendo da face da textura
que estamos tentando renderizar,
Godot examinará o pixel
naquele ponto e o
projetará aqui face da textura
que estamos tentando renderizar, Godot examinará o pixel naquele ponto e o
projetará Mas, novamente, como essa
textura não foi
mapeada corretamente no Blender ou em
qualquer outro lugar da imagem, tivemos que ajustá-la
aqui embaixo para que ela se encaixasse Então, podemos remover isso simplesmente pressionando nosso
amigo na seta circular, e então vamos subir até aqui
e vamos limpá-la Na verdade, vamos
colocá-lo de volta por um segundo. Porque você também pode colorir alterando a cor do
albedo Então, entre essas duas coisas, você pode ter um
bom controle
sobre a aparência
real do seu objeto. Então, o que Gadot realmente faz
é pegar a textura e depois pintá-la
com base na Então, se você quiser apenas
a cor real, deixe-a como branca. Então, vamos esclarecer isso novamente. E a próxima que nos interessa é a transparência. Portanto, se você quiser um objeto
semitransparente, você pode alterá-lo. Você pode alterá-lo de desativado para um
desses valores diferentes Alpha é o mais
simples. Agora, é claro,
não vai parecer
diferente porque nosso
albedo é totalmente Então, se voltarmos e expandirmos nosso albedo e
mudarmos o Alfa, que é a transparência, agora você pode ver
que o objeto está ficando mais transparente e
podemos realmente ver Vou mudar isso de volta. Outro interessante
é o metálico e sua rugosidade correspondente Então, esses dois
permitirão que você faça o objeto parecer mais
metálico, daí o nome E então a rugosidade
determinará o quão
áspero é o objeto E, ao fazer isso, determine quanta luz está realmente
saindo da coisa. Não estamos obtendo uma imagem
totalmente precisa das configurações com nosso cubo, e isso se deve parcialmente à iluminação
do ambiente, que definitivamente mudaremos em uma aula futura Mas se você quiser ver como deveria ser, se
tudo o resto fosse igual, você pode ver a prévia
na parte superior do material e ela mostrará os
resultados das configurações. Então, se
mudarmos esse albedo, digamos para um pouco
escuro ou cinza, e se movermos bem o metal para
baixo, o metálico Vamos mover o especular
um pouco para baixo e a rugosidade um pouco mais
para baixo. Isso
não parece bom. Então, sim, como você pode ver, alterar esses valores
mudará a aparência do seu objeto e parecerá especialmente interessante quando
começarmos a envolver a iluminação. Outro que
usaremos
eventualmente é a emissão, e a emissão permitirá que o objeto emita
cor e brilho Então, se ativarmos e mudarmos a cor da
emissão para verde, agora o objeto está brilhando em verde, e se mudarmos o multiplicador de
energia, agora ele está E
também temos várias outras configurações
interessantes que abordaremos também temos várias outras configurações
interessantes que abordaremos mais detalhadamente mais tarde, quando
decidirmos embelezar nosso jogo. Então, o que faremos na próxima lição é construir o tanque
controlado pelo jogador a partir de primitivos
e
usaremos o albedo, os metais e
a rugosidade
para fazer com que pareça na próxima lição é construir o tanque
controlado pelo jogador a
partir de primitivos
e
usaremos o albedo, os metais e
a rugosidade
para fazer com que pareça meio decente. E então, nas próximas aulas, vamos revisitar algumas
dessas configurações de materiais e adicionar texturas, mapas de relevo e todas essas vantagens
para que nosso jogo
tenha uma aparência muito boa para que nosso jogo
tenha Sinta-se à vontade para jogar
com esses valores. Basicamente, não
há como quebrá-los. E então, você sabe, o
pior vem para o pior. Você simplesmente volta ao
material e diz, claro, e então você
volta ao zero, e então você pode começar de novo. Então, vamos passar para a
próxima lição, onde vou explicar como construir nosso tanque e
embelezá-lo um pouco, e então criaremos o mundo e nos moveremos pelo mundo.
Nos vemos lá.
8. Como criar objetos complexos a partir de primitivos: o tanque: Bem vindo de volta. O que vamos fazer agora é aperfeiçoar nossas novas habilidades de
manipulação primitiva e construir todos os componentes
a partir de componentes
a partir de primitivos que usaremos em nosso
jogo Geralmente, isso não é o que você faria com um produto
profissional. Normalmente, você teria uma
equipe de arte que criaria suas malhas e outros enfeites
para você importar, e veremos
isso posteriormente no curso, importando alguns
modelos mais bonitos para usar em Mas quando se trata de prototipagem e apenas de
colocar as coisas em funcionamento para que você possa vê-las
funcionando ou apenas de ter
algo pronto para algo começar a codificar seu script de
movimento,
por exemplo, esse tipo
de coisa é Além disso, se você está
realmente optando por um visual extremamente retrô de
baixo teor de poliéster, talvez
queira criar coisas
assim em primeiro lugar Então, em última análise, nesta lição, o que
vamos fazer é construir nosso tanque
e, em nossa próxima lição, vamos construir o
campo de jogo e também tentar salvar
cenas individuais para duplicar objetos Então, vamos começar aqui
com uma nova cena em três D. Então, basta
clicar em três cenas D, e isso
lhe dará um nó três D. E esse nó três D é basicamente um nó vazio que é puramente uma posição
no espaço de três D, como já
vimos, representado pelo nosso objeto de transformação
aqui no inspetor Vamos renomeá-lo,
então clique nele uma vez para selecioná-lo
e, em seguida, clique nele novamente, ou você pode
clicar com o botão direito do mouse e selecionar renomear, e vamos chamá-lo E, eventualmente,
em futuras aulas, duplicaremos esse
tanque para criar nossos inimigos Além disso, é uma
boa ideia salvar seu trabalho. Então, por que não
selecionamos Salvar cena e a colocamos na raiz
da nossa pasta de recursos, que significa que ela vai
para a raiz do nosso projeto, e nós apenas selecionamos Salvar, e isso
nos dará a cena do tanque. Agora, se você ver essa
mensagem de erro aqui, não entre em pânico. Esse é um bug do
Gadot que
existe desde a era
dos quatro pontos dois, e parece que ainda não foi corrigido Novamente, no momento
desta gravação, estávamos em 43 estábulos. Então, novamente, se você ver esse
erro, simplesmente ignore-o. Na verdade, isso não
afeta nada e será corrigido eventualmente. Vamos lá, oh, vamos usar um agrupamento de
três Ds de instância de malha para construir nosso tanque Então, a primeira coisa que
vamos fazer é clicar com o botão direito do mouse em Tank e vamos
fazer o nó Adhild. E
trabalharemos extensivamente
com o nó D da
instância Mesh três aqui Observe também que, depois abrir essa janela de criação de novo
nó, você poderá pesquisar se
souber o nome do nó. Caso contrário, você pode simplesmente expandir as árvores de nós até
conseguir o que deseja. A maior parte do que vamos
trabalhar está na ramificação D
do nó três, por assim dizer. Pelo menos até trabalharmos ou pelo
menos até começarmos a criar nossa interface de usuário e começar a trabalhar com
som e coisas assim. Mas de qualquer forma, agora,
vamos clicar na malha três D e
criar uma nova. E agora que
temos uma malha três D, podemos adicionar uma nova primitiva Então, vamos abrir essa pasta e precisamos de uma nova malha de caixa, e aí está, nosso
bom amigo, o cubo Agora, o que vamos fazer é que esse cubo será
o centro do nosso tanque Então, vou dar a
ele um novo material, um novo material padrão três D, e vou
mudá-lo para cinza. Então expanda o albedo,
clique na cor, arraste a coisa um
pouco para baixo até obtermos algo bonito e cinza
, e pronto Geralmente, o que você quer fazer
ao alterar o tamanho dessas
primitivas é quase sempre trabalhar diretamente no inspetor porque Gadot, pelo
menos até onde eu sei, não tem nenhuma ferramenta para esticar e
esmagar
diretamente esmagar Então, vamos aqui e
vamos dizer que agora
é 0,5, mas vamos fazer com que seja 0,25 Agora, o que estou fazendo aqui
é puramente artístico. Em última análise, o que
vou fazer é um monte
desses primitivos juntar
um monte
desses primitivos para que
se pareçam Sinta-se à vontade para mudar
qualquer uma dessas coisas, alterar as cores, alterar
as proporções, fazer com que seu tanque tenha a aparência que você
quiser. Há apenas algumas coisas que você
precisará fazer exatamente
da mesma forma que eu fiz, principalmente quando
se trata de cuidar da torre, e lidaremos com isso
quando chegarmos a esse ponto Então isso vai ter
0,25 metros de altura, e digamos que vai
ser Whoa, isso é muito grande. Também está na direção
errada. Digamos, 3 metros
mais ou menos, ou queremos cinco?
Sim, boa pergunta. Tudo bem, vamos com três e ver aonde o vento nos leva E 1 metro de largura é bom. Agora, para criar a metade
inferior do tanque, você pode ficar tentado
a simplesmente fazer Controle D e
duplicar sua malha, arrastá-la até aqui e
começar a manipulá-la Mas você teria um problema. Porque, como você duplicou
o nó existente, esses nós compartilham o
mesmo recurso de malha Ele não duplicará o recurso
de malha em si. Então, se você fosse mudar isso
agora, vamos fazer cinco, isso mudará
os dois porque
eles estão operando a partir
da mesma malha. Então, o que você quer fazer aqui
é mudar. Então, você acessará o
menu suspenso da malha e selecionará Make Unique. E isso permitirá que você altere essa malha sem
afetar a malha existente. E nós vamos fazer isso. Então, na verdade, vamos redefinir
tudo isso para que
seja um cubo novamente, e vamos mudar
a cor do material porque
agora queremos que seja verde E temos exatamente o mesmo
problema porque, novamente, é compartilhar o
material, então queremos mudar isso e tornar
isso único também. E agora, se mudarmos
a cor do albedo, devemos ter There we go Agora podemos obter um belo
verde sem
que isso afete mais nada.
Clique nele uma vez para fechar. Tudo bem, então a
largura é a mesma, e vamos fazer
o Y a meio metro E o que você pode fazer
aqui é usar as setas para mudar
a orientação e clicar
nessa coisa para as vistas ortogonais, de
modo que você possa alinhar as coisas da forma mais
perfeita possível mais
perfeita Mas você também pode fazer isso
por meio da transformação. Digitando os
números diretamente. E, na maioria das vezes, é
isso que costumo fazer porque sei o quão grandes são as
coisas que estou fazendo. Então, neste caso,
temos que o Y tem meio metro
de altura, então isso significa que de zero até o
fundo será 0,25 Então, se eu mudar isso para 0,25, isso deve estar alinhado
incorretamente E isso é porque, certo. Bem, faça com que seja 0,5, e isso
também vai estar errado. É zero ponto Ok, bem, isso me serve bem para tentar
fazer matemática na minha cabeça. Tudo bem, vamos
arrastar isso aqui. E se você aumentar o zoom o suficiente, você pode ver que é o mais próximo que importa. Também mencionarei
uma das razões pelas quais você não
gostaria de fazer
isso em um jogo real,
embora, em nosso caso, como
nosso jogo tem baixo teor de poliéster,
isso realmente não afete nada
, pois isso realmente não afete nada você terá
problemas com a otimização Então, por exemplo, quando
terminarmos nosso tanque, nunca veremos
essa face
desse cubo porque ela
ficará escondida na
metade inferior do tanque Da mesma forma,
nunca
veremos o topo desse cubo verde porque ele também ficará escondido por esse bloco cinza E mesmo que
nunca os vejamos. Gadot ainda
tentará renderizá-los. Então, o que vamos fazer
é que Godot renderizará um monte de coisas que nunca
vemos, que não
causará uma queda de desempenho em nosso caso, porque nosso jogo é tão baixo que
isso não importa Mas, em última análise, você gostaria de
construir essas malhas em um programa externo
como o Blender, de forma que essas faces invisíveis simplesmente não façam parte
do modelo Mas, novamente, tudo o que estamos fazendo é prototipagem, então
está tudo bem Então, vamos recuar um pouco para fazer com que
pareça meio legal. E então duplicaremos essa malha e a
moveremos um pouco mais para trás. E o que vamos fazer aqui é, na verdade,
transformar a malha em um prisma e dar a
ela seu próprio material,
novamente, um novo material padrão , queremos que ele tenha
a mesma cor entanto, queremos que ele tenha
a mesma cor dos outros materiais. Então, vamos expandir isso. Nós vamos para Albedo. E então, quando
clicamos na cor, agora temos um pequeno conta-gotas Então, se clicarmos no
conta-gotas e entrarmos aqui, podemos obter exatamente a mesma cor, o que significa que agora essas
duas coisas estão Portanto, uma das configurações
úteis prisma é
da esquerda para a direita, o que permite inclinar a parte superior
do triângulo Então, se
definirmos como zero, será um triângulo
perfeitamente reto. E agora queremos transformar esse cara de um jeito
que fique assim E vamos garantir que
a transformação esteja correta. Então, isso está um pouco errado. Então, queremos que seja
igual a 180, e pronto. E agora vamos
precisar que tenha
a mesma altura que esta aqui. Portanto, a altura é
metade na direção Y. Então, vamos mudar isso para uma
metade na direção Y. E também queremos que não seja tão largo na direção
X. Então, vamos fazer com que seja 0,5. E podemos trazer isso, e ainda assim
não é que seja muito grande. É que o
outro está muito longe. Então, se movermos isso para
lá,
clicarmos nisso e
movermos isso para cá, parece muito bom, embora
tenhamos que aumentá-los um pouco em termos
de transformação Ainda não
descobri o que essa posição Y
deveria ser Zero, 3,75 talvez. Isso
parece muito bom. E então essa malha precisa
ficar um pouco acima. Deve ser 0,5, menos 0,5. Lá vamos nós. Isso
parece muito bom. Embora eu
gostaria de saber, ok, esse material realmente
parece muito escuro. Então, queremos que eles sejam iguais. Então, vamos abrir isso
e o albedo. Tudo bem, tem aquele feitiço, e então olhamos para este Vamos aqui, o albedo. Sim, são números
diferentes. Então, vamos copiar este. Espere? Não. Eles são
do mesmo número? Copie esse. Vá aqui. Não, eles não são da mesma cor. Eu não sei o que eu era Eu não
sei o que aconteceu lá. Provavelmente é por causa
da iluminação, na verdade. Ok, vamos lá.
Isso é perfeito. Agora, vamos
pegar essa aqui e
duplicá-la, girá-la e usá-la para
a outra parte aqui Então, mais uma vez,
expandiremos a malha. Expandiremos a transformação. Transformamos, mudaremos
que o Y precisa ser 180 agora. Então, agora rotacionamos isso. Queremos isso aí, e
esse vai ser 2,5? Não, bem, eu cometi
o mesmo erro
que cometi antes. Preciso
torná-lo único. Lá vamos nós. E o
que foi esse T two é demais. 1.5. Parece muito bom. Mover isso. 0,75. Legal. Tudo bem, então este é o
fundo do nosso tanque, e está muito bom Agora vamos
duplicar esses três. Então, selecionamos um clicando com o botão
esquerdo nele
e, em seguida, clicamos
com o botão esquerdo para obter os três. E então podemos duplicá-los. E então podemos
girá-los ao longo do eixo X. Então, vamos em 180 graus
e agora os movemos para cima Qual foi o
valor negativo desse? Então, podemos copiar isso. E depois de selecionarmos
todos os três, podemos realmente modificar todas as suas posições ao
mesmo tempo. E precisamos inverter o
sinal lá. Estrondo. Perfeito. Ok, então vamos clicar em Controles, para garantir que salvemos nosso
trabalho caso nosso computador exploda, porque não
queremos ter que
fazer isso de novo. E agora vamos
fazer a torre. Mas antes disso, seria uma boa ideia
agrupá-los como o corpo. Então, vamos adicionar outro nó
filho ao tanque, e este será
apenas um nó três D. Vamos chamá-lo de corpo. E nós vamos nos mudar. Vamos selecionar todos eles
e vamos movê-los. Vamos
arrastá-los até aqui para colocá-los debaixo do corpo E isso significa que
agora, se precisarmos
manipular o
corpo inteiro de qualquer forma, forma ou forma mais
tarde, podemos fazer isso Mas estamos mais preocupados em fazer algo semelhante
para a torre Então, vamos criar
outro nó três D, vamos chamá-lo de torre E desta vez,
vamos adicionar outra instância de malha três D, e esta será uma trilha
de tubo, que tem um nome estranho de malha Mas o que acontece é que é uma
espécie de cilindro, mas você pode mudar o número
de lados do cilindro. Então, se formos, digamos, seis, agora
temos um hexágono. Se chegarmos a 12, teremos o
que quer que seja , um dodecaedro,
acho Então, vamos reduzir isso de
volta para seis
e, mais uma vez, pegaremos bem a cor, você sabe,
na verdade não precisamos fazer isso. Então, vou mostrar como copiar todo
o material em um
momento. Então, vamos pegar isso. Vamos mudar o
raio para 0,125, que é muito pequeno. Digamos que 0,25. Isso é melhor. E então
mudaremos a altura, que é tecnicamente a Então, se mudarmos o
número de seções, sim Então existe e podemos
realmente verificar isso, e eu vou te mostrar em um momento.
Então, vamos aumentar isso. E se formos ver,
ok, não está sob vista. Está sob o
Não, não está sob os três pontos. Onde estava aquela coisa? Ok, estava aqui e embaixo.
Esses três pontos. Se formos aqui e
mudarmos da tela normal para a tela wireframe, boom Agora podemos ver o e
eu vou centralizar isso novamente. Você pode ver os polígonos,
os triângulos que
compõem sua primitiva. Então, neste caso, o que temos aqui é que temos duas seções, que são a metade superior e
a inferior, e cada seção
tem vários anéis. Então, se eu mudar
isso para isso, agora temos apenas duas
seções, ou melhor, dois anéis. Portanto, essa é uma forma de reduzir o número de seções
em sua coisa. E por alguma razão,
não me deixa fazer uma seção. De qualquer forma, são necessários dois. E podemos realmente
mudar a forma
dessa coisa usando as curvas, mas não vamos fazer isso Portanto, o comprimento da seção é bom. E, na verdade, não,
vamos reduzir isso. Para 1,25, isso deve achatá-lo. Sim, lá vamos nós.
Ok, então vamos pegar isso. Então aqui está a torre. E tudo bem, vou colocar isso de
volta no modo normal. Estrondo. Então, o que temos
aqui é que o nó
raiz original da torre está aqui, mas depois mudamos para a instância de
malha aqui em cima Então, na verdade, queremos
alterar a
transformação das instâncias da malha para
zero, zero, para que
fiquem centralizadas, para que fiquem centralizadas exatamente onde a torre
deveria estar E agora vamos movê-lo
para trás e para baixo, de modo que fique diretamente contra o corpo o mais
próximo possível , porque não
queremos que nenhuma luz
espreite pelo Nós vamos para um desses
segmentos corporais, não aquele. Nós vamos para um
desses segmentos corporais. Agora podemos copiar o material e ir aqui e
depois colar o material. E agora não precisamos nos
preocupar em mexer com o conta-gotas e garantir que obtemos as cores
certas Então cole, bum, aí está. E agora vamos
fazer outro
desses para o barril Então, desta vez,
vamos usar um cilindro e vamos girá-lo E também podemos girá-lo
assim. Então, se
fizermos isso, faremos assim. Agora, idealmente
, essa rotação mudará quando
jogarmos o jogo. Vamos fazer com que
possamos levantar e abaixar o cano Mas, por enquanto, queremos que
seja bom até 90 graus. Abra a malha. Cole
o material novamente. Vamos mudar o Whoa. Tudo bem, então as alturas. Vamos fazer com que seja 1,5. E mudaremos o raio superior
e inferior Então, como você pode ver, se eu
mudar o raio superior, ele meio que o
transforma em um cone Tudo bem, então
vamos realmente fazer com que seja 0,120 0,1. Sim, 0,1. Parece muito bom. Agora, simplesmente arrastamos esse cara até
aqui até que fique, mais
uma vez, o mais carnudo
possível com a torre E se entrar um
pouco, tudo bem. Não precisa ser perfeito. É só que queremos que
seja o melhor que pudermos. Tudo bem. Parece muito legal. Eu não sei. Eu ainda
acho que isso é muito grande. Vamos fazer com que seja 0,05. Lá vamos nós. Eu gosto disso. E agora vamos adicionar um focinho. E o focinho
vai ser basicamente o
mesmo que essa coisa, então podemos duplicá-lo. E vamos tornar a malha única novamente para que
possamos modificá-la. Vamos mudar
a transformação. Uh, vamos
dar uma rotação de 90. O que acabou de acontecer? Hmm. Interessante. Eu não
sei para onde isso foi. Tudo bem, a posição é zero, zero. Tudo bem, você sabe
o que? simplesmente deletar isso
e fazer isso de novo. Tudo bem, vamos fazer
isso à moda antiga. Vamos apenas adicionar outra
instância de malha três D. Vamos dar a ela uma trilha de tubo. Mais uma vez,
colaremos o material correto. Vamos mudar o raio para, digamos, 2,5 por enquanto Vamos mudar isso momentaneamente. Seções. Vamos
reduzi-los novamente. O radial desce para seis. E depois transforme 90. Oh, eu vejo o que fiz da última vez. Tudo bem, eu vejo meu problema. Em vez de mudar a rotação,
mudei a posição, então ele a colocou em 90, que estava fora da câmera. Tudo bem. Claramente,
preciso de outra xícara de café antes de
tentar ensinar hoje. Então, vamos mover isso para cá. Agora, como você pode ver, obviamente, isso é muito grande,
embora possa ser legal para algumas pessoas. Mas vou mover isso para lá e depois mudar
o raio novamente. Então, vamos fazer o raio zero, um. Isso parece muito melhor. Ok, agora temos um tanque, e é um tanque bonito. E a razão pela qual fizemos a torre dessa
maneira é porque
queremos um ponto central para a torre possa
manobrar Então, como a torre
está centrada aqui, normalmente, vamos dar uma
olhada no cano Normalmente, se eu fosse
girar esse cano, bem,
vamos girá-lo, você pode ver que ele está girando
em torno do ponto central da malha,
e não há como
alterar o ponto de ancoragem da própria malha
de forma que Gadot considere que
esse é o que Gadot considere que esse Sempre estará aqui. É por isso que
usamos um nó três D como basicamente o ponto de ancoragem de todo
o objeto, porque
agora, se eu girar o nó, o tanque gira
exatamente como deveria E agora que penso nisso, teremos que fazer
algo semelhante para poder girar a própria torre.
Então, vamos fazer isso agora. Adicionaremos outro filho, que é um nó três D, e este será a rotação das torres, ou melhor, o ponto de ancoragem do
barril E então pegamos as
duas peças do barril e as arrastamos até
aqui para que sejam colocadas ancoragem do
barril E agora, se eu girar isso, o cano pode
girar para cima e para baixo. Porém, como fizemos isso e o barril está
no centro aqui, o que realmente queremos fazer é mover isso um pouco para baixo Tudo bem, vamos mudar isso. E, claro, os barris
estão compensados incorretamente agora, então vamos lidar com Vamos ajustá-lo um
pouco assim. Agora, esses dois aqui embaixo. E, novamente, você pode
selecionar as duas coisas ao mesmo tempo para poder
movê-las juntas. Agora temos isso aí. E agora, se
girarmos o cano,
o cano gira bem, o cano gira bem, embora
devêssemos movê-lo um pouco para
dentro para que não
vejamos essa costura.
Então aí está. E, eventualmente, vamos
querer bloquear a rotação do cano para que ele não
passe pelo fundo
do tanque, mas aí está Tudo bem. Controle S novamente. Nós temos um tanque.
Só há mais um problema: queremos que a
base,
queremos que a origem, a posição
do ponto de ancoragem raiz do tanque esteja no solo Então, já que é por isso que criamos nossas partes do corpo ligadas
a um nó de tanque, agora tudo o que precisamos
fazer é movê-las para cima Oh, vamos fazer isso
na posição aqui. Nós os movemos para cima Agora, o deslocamento do tanque
está na base aqui, e é exatamente
onde queremos que esteja Tudo bem, isso foi muito. Se você quiser continuar
praticando
manobrando pelo espaço
Gado three D e manipulando primitivas de
malha, sinta-se à vontade para trocar
seu tanque ou
adicionar mais peças a ele seu tanque ou Caso contrário, nos vemos
na próxima lição, onde vamos construir o
campo de jogo. Nos vemos lá.
9. Como criar o campo de jogo: Bem vindo de volta. Nesta lição, vamos construir
o campo de jogo para que
tenhamos algo para os tanques e
seus inimigos
correrem e criaremos uma nova cena,
para que possamos entrar na
cena e em uma nova cena E, novamente, será uma cena em três D, então um nó três D. E
vamos renomear essa, e vamos chamá-la de arena jogos, campo de batalha
ou o que você quiser Em seguida, adicionaremos uma instância de malha
três D. E, mais uma vez, daremos a ela uma malha de caixa. Embora, nesse caso, você também
possa usar uma malha plana. Porém, em minha experiência, às vezes
descobri
que os aviões não registram a
colisão corretamente. Às vezes, a física de Gado
fica um pouco maluca. Então, vamos com uma malha de caixa e vamos
alterá-la nas direções X e Y para 100. Bem, não a direção Y, mas sim
a direção Z. E podemos diluí-lo um
pouco, torná-lo 0,5. Não que isso realmente importe. E então, mais uma vez,
um novo material, e este vai ser acastanhado Lá vamos nós. Temos um campo de jogo.
Agora vamos dar um
pouco de cor ao
nosso campo de jogo adicionando algumas árvores ,
algumas colinas e algumas
pedras também Então, adicionaremos uma nova
instância de malha. Na verdade, não. Adicionaremos um novo nó três D e o chamaremos de árvore. Ok, vá lá. Clique com o
botão direito. Lá vamos nós. E essa árvore, novamente, será um par
de instâncias de malha. Portanto, a primeira instância de malha
instantânea confusa não
é uma palavra fácil de dizer A instância de malha será um cilindro. E esse cilindro vai ser marrom escuro para ser
o tronco da árvore. E nós vamos conseguir. Bem, o raio está bom
e vamos fazer com que seja de 3 metros. Vou deslizar isso até
aqui de forma que
fique nivelado com o chão E também adicionaremos
uma esfera na parte superior. Então, outra instância de malha, esta será uma malha esférica, e o material será verde Agora, é claro, essa
esfera é muito pequena, então vamos contrair
o material, e então vamos para o raio,
e vamos torná-la, digamos, duas, e a altura também
será duas E neste ponto, você pode
fazê-los como quiser. Então, se eu fosse fazer esses cinco, ficaria assim,
o que é muito legal. Originalmente, eu os tornei
perfeitamente esféricos, o que também funciona, mas
agora que penso nisso, eu meio que gosto
um pouco mais disso Então, faremos isso. E
vamos mais uma vez nos certificar de que tudo bem, agora
temos uma árvore Agora, queremos as árvores. Queremos poder usar a
árvore basicamente como uma peça pré-fabricada forma que possamos copiar colar
e colocar
quantas árvores quisermos Mas, para fazer isso,
precisamos de uma forma
comum de nos referirmos a cada árvore, porque
digamos que copiamos,
acabamos de fazer o Controle D e copiamos e colamos
várias dessas árvores. E então, por algum motivo mais tarde, decidimos que queríamos que o tronco da árvore fosse
azul, por exemplo. Bem, teríamos que
voltar e
trocar todas essas
árvores manualmente. E se colocarmos 100 árvores
em nosso campo de jogo, seria muito trabalhoso Então, vamos clicar com o
botão direito do mouse e selecionar
Salvar ramificação como SN. E então já está assim, ele automaticamente padroniza o nome do arquivo para o
nome do Então, vamos ficar bem aqui. Vamos simplesmente clicar em tree
e, mais uma vez, ignorar esse erro de análise Simplesmente nunca vai embora. E agora temos uma árvore. Então, se quisermos, agora
podemos arrastar mais árvores para nossa cena, e
temos duas árvores. Então eu vou fazer isso
algumas vezes. E você pode fazer uma verdadeira
floresta se quiser, mas vou
colocar três aqui E vamos fazer a
mesma coisa e construir uma colina. E não será a colina
mais bonita
do mundo por causa das
limitações de nossas malhas, mas vamos fazer um prisma e vamos torná-lo E vamos
torná-lo marrom. Faça com que seja um pouco mais
marrom do que o campo de jogo. E devemos renomear
isso para Hill. Agora que temos isso,
podemos fechar o material e alterar a transformação porque
queremos girá-la E então vamos
igualar isso para menos 120. E vamos
igualar isso para menos 120. O que na verdade não é
totalmente correto, mas na verdade não é. Parece que menos 115. Não. Interessante Ok, independentemente disso, agora
temos uma colina, que ainda não é grande o suficiente. Vamos fazer com que sejam sete ao redor. E isso é apenas um gosto puramente
pessoal aqui. Não há nada incrível de sim ou não. É por isso que isso precisa
ser desse tamanho. Só estou fazendo isso porque é o
que eu quero que seja. Você mesmo pode
alterá-los facilmente. Além disso, dado o fato de que as colinas são literalmente
como triângulos, elas não precisam ser muito detalhadas para os propósitos
de nosso protótipo aqui, mas você pode facilmente adicionar mais instâncias de malha às colinas e
torná-las Mas vamos colocar
isso aqui. E mais uma vez, clicaremos com o botão
direito do mouse em Salvar como visto. E agora temos uma colina, então
vamos adicionar outra colina. E podemos facilmente fazer uma pedra
fazendo a mesma coisa. Então eu clico com o botão direito do mouse e dupliquei e
chamaremos isso de uma pedra E vamos salvar esse
galho como uma cena. Tudo bem, havia
uma mensagem de erro lá. Salve o ramo da cena. Qual foi a
mensagem de erro? A mensagem de erro foi pode salvar a ramificação de uma cena
já instanciada. Para criar uma variação
de uma cena, você pode criar uma cena herdada
com base na cena instanciada Então, não queremos fazer isso. Então, acho que vamos
fazer a pedra manualmente. Veremos
cenas instanciadas em uma lição futura. Então, por enquanto, vamos
voltar para a Arena. Child Node, instância
três D. Rock. E vamos fazer com que as rochas sejam
um pouco diferentes. Faremos as rochas
como uma esfera, mas elas serão pequenas
e estarão meio enterradas na metade
enterradas no chão. O albedo é cinza. E vamos fazer o raio de 0,75. E também salvaremos a
rocha como sua própria cena de rock. E pressionaremos o Controle D
para duplicar as pedras algumas vezes e
moveremos algumas Agora temos nossa arena, e as colinas estão meio desligadas, então é
bom termos feito
uma cena com elas para que eu possa
mostrar a vocês como ajustar isso. Então, vamos dar uma olhada em como clicar
duas vezes não funciona. Tudo bem, vamos para cá. Então, o que
podemos fazer é
clicar duas vezes nesse pequeno ícone
que diz Abrir editor, podemos abrir a
cena Hill no editor. Mas, ao fazer isso,
podemos editar a cena
e, em podemos editar a cena
e, seguida, todas as outras cenas serão atualizadas para levar
isso em consideração. Então, vamos dar uma olhada aqui. Temos nossa transformação,
o que é estranho. Continue perdendo a noção disso. Ok, então vamos realmente trazer o vermelho para frente. Lá vamos nós. Ok, bem, em vez
de mexer com isso, a maneira mais fácil de consertá-lo
é simplesmente movê-lo
um pouco para baixo para que a parte inferior seja cortada pelo terreno Então, agora, se salvarmos isso e voltarmos para Oh,
nunca salvamos nossa arena. É melhor fazer essa
cena, salvar a Arena. Um Hmm. Ok. Não. Ainda temos
isso, correto? Ok, sim, é
só a sombra, não. Ali mesmo. Ok, agora as colinas estão
devidamente alinhadas com a arena. E, novamente, você
notará que mudamos a posição Y da colina diretamente na própria cena da
colina
e, em seguida, as duas
colinas foram
atualizadas automaticamente quando a salvamos e
voltamos ao nosso nível principal. Ok. Oh, esse é o nosso nível
, tão incrível quanto parece. E se você
quiser continuar
praticando a criação de cenas e colocação de pré-fabricados no nível, por que não
aprimorar um pouco Uma boa coisa a fazer
provavelmente seria fechar
essa fronteira com colinas para que, quando eventualmente
implementarmos a colisão na física, o tanque não caia
da borda do mundo Em nossa próxima lição,
adicionaremos uma câmera
e, depois disso,
abordaremos
as coisas boas. Então eu
vou te ver lá.
10. O nó Camera3D: Nesta lição, analisaremos todas as cenas que
criamos inicialmente e não apenas as
reuniremos em
uma cena principal, todas as cenas que
criamos inicialmente
e não apenas as
reuniremos em
uma cena principal,
mas veremos nó
da câmera e como
é essencial dar vida aos seus
três jogos D. Então, temos nossos tanques. Nós temos nossas pedras. tudo o que criamos
na lição anterior. Agora, se
tentássemos rodar nosso jogo, não
obteríamos nada
particularmente impressionante. Então, vamos fazer isso. O primeiro problema que temos
é que não
definimos o que Godot
chama de cena principal Então, como mencionei antes, tudo em Gadot é uma cena, e Godot precisa saber qual é
a cena raiz padrão que ela será carregada e executada
quando iniciarmos o Então, por enquanto, vamos simplesmente
transformá-la na arena. Então, se você tentar rodar o jogo sem ter definido
uma cena padrão, Godot vai te dar
esse diálogo que diz: Nenhuma cena principal foi definida Selecione um. E se dissermos selecionar atual, já que a arena
é nossa cena atual, essa é a cena que
Gadot carregará quando o jogo começar.
E não recebemos nada. E a razão pela qual
não obtemos nada é que
estamos jogando em um ambiente
tridimensional, e Godot não consegue renderizar um ambiente tridimensional
sem uma câmera Então, como você deve ter adivinhado, uma câmera em Godot é um E queremos conectar a
câmera ao nosso player. Então, vamos voltar
à nossa cena de tanque e clicar com o botão
direito do mouse em Adicionar nó secundário. E o que queremos é a câmera três D. Agora observe que,
em muitos casos, também
há duas versões D dos mesmos nós em que
estamos trabalhando. E isso é para ambientes planos baseados em
sprites em dois D. Então, se você estivesse fazendo um jogo de rolagem lateral
baseado em Bitmap ou um RPG japonês à moda antiga, estaria usando dois nós D ou
dois nós D. Mas como estamos trabalhando inteiramente em três
D neste curso, queremos apenas os
nós para três D, pelo
menos até chegarmos à parte
da interface do usuário. Então, selecionaremos a Câmera
três D e a adicionaremos. E agora temos uma câmera
acoplada ao nosso tanque. E você pode ver agora
que temos uma câmera, na verdade, deixe-me excluí-la para
que você possa ver a diferença. Foi um pouco sutil. Então, agora que a câmera
desapareceu, não vemos nada aqui. E agora, se adicionarmos
uma câmera novamente, agora
temos a opção visualizar nossa câmera
na janela frontal. Então, se clicarmos nesta ou
na janela principal, em vez disso. Então, se clicarmos aqui, agora
podemos ver o que temos. E, claro,
parece lixo porque não
alinhamos adequadamente nossa câmera Então, vamos fazer isso.
Vamos desmarcar isso Mas, na verdade, em
vez de desmarcar isso, vamos voltar para visualizar e agora vamos
para duas portas de visualização E, como você pode ver,
nossa porta de visualização superior é o que você pode
ver na câmera, e nossa janela de visualização inferior é a mesma visão em três D
que tínhamos antes Assim, podemos usar essa visão inferior para orientar nossa câmera e vê-la atualizada em tempo real, o que nossa câmera está realmente vendo Então, vamos arrastar nossa câmera para cima porque uma câmera é
apenas um nó
tridimensional, igual aos outros com os quais
estamos trabalhando. Então, podemos
manipulá-lo da mesma forma. Então, vamos
girá-lo para frente, e vou
ajustá-lo um
pouco para torná-lo igual
a menos 90 E eu vou
arrastá-lo um pouco para trás. E vamos movê-lo um pouco para cima e depois
incliná-lo levemente para baixo para
que possamos ver nosso tanque
em toda a sua glória E, claro, a câmera
tem vários grupos de configurações com as quais
brincaremos em aulas futuras. A mais importante delas
é a configuração do ambiente. Mas você também pode alterar o campo de visão da
câmera, que são planos de recorte próximos e
distantes, o
que na maioria das vezes você realmente
não quer fazer Você notará que, se
colocá-lo muito próximo, o tanque eventualmente
desaparecerá porque o
que o
plano de recorte próximo e distante
determina é onde a câmera começa
a renderizar
e onde a câmera termina a renderização a câmera termina a E esse é um
volume de três D por si só. Portanto, qualquer coisa nesse
volume será renderizada. Então, vamos redefini-los novamente. E essa também é uma configuração
extremamente importante, e determinaremos qual câmera está realmente sendo renderizada Portanto, é possível, você já deve ter visto isso
em outros três jogos D ter várias câmeras,
várias visualizações de câmera. E uma das maneiras de
fazer isso é simplesmente forçar
manualmente a câmera
para uma orientação diferente. Mas uma forma mais comum é
simplesmente ter várias câmeras e permitir que você
veja apenas a imagem vista por uma
delas por vez. Então, se tivéssemos duas câmeras, e pudéssemos me deixar, eu
adicionaria uma segunda câmera e veremos isso em tempo real. Então, duplicado. E a segunda câmera, vamos movê-la. Bem, vamos fazer uma prévia
e, claro,
não vemos nada interessante. Então, se voltarmos aqui,
é a câmera atual. E então, se formos aqui,
podemos mudar isso para
a câmera atual. Agora, isso não vai mudar
nada aqui, porque
estamos visualizando automaticamente nossa câmera principal Então, na verdade, isso não é
atualizado corretamente. Isso pode ser um bug,
eu posso estar fazendo algo errado.
Não tenho como saber. Mas se agora
formos fazer nossa cena, não
ganharemos nada novamente porque eu
não a mudei. Então, esta é realmente uma boa
oportunidade para lhe dizer como mudar sua cena
padrão no Gado. Então, se formos para as configurações do
projeto e se formos correr, você poderá
ver a propriedade da cena principal. Então, podemos mudar isso, e atualmente o
configuramos para Ana, que não tem câmera. E se mudarmos para tanque, que tem a câmera,
agora, se
rodarmos o jogo, veremos nosso tanque em
toda sua glória apagada, e estamos vendo a visão da nossa câmera inicial porque
é a primeira câmera, então é o padrão
porque nenhuma de nossas câmeras está
configurada como atual Se configurarmos a segunda
câmera como atual e depois executarmos a cena novamente, devemos ver
a visão da segunda câmera. E aí está. Então, é claro, isso
não nos faz bem, porque tudo o
que vemos é o tanque. E isso ocorre porque o tanque não
está atualmente na arena. Então, vamos voltar para a arena. Agora, poderíamos arrastar o tanque
diretamente para a arena, e realmente não há
nada de errado nisso, mas eu gosto de manter minhas estruturas separadas
e hierárquicas, que é uma palavra que
não é fácil de pronunciar Então, vamos criar uma
nova cena e, mais uma vez, será
um nó três D, e esse que
vamos chamar de jogo. E o jogo, como
você pode imaginar, incluirá a arena, e tudo o que tivemos que fazer foi arrastá-la dentro porque
já a criamos, e depois
arrastaremos um tanque. E agora, se salvarmos
nosso jogo como uma cena, a primeira tentativa que faremos é
limpar isso um pouco e remover
essa câmera mal orientada E agora que
fizemos isso, Gadot
voltará a usar essa câmera como padrão, mas vamos configurá-la como atual de qualquer maneira,
apenas
para manter as coisas consistentes E agora, se
voltarmos ao nosso projeto e mudarmos a cena atual de tanque ou a cena padrão do jogo atual para tanque, não, se voltarmos e mudarmos a cena padrão
de tanque para jogo, e então fecharmos isso
agora, se
rodarmos nosso jogo, veremos tudo o
que esperaríamos ver. E nós fazemos. Agora, é claro, não
colocamos nenhuma iluminação ou algo parecido
no ambiente. Então, é claro, está
completamente escuro. Não temos camarote,
nada disso. Mas tenha certeza de que
melhoraremos nosso jogo
muito, muito Mas antes de fazermos
isso, precisamos
aprender um pouco
sobre vetores e como organizar algumas
dessas coisas para que
possamos realmente movimentar no mundo do jogo E nesse ponto, precisaremos
ver o que estamos fazendo. Então,
analisaremos os ambientes e a iluminação.
Te vejo lá.
11. Vetores: Bem-vindo de volta. Nesta lição, vamos dar uma olhada
no conceito matemático
conhecido como vetor. E a razão pela qual vamos
fazer isso é porque os vetores são usados constantemente, intensamente e
em todos os lugares nos videogames, especialmente quando se
trata de três ambientes D. E como estamos trabalhando
apenas em três D, e vamos fazer muitos trabalhos de física
e
mover objetos em
um espaço de três D, é um bom conceito de se conhecer. Então, eu configurei um nó de
dois D aqui, e a razão pela qual
fiz
isso é que é um pouco mais fácil ilustrar conceitos vetoriais em dois D do que em três D, mas a matemática e os conceitos
são exatamente iguais Então, se você entende um,
você entende o outro. Já estamos
trabalhando um
pouco com vetores,
como você pode imaginar, sob a
propriedade de transformação de nossos nós, e vamos voltar ao nosso tanque, e podemos ver isso um
pouco mais corretamente Temos a posição,
a rotação e os valores da escala, e todos esses são vetores Um vetor é um conceito
matemático definido por uma direção
e uma magnitude. E a magnitude é
simplesmente uma maneira elegante de dizer o tamanho desse vetor Então, se voltarmos para
dois D e voltarmos para esse nó em branco que eu criei,
poderei mostrar isso a vocês. Agora, o que eu fiz
com a grade aqui foi ligar a
própria grade pressionando bem, na verdade, eu não pressionei
nada para fazer isso. Mas se você pressionar este botão
aqui para fazer o encaixe na grade
e, em seguida, se você passar por baixo
dos três pontos e selecionar configurar o Snap e garantir que o
pixel Snap esteja definido, ele encaixará o que
você estiver fazendo na grade, como mostrei antes quando
estávamos fazendo três D. E o que eu
fiz foi configurar encaixe em um pixel
para a etapa
da grade, para
que possamos ver muitas coordenadas
mais fácil. Então, vou adicionar um
nó filho aqui chamado cast two D. E observe que também há um
cast three D,
mas, como eu disse, tirar uma dimensão
da equação facilita um pouco
a conceitualização Mas, novamente, a matemática
é exatamente a mesma. A única diferença entre lançar dois D e lançar três D é que o molde dois D não tem um componente Z porque
em duas dimensões, estamos trabalhando apenas em X e Y, mas em três dimensões,
estamos trabalhando em X, Y e Z. Então, felizmente para nós, um raio ou um raio é um vetor Então, como você pode ver
aqui, é uma flecha. Agora, se você jogar uma dessas
em seu jogo, você não verá
essa flecha em seu jogo. Isso é apenas para fins de exibição e
depuração do
editor , para que você
possa realmente ver para onde
seu vetor E é um
pouco estranho porque existe um
valor chamado posição alvo, e esse tipo de
contorno é tentar o que estamos
tentando mostrar Mas, de um modo geral, tratamos todos os vetores como
se eles começassem em
zero, zero, embora,
obviamente, para uma projeção de raios, você possa dizer que ela comece
onde quiser Mas, matematicamente falando, não
importa
se um raio ou um vetor começa
em zero ou começa em 34 16 ou em qualquer outro lugar que
decidamos colocá-lo Toda a matemática é
a mesma e assume que os vetores começam na origem de qualquer espaço local em que se
originam E isso é outra coisa
sobre a qual devemos falar um pouco, que é espaço local
versus espaço global. Então, como você pode imaginar, três espaços
D e dois espaços D também são divididos ou pelo menos as posições são
definidas em coordenadas. E sempre usamos coordenadas
,
por exemplo, dizendo ao nosso tanque que ele
está localizado na posição 000. É um conjunto de
coordenadas no espaço local. E agora, o espaço local
é relevante para o objeto em que você está
trabalhando, ou melhor , é seu próprio espaço
independente. E então esse espaço pode ser definido em relação
a um espaço maior, que nove em
cada dez vezes é espaço global. Então, por exemplo, neste caso, se assumirmos que
nosso nó de jogo que criamos na
lição anterior é o espaço global, e se sua origem de 000 é o ponto morto de tudo o
que nosso jogo usa, e então dizemos que nosso tanque, todo
o nosso
tanque está localizado em 7,34 em relação à
origem do Bem, como o tanque tem
seu próprio espaço local, o corpo do tanque está localizado
em 00 ou, na verdade, acho que não. Vamos
verificar a transformação. Não, o corpo do tanque está localizado
a 0,626 no espaço local, o que você adicionaria à posição global
do tanque para obter
a
posição global real desse objeto Então, tudo é hierárquico. Você pode detalhar e ter
vários espaços locais. Então, por exemplo, a torre
Tanks tem seu próprio espaço local
porque tem vários
objetos embaixo Portanto, a origem dos tanques ou a origem das
torres é zero, zero, o cano é,
na verdade, sua posição é em referência à
posição dos tanques e assim por diante Tudo isso é muito
complicado, na verdade. Mas tudo isso é basicamente uma
maneira extremamente elegante de dizer que esse 00 pode na verdade ser um conjunto diferente de
coordenadas no espaço mundial, mas quando se trata de cálculos
vetoriais, nada disso importa Então, os vetores
terão uma magnitude, e a magnitude
é o comprimento dessa linha Então, vamos mudar isso de forma
que o ponto final esteja aqui. Portanto, para uma projeção de raios,
que é um vetor, a extremidade do vetor é indicada pelo parâmetro de
posição alvo E nesse caso, temos 56 por 24. Então essa é essa coordenada aqui. É 56 X e 24 Y. Agora, a magnitude do vetor é
o
comprimento dessa linha,
que é calculada
matematicamente falando, pelo teorema de Pitágoras, que não é fácil de pronunciar,
porque forma um triângulo retângulo que não é fácil de pronunciar, Agora, a magnitude do vetor é
o
comprimento dessa linha,
que é calculada
matematicamente falando,
pelo teorema de Pitágoras,
que não é fácil de pronunciar,
porque forma um triângulo retângulo aqui. Felizmente, não precisamos
nos preocupar com isso porque Gadot nos fornece classes
vetoriais para o script
GD que
calcularão tudo o que você
poderia querer
calcular para um Você pode calcular sua magnitude. Você pode calcular coisas
como produtos pontuais. Você pode adicioná-los
e subtraí-los, o que veremos em breve Mas é uma boa ideia conhecer esses conceitos pelo menos em um nível básico para
que você possa dizer
: Ah, para fazer
isso com um vetor, preciso fazer essas duas coisas em
particular, e veremos algumas
dessas coisas em um momento. Mas agora estamos
falando um pouco sobre vocabulário. Portanto, as coordenadas são o ponto do vetor em relação à
origem do vetor
e, em seguida,
a magnitude do vetor é o
comprimento dessa linha. Agora, obviamente, a magnitude que podemos usar para fazer todo
tipo de coisas legais, por exemplo, se quisermos encontrar
a distância entre dois objetos
em nosso mundo de jogo, se assumirmos que
um dos objetos era a origem do vetor
e, em seguida, a localização
do segundo objeto no espaço
mundial era o
ponto final do Se calculássemos a
magnitude do vetor
, saberíamos
a distância em metros dos objetos
entre si. E vamos analisar
isso um pouco quando falarmos sobre mirar e disparar
balas em uma Então, vamos adicionar uma segunda emissão de raios. E vamos mover o
primeiro para cá. E, na verdade, vamos
torná-los um pouco menores. Mas de qualquer forma, vamos até
este e aquele. Agora, vetores, antes de prosseguirmos, um vetor com magnitude de um é chamado de vetor
normalizado E usamos muito vetores normalizados na leitura
de entrada e também em qualquer lugar onde
não queremos que o vetor esteja, por falta de um termo melhor, contaminado pelo comprimento
do E vamos analisar isso quando falarmos mais sobre informações. Mas como os vetores são estruturas
matemáticas, podemos adicioná-los e
subtraí-los uns dos outros Então, vou pegar esse vetor aqui e
adicioná-lo a esse vetor aqui. Agora, visualmente falando,
o que isso significa é que eu deveria ter deixado
isso onde está. Mas de qualquer forma, visualmente falando, quando você adiciona dois vetores, é
isso que você obtém Você pegará o primeiro vetor
e, ao adicionar o
segundo vetor a ele, basicamente o
colocará no final
do vetor. E esse novo ponto final é equivalente
a um terceiro vetor Opa. Vamos tentar isso de novo. Então, vamos colocar isso de volta em zero. E, na verdade, deixe-me
mudar este para que
fique um pouco mais claro. Então, se adicionarmos esse
vetor a esse vetor, obteremos funcionalmente
esse vetor porque o que você faz é adicionar as coordenadas
dos dois pontos finais Então, este é 24 32, e se adicionarmos 016 a ele, obtemos esse terceiro
valor que é 24 32 E isso é importante
porque quando vamos
ver isso em cerca de duas aulas, quando
começarmos a mover nosso tanque, a maneira como
vamos mover nosso tanque é que a velocidade do tanque ou sua velocidade é
representada por um vetor, e vamos
mudar essa velocidade
adicionando mais velocidade
a esse vetor Como um segundo vetor. E
isso ficará um pouco mais claro quando realmente
analisarmos isso matematicamente Mas seria
assim no espaço visual. Agora, a outra coisa
que veremos rapidamente é como
subtrair vetores Então, se pegássemos
esse terceiro vetor aqui e o
subtraíssemos
do primeiro vetor, obteríamos o
equivalente do segundo vetor E eu vou
contornar isso. O que significaria que é uma
maneira rápida e suja de
descobrir como dois objetos
podem ficar frente a frente. Então, se quiséssemos descobrir o vetor, queríamos
descobrir a direção em
que algo nessa
posição precisaria
olhar para ver
algo nessa posição, você subtrairia
os dois vetores que representavam
suas Portanto, a matemática vetorial é um tópico muito
longo e complicado. Mas, por enquanto, tudo o que realmente
precisamos saber é que os vetores são
representados por um ponto em três espaços D
ou em dois espaços D. E adicionando
ou
subtraindo-os ou calculando o
comprimento do vetor, você pode obter várias propriedades
ou afetar várias coisas
no mundo do jogo E, como eu disse, em
uma ou duas aulas, quando começarmos a mover
as coisas, você verá como isso
funciona no código.
12. O nó CharacterBody3D: Bem vindo de volta. Nesta lição, finalmente
começaremos
a mergulhar
nas coisas que compõem
nosso jogo real e começaremos a programar Mas antes disso,
vamos ficar um pouco fora de
ordem,
porque, se você se lembra, quando você executa o
jogo, está escuro. Agora,
falaremos sobre iluminação e ambiente em
uma lição posterior. Mas, por enquanto, vamos ver uma maneira muito
rápida e suja inserir a iluminação
que temos por padrão nesta
cena em nosso jogo. E isso é feito sob
o meio ambiente. Portanto, os três pontos
ao lado desses botões
exibirão o sol de visualização e o ambiente de visualização E já gostamos da aparência
, então basta clicar em
Adicionar sol ao SN. E que Gadot copiará
todas as configurações que o sol atual está mostrando nesta janela de visualização em um nó de luz direcional
e as adicionará à arena E agora, se começarmos
nosso jogo, ele estará aceso, embora não tão iluminado quanto
poderia
, porque obviamente
não temos luz
de fundo do ambiente. Mas, novamente, vamos
analisar isso mais tarde. No momento, só precisamos
ver o que estamos fazendo. Então, vamos voltar para o nosso tanque. Gadot permite que você
anexe scripts, que são miniprogramas,
a qualquer nó do seu jogo E pela interação
desses scripts é
como você obtém um jogo. Então, vamos
adicionar que clicaremos no
nível raiz do nosso tanque e acessaremos esse botão aqui, que é anexar um script novo
ou existente. Vamos manter a
linguagem como script GD, e ela herda o nó
três D. Na verdade, vamos mudar
isso em um Sim, vamos fazer isso agora. Ok. Então, nosso tanque atualmente é
um nó três D, e até agora, tudo bem, mas
na verdade queremos mudar isso. Então, vamos clicar com o botão
direito do mouse e fazer a alteração de tipo. E vamos mudar isso, não
vamos fazer isso. Vamos mudá-lo para um corpo de personagem três D. Agora, o que é um
corpo de personagem três D? corpo de um personagem três D é um
corpo físico três D, que é a base de todos os nós baseados em
física em Gadot E queremos física porque
queremos fazer coisas
como poder mover nossos personagens e
fazê-los colidir
uns com os outros e fazer física Agora, já que nosso tanque
será controlado por nossos scripts e pelos controles
que o jogador usa. Não queremos que o tanque seja
afetado apenas pela física. Então, vamos usar o nó D três do corpo do
personagem, que é um nó que só
interagirá com os sistemas
físicos da maneira que o script que anexamos
a ele manda. E isso não faz muito
sentido agora, mas fique comigo e tudo
ficará claro em alguns instantes Então, mudamos o
tipo do tanque para um corpo de personagem dois D
ou corpo de personagem três D, e imediatamente
temos um problema. Gadot vai nos avisar que
esse objeto não tem forma, então não pode colidir
com outros objetos e não pode interagir
com E agora não nos
importamos com isso. Então, vamos deixar Gadot continuar
nos avisando e reclamando, e vamos simplesmente ignorar
isso por enquanto, e vamos lidar com Então, novamente, vamos tentar
anexar um script ao Gado e agora podemos ver que ele herda do corpo três do personagem
D. Isso ocorre porque o script
GD é uma linguagem de script
orientada a objetos, que significa que você pode dizer aos objetos em seu
jogo, como seu tanque,
que ele
herda
o comportamento de um nó Então, o que estamos fazendo aqui
é dizer a Gadot que nosso tanque é um corpo de
personagem três D, mas vai
ter algumas
coisas extras que vamos adicionar Então, queremos todos
os comportamentos, todo
o código e
tudo o que vem com o corpo do personagem três D por padrão
e, em seguida, adicionaremos
algumas
funcionalidades adicionais . E vai nos perguntar: onde queremos
colocar nosso roteiro? E eu gosto de manter
as coisas organizadas,
então, na verdade, vou pedir para ele usar uma pasta diferente. Eu gosto de colocar todos os meus scripts
em sua própria pasta. Então abrimos e criamos uma nova
pasta chamada scripts, e agora vamos
colocar nosso
script de tanque nessa pasta de scripts. Você também pode fazer o mesmo
com as cenas. Normalmente, o que eu faço
é ter uma pasta para scripts e outra
pasta para cenas. Mas, sim, por enquanto
, está perfeitamente bem. Na verdade, não
teremos
muitas outras cenas neste jogo, então esse nível de organização não
será necessário. Mas talvez eu mude as
coisas quando começarmos
a adicionar efeitos
sonoros,
texturas e outros enfeites Na verdade, o Gadot é
inteligente o suficiente para que, se você se mover na maioria dos casos, seja inteligente o suficiente para que, se você mover objetos para pastas
diferentes, ele possa atualizar sua árvore de cenas e todos os links relevantes sem que você precise atualizá-los
manualmente Assim, você pode mover suas coisas o quanto quiser,
e elas não quebrarão. Ok. Então, agora que
criamos esse script, temos um script em branco. E no topo, temos a palavra-chave estende
o corpo do
personagem três D, e é assim que Gudo sabe
que nosso script de tanque, que agora está anexado
ao nosso personagem de tanque, herdará do corpo do personagem três
D. Podemos, se quisermos, dar a ele seu próprio nome de classe
para que, dentro do jogo, saibamos que é do tipo tanque e então
podemos nos referir a ele como tal Então, sim, vamos fazer isso. Agora, eu tenho o modelo de
script padrão desativado. Normalmente, você receberá comentários extras e
algumas funções padrão
definidas para você, mas vamos
redefini-las em breve de qualquer maneira E então, no futuro, você pode ativar o modelo ou
deixá-lo desativado de qualquer maneira. Mas sim, é assim que começamos e depois clicaremos em Controles para garantir que
não percamos nada. E antes de passarmos
para a próxima lição e começarmos a falar sobre como controlar
nosso tanque por meio da entrada do usuário, vamos dar uma olhada no básico de como vamos interagir com o corpo três de um personagem D. Então, o
corpo três D do personagem tem uma função conhecida como processo
físico E, como existe, a entrada ou o preenchimento automático tentará
criá-la para nós, possamos deixá-la
e, dessa forma, não
precisamos nos preocupar lembrar sua assinatura de
função E, como variável, leva
a quantidade de tempo que
passou entre as chamadas
ao processo físico. Isso é expresso como uma flutuação, então provavelmente
será 0,012 ou algo parecido,
W, é claro,
sendo um segundo inteiro O processo físico é chamado uma
taxa de 60
vezes por segundo, que é o
motor de física usado por Gadot Felizmente, não
precisamos escalar nenhuma de
nossas relações de velocidade
no processo físico
no corpo do personagem
três D por Delta porque todos os cálculos
básicos já
levam isso em consideração Mas para outros tipos
de objetos físicos, nós o faremos, e lidaremos
com isso quando surgirem. De qualquer forma, não precisamos
definir uma variável chamada
velocidade porque uma já
está embutida no corpo do
personagem três D. Então se simplesmente escrevermos corretamente, podemos atribuir um novo vetor
três a esse E fazemos isso
usando a palavra-chave do
construtor vector três E como você pode ver, novamente, Gadot está tentando
nos dizer que é assim que você
define essa variável, e esses são os valores que
você tem que colocar nela Então, na verdade, queremos
esse terceiro porque nós mesmos forneceremos
o X, o Y e o Z. Então, se fizéssemos isso, forneceríamos uma velocidade zero, o que, é claro, significa que nosso tanque não vai se mover, mas
não vamos fazer isso Queremos que nosso tanque se
mova na direção X. Portanto, neste caso, ele se moverá exatamente
ao longo do eixo X,
porque é para ao longo do eixo X esse lado
que está voltado atualmente. Então, vamos
mudar esse valor para, digamos, dez, só
pra caramba E agora o
corpo do personagem três D tem um método chamado
mover
e deslizar, e mover e deslizar
calculará a velocidade, fará vários cálculos diferentes
e, por fim, moverá o tanque E como estamos
forçando a velocidade a esse valor constante em
cada processo físico
, ela nunca
diminuirá ou algo parecido E se apertarmos o botão
play aqui, você pode ver agora que nosso
tanque está avançando e continuará
avançando até a
profundidade térmica do universo. E, novamente, observe que
ele não está caindo, porque não
atribuímos um vetor descendente
a ele para simular a gravidade Então, novamente, o Y, a velocidade de subida
e descida e a velocidade Z, que entra e sai, permanecerão
constantemente em zero, e o tanque
avançará até uma velocidade Agora, o que
realmente significa dez? Hum, eu não tenho 100% de certeza. Os valores fornecidos para os cálculos de velocidade,
até onde eu sei, não
estão em, tipo, metros por segundo ou pés por segundo
ou algo parecido, ou unidades por segundo,
são arbitrários Então, uma das coisas que
você precisa fazer para ajustar seu processo
físico é começar com um valor e
depois continuar jogando
com esses valores até que eles realmente se
pareçam com o que você deseja,
infelizmente Vou fazer uma
pesquisa sobre isso
e, se descobrir que está errado
, atualizarei
em uma lição futura. Mas, por enquanto, vamos
passar para a próxima lição, e veremos como capturar os controles
do teclado para mudar isso e
realmente fazer o tanque se mover da maneira que
queremos. Te vejo lá.
13. Reação à entrada do jogador: movimento: Bem vindo de volta. Nesta aula, nós vamos
aprender como consultar os controles
do teclado do usuário para manobrar nosso
tanque no espaço de três D. Portanto, todo movimento ou toda leitura
de entrada em Gdo é feita por meio do
que chamamos de ações E podemos ver as
ações definidas para um projeto nas
configurações do projeto e no mapa de entrada. Agora,
a sua ficará assim por padrão porque o GADO tem
várias ações incorporadas, mas por algum motivo,
ele se recusa a
mostrá-las até que você
clique neste botão E aqui você pode ver um
monte deles. Então, os que mais nos interessam são os da interface
do usuário, que são especificamente UI esquerda,
UI direita, UI up e UI down. E você pode ver aqui
que eles são mapeados para várias configurações de
controle diferentes Portanto, a interface esquerda é mapeada para a seta
esquerda no teclado, bem
como para um
botão específico do Joypad ou para um acesso ao JoyPad Portanto, não importa o dispositivo
de controle que você usa. Se você conectar um
joystick e pressionar o botão relevante, você
vai sair Ou se você pressionar
a seta esquerda
no teclado, você
vai tirar eu para a esquerda. Ou se você mapeá-lo
para um botão do mouse, o que pode ser feito manualmente,
ele também fará isso. Mas não vamos
fazer nada disso. No entanto, você pode realmente criar
o seu próprio. Então, por exemplo, se
você quisesse sobrecarregar a exibição do
mapa para a chave, você poderia criar uma nova
ação chamada mapa e , em seguida, mapeá-la para o MK,
e tudo bem Então, a primeira coisa que vamos
fazer é realmente fornecer uma referência ao
tanque do jogador dentro do objeto do jogo. E parece que eu
já o renomeei aqui, mas era assim que parecia
originalmente Então era tanque, e então vamos
renomeá-lo para jogador Tank E a razão pela qual o
renomeamos é porque,
eventualmente teremos um
monte de tanques para representar inimigos e coisas do tipo, e não queremos
saber qual é qual Então esse será
o jogador. E um dos outros motivos pelos quais damos um nome a ele é para que
possamos manipulá-lo diretamente com os controles, o que
veremos em um minuto Se acessarmos o script do jogo e usarmos a palavra-chave export, podemos fazer com que qualquer variável que
definimos na palavra-chave export apareça no
inspetor aqui Então, por exemplo, se eu
simplesmente definir uma variável chamada X, você não a verá. Mas se eu
exportasse essa variável, e se eu escrevesse a exportação corretamente e usasse a anotação
correta,
oh, sim, ela fornece que
requer um tipo, então vamos lá Agora, se eu
fizesse isso, a variável X aparece no inspetor e eu posso alterar
seus valores aqui, mesma forma que faríamos para
a transformação ou da
mesma forma que faríamos para
a transformação ou
qualquer outra coisa que
usamos até agora Então, neste caso, vamos criar um chamado player e vamos bloquear
seu valor em tanque. E, ao fazer isso,
forçamos Gadot a reconhecer ou limitar qualquer coisa
que arrastamos até aqui Então, por exemplo, se eu quisesse
arrastar Ana até aqui, Godot não me deixaria Mas se eu fosse arrastar o
jogador Tank, que é, claro, um tanque, Ooh Ganhe, arraste. Lá vamos nós. Agora temos isso atribuído.
Então, quando sairmos,
quando manipularmos a
variável player em nosso script, ela chamará os métodos desse script
específico, que é, obviamente, um tanque E a razão pela qual o nome da classe está disponível para nós é porque o
definimos aqui. Então, vamos salvar nosso jogo. Roteiro. Além disso,
parece que comecei a gravar depois de anexar o
script ao objeto do jogo. Então, se você estiver
acompanhando em casa, a primeira coisa que você
deve fazer é anexar um script à
sua classe de jogo, da mesma forma que fizemos
com um tanque com nosso script de tanque
ao objeto tanque
na lição anterior. Então, agora que
temos isso disponível, vamos tornar
o jogo responsável por coletar a entrada
e não o tanque. E a razão pela qual
vamos
fazer isso é porque mais tarde
teremos outros tanques
para representar os inimigos, e não queremos separar o código que lê os
controles do tanque do jogador dos tanques inimigos e
de
todas essas outras coisas. Portanto, é melhor ter apenas
um tanque genérico e deixar o jogo manipular o tanque do
jogador diretamente e depois deixar a interface manipular os tanques inimigos diretamente para que eles tenham
uma interface comum Agora, todos os nós em Gado têm um método predefinido chamado entrada de chave
não tratada, e é isso que
vamos usar Esse método é chamado sempre que
o usuário pressiona uma tecla. Sempre que o usuário
libera uma chave, sempre que o usuário
mantém pressionada uma chave, qualquer evento chave relacionado no Gadot, esse
método é chamado E a razão pela qual estamos usando esse método em vez de monitorar diretamente a entrada da chave do
usuário,
digamos, no método de processo ou qualquer outra coisa, é que esses métodos só são chamados quando
o status da chave muda, então não estamos constantemente puxando repolando
e consultando Portanto, uma das regras
fundamentais da programação de computadores é
não trabalhar
mais do que o necessário. Seja o mais preguiçoso possível. Então, não
queremos que Gadot diga
constantemente : “A chave
está abaixada A chave está abaixada?
A chave está abaixada? Só queremos que
a chave seja: “Ei, estou triste e depois faça com que
Go Gadot reaja a ela Então é isso que
vamos fazer aqui. Então, nesse método, vamos
definir duas variáveis. Vamos definir
um chamado valor de giro, que
será flutuante, e definiremos
um chamado valor de movimento E também será
um carro alegórico. E esses valores serão
zero, menos um ou um, dependendo do
estado da nossa entrada. E como você pode imaginar, vamos manipular o tanque com base nesses valores Então, o que queremos
fazer, por exemplo, é se o mouse esquerdo ou
a seta esquerda for pressionada, queremos que o
tanque gire para a esquerda, o
que seria na direção
negativa E se mantivermos
pressionada a tecla de seta para a direita
, o tanque girará
na direção positiva E se nenhuma tecla for pressionada, o tanque não girará de jeito nenhum E fazemos isso usando
a entrada Singleton, que é responsável por lidar com todas as
entradas no GIDO E vamos usar uma
função chamada eixo G. E o Gaxis usa dois parâmetros. É preciso uma ação negativa
e uma ação positiva. E você pode ver a definição da
função aqui na dica
abaixo Então, vamos dar a
esquerda e a direita. Agora, o que é toda essa bobagem sobre ações positivas e
negativas Bem, é possível
que um valor de entrada tenha uma faixa de valores
porque é possível, por exemplo, se você estiver
usando um controlador,
empurrar um pouco para a esquerda
ou totalmente para a esquerda. E Gadot representa isso
com um valor de cerca de zero a um para mostrar o
quanto à esquerda o
manípulo está sendo pressionado E queremos combinar isso com o valor na outra direção,
o que não é realmente possível. Ou talvez meio que seja. Quero dizer, as coisas ficam engraçadas quando
você está lidando com analógico. Mas o que estamos fazendo é que, como estamos usando o teclado, a força de entrada do comando esquerdo será zero,
o
que significa que a tecla não está
sendo pressionada, ou 1, o que significa que a tecla
está sendo pressionada. No entanto,
queremos diferenciar qual é negativo e
qual é positivo E como eu já disse que
queremos que a esquerda seja
representada por negativo, nesse caso específico, a
função de entrada get access perguntará se a
ação esquerda está acontecendo ou não. Se for e for
a ação negativa
, ela
retornará menos uma. E como somos a ação
positiva, se ela estiver se mantendo pressionada, obteremos uma. Então, esse
trecho de código
retornará menos um, zero ou um,
dependendo de como esses botões
estão sendo pressionados. E se você segurar
os dois ao mesmo tempo, eles se cancelam
e sai zero, o que também é o que queremos. Então, vamos fazer a mesma
coisa com o valor do movimento,
embora, neste caso, seja UI
down e I up, o
que parece um pouco invertido , , mas Gadot representa para frente e trás com a coordenada Z e a coordenada Z,
e eu vou realmente Portanto, a coordenada Z está
voltada nessa direção. O que é para você, e essa
é a direção positiva. Então Z descendo é positivo. A subida Z é negativa. Então, normalmente
pensaríamos que o aumento era positivo, mas na verdade é inverso É por isso que o
invertemos no script aqui. E Gadot está reclamando
porque, claramente, eu não sei a diferença
entre um positivo e um igual Então, agora que
temos esses valores, podemos verificar se estamos obtendo o que queremos
imprimindo-os .
Então, vamos fazer isso. Então, agora, se eu começar meu jogo. Bem, o tanque está se movendo
porque não removemos nenhum código de nossas aulas
anteriores. Então, vamos ignorar
isso por enquanto. Não vai a
lugar nenhum. Mas você verá que, se eu pressionar e soltar o botão para cima, a
força de entrada está alta. E para baixo. E agora, se eu fizer para a direita e para a esquerda, obteremos nossos zeros e nossos negativos exatamente
como queremos. Então, vamos remover esse código
do processo físico e colocar a palavra-chave pass aqui para indicar que essa
é uma função vazia, e teremos que
definir alguns valores e variáveis
para fazer nosso tanque funcionar. Então, a primeira coisa
que precisaremos fazer é definir alguns
valores
para determinar a velocidade com que nosso tanque
se moverá e girará Então, vamos exportar uma
variável chamada velocidade de giro. E uma coisa a notar
é que, tecnicamente, Gadot usa o snake case para suas Mas eu sou programador
de Sea
Sharp e Java nos últimos 15 anos, então tenho
a tendência de usar camel case Provavelmente vou alternar
inconsistentemente entre os dois durante todo o curso, então não siga meu exemplo.
Escolha um e fique com ele. Mas de qualquer forma,
a velocidade de rotação será uma flutuação e a velocidade de movimento
também será uma E também vou mostrar
um pequeno truque de anotação
que, se você um pequeno truque de anotação estiver familiarizado
com as versões mais antigas Gadot, foi adicionado por volta da era do
Gadot, foi adicionado por volta da era 4.2.
Não tenho
certeza de onde. Mas se você quiser
adicionar uma dica de ferramenta, vamos
ao nosso tanque aqui. Você pode ver que temos velocidade de
giro e velocidade de movimento, e se você passar o mouse sobre elas, você recebe uma dica de ferramenta e diz: Nenhuma descrição disponível.
E isso te deixa triste. Então, se você quiser
adicionar uma dica de ferramenta, basta usar uma hashtag dupla Uma única hashtag é um comentário, que significa que Godo a ignorará Mas se for uma
hashtag dupla, é uma dica de ferramenta. Então, vamos girar a velocidade em graus. Em vez disso, a
velocidade de rotação do tanque em graus. E é uma cor um pouco
diferente, então você pode ver que
é uma anotação Agora, se formos até
aqui, temos dicas de ferramentas, e é maravilhoso. Desde que
descobri isso, estou apaixonado por isso. Eu anoto tudo agora. Então, como prometido,
eu realmente pesquisei um pouco
e descobri que, embora Godot se refira às três unidades da grade D como metros e aja
como se fosse a mesma unidade de medida que
seria no liquidificador,
que também usa unidades, Godot não se importa É só uma unidade. Você pode
considerá-los em polegadas, metros , unidades de
liberdade, como
quiser chamá-los, e os cálculos funcionarão
todos da mesma forma. Então, sim. Vamos apenas
considerá-lo arbitrariamente como medidor. Eu realmente não acho que isso importe. E forneceremos
alguns valores padrão aqui. Portanto, nossa velocidade de giro
em graus é 20, e
digamos apenas graus. E a razão pela qual
definimos isso dessa forma é porque a rotação pode ser tratada no GaDo em
graus e radianos Internamente, no motor, tudo é feito em radianos, mas ele aceita graus como valores de entrada em
muitos casos, e você pode converter entre
os dois com bastante facilidade Pessoalmente, e muitas vezes quando você está fazendo modelagem em
três D e
coisas assim, é mais fácil
pensar em graus porque quando você diz ângulo,
o que a maioria das pessoas pensa? Eles pensam em ângulo de 45 graus, ângulo de
90 graus,
ângulo reto, qualquer coisa. E tudo isso está em graus, mas todo o resto
está em radianos Portanto, geralmente é uma
boa ideia indicar qual valor você espera ao criar
uma variável como essa Então, sim, graus de velocidade de giro. E a velocidade de movimento está em
unidades por segundo, então não precisamos
definir nada lá. É igual a dez. Então, novamente, dez unidades por segundo. Agora,
precisaremos de um par de métodos que
atualizem esses valores
e também
precisaremos dos valores em
si, e também
precisaremos dos valores porque
são apenas constantes Isso significa apenas que, ei, quando o tanque girar,
ele
girará a 20 graus por segundo, mas precisamos de algo para
realmente monitorar qual é
a velocidade de
rotação atual do tanque. E vamos ver
por que isso acontece em um momento. Então, vamos definir uma variável
chamada velocidade de rotação. E isso é um que é um flutuador, e então teremos outro chamado velocidade de
movimento E esses valores são
os que serão modificados pela entrada,
como veremos em breve. Mas a primeira coisa que precisamos
fazer é definir mais algumas
funções,
e uma delas
será chamada de definir velocidade de giro. E será necessário um valor de
entrada, que é um valor flutuante. E, por enquanto, vamos
configurá-lo para ser aprovado para que
não faça nada. É chamado de
eliminar uma função. Podemos defini-los sem
realmente fornecer nenhuma informação para que
possamos configurar a estrutura. E
teremos definido a velocidade de movimento. Agora que temos esses valores, podemos voltar ao jogo
e, em vez de apenas
imprimir esses valores, podemos pegar o
tanque do jogador e definir sua velocidade de giro com
base no valor do turno. E podemos definir a velocidade de
movimento do jogador com base em seu valor de movimento. Então,
o que tudo isso significa? O que isso significa é que, quando
o estado da chave muda, quando o usuário pressiona
ou solta uma tecla, seja
, quando o usuário pressiona
ou solta uma tecla,
essas informações são calculadas, como mencionamos anteriormente, como mencionamos anteriormente,
e esses
valores modificam as velocidades de giro
e movimento existentes Portanto, se o tanque
não estiver se movendo, sua velocidade
de rotação será zero. O que será refletido pelo fato de que o
valor do turno que está sendo passado é zero. E se o tanque estiver girando
para a esquerda, bem, a velocidade
de rotação será
a velocidade de giro existente
modificada pela direção Portanto, seria menos 20 para esquerda e 20 positivos para a direita. Então, o que realmente queremos
fazer é definir a variável de velocidade de rotação igual à velocidade de
giro do tanque em graus multiplicada
pelo valor de entrada Então, novamente, já que se tivéssemos
pressionado a tecla esquerda, o valor de entrada seria
igual a menos um. Isso significa que a
velocidade de rotação seria 20 vezes menos um,
o que é menos 20, que significa que o tanque estaria girando menos 20 graus, o que
o giraria para a esquerda e o
mesmo para a E vamos fazer
a mesma coisa com
a velocidade de movimento. Então, a velocidade de movimento será igual Bem, uh, velocidade de
movimento
será igual à velocidade de movimento, e foi
aqui que eu criei duas variáveis com nomes
ambíguos, então você não deve fazer isso Vamos chamar isso de velocidade de avanço. Agora, vamos chamar isso
de velocidade de movimento, e essa é velocidade de avanço. Portanto, a velocidade de avanço
é igual à
velocidade de movimento vezes o valor de entrada. E agora que
temos esses valores, podemos modificar os valores
existentes dos tanques com esses novos
valores no processo físico. Então, o que o processo físico faz, como mencionei antes,
é ser chamado 60
vezes por segundo, e é aqui que você faz todas as manipulações
de,
digamos, velocidade ou rotação
ou qualquer coisa que possa afetar
os valores físicos dos tanques Então, no nosso caso, essa
seria a velocidade do tanque e, claro, a rotação do tanque Então, a primeira coisa que
vamos fazer é definir a rotação
do tanque igual à rotação atual
mais a velocidade de rotação. Então, como fazemos isso?
Bem, existem duas maneiras. Há uma variável dentro do nó três D
chamada rotação, mas também há uma
chamada graus de rotação. E, como eu disse, como
gosto de trabalhar em graus, e os graus de rotação são uma variável de conveniência
específica para isso, definirei os graus de rotação
iguais a um novo vetor três e
começaremos com três zeros Então, o que isso significa
é que não há
absolutamente nenhuma rotação. Mas o que queremos
fazer é girar o tanque ao longo do eixo y porque
o eixo Y é aquele que
está reto para cima e para baixo E se girássemos
o tanque ao longo desse eixo, o tanque realmente
giraria no mesmo lugar Então, como você pode ver aqui, como
é a linha verde clara, e essa é a rotação
verde clara, se eu movesse isso,
o tanque se moveria assim. E é isso que
queremos fazer em código. Então, voltamos aqui
e nos graus de rotação, e queremos mudar
o componente Y. Portanto, o componente Y agora
é igual
à velocidade de rotação vezes Delta. E isso é porque
queremos escalá-lo pela quantidade de tempo que passou entre os quadros,
que é o que é Delta. Caso contrário, a velocidade de rotação, que é
20 ou menos 20, seria
chamada de 60 vezes
por segundo, que significa que a
cada 60 graus de segundo, a rotação seria atualizada o
que significa que a
cada 60 graus de segundo,
a rotação seria atualizada em 20 graus em
qualquer direção, e não queremos um tanque
que gire como um topo Então, isso deve realmente funcionar. Vamos rodar nosso jogo e ver. Agora, se eu pressionar para a esquerda,
absolutamente nada acontece. E se eu pressionar para a direita,
absolutamente nada acontece. Bem, está quebrado. Tudo bem, vamos ver qual é o problema Provavelmente, o problema é que não estamos fazendo
movimentos e deslizamentos. Não acho que seja esse o
caso, mas vamos verificar. Não, esse não é o caso. Ok, eu vejo qual é o problema. O problema é que
estou
definindo incondicionalmente a rotação para um valor, enquanto queremos que
ela seja igual ao valor atual
mais
o novo valor Porque isso é que isso nos
dará 20 ou menos 20. E se mudarmos a
rotação apenas para 20, não obteremos
uma rotação consistente. Nós somos o tanque que
vai se travar em 20 ou menos 20, e isso
será o fim de tudo. O que queremos que ele faça é que ele
mude gradualmente ao longo do tempo. Então, se a rotação foi zero, então adicionamos isso de forma que seja menos 20 ish em um segundo. E então, no próximo turno, é menos 40 em um segundo
e assim por diante. Então, isso deve realmente
resolver o problema. E nós temos isso ao contrário, e isso é porque precisamos
reverter os valores aqui Perfeito. Agora temos
um tanque giratório e fazemos exatamente a mesma
coisa com o movimento, quase Então, o que precisamos
fazer é definir o corpo do personagem com três Ds
embutidos na variável de velocidade, que aparentemente não
consigo soletrar E a velocidade será igual
a alguma coisa. Agora, há algumas maneiras diferentes
de
determinar como mover um
nó com base em sua face. O mais simples é pegar um vetor voltado
para frente, multiplicá-lo pelo
valor do movimento
e, em seguida, ajustá-lo
à velocidade E embora isso seja perfeitamente
aceitável, na maioria das vezes, Gadot realmente
recomenda que você não faça isso por uma
série de razões matemáticas Também fica um pouco complicado porque você tem que
levar em consideração a orientação do tanque e
o fato de Gadot
considerar que o Forward está
na direção Z
e todo tipo de outras bobagens que provavelmente
estão fazendo você olhar para mim, Do que diabos esse
cara está falando A maneira mais fácil é usar uma ferramenta interna ou um objeto interno chamado
base de transformação. Portanto, cada nó em Gadot tem uma variável interna
chamada transform, e transform é
exatamente o que parece É basicamente esse objeto aqui, que determina a
posição, rotação e
escala do objeto e provavelmente
algumas outras coisas que estou
esquecendo no espaço de três D. E Gadot gerencia todos
esses cálculos por meio de esses cálculos por meio seu mecanismo de física
sob o capô E uma das variáveis
internas
da transformação que ela nos dá é essa coisa chamada base. A base é o resultado de todos esses cálculos antes de qualquer modificação extra
que você possa fazer. Então, eu vou
te mostrar como isso funciona. Opa. Control K.
Vamos comentá-los e
vamos voltar ao jogo, e vamos
mudar isso um pouco Imprima o player dot
transform dot BASIS. Agora, basta tocar em uma tecla e
ele parará de rodar o jogo. E essa é a base. A base é um
vetor de vetores. E o que isso lhe dá
é a orientação do seu objeto em vários
contextos diferentes O mais útil para nós é o contexto X
porque esse vetor determina a orientação X e Z
do nosso tanque após a
rotação ter sido aplicada. E para mover
o tanque para frente, queremos movê-lo
no plano XZ. Então, isso seria uma combinação dessa direção e
da direção azul para frente e para trás na direção em que
o tanque está voltado. Então, se voltarmos ao nosso roteiro e pudermos nos
livrar disso, a velocidade do tanque será
igual à base do tanque, o componente X da base
do tanque, multiplicado pela velocidade de
movimento E o que isso fará
é escalar o vetor X pela velocidade de movimento, que é exatamente o que
precisamos para a velocidade Agora, se eu chamar mover e deslizar, isso deve permitir que
o tanque avance em qualquer direção em
que esteja. Então, vamos cruzar os dedos. E, uh, não. É porque a
velocidade de movimento é uma constante. Na verdade, queremos velocidade de avanço. E é por isso que você
precisa nomear suas variáveis de forma criteriosamente
responsável Ok, vamos lá.
Agora, se eu pressionar para frente, o tanque avança. Se eu empurrar para trás, ele se move para trás. Se eu girar o tanque e agora movê-lo para frente,
lá vamos nós Vamos mirar na árvore e vamos direto até a árvore. E isso é porque não
permitimos nenhum tipo de colisão. E a única razão pela qual
parece que temos uma
colisão é que como não estamos aplicando nenhuma velocidade na direção Y, o tanque não está sendo afetado
pela gravidade de forma alguma, então não vai cair Mas agora temos um tanque em movimento e podemos passar para
a próxima lição. Então eu
vou te ver lá.
14. Reação à entrada do jogador: controlando a torre: Bem vindo de volta. Nesta lição, que será infinitamente mais fácil do que na última, vamos aproveitar
o que aprendemos
na última lição para
manipular a torre do tanque Portanto, a primeira coisa que
precisamos fazer é fornecer algumas
variáveis extras ao nosso tanque. Especificamente, precisamos de uma velocidade de rotação da
torre. E também precisamos de uma velocidade angular da
torre. Porque a torre será capaz girar e também de
subir e abaixar E, como resultado disso, também
precisaremos de
uma velocidade de movimento da torre E, finalmente, e a
torre. Lá vamos nós. Vamos precisar de um
ângulo máximo para a torre, de modo que não
possamos deixá-la girando ao redor Os graus máximos do ângulo da torre flutuam. E vamos chamar isso de 15. E precisaremos algumas funções semelhantes para manipular a torre da mesma forma que fizemos para
girar e mover Então, vamos fazer rotações. Torres Não. Isso exigirá
um valor de entrada. E torre angular. Não consigo digitar para salvar
minha vida, não é? E agora que os temos, podemos alterar a
rotação e a velocidade
do ângulo exatamente da mesma forma
que fizemos para girar
e girar E só para
simplificar, o ângulo da torre,
a
velocidade de subida e descida serão exatamente
a mesma velocidade que a
velocidade de subida e descida serão exatamente
a a velocidade movimento
da torre,
a velocidade de rotação Se você quiser fazer um exercício, se quiser
alterá-lo para que ele use
um valor diferente, seria um bom
exercício
para você fazer nas horas vagas. Tudo bem. Portanto, antes de
podermos manipular esses valores por meio dos
controles e também adicioná-los ao nosso processo físico, que
faremos, precisamos de referências à parte da
torre do tanque Então, se voltarmos ao nosso valor de
três D aqui, nossa visão de três D aqui,
em nossa lição anterior, na verdade
criamos um nó
para representar o tanque, que contém as
instâncias de malha do tanque, e então também criamos
um ponto de ancoragem do barril, que articula o
cano à torre Agora, precisamos obter referências a esses valores
de dentro do tanque. E há algumas
maneiras de fazer isso em Gadot. Mas hoje em dia, em quatro pontos
dois e quatro pontos três, a maneira mais fácil de fazer isso é
usar referências de objetos. Então, vamos exportar mais
alguns valores. E como ambos
são do nó três Ds, podemos
fixar o tipo no nó três D,
então vamos
exportar a torre
e vamos
exportar a dobradiça então vamos
exportar a torre da torre E agora que eles existem,
podemos ir até o tanque e arrastar a torre até
aqui e a dobradiça da torre, que é o ponto de
ancoragem do cano E depois vamos
agrupá-los um pouco. Portanto, os graus
de rotação da torre serão modificados
exatamente da mesma forma
que os tanques, criando um vetor de rotação e usando a velocidade de rotação torre vezes
a
velocidade de rotação da
torre Delta vezes Delta torre E vamos fazer a mesma coisa com
a dobradiça, mas não exatamente Então, os graus de
rotação das dobradiças atuais serão modificados por
um vetor três, mas vamos girá-lo em
um ângulo diferente Vamos girá-lo ao
longo do eixo Z para que ele se mova para cima e para baixo, porque o eixo Z está aqui
se movendo para dentro e para fora E então, se fôssemos
girá-lo com o azul, que representa o Z, ele
subirá e descerá Isso significa que as propriedades X e Y
do
vetor serão zero,
mas o delta da velocidade de
rotação da torre, ou melhor,
do componente
Z será o delta da velocidade de
rotação da torre E vamos
fazer mais uma coisa. Precisamos fixar os graus
de
rotação nossa faixa máxima de ângulo, e fazemos isso com
o método clamp F porque vamos trabalhar com
flutuadores Então,
graus de rotação da dobradiça Turrent . E queremos a propriedade Z porque
essa é a rotação de cima para baixo. graus de rotação da dobradiça Z são
iguais ao valor de retorno do grampo F. E o que queremos fazer é que o grampo F O primeiro é o
valor que estamos fixando. O segundo é o mínimo do alcance ao qual
estamos nos fixando e o terceiro é o alcance máximo do
que estamos fixando Então, serão graus de ângulo máximo
negativos
e graus de ângulo máximo
, respectivamente. Então, agora, se tentarmos girar nossa torre ras ou abaixá-la fora dessa faixa, esse método a
fixará dentro dessa faixa, e não teremos a torre girando na
direção vertical, que é exatamente
o que Então, agora que
fizemos tudo isso, precisamos modificar nosso método de
jogo ou nosso método de entrada
de chave
não manipulada do jogo para que tudo isso funcione Então, como você
vai fazer isso? Bem, o que vamos
fazer é assumir que, se o jogador pressiona a tecla de controle, ele está manipulando
a torre
e, se não tiver
a tecla de controle pressionada, está manipulando Então, precisamos verificar
nossa entrada Singleton, e vamos usar o método se
a tecla física
for pressionada E então
vamos procurar
a chave de controle,
e aí está. Agora, se a
tecla de controle for pressionada, queremos usar a curva
nos valores de movimento da torre Caso contrário, queremos
usá-lo para o tanque. Portanto, temos o conjunto de jogadores, torre de rotação
do jogador com
o valor do giro e a torre o valor do giro e a ângulo
do jogador
com o valor do movimento No entanto, isso funcionará, mas haverá um bug. E uma das melhores vantagens de adquirir mais experiência
com programação é que você poderá identificar bugs antes de realmente
encontrá-los durante o teste. Então, digamos que
pressionamos a tecla de controle, pressionamos
a tecla de seta para a direita, giramos a torre e soltamos
a tecla de controle Bem, isso vai pular desta seção para esta seção
, que significa que
não atualizará a velocidade de rotação
da torre com o valor atual da curva Então, em vez de passar de zero aqui para impedir que a
torre gire, ela vai
direto para baixo Então, o que precisamos fazer é
interromper explicitamente movimento e
a
rotação do tanque quando estamos
manipulando a torre E fazemos isso explicitamente passando zero como a velocidade da curva E se estivermos
manipulando o tanque
, queremos forçar os valores das
torres a E isso deve funcionar. Então, agora, se eu mover meu tanque
da maneira normal, é ótimo. Agora, se eu mantiver o controle, bem, algo está errado.
Mas estamos perto. Então você pode ver que, se
eu segurar o controle e o tanque estiver
girando e girando, parece
que
estou
usando acidentalmente os mesmos valores Velocidade de rotação T, velocidade do ângulo da
torre. Ah, hein. E aqui está. Em vez de usar a velocidade do ângulo da
torre para inclinar a torre, estou usando a velocidade de rotação Agora, isso deve funcionar.
E aí está. E, como você pode ver, se eu
tentar inclinar a torre em um valor
maior do que a faixa de ângulo que
definimos, isso não funciona E você pode até mesmo e, claro,
agora, se eu estiver movendo um tanque e
eu bater no chão se eu apertar o controle, o tanque para de se mover e
a torre continua funcionando Ok. Então, como você deve
ter notado, atualmente
podemos
dirigir por entre árvores, pedras e colinas,
e isso é ruim. Então, em nossa próxima lição, aprenderemos como
configurar a colisão
e, depois disso, as coisas
ficarão interessantes Podemos começar a
causar estragos e destruir coisas. Então, nos vemos
na próxima lição.
15. Colisão: Bem-vindo de volta. Esta lição será
infinitamente mais simples do que as duas últimas e ainda
mais simples do que a Então, se sua cabeça
estava girando por
causa de toda aquela bobagem de matemática vetorial
e rotação, essa vai ser
um pouco difícil Então, vamos
analisar a colisão e corrigir
esse pequeno aviso amarelo Então, isso vem reclamando desde que transformamos nosso tanque em um corpo de personagem três
D que ele não tem forma Então, vamos dar um. Então, vamos para nossa visão em três D. E eu cliquei no Z, e bem, primeiro de tudo, eu me certifiquei de que
era e não é isso Eu me certifiquei de que era
uma visão de duas portas e cliquei no Z e
no Y para que
tivéssemos essa bela visão de cima para baixo e para frente para Então, como mencionei antes, nosso tanque é um tanque do tipo, que é um
corpo de personagem três D. Que é um objeto físico, e um objeto físico requer formas de
colisão
para funcionar E como nunca adicionamos um
nó em forma de colisão a essa coisa, tivemos esse
pequeno ícone amarelo que estava zombando de
nós esse tempo todo Então, vamos
adicionar um nó filho e vamos adicionar uma forma de
colisão três D. Boom. Agora, a forma de colisão
três D requer uma forma muito semelhante às primitivas de malha que
estamos usando Então,
vamos usar o formato de uma caixa e agora temos vários
widgets que nos
permitirão indicar o tamanho e a
orientação do Xbox Então, a primeira coisa que
vamos fazer é arrastar isso um pouco para
cima. E então vamos e, por algum motivo,
está estourando Isso deve ser um bug e Gadot. Às vezes, ele se encaixa
nos encaixes das grades,
mesmo que você não queira Então, vamos ver se
consigo, vamos lá. Não sei por que estava
preso a isso antes. De qualquer forma, você pode usar
esses pequenos círculos rosa para alterar o tamanho e a
posição da sua caixa. Então, o que queremos fazer é garantir que a caixa cubra todo o nosso
tanque em ambas as direções Então, queremos que cubra o
tanque nessa direção. E, olhando
para baixo, queremos ter certeza de que também é longo o suficiente para cobrir o tanque
nessa direção. Então, agora que temos uma caixa
ao redor do tanque, quando tentamos fazer com que o tanque se mova usando o método
Move and slide. Vamos analisar isso
novamente. Então, como em nosso
processo físico nos
movemos e deslizamos, Godot tentará colidir nossa
caixa em forma de
colisão E como você pode ver, o pequeno
aviso está desaparecendo agora. Ele tentará colidir
aquela caixa em forma de colisão com
qualquer outra caixa em forma
de colisão que
tenhamos em nosso nível de jogo. E
no momento não temos nenhum. Então, vamos fazer com que nossas árvores, rochas e colinas possam colidir Então, nossa árvore, vamos
voltar para nossa árvore, e nossa árvore é um nó três D, então vamos dar a ela uma forma de
colisão E se tentarmos fazer isso, receberemos um erro
e um aviso. O aviso, é claro,
porque não temos uma forma. Mas o erro é que
nossa árvore não é
do tipo certo de nó para realmente usar uma forma
de colisão Portanto, existem três tipos de corpos
físicos que
usam colisão. Já temos um corpo de personagem três D, que é o nosso tanque, mas também
temos que mudar o tipo. Um corpo estático três D e um corpo estático três D é um objeto físico
que não se move. E não só não
se move, como nunca se move,
o que significa que Gadot
não tentará aplicar gravidade ou qualquer outra coisa
a ela, mas pode colidir Então, agora que temos
uma forma de colisão, vamos mudar a forma da colisão para um
cilindro E agora podemos mudar o tamanho
do nosso cilindro e
movê-lo para cima E, novamente, está quebrando
por algum motivo. Esse é um bug desagradável. Lá vamos nós. Não sei
por que continua fazendo isso. Eu não gosto muito disso. Mas, novamente, podemos usar
as alças para indicar o tamanho do cilindro. Então, agora nossa árvore está completamente coberta por uma colisão Opa, por uma forma de colisão E realmente funciona. Então, sim, você pode ver
que está cercado
por esse cilindro. E nós vamos fazer
os outros também. Mas agora, sem nenhum código
adicional, se eu me deparar com a árvore, bum, não
consigo correr pela árvore. Então, vamos adicionar formas de colisão às nossas rochas e colinas, e então podemos passar
para a próxima lição Então, novamente, teremos
que mudar a colina. Então, podemos realmente transformar
a colina em um nó secundário. Então, teremos que chegar a um corpo estático
porque é uma malha, o que significa que vamos
perder todas essas informações. Então, na verdade, teremos que ser complicados. Vamos adicionar um nó secundário, que será
um corpo estático três D. E, em seguida, clicaremos com o botão direito nele
e diremos criar
a raiz da cena,
e agora eles serão invertidos O corpo estático três D é
enorme, e não queremos isso. Vamos mudar
isso em um momento. Mas agora a colina está ligada ao corpo
estático três D. Então, vamos voltar à transformação, e as transformações estão Por alguma razão,
essa coisa é enorme. Não sei por que isso
acontece, mas vamos
dar a ele uma forma de colisão E vamos com um grito. Vamos usar uma visão
dupla novamente. E mais uma vez, isso
não está certo. Aí está. Visão dupla, boom. Nós temos tudo para baixo e para cima. E acho que, ah, sim, é
porque essas posições estão erradas, então vamos mudar Vamos redefinir isso para zero. E agora temos
isso aqui, mais ou menos. Então, queremos manter as
rotações iguais, mas queremos que
seja localmente até 00 E agora o
corpo estático três D não é nem remotamente tão grande quanto era antes, que
é o que queremos Então, vamos mover
isso para que possamos ver. E como é
quadrado em sua base, adicionaremos uma caixa como
fizemos com o tanque. E então vamos simplesmente
esticar esse cara e girá-lo
para que fique inclinado no mesmo tipo de orientação
angular da própria
colina E perfeito. E
faremos o mesmo com uma rocha. Então, novamente,
precisaremos adicionar um nó filho. Corpo estático três D, faça fuzil. Vamos nos reorientar Bem, esse estava
realmente correto. E daremos ao
corpo estático sua própria forma de colisão. E também faremos
desse um cilindro. Mamãe. Porque apesar de
serem pequenos, na verdade não
queremos lidar com as interações físicas
de dirigir sobre rochas Só queremos que o jogador
não consiga
se mover ao longo ou sobre eles. Nos poupa muita
dor de cabeça. OK. E a última coisa
que vamos
fazer é
colocar as máscaras de colisão Então, o que é uma máscara de colisão? Uma máscara de colisão é
um conjunto de bandeiras que diz a Gadot o que colidir
e o que não colidir Então, embaixo do nosso tanque, podemos ver que há
uma aba de colisão sob o corpo do personagem três
D. E se a
expandirmos, teremos um monte de camadas e um
monte de máscaras A camada é a camada de colisão qual o objeto pertence Então, vamos renomear alguns deles. Portanto, edite os nomes das camadas. A primeira camada será jogada. A segunda camada será um obstáculo. E na camada três, mesmo que ainda
não tenhamos nenhuma,
seremos inimigos. Agora podemos dizer que o jogador
está na camada de colisão um, que é o jogador,
e ele colide E se desmarcarmos isso, ele não
tentará
colidir consigo mesmo, porque isso é ao mesmo tempo
tolo e impossível. Mas se clicarmos
em dois e três, isso significa que
qualquer coisa que esteja configurada para as camadas de colisão de obstáculos
ou inimigos, o jogador colidirá Então, se voltarmos para a árvore e expandirmos a colisão
e a colocarmos em obstáculos, e depois deixarmos
a máscara em um, ela colidirá
com o jogador E agora faremos o mesmo com
as colinas e também as colocaremos na
camada de obstáculos Eles colidirão
com o jogador e o mesmo com a rocha E, funcionalmente falando,
isso não mudou nada. Opa. Então, bem, o que há de errado aí? Isso é estranho. Eu movi o tanque de uma forma que não deveria
ter movido? Bem, uma das
colinas mudou. Oh, eu vejo o problema. Eu
mudei uma das colinas e agora ela está diretamente
em cima do tanque. Então, vamos mudar essa. Vamos voltar para a arena e encontraremos a colina que estava diretamente
no centro, e vamos
movê-la para cá. Então temos uma
segunda colina aqui, que é estranhamente
orientada. Mude isso. Deveria ser melhor.
Ok, agora vamos começar o jogo novamente.
Ok, muito melhor. Agora, se eu correr direto
para essa pedra, vou bater nela e parar. Boom, e lá vamos nós. E agora faremos o mesmo para
uma das colinas. Passe direto por essa árvore. E bum, chegamos à colina. E como você pode ver, como estou batendo na
colina em um ângulo, estou deslizando ao longo dela, e é isso
que mover e deslizar Se você não quiser deslizar
ao longo do objeto com o qual está colidindo e apenas fazer com
que seus tanques parem, existe um método chamado
mover e colidir E vou mostrar isso
para você muito brevemente. Na verdade, não
vamos usá-lo, mas temos que mover e colidir, e mover
e colidir, na verdade, exige muito
mais parâmetros do que mover e deslizar No mínimo,
ele mede nossa velocidade. Mas. Mas ele não o escala sob o capô
da mesma forma que o slide móvel. Portanto, temos que modificar nossa
velocidade por meio de nosso Delta. Agora, se eu voltar e
tentar bater em uma colina, meu tanque não vai
se mover ao longo da colina Isso simplesmente vai parar. Boom, e aí vai. Agora ele ainda pode girar, mas agora, se eu avançar, o tanque não
deslizará ao longo da colina Então, dependendo do tipo de jogo
que você quer fazer, essa é uma preferência
pessoal. Você pode
deslizar ou não deslizar. Vamos
voltar a deslizar só porque é
um pouco mais fácil E agora que podemos
colidir coisas, vamos começar a disparar
projéteis e explodir Então, nos vemos
na próxima lição.
16. O nó RigidBody — disparando uma concha: Bem vindo de volta. Nesta lição,
vamos ser violentos e vamos implementar os controles
e
a matemática muito complexa de três
D que nos
permitirão disparar projéteis
contra nossos oponentes Mas antes de fazermos isso, há alguma reorganização
que precisamos fazer Então, quando você começa a lidar
com a matemática em três D, a orientação de
seus modelos é importante. Isso importa muito. E o fato de
termos nosso tanque voltado para o eixo X
vai começar a nos causar problemas porque
Gadot realmente assume que o eixo
Z positivo está Então, no mínimo, você teria que girar todos os seus cálculos
de ângulo em 90 graus, e isso é insano.
Não estamos fazendo isso. Então, vamos pegar todos os nossos subcomponentes do nosso tanque porque o tanque em
si não vai ser girado de forma engraçada, mas vamos
pegar todos esses itens e vamos
girá-los 90 graus no eixo Z. E isso está completamente incorreto. Vamos tentar isso de novo.
Vamos ver o corpo aqui. E é 90 graus ao longo
do eixo y, não do eixo Z. E, na verdade, tenho café na minha
frente hoje, então não tenho desculpas. Tudo bem. Agora, é claro, está correto, mas como a torre foi deslocada,
ela precisa
ser ajustada precisa
ser Então, vou arrastar isso
de forma que
fique em zero X e, portanto,
perfeitamente centralizado E eu fiz isso errado. Na verdade, são 90 graus
na direção oposta.
Lá vamos nós. Agora, é claro,
a câmera está desligada, então teremos
que reposicionar
a câmera completamente,
e isso não é grande coisa Vamos usar nosso amiguinho
verde para manobrá-lo nas posições X
Z corretas Garantiremos que, falando de
forma transformada, ele esteja diretamente no X
e, em seguida, simplesmente o giraremos para que
fique voltado para o
tanque da maneira que deveria estar Vamos igualar isso
para menos 180. Vamos pré-visualizá-lo. Parece bom. Ooh. Na verdade,
aquela torre está um pouco à frente.
Bem, vamos trazê-lo de volta. Sim. Ok, agora estamos bem e tudo está
devidamente orientado. Vamos nos certificar de
que está tudo bem. Nossa caixa de colisão
está um pouco desligada. Além disso, acho que o
tornamos um pouco grande demais. Vamos reduzir isso um pouco, não que isso importe
muito, e estamos bem
nessa direção Ok, outra coisa
que vou
mencionar é que depois desta
aula ou durante esta aula, o inspetor do
nosso tanque vai começar
a ficar confuso porque vamos
adicionar,
tipo, outras quatro variáveis aqui com as quais queremos
poder jogar Felizmente, há uma
maneira de lidar com isso. Podemos usar algumas anotações
extras de exportação para organizar
nossas informações aqui Agora, o primeiro
que é extremamente
útil é chamado de Grupo de Exportação. E isso requer um rótulo. Então, depois de fazer isso, tudo o que é
exportável que vem depois dessa tag será
colocado no grupo, então agora você pode
recolhê-lo e reabri-lo E se você quiser
limpar o grupo, basta colocar outro desses aqui
e retirar o rótulo, e então tudo
voltará para onde deveria estar. Agora, é claro, Gadot gosta de colocar os
grupos na parte inferior Então, mesmo que não tenhamos
nenhum grupo, grupo, nenhum grupo, todas as coisas sem grupo
vão para o topo, e todas as coisas do grupo
vão para o fundo. Outra, que é um
pouco menos útil do ponto de vista visual,
é chamada de categoria Exportar, que cria um cabeçalho cinza completamente
novo aqui. E isso pode ser o que você quer. Você nunca sabe. Então aí está. Vamos agrupar o material para a
torre em seu próprio grupo E temos velocidade de giro, velocidade movimento, isso é bom. Ângulo traseiro da torre,
blá, blá, blá. Todas essas coisas estão, na verdade, relacionadas à
torre, então estamos bem E vamos deixar as coisas
assim por enquanto. E antes de
continuarmos, precisamos fazer uma
modificação nosso código existente devido à
rotação do modelo de tanques. Ou seja, temos que mudar o fato de que estamos calculando nossa velocidade usando a base de
transformação como base, atualmente
estamos
usando a propriedade X, mas precisamos mudar isso para Z.
E uma vez que fizermos isso,
nosso tanque deve estar manobrando da Oi Tudo bem, estamos bem. Agora, vamos criar
e adicionar a concha. Então, é claro, a primeira
coisa que precisamos fazer é criar
o próprio modelo de concha,
ou melhor, a cena da concha. Então, vamos fazer uma nova cena, e
será uma cena em três D. Mas em vez de usar um nó, vamos clicar com o botão direito do mouse, mudar o tipo e
vamos mudá-lo para um corpo rígido três D. Agora, o que é um corpo rígido três D Corpo rígido três D,
como o corpo do personagem três D e o corpo estático três D
que usamos até agora É um objeto físico. Somente nesse caso, é um objeto físico
que pode realmente receber forças como gravidade, empurrar
e assim por diante E vamos afetá-lo pela gravidade e
também pela velocidade inicial do
cano de nossa arma
para poder ser disparada e colidir
com Então, vamos renomear isso e vamos
chamá-lo de shell E vamos
voltar para três D e adicionar uma instância de
malha três D novamente. E esta vai
ser uma malha de trilhas tubulares. E a razão pela qual
vamos usar uma malha tubular é porque
podemos manipulá-la de
forma que possamos fazê-la parecer
uma concha sem realmente fazer mais nada Então, vamos clicar com o botão esquerdo
na malha para abri-la. Mas a primeira coisa
que temos que
fazer , como fazíamos antes, é girá-la para
que fique voltada para frente Então, voltaremos para a
transformação e a giraremos ao longo do eixo X para que
agora fique voltada para frente E como podemos, aumentaremos os degraus
radiais para dez, o que significa que será um pouco mais redondo Na verdade, poderíamos
aumentar isso ainda mais se quiséssemos Mas quanto mais
polígonos um objeto tem, mais lento ele é Então, vamos reduzir
isso para oito. Isso realmente não vai
importar a longo prazo. Então, para a parte inferior aqui, vamos mudá-la de forma
que fiquemos voltados para os lados para que possamos
ver o que estamos fazendo E, na verdade, para
este top, vamos fazer de cima para baixo. Ok, agora podemos ver
o que está acontecendo. Então, vamos mudar
as seções para duas, e vamos
mudar o raio
e o comprimento da seção Agora, queremos que isso caiba dentro do tanque. E, na verdade, vamos
economizar nosso trabalho e consertar o tanque enquanto eu
tenho isso em mente. E o que quero dizer
com consertar o tanque? Bem, a primeira coisa
que
precisaremos fazer é indicar onde o projétil
vai disparar do tanque. Pode adicionar um nó três D, mas há algo que é um pouco mais útil para nós, e é chamado de marcador três D. E um marcador
três D, como você pode ver, é filho do nó três D, então basicamente é apenas
um nó três D. No entanto,
o marcador três D é
basicamente um É meio difícil
ver daqui, deixe-me ver se consigo
esticar um pouco. Sim, não é fácil de ver. Mas um marcador três D é basicamente o equivalente
a três pontos D. E mesmo que seja meio difícil ver nessas janelas, por causa dos Gizmos, deixe-me ver se consigo
. Lá vamos nós. Ok. Então, se eu desmarcar, é um pouco mais fácil de ver Então, aqui, você pode ver
que é basicamente um conjunto de miras que indica onde o ponto está
no espaço de três D. E isso não
aparece no jogo. Esta é apenas uma
referência para que você possa dizer onde
está sem precisar selecioná-la, porque normalmente, se eu selecionasse um nó
, ele seria destacado. Mas, nesse caso, o marcador sempre mostra onde está Então, inclinei e posicionei o marcador de forma que fique dentro do nosso cano,
que
é o que queremos porque o projétil vai
disparar Na verdade, isso nos causa algumas complicações
leves, mas parece melhor
a longo prazo. Quero dizer, então poderíamos
colocar o marcador aqui, e então
geraríamos a concha aqui E isso
é totalmente bom,
mas isso significa que a concha basicamente
aparecerá na frente do barril
e depois disparará para aparecerá na frente do barril
e depois E só por
uma questão de realismo, na verdade
queremos que
nossa concha apareça dentro do cano e
depois atire Portanto, o desenvolvimento de jogos tem
tudo a ver com compromisso. Ok, agora que
temos um marcador e ele
está ligado ao barril
e a tudo mais, podemos
voltar ao que estávamos fazendo Então, vamos voltar para nossa concha. Mas primeiro, antes de fazermos
isso, temos que ver tamanho real de um barril Portanto, tem um raio de 0,1 e
um comprimento de seção de 0,2.
Vamos lembrar disso. Então, queremos que o raio
seja um pouco menor. Então, digamos 075. E eu já esqueci.
Qual era o raio Em vez disso, qual foi o comprimento? O comprimento da seção foi de 0,2. Digamos, 0,175. E uma maneira rápida de saber se isso está correto
ou não é
pegar nossa concha e arrastá-la para
a cena principal do jogo. E poderíamos colocá-lo aqui. E, uh, e isso parece
ser do tamanho certo. Perfeito. Ok, então
vamos deletar isso. E voltaremos
ao que estamos fazendo. Então, vamos voltar
para a concha, e vamos
mudar seu material, material
padrão, albedo, e vamos
torná-la cinza escuro E vamos modificar uma
curva. Então, o que é uma curva? Uma curva é uma
linha curva que
afetará o objeto
dependendo do tipo de objeto Então, neste caso, ele aplicará a curva
à seção do
cilindro em que estamos. Então, na verdade,
vamos reduzi-lo para dois ou talvez um, digamos,
e agora estamos aqui, e podemos arrastar
isso
e clicar
para adicionar outro ponto e , em
seguida, arrastá-lo para baixo E agora você pode
ver que a forma do cilindro realmente
mudou para seguir a curva. E vamos adicionar, adicionamos
uma segunda seção
e, na verdade, vamos movê-la um pouco mais para que
a concha fique um pouco mais
Woop, isso é demais. E então clicaremos
nesta pequena alça aqui Essas são as curvas de Bezier,
acho que você E então ajustamos
isso um pouco, e agora temos uma forma real de
bala para nossa concha, e ela está voltada
na direção errada, então precisamos encará-la
na direção certa Então, queremos girar a malha três D 180
graus ao longo do eixo y. E agora está voltado para
a direção correta. Bom. Tudo bem, a concha
vai precisar de duas coisas Vai precisar de
uma forma de colisão. Então, já temos um
desses aqui em nossa história. Vamos clicar nisso. Dê a
ele uma forma de colisão. A forma
da colisão será Podemos dar a ela uma cápsula ou um cilindro Vamos dar um
cilindro, porque
estamos usando cilindros até
agora, de qualquer forma Transformar. Vamos ter girar esse cara em 90 graus E agora vamos
redimensioná-lo para que caiba, mesma forma que fizemos com
nossos outros objetos E nesse caso, o
ângulo na frente
da concha não
importa realmente em termos de colisão, então vamos
deixar do jeito que está E, finalmente, o
shell exigirá um script. E nos certificaremos de
colocá-lo em nossa pasta de scripts. E vamos nomear
a classe como shell. Agora, ela
precisará fazer duas coisas. Ele precisará
acompanhar todas as colisões que tiver E quando realmente
dispararmos a maldita coisa, vamos
querer que ela olhe na direção de
sua trajetória de voo E isso é
realmente muito fácil. Nós podemos fazer isso agora. Então, em nosso método de processo físico, simplesmente
queremos usar
a função look at. A função de análise pega um alvo e também
requer o up. Então, qual é o alvo? Bem, o alvo é onde a concha está viajando
e onde a concha está viajando em qualquer ponto é a posição global da concha, que é um vetor que indica
onde ela está no mundo, mais a velocidade linear E a
velocidade linear é o vetor que indica em que direção a concha está se movendo
e com que velocidade Então, se você somar esses
dois, obterá a direção em que
o vetor está se movendo. Então, isso executará todos os quadros. E, basicamente,
a cada quadro, o projétil
atualizará sua posição ou rotação e, basicamente,
sua orientação angular forma que fique olhando
na direção em que está disparando E dessa forma, a
concha se
arqueará ao longo de seu caminho
de movimento, em vez simplesmente saltar por todo
o lugar, como
faria com um objeto
físico normal Se você não fizesse isso, na verdade, o projétil estaria apontando
na direção em que estava disparando porque estamos prestes a
orientá-lo de forma que ele faça Mas, na verdade, ele não se
curvará para baixo durante o voo. Ele meio
que,
tipo, voará direto
e depois E isso é um pouco chato. Nós não queremos isso. E também precisaremos
acompanhar as colisões. Então, fazemos isso conectando
o que é chamado de sinal. Agora, um sinal é uma mensagem
que qualquer objeto Gado pode
enviar e qualquer outro objeto GA Do pode se conectar a esse
sinal e ouvi-lo. E quando o sinal é emitido
, qualquer coisa que esteja ouvindo
o sinal chamará um método que você
especificará Então, neste caso, queremos
a forma de colisão. Não, na verdade não
queremos a forma de colisão. Queremos a concha. Preciso
fazer algumas coisas. A primeira coisa que precisamos
fazer é indicar
ao projétil que ele monitorará as colisões E fazemos isso expandindo o grupo de solucionadores e
clicando no monitor de contatos, e então temos que indicar que máximo de contatos
deve ser maior que zero máximo de contatos é um
parâmetro que diz: quantas colisões esse objeto vai
verificar antes de simplesmente
não se importar mais? E queremos que
tenha pelo menos um. Você pode aumentar esse
valor se quiser, mas seu projétil, na verdade só atingirá um
alvo e depois
explodirá, então isso não
importará neste particular Então, quando tivermos
tudo configurado, podemos clicar no shell e depois ir do inspetor para
o nó E o nó
mostrará todos os sinais que esse nó em particular é
capaz de emitir E como é um corpo rígido
três D com uma
forma de colisão configurada corretamente, a concha
emitirá esses sinais, e o que nos
interessa é Então, sempre que qualquer
outro corpo físico entrar na colisão
desse corpo rígido, ele acionará esse
método se o conectarmos Então,
vamos descer até o botão de conexão. Ele nos dirá que nos
perguntará em qual objeto
queremos colocar a função e como queremos que a
função seja chamada. E esses dois padrões estão corretos , então vamos clicar E agora, sempre que a concha atingir outro objeto que
seja capaz de atingir, esse método
será chamado E vamos preencher
esse método daqui a pouco. Mas também precisamos
ter certeza de que nossas camadas de colisão
estão definidas para o projétil, e o projétil não fará parte de
nenhuma das camadas que já
definimos porque
não é um jogador, nem um
inimigo, nem um obstáculo Então, podemos realmente
desmarcar tudo isso para que não seja considerado
parte de nenhuma camada Porque o projétil será
disparado tanto pelos jogadores
quanto pelos inimigos. Então, queremos que ele seja capaz
de colidir com o jogador, e será o
mesmo projétil para todos eles. Então, queremos que ele possa
colidir com o jogador. Queremos que ele seja capaz
de colidir com obstáculos e queremos que ele seja capaz de
colidir com inimigos E uma coisa que
eu esqueci de fazer foi esquecer de causar
qualquer tipo de colisão na arena Então, a concha vai cair no chão
se não fizermos isso. Vamos voltar aqui. para nossa instância de malha três D, e precisamos mudar
isso para bem, na verdade, o que precisamos fazer é adicionar um corpo estático três D e vamos
chamá-lo de ground. E vamos adicionar
a instância de malha três D
que é o solo
e, em seguida, vamos adicionar uma forma de colisão ao solo Caso contrário, a concha
cairia pelo mundo,
e isso seria ruim. Então, formato de caixa. Nós , vai ser
difícil pegá-los. Aqui. E só queremos que essa forma
colida com projéteis Então, colisão terrestre. Vamos dar a ele sua própria camada. Então essa é a camada do solo, e ela só colide Bem, na verdade,
parece que
vamos precisar de uma camada projetiva, não é? Ok, então concha. Tudo bem, então a concha é uma concha e colide com tudo E vamos apenas
verificar se nossa mãe. Ok. Sim, porque às
vezes quando você muda as
máscaras de colisão em vários objetos, se você não fizer isso
corretamente, isso pode causar todo tipo de comportamento tolo Então, vamos nos certificar de que ainda
estamos bem com
nosso tanque em movimento. Boop, sim, está tudo bem. Ok, então vamos voltar
ao nosso script de jogo e vamos modificar
nosso manipulador de controle aqui E queremos verificar se há
outro objeto do jogo, exceto a interface do usuário,
que
é mapeada tanto para a tecla
enter quanto para a barra de espaço E vamos usar
o
método de ação I pressionada porque isso só será acionado no quadro em que a
tecla foi pressionada. Se você continuar
pressionando a tecla, essa ação não
continuará sendo acionada. Então, isso garantirá que um projétil
seja disparado
por tecla pressionada. Portanto, se a entrada for uma ação que
acabei de pressionar,
aceito que o jogador dispare o Shell. E
ainda não
criamos o método fire shell, então vamos fazer isso agora. Ah. Para disparar um projétil, precisamos ter uma
referência ao projétil. Então, de volta ao nosso tanque, forneceremos mais
algumas variáveis de exportação. E vamos criar um grupo de exportações para que possamos
organizar essas coisas. Temos uma torre de
grupo de exportação. Portanto, há uma boa
volta para o tanque. Aqui vamos nós. Tudo bem Então, a primeira coisa que
precisaremos para
poder exportar é o que
chamamos de pré-fabricado E isso é basicamente um link para
a cena que vamos
instanciar sempre que
dispararmos um projétil, que é nossa cena de projétil E como não precisamos
definir o tipo dessa cena, tudo bem se você
deixar isso vazio, mas é bom saber que o tipo de cena é
chamado de cena lotada. Agora, se eu quiser, posso simplesmente arrastar minha cena de
concha até aqui. Ele será automaticamente
carregado e armazenado em cache nessa variável quando o tanque for instanciado como parte do
jogo, o que é atualmente Então, agora, quando disparamos um projétil, vamos criar
um novo desses objetos de concha. Portanto, temos var shell, que é do tipo shell será igual à instância
shell prefab dot E uma vez que fazemos isso, na verdade precisamos de mais uma coisa aqui que seja bastante importante, embora não haja problema se a
implementarmos um pouco
mais tarde, mas faremos agora. Vamos definir
um sinal de que o tanque
dispara sempre que dispara um projétil. E a razão pela qual
vamos fazer isso é porque, de dentro do tanque, não
temos
acesso direto ao mundo porque o tanque é
filho do mundo. Podemos obtê-lo chamando
a propriedade principal do tanque, que é uma
propriedade embutida de um nó três de D, mas isso depende do fato de que sabemos
o que é essa hierarquia e sabemos que o jogador seria capaz de obter a mãe, que é o jogo,
e então
seríamos capazes de obter Ana
de dentro do Mas há
várias maneiras pelas quais
podemos quebrar essa hierarquia
durante a produção Então, isso não é
realmente uma boa ideia. Queremos que as coisas sejam encapsuladas o
máximo possível, o que significa que elas
não precisam saber nada além de si mesmas Então, tudo o que fazemos é mandar
o tanque disparar um sinal, e vamos
dar uma referência ao projétil que
foi disparado. Isso significa que depois de
instanciarmos nosso projétil, emitimos esse sinal
e passamos para ele o projétil
que acabamos E agora nada acontece. Esse sinal simplesmente
sai para o éter desaparece
e existe até a profundidade
do universo,
ou você termina o jogo, o
que ocorrer primeiro Então, o que precisamos fazer é que o jogo
ouça esse sinal. E há algumas
maneiras de fazer isso. Podemos
conectá-lo da mesma forma que
fizemos com a
forma de colisão na carcaça, mas ainda não
decidi se quero que o tanque sempre
exista ou não Então, vamos definir
uma função pronta. Agora, ready é chamado sempre que um nó entra na árvore da cena. Portanto, é, para todos os
efeitos, a função que você chama
quando o nó está pronto e deseja que ele
faça um monte de
coisas antes de realmente
começar a fazer as coisas Então, neste caso, queremos que os jogadores Shell
disparem um sinal e queremos
conectá-lo a um método que
chamaremos de Shell Fred. E, claro, Deus O está
mal-humorado porque ainda não
definimos esse método,
então vamos fazê-lo Funk em projétil disparado. Agora, como esse método é chamado em resposta ao
sinal que definimos, ele requer os mesmos
parâmetros do sinal. E como o sinal usa um parâmetro
de objeto do tipo shell, precisamos definir também
precisamos definir
isso como parte do nosso manipulador de
sinais Agora temos
esse método que será
chamado quando receber chamado quando receber o sinal de que o
projétil foi disparado. E tudo o que o jogo precisa
fazer é adicionar a concha secundária, porque queremos que o jogo adicione
a concha
ao gráfico de cena com
todos os outros objetos. Então, se você monitorar durante
o jogo, e pudermos ver isso em um momento
, ele aparecerá aqui. Então, vamos fazer isso.
Vamos rodar nosso jogo. E você pode monitorar o que seu jogo está fazendo
enquanto o jogo está sendo executado. E é um pouco mais fácil fazer quando o jogo
está no modo Janela, e é por isso
que eu não o tirei do modo
Janela Então, se voltarmos
ao nosso editor,
acessarmos o gráfico da cena
e clicarmos em Remoto, esse é o
gráfico da cena real do seu jogo de corrida. Local é aquele com o qual você está
trabalhando no editor. Remoto é o
que está no jogo. Agora, se eu voltar
para a janela do meu jogo e pressionar a barra de espaço, você pode ver que
temos uma concha. Foi adicionado
ao mundo do jogo. E agora, se eu recuar, podemos realmente ver isso. Está aqui mesmo. E isso é porque ainda não lhe demos nenhuma força ou algo
parecido. Então, tudo isso aconteceu e você realmente não
pode ver isso desse ângulo
de câmera. Tudo o que aconteceu foi
que ele simplesmente caiu e caiu no chão, e agora está fazendo todo tipo de bobagem
maluca porque está
colidindo com o Então, podemos ver isso um pouco mais facilmente se
formos até a concha, acessarmos Lock
e atingirmos o Y linear. E isso significa que a concha não
subirá nem descerá, independentemente do tipo de física aplicada a ela Então, agora, se eu disparar um
projétil e me afastar, você pode realmente
ver onde ele está. E isso provavelmente é
porque, bem, eu realmente não
sei por que isso acontece, mas vamos corrigir isso
porque isso não é realmente
o que queremos, de qualquer maneira. Então, vamos voltar ao Shell e deixar o Y linear bloqueado por enquanto, porque
queremos poder
depurar onde nosso shell está aparecendo quando o geramos
pela primeira vez Ok, uma coisa que precisamos corrigir antes de continuarmos é que eu
esqueci de fornecer o vetor up
para nossa função de análise Então, sempre que você olha, e também há várias
outras funções que
exigem um vetor de referência,
geralmente o vetor ascendente, basicamente, você só precisa fornecer o
vetor três pontos para cima, que é um vetor constante que indica para cima na direção Y. E Godot usa isso
para todos os tipos de cálculos para garantir que tudo esteja
orientado corretamente. Ok. Portanto, a primeira coisa que
precisamos fazer para disparar nosso projétil corretamente
é colocá-lo onde deveria estar. Porque agora,
tenho a sensação que, quando
geramos a concha, ela está simplesmente surgindo às 00
no mundo Então, vamos mudar isso.
E para mudar isso, precisamos de uma referência
ao ponto de disparo,
que é o marcador três D.
Então, var, marcador de
ponto de fogo do projétil três B. Agora, simplesmente
arrastamos isso até aqui e temos uma referência
ao ponto de disparo Também precisaremos definir
a velocidade do cano para a
concha. Então, vamos fazer isso. Obrigado. Esta é a velocidade ou a velocidade que vamos aplicar
ao projétil quando ele disparar, e podemos torná-lo um int Podemos torná-lo igual a 20 e, seguida, você pode alterar esse valor em
seguida, você pode alterar esse valor
posteriormente, se decidir que é muito rápido ou muito lento. E antes de realmente
começarmos a colocar a
concha no mundo, também
há outra
coisa que devemos fazer. E isso é, devemos fornecer um valor aqui chamado
Ignorar camada, que é um número inteiro E por que vamos fazer isso? Bem, porque, como
mencionei antes, cada projétil será disparado pelo jogador
ou pelos tanques inimigos, e não queremos que o projétil colida com sua própria
equipe, por assim dizer Para o jogador, isso significa que não
queremos que um projétil
disparado pelo jogador possa
testar colisões
com o jogador, especialmente porque estamos gerando o projétil dentro do cano
da arma do Vamos precisar de um
pouco mais de lógica para os inimigos, porque se simplesmente
desativarmos a colisão um projétil inimigo
contra outros inimigos, isso significa que os
inimigos serão capazes atirar uns nos Então, quando chegarmos ao
ponto em que estamos fazendo IA, basicamente
faremos com
que os tanques não atirem quando não tiverem
uma linha de visão clara para o jogador e se houver
outros tanques por perto. Existem outras maneiras de
resolver esse problema, mas é assim que
vamos fazer. O que isso significa é que
temos que fornecer o índice de camada da
colisão que queremos
desativar sempre que um
projétil é disparado, porque o mesmo
método de projétil de fogo será usado tanto pelos jogadores
quanto pelos tanques inimigos Então, no caso do jogador,
será a camada um,
porque, como você lembra, os valores das
camadas começam em um, mesmo que diga
que é o bit zero, o que é meio desagradável Então, temos um
projétil de fogo igual a um
e, dentro do tanque, vamos dizer
ao projétil que
defina o valor da máscara de colisão
igual à camada de ignorar e vamos
configurá-lo como falso E isso significa que
se um jogador disparar um projétil e passarmos por
um como camada ignorada, ele irá para o projétil. E vai definir
a camada de colisão
ou a colisão, eu
fiz essa camada ou
fiz Máscara de colisão. Isso está correto. Eu quero ter certeza de
que é o certo. Então, vai para a máscara
de colisão. Isso definirá a camada
um como falsa, o que significa que a
desativará. Isso significa que um projétil
disparado pelo jogador
não colidirá com o jogador,
que é o que queremos E podemos ignorar esse
erro porque não
salvamos essa função antes de
colocá-la aqui Por isso, foi lamentável
que as assinaturas não coincidissem e
agora estão boas Depois de fazer isso,
podemos realmente começar a posicionar e
orientar a concha Agora, não queremos
fazer nada com a posição ou
rotação
das conchas antes que elas sejam
adicionadas ao mundo Caso contrário, receberemos
uma mensagem de erro, algo como Is inside trees equal to false. E embora não seja realmente um grande problema,
nós meio
que não queremos que Godot cometa
erros em Então, a posição global da concha. É igual à posição global dos Shell Fire
Points. E agora, se formos ao nosso jogo, e para tornar isso um
pouco mais fácil de ver, vamos girar nosso cano E nós disparamos, aí está nossa concha. Agora, é claro, está voltado para
a direção errada e não está se movendo nem
nada parecido. E estamos prestes
a corrigir isso a seguir. Orientar a concha é
um pouco mais complicado. Na verdade, levei
algumas horas
para descobrir isso antes de filmar, para que você possa se
beneficiar de toda a minha dor Então, estamos perdendo
algo em termos. Ok, então eu a chamei de
dobradiça da torre. Deveria ser
junta de torre, mas de qualquer forma. Boop. Isso é melhor? Isso é melhor. Ok. Portanto, para
girar o projétil, precisamos levar em
consideração que, na direção X, as dobradiças
da torre, a Isso não faz
muito sentido. Vamos dar uma olhada nisso. Então, se voltarmos
para o tanque, Boop. Bem, vamos ver
isso de cima. Então, o ponto de ancoragem do cano, ao
qual nos referimos no script como a dobradiça
da torre, está aqui E como o tanque
está voltado para frente, que está na direção Z
positiva, giramos a dobradiça
com a rotação X. Mas como o tanque é realmente girado em seu espaço
local em 90 graus, na verdade
estamos
girando-o na direção Z. Então, isso é simplesmente irritante
quando todos saem. Então, a rotação Z, neste caso, é a rotação para cima e para baixo, porque quando originalmente tínhamos o
tanque voltado para a direita, era isso que o
movia para cima ou para baixo. Então, isso inclinará a concha
na direção correta. No entanto, precisamos
inclinar a concha forma que ela fique voltada para cima
e, por algum motivo, isso
exija que invertamos a rotação Não sei por
que isso acontece, mas é. Então, precisamos
levar em consideração a rotação da torre
na direção Y. Porque a dobradiça da torre não gira realmente na direção
Y. A torre gira. E vamos dar uma
olhada nisso novamente. Vamos voltar para três
D. Então, a dobradiça, que está aqui ish, não gira quando
a torre gira Então, para que o projétil aponte na direção em
que será disparado, temos que levar em consideração
a rotação das torres. Então, quando fizermos tudo isso, a concha ficará
voltada para a orientação
correta. Então, vamos lá, desse jeito, e vamos atirar. E isso vai me fazer de
idiota, não é? Tudo bem? Vamos ver
qual é o problema. Bem, isso foi divertido de depurar. Ok, então por algum motivo,
o projeto mestre, onde fiz isso funcionar ontem com
exatamente os mesmos números, não
está fazendo a
mesma coisa que esta versão
do projeto com
exatamente os mesmos números. Yay. Então, a maneira como consegui consertar
isso
foi fazendo algumas coisas. Primeiro,
voltamos para a concha e garantimos que a orientação fosse feita de
uma maneira um pouco diferente. Você deve ter
notado
que inicialmente giramos primeiro a partir do eixo X, e não sei por que fizemos isso. Não deveríamos
ter feito isso de jeito nenhum. Mas eu reiniciei a rotação e a
alterei de forma que, em Y, nós a movemos, a giramos forma
que a concha
estivesse voltada para frente e na direção Z que
a concha estivesse voltada para frente O que acontece se eu mudar
isso de volta para zero? Estranho. Então eu acho que a orientação da base
da malha exigia isso. Não tenho certeza do porquê disso. E também verifiquei se as orientações
dos tanques
estavam corretas
e instalei a
torre embaixo do corpo, em vez de diretamente embaixo do Não tenho certeza por que isso teve um efeito sobre isso.
Realmente não deveria. Mas, sim. Então, uma vez que
tudo isso foi feito, podemos efetuar a
rotação pelo
Fator original para o Z, que era o valor negativo
da rotação das dobradiças
da torre para
cima e para baixo, o que Mas para que a
rotação Y funcionasse corretamente, tivemos que adicionar a rotação das torres à
rotação dos tanques Caso contrário, ele teria
sido orientado corretamente somente se o tanque estivesse voltado para cima,
para frente ou para trás Agora, se formos
assim e subirmos até aqui e
depois apertarmos a barra de espaço, afastaremos o cano para que você possa vê-lo Agora temos uma concha
perfeitamente orientada. E se eu orientar o
tanque, a mesma coisa. Então, a moral da
história é que às vezes você só precisa brincar
com os números para ter
certeza de que tudo está
alinhado corretamente, porque visualmente
falando, muitas
dessas orientações funcionam enquanto
matematicamente não funcionam E isso é ruim. Então, a
próxima coisa que temos que fazer é fornecer
o que é chamado de impulso E um impulso na física é uma força
aplicada única a um corpo Então, se quiséssemos que a concha se movesse
constantemente para
todo o sempre, aplicaríamos uma
força, mas não o fazemos. Só queremos que tenha uma explosão
inicial para que
seja impulsionada e, em seguida, a gravidade
e a velocidade E isso é chamado de impulso. Então, um impulso é um vetor três. E neste caso, e eu não tenho certeza de
por que isso é feito dessa maneira. Você pensaria que
seria na outra direção, mas não é, e eu realmente
não me importo. Começamos com o vetor traseiro, que está na
parte traseira da concha, e vamos multiplicá-lo pela
velocidade do focinho E então, uma vez que tenhamos
feito isso, podemos aplicar esse impulso à nossa concha Infelizmente, isso não é
tudo porque o vetor de volta é um vetor
normalizado, o que significa que só
será um na direção Z
negativa E não será
orientado
corretamente para a orientação dos
tanques. Então, basicamente, para encurtar a história, teremos que girar esse impulso com a orientação dos
tanques Então, podemos fazer isso
aqui embaixo. Então, se pegarmos nosso impulso
inicial, que é um vetor reto para trás multiplicado pela nossa velocidade
muscular, vamos dar uma olhada em nossa concha, então para
trás está uma unidade aqui, e então a multiplicamos
pela velocidade do focinho Então, na verdade, está
lá em algum lugar. Mas agora temos que
orientá-lo para a concha. Então, vamos voltar para o nosso tanque. Isso significa que
temos que girá-lo e espero que
isso esteja correto, que acabei de mudar
todas as orientações, mas temos que girá-lo
ao longo do eixo direito,
que é o eixo X em relação à
orientação da E então temos que
fazer o mesmo com o eixo ascendente porque estamos
inclinando a concha para cima Embora, neste caso, eu ache que, como
adicionamos esses dois, não
precisamos
compensar isso Então, vamos
mudar isso de volta para a rotação da
concha Y e
ver o que acontece. E então, uma vez feito isso, podemos fazer casca, aplicar e vamos usar
um impulso central, que significa que o
impulso será
aplicado diretamente no
centro do objeto Também é possível
aplicá-lo fora do centro, mas realmente não precisamos disso. Então, impulso que deve
disparar o projétil. Agora, veja como não funciona.
Sim, está um pouco errado. Pelo menos Ah, e parte
do problema é que acho que não desativamos o, ainda
temos o Y linear marcado lá, então vamos desmarcar isso Talvez isso resolva isso. Ufa. Sim, sim, isso acontece. Então, agora temos nossos
projéteis disparando e eles estão
disparando corretamente em E a vida é boa. E você pode ver que eles estão invertidos Incrível. Então, vamos
ter que consertar isso. E então, quando o
fizermos, estaremos prontos para ir. Sim, os projéteis estão invertidos. Isso é hilário. Tudo bem, vamos
verificar o porquê disso. Ok, erro estúpido. Portanto, há mais um
parâmetro para a
função look at que meu código original tinha que essa versão
do código não tinha. E isso é verdade. Então Look at tem um terceiro parâmetro que
diz usar a frente do modelo, o que significa que ele se orientará em direção ao eixo Z,
que é para frente Caso contrário, ele
trata a câmera para frente, o que é negativo, então exatamente
o oposto. Então, se definirmos isso como verdadeiro, é por isso que a concha foi virada,
porque estava assumindo que o eixo Z
que controla para frente
e para trás estava Então, agora, depois de toda essa bobagem, Boom, temos uma concha
inclinada co
17. Ambiente: iluminação mundial e sol global: Bem-vindo de volta. capítulo
curto, mas não menos
interessante, veremos como modificar
a aparência do ambiente usando
o ambiente mundial
e
os nós de luz direcional Então, como você pode ver
aqui, eu apaguei a luz direcional
que usamos como nosso sol temporário nas
últimas aulas
e também mudei
a
cor de fundo para e também mudei que
pareça um pouco
com o pôr do sol Agora, isso está inteiramente em
pré-visualização, se eu fosse rodar o jogo, você pode ver
que temos Nodite e o céu é cinza e não se parece em nada com
o pôr do sol que criamos E isso é porque essas
são puramente visualizações e são controladas por
esses dois botões aqui Temos o ambiente de pré-visualização,
que se desligarmos, lá vai o pôr do sol, que cobre o chão, o
horizonte e o céu. E também
temos uma prévia da luz do sol. Então, se desligarmos isso,
nossa luz do sol vai embora. E se desligarmos os dois, não
conseguiremos ver muita coisa. Então, o objetivo
é permitir que você ajuste as configurações do ambiente
e as obtenha imediatamente antes adicioná-las ao seu mundo de jogo, porque nas
versões anteriores do Gadot, você tinha que ajustar as configurações manualmente
e depois executar
o jogo toda vez quisesse ver como elas pareciam
diferentes, e isso era uma
chatice Vamos clicar nesses três pontos e obteremos
essas configurações
tanto para o ambiente
de visualização quanto para o sol de visualização E podemos mudar aqui
todas as coisas que
queremos mudar. Então, para o sol, por exemplo, podemos mudar seu ângulo. Podemos mudar seu azimute,
seja lá o que isso signifique. Podemos deixar o sol muito quente se quisermos
tatuar,
por exemplo, e mudar a
distância das E quando tivermos
um sol de que gostamos, vamos fazer algumas sombras longas Assim que tivermos um sol que
gostemos , vou colocar isso de volta em um. Podemos então adicioná-la à
cena como uma luz direcional. Agora, veremos mais
sobre
a iluminação em uma aula futura, mas a luz solar é simulada por uma luz direcional
. Então aqui está um. E então observe que como adicionei uma
luz direcional à cena, não
posso mais mexer com
o sol no painel de visualização porque, como a cena já contém uma luz
direcional três D, ela não permite
mais
usar as configurações de visualização porque está usando as configurações
do que
já está E podemos fazer o mesmo,
pelo meio ambiente. Então, como você pode ver, eu
mudo a cor do céu para laranja. Eu posso torná-lo ainda mais
escuro se eu quiser. Ou se quisermos estar em um planeta alienígena,
podemos torná-lo verde. E há uma pequena
limitação aqui pois embora você possa
alterar bem o solo, você pode alterar a cor do
solo aqui. Se você quisesse,
você poderia realmente alterar o que é chamado de Horizonte, que é essa pequena faixa brilhante no meio entre o céu e
o solo, mas você não pode fazer isso
através da pré-visualização do sol Então, vamos decidir que
esse sol verde-limão é exatamente o que nós e , em seguida, clicaremos em Adicionar
ambiente à cena e obteremos um nó
ambiental mundial. Agora, o
nó World Environment tem várias opções, mas uma delas é
que podemos modificar as configurações
de ambiente com as quais jogamos aqui, e que estão no recurso de
ambiente. Então, se
clicarmos nele, abriremos, e aquele com o qual estávamos
brincando é o céu. Então, se você abrir o céu e depois abrir o material do céu,
o material do céu é
um céu processual Agora também podemos
usar camarotes e outras coisas, e veremos isso
em uma
lição posterior Se expandirmos o céu, você terá que cavar bem
fundo neste. E então, se você
finalmente descer e abrir as próprias
configurações do céu, aqui estão as configurações
que alteramos, e agora, se quisermos mudar
o horizonte, podemos fazer isso. Agora você vê que eu tenho mais um horizonte
laranja lá atrás. E você também pode
mudar o chão, então eu vou mudar o chão
e vou torná-lo vermelho. Então, agora temos um planeta verdadeiramente alienígena com
o qual estamos mexendo E você também pode alterar o ângulo do sol aqui,
se precisar. E isso é muito profundo. Há também várias outras configurações,
semelhantes às
dos materiais que
examinamos anteriormente
para espaço na tela, oclusão do
ambiente e também
neblina e neblina E isso é meio
difícil de acertar. Mas, você sabe, se você
quiser lutar em uma
tempestade de neve, aí está Agora, esse ambiente
realmente afetará o jogo inteiro porque se você entrar no jogo, já que esse ambiente
faz parte da arena, e a arena faz parte do jogo, então, quando
entrarmos no jogo, veremos isso, e
parece meio louco. Mas você também pode substituir
isso ou, pelo menos ,
adicionar um
ambiente à sua câmera E, na verdade, essa costumava ser a única maneira de fazer
isso em Gudo
, então bom que você
não precise mais lidar com isso. Mas
ainda está disponível. Então, digamos, vamos
voltar para nossa arena. Vamos voltar ao Meio Ambiente
Mundial. E eu apaguei a neblina? Sim, parece que eu
apaguei a neblina. OK. Então,
digamos que queremos que nosso mundo seja, por falta de uma
palavra melhor, normal, mas em um determinado nível ou
por meio de uma câmera específica, queremos uma configuração de neblina Assim, podemos adicionar um ambiente
diretamente à câmera, e isso nos dará todas
as mesmas configurações. Então, agora podemos simplesmente ficar sob a
neblina e ativá-la. E agora, se eu executar o jogo, ele deve combinar os
dois, e funciona. Na verdade, parece muito
bom. Tudo considerado? Então, sim, em seu nível
mais básico, é como você altera o ambiente e a
iluminação em suas cenas. E, novamente, veremos luzes
direcionais e
coisas do gênero em uma lição futura, mas isso
lhe dará o básico Nos vemos na próxima lição, onde começaremos a programar novamente.
18. Jogabilidade: adicionando tanques inimigos por meio de cenas herdadas: Bem-vindo de volta. Nesta lição, vamos dar
uma olhada na criação cenas
herdadas para que possamos subclassificar nosso tanque e fornecer um novo tanque com funcionalidade
adicional Então, vamos dar uma
olhada no nosso tanque. É um
tanque muito legal, e
temos roteiros que farão coisas, dispararão,
se moverão e todas essas coisas boas. Mas para um tanque inimigo, vamos querer informações
adicionais. Queremos que o tanque inimigo
tenha uma cor diferente. Vou fazer com que os tanques
inimigos recarreguem mais devagar. Além disso, eles
precisarão ser controlados por uma máquina de estado de
IA, que vamos desenvolver
na próxima lição, eu quero dizer. Se não, definitivamente não
menos do que duas aulas depois
. Provavelmente o próximo. De qualquer forma, resumindo, queremos adicionar um módulo de
IA adicional a esse tanque. Agora, poderíamos simplesmente copiar a cena do tanque existente e adicionar nossas novas
informações a ela. Mas como é um arquivo
totalmente separado, se fizermos alguma alteração
no tanque original, não se propagará
para o novo tanque, e queremos que eles façam isso Então, vamos usar o que é
chamado de cena herdada. Então, entramos na cena,
em vez de uma nova cena, dizemos cena nova e
herdada, e ela nos perguntará de qual cena queremos herdar Então, vamos herdar do tanque. Agora temos uma nova cena, e é nosso tanque. O nome está em branco, o que significa que é único. Mas todos esses nomes amarelos, esses são os
nós originais do tanque, mas são coloridos em
amarelo para mostrar que são herdados
da outra cena Agora, se
mudássemos a outra cena, as informações nessa
cena seriam atualizadas. Então, por exemplo, a
primeira coisa que vamos fazer é salvar isso e
chamá-lo de tanque inimigo. Agora, se eu fosse até o tanque e fosse até o cronômetro de recarga,
alterasse o tempo de peso para
cinco e depois o salvasse Agora, se formos até o tanque inimigo, o cronômetro de recarga agora é cinco porque é herdado do tanque
original Então, vamos reduzir isso para dois. No entanto, é possível
alterar essas coisas independentemente da classe
original ou da cena original. Então, se voltarmos para o tanque inimigo, vamos
renomeá-lo para Tanque Inimigo E vamos soletrar
corretamente. Aqui vamos nós. Além disso, podemos realmente alterar os dados nesses valores e isso substituirá o que
vem do tanque original Então, no tanque original,
o cronômetro de recarga é dois, mas no cronômetro de recarga do inimigo, vamos
mudá-lo para Agora clicamos em salvar e, se
voltarmos ao tanque original, o temporizador de peso ainda é dois, mas no
tanque inimigo, é três E vamos fazer o mesmo, vamos mudar um pouco
a cor, e essa é a
aba errada. Lá vamos nós. Então, se formos até o corpo, vamos selecionar
que não é o correto. Onde está? Qual deles
é? Aí está. Vamos mudar a cor. Bem, podemos mudar a
cor da malha original. No entanto, como mencionei antes, isso é salvo em várias cenas e é um pouco complicado, então teríamos que torná-lo
exclusivo para essa cena. E, na verdade, não
queremos fazer isso. Então, vamos dar uma olhada em um novo recurso, ou pelo menos novo
no sentido de que ainda não o
examinamos, a substituição do material da superfície O que isso faz é que você pode fornecer um material completamente
novo aqui, e ele substituirá
esse material Então, agora temos nosso branco
padrão, e vamos até albito e vamos
mudá-lo para cinza escuro E economizaremos. E agora, apenas para os tanques inimigos, eles têm uma faixa cinza no corpo E agora seremos
capazes de diferenciá-los. Então, agora, se entrarmos no jogo, se quisermos arrastar
um para nossa cena, o
que fazemos,
pegaremos o tanque inimigo , o arrastaremos até aqui
e, em seguida,
usaremos a
coisa para movê-lo ,
colocaremos aqui e mudaremos a
orientação. E agora, em nossa cena,
temos um tanque inimigo. E se olharmos para ele, ele tem informações que não
podemos ver
porque não foi exportado Então, vamos clicar aqui para
abri-lo. E lá vamos nós. Estamos de volta ao nosso tanque inimigo e podemos verificar se suas informações estão como deveriam
ser. Recarregue o cronômetro É. Agora, se você quiser
alterar as informações a partir daqui, clique com o botão direito do mouse e
selecione filhos editáveis E isso permitiria que você
alterasse essas informações aqui, e elas seriam salvas nessa
instância específica do tanque. Então, poderíamos realmente mudar as cores dos tanques diretamente daqui e
individualizá-los, mesmo que estejam todos
na mesma equipe, por assim dizer Ok, então esse é o
fim desta lição. Junte-se a mim na próxima lição e continuaremos
com mais coisas legais.
19. Como destruir os tanques: Bem vindo de volta. Nesta aula, nós vamos
aprender como configurar os tanques inimigos de forma que eles possam ser destruídos
pelo jogador. E a primeira coisa que
vamos
fazer é mover
o tanque inimigo para que
fique um pouco mais
visível para o jogador. Dessa forma, não
precisaremos procurar o cara toda vez que iniciarmos o jogo. Ok, muito melhor. Então, a primeira coisa que precisamos
fazer é alterar alguns dados
adicionais do tanque que foram herdados do jogador e
que não precisamos mais Então, se expandirmos o
tanque, na verdade, não, devemos fazer isso a
partir da cena dos tanques para que isso afete
todos os tanques. Então, a primeira coisa que precisamos
fazer é
ir até a câmera e você notará que a
câmera está configurada como atual. Isso é ruim porque queremos apenas que a câmera do player esteja
atualizada, então desmarcamos isso Caso contrário,
veríamos o jogo
do ponto de vista
do tanque inimigo
e, você sabe, apesar de
direitos iguais para tanques e tudo mais, queremos que o jogador possa
ver
o que está fazendo. Além disso, o tanque está atualmente configurado para a mesma camada de
colisão do jogador Então, precisamos desmarcar isso, e precisamos verificar isso para
que fique na camada do inimigo E não queremos que isso aconteça. Bem, queremos que ele colida
com outros inimigos porque não queremos que os tanques
se atropelem, mas também queremos que
colidam com o jogador E isso deve nos cobrir. Agora, o outro problema é
que o tanque está herdando no
momento ou está configurado como tanque no script E, como mencionamos
no capítulo anterior, o tanque terá algumas informações adicionais
que precisarão ser
tratadas no script. Então, vamos
até o inspetor e vamos até
o final, onde
diz: roteiro E isso mostra o
script que está atualmente anexado
ao tanque inimigo. E fiquei agradavelmente
surpreso ao descobrir que eles atualizaram isso
recentemente Então, se eu for aqui e
selecionar extend script, que é exatamente o que queremos, ele
gerará automaticamente um novo script herdado do tanque
chamado Enemy Tank, que é exatamente o que queremos, exceto que
o queremos na pasta de scripts Ok, agora vamos criar
isso. E estamos bem. Nas versões anteriores do Gadot, era necessário desanexar manualmente
o script e
reanexá-lo ou, pelo menos criar
manualmente o
script e, em seguida, definir o nome da classe e
anexá-lo ao inspetor E agora está mais
simplificado. Eu adoro o software
de código aberto. Então, vamos nomear
esse novo script de tanque, se conseguirmos
soletrá-lo corretamente, AI Tank E também vamos mudar algo sobre os tanques em
geral porque, no momento, é
possível que um projétil
atinja não apenas um tanque, mas também os obstáculos
ou o chão da arena. Mas a única coisa que
queremos destruir é um tanque. E há algumas maneiras diferentes
de indicar que somente
tanques podem ser destruídos. Vamos dar
uma olhada em um dos mais
simples,
que são os que Então, se
voltarmos ao script do tanque ou se voltarmos ao
objeto do tanque e entrarmos no nodo, veremos sinais e grupos. Então, se mudarmos para
a guia de grupos, você verá que não temos grupos. Então, criaremos um novo grupo
e o chamaremos de slable. Agora, ele
será automaticamente colocado sob os grupos de cenas, o que significa que ele só é
válido para qualquer objeto dentro dessa cena e não é reconhecível fora da
cena. Nós não queremos isso. Então, vamos
clicar com o botão direito do mouse e convertê-lo em um grupo global. Isso significa que qualquer cena em todo
o jogo
pode ser adicionada a esse grupo Agora, se clicarmos em Salvar e
formos para o tanque inimigo, podemos ver que o tanque inimigo, por ser
um tanque derivado está automaticamente
na categoria vendável Então, agora em Shell, nosso script de shell, originalmente, temos esse
método no corpo inserido com o qual
não fizemos nada há alguns capítulos
ou algumas lições Então, a primeira coisa que queremos
fazer é
definir realmente o tipo de
corpo que está chegando,
e queremos que seja um corpo físico três D. E isso
basicamente tentará forçar qualquer objeto
que seja passado por esse método
para que seja passado um corpo
físico três D,
e
isso funcionará porque a única coisa com a qual
a concha pode colidir são outros corpos físicos.
três Ds, que incluem os corpos estáticos, corpos rígidos e corpos de
personagens Então, ainda queremos que a
concha desapareça. Mas agora, e na verdade, se não fizemos isso, isso é
parcialmente por conveniência. Também é parcialmente porque
as variáveis que têm seus tipos definidos especificamente são um pouco mais eficientes
para serem acessadas por Gadot Mas se criássemos
uma declaração if then aqui, e tivéssemos que ir para o corpo
e depois bater em um ponto, bem, não
teríamos preenchimento automático
porque Gadot
não sabe que tipo
de variável é essa Então, se o forçarmos a chegar a um corpo
físico três D, agora, se descermos até
aqui e acertarmos o ponto, agora
teremos o preenchimento automático E o método que
queremos é chamado de I em grupo. E eu me pergunto se
você pode arrastar isso. Não, você não pode. Então, teremos que
digitá-lo manualmente. Então, se o corpo que
passamos está no
grupo destruível, então queremos
destruir o corpo, e podemos fazer isso com
o método dos três corpos Agora, se executarmos nosso jogo, devemos ser capazes de explodir
o tanque inimigo. Ainda está nublado Estrondo. Tente novamente. Estrondo. Não. Estrondo. Tudo bem, não tenho certeza se estou
batendo no tanque ou tenho um
erro no meu script Lá vamos nós. Golpe direto. Talvez queira tornar um
pouco mais fácil atingir o tanque
e fazer experiências ou
nos inspecionar para investigar Essa é a palavra que estou
procurando. Talvez queiramos investigar por que isso estava
acontecendo. Mas, sim. Então, isso é tudo para esta lição. E na próxima lição, daremos aos nossos tanques
inimigos um pouco de inteligência que eles possam atirar
no jogador e tentar
atirar de volta nele, caso
contrário,
o jogo não
seria muito justo ou divertido, Tudo bem, nos vemos lá.
20. IA: máquinas de estado: Bem-vindo de volta. Nesta lição,
aprenderemos como
criar uma máquina de estado
que, na próxima lição, conectaremos nossos tanques inimigos forma que eles possam dirigir, procurar o jogador
e depois atirar nele, e então
teremos um jogo. Então, o que é uma máquina de estado? Uma máquina de estado é uma classe ou
um objeto ou qualquer outra coisa. No caso de Godo,
pode ser um nó, e vamos
transformá-lo em um nó Mas, independentemente disso, uma
máquina de estado basicamente monitora um estado.
E o que é um estado? Um estado é bom, é um estado de ser, na verdade. Então, por exemplo, um tanque inimigo
pode ter vários estados. Ele pode estar procurando
por um jogador. Pode estar atacando o jogador. Pode estar morto. Basicamente,
um estado é uma forma de descrever o que o tanque está ou deveria estar fazendo
em um determinado momento. E podemos fazer
a transição de um estado para o outro com base em vários fatores. Então, por exemplo, se o tanque
não viu o jogador, ele pode estar no estado de
busca, que significa que ele
se moverá pelo mapa. E depois de
avistar o jogador, ele pode mudar para o estado de
ataque, o que significa que
estará atacando o jogador, e assim por diante No entanto, vamos
fazer isso de forma inteligente. Vamos fazer uma máquina de estado
independente que pode lidar
teoricamente com qualquer estado
sem precisar ser codificada especificamente
para o tanque inimigo Dessa forma, se quiséssemos adicionar uma máquina de estado às nossas
árvores, por exemplo, para que elas crescessem ou pegassem fogo ou
algo parecido, seríamos capazes de
fazer isso com muita facilidade. Então, a primeira coisa
que vamos fazer é, em nossa pasta de recursos, criar uma nova cena, e essa cena será um nó. E vamos chamar o nome da
cena de máquina de estado. E isso é basicamente que eu não
sei soletrar para salvar minha vida. Isso é basicamente apenas uma maneira de contornar a criação manual de
uma cena
na árvore Poderíamos facilmente ter feito isso
aqui indo para uma nova cena, mas isso realmente não importa. Então, clicaremos em OK. E
agora temos uma máquina estatal. Então, se clicarmos duas vezes,
podemos abrir a máquina de estado
e, como você pode ver, é um nó vazio sem
absolutamente nada anexado. E isso é chato. Então, vamos adicionar um
script à nossa máquina de estado, que será
chamado de Máquina de Estado. Vamos garantir que ele
vá para a pasta de scripts. E agora
veremos como, na próxima lição, você pode arrastar e soltar essa máquina de estado em
qualquer objeto que desejar. Então, a primeira coisa que
vamos fazer é dar a ela
seu próprio nome de classe. E o que uma
máquina estatal precisa fazer? Bem, a máquina de estado precisa
monitorar qualquer estado em que esteja atualmente e, em seguida, determinar quando é hora de
mudar o estado. E, felizmente, a maior
parte disso depende
do próprio estado. Portanto, nossa máquina de estado
só
precisa acompanhar em que
estado está atualmente. E provavelmente acabei de dizer isso, mas estou ficando
velho. Para o nosso estado? Bem, na verdade,
antes de
fazermos isso, precisamos
criar uma classe estadual. Então, vamos analisar os scripts. Vamos adicionar uma nova pasta especificamente para
nossa máquina de estado. Vamos arrastar o script da
máquina de estado até
lá e, felizmente, Gudo é inteligente o suficiente para reconhecer que
movemos nosso recurso,
então, na verdade, não precisamos
mudar onde não
precisamos alterar nenhum caminho de
arquivo ou qualquer coisa Nada vai quebrar.
É glorioso. Então vamos
criar um novo script, e ele vai herdar. Bem, ele não vai
herdar de Então, devemos realmente fazer isso
dessa maneira? Sim, por que não? Sempre podemos excluir isso.
Máquina de estado, novo script. Declare e depois crie. Agora, um estado não
será um nó, porque
os estados não precisam
se processar de forma independente, nem
precisam estar na árvore da cena. Só queremos uma classe de script GD
autônoma e direta. Então, vamos chamá-lo de
nome, nome da classe. Oito. Agora, poderíamos transformá-lo em um nó, mas só teremos um deles
em jogo
a qualquer momento
para uma máquina de estado, então poderíamos facilmente
transformá-lo em uma classe e atribuí-lo dentro do script, o
que estamos prestes a fazer. Basicamente, cada
nó que você adiciona à árvore de cena tem
uma sobrecarga de processamento, então não queremos ter
mais nós do que precisamos E antes de fazermos qualquer outra coisa, agora podemos voltar e dizer à máquina de estados que ela tem um estado
do tipo estado. Portanto, essa variável de estado é o estado em que a máquina de estado está em um determinado momento. Agora, como a
máquina de estado é um nó, podemos atribuir a ela uma função de
processo, e isso significa que a cada 60 segundos ou basicamente quantos o
jogo for capaz de suportar, GIDO
executará essa função. É semelhante à função do
processo físico que
examinamos anteriormente, exceto que o sistema de
física
sempre tem a garantia de funcionar
a 60 quadros por segundo. A função do processo não é. GIDO tenta executá-lo
a 60 quadros por segundo, mas se o computador ficar lento, a função do processo
geralmente é a primeira a falhar Então, vamos contar
ao Poço,
vamos verificar primeiro. Então, basicamente, o que
queremos fazer é que o estado
esteja pronto para mudar? Em caso afirmativo, altere-o. Caso contrário, processe-o. Sim, vamos ter um erro
aí , tudo isso são comentários. Agora, felizmente, tudo isso é feito dentro da própria classe
estadual. Então, definiremos uma função chamada está pronta para mudar de estado. E vai
devolver um Bleion. E nossa aula estadual será
apenas um esboço. Vai ser
uma aula abstrata. E o GaDo não impõe classes
abstratas, a menos que você esteja trabalhando em C Sharp,
o que não estamos Mas você nunca
vai instanciar a classe estadual sozinha Sempre vamos substituí-lo em classes
secundárias por meio programação
e herança orientadas a
objetos E vou explicar
isso em um momento. Tecnicamente,
o usamos o tempo todo, mas vou explicá-lo
com mais detalhes assim que o fizermos E este
retornará falso por padrão. Porque um estado
completamente vazio nunca mudará de estado. Então, é claro, precisaremos
de uma função de processo. E desta vez, não estou colocando
o sublinhado na
frente porque, na verdade, não
sei por que Godot usa sublinhados para algumas de suas funções
internas dessa forma, mas não vamos fazer isso,
principalmente porque
, à primeira vista,
você pode pensar que é um processo de
nó, e não é E, na verdade, uma
coisa que também precisaremos é passar a máquina de estado para cada um desses métodos. Na verdade, depois de
criarmos o estado, poderíamos apenas fornecer uma referência
à própria máquina de estado. Na verdade, não, não precisamos
passar pela máquina estadual. O que precisamos
transmitir é o que é
chamado de objeto monitorável E isso não é fácil de dizer. Então, vamos chamá-lo apenas de objeto
monitorável. E o objeto monitorável, na verdade, não
vamos definir um tipo porque ele pode ser
literalmente qualquer coisa Portanto, o processo não
precisa necessariamente fazer nada. E então teremos
outro método que será
basicamente um manipulador de eventos,
portanto, altere o estado E mais uma vez, precisaremos
do objeto monitorável. Um estado
inalterado será chamado sempre que
mudarmos nosso estado Então, vamos falar um pouco mais sobre
esse objeto de tabela de monitor, e vou evitar dizer essa palavra o máximo possível,
porque não é fácil dizê-la. E na verdade, você sabe o que? Podemos simplesmente trocá-la
em vez da banheira do monitor, o que implica, você sabe, que há algo
especial nisso. Bem, vamos chamá-lo de monitorado
porque é isso que é. E também é mais fácil dizer: Objeto
monitorado. Aí está. O que é um objeto monitorado? Portanto, a máquina
de estado monitorará
tudo o que estiver conectado. Nesse caso, será
o tanque inimigo. E o objeto que a própria
máquina estatal e, portanto, os estados estão monitorando é o que determina se
os estados mudarão ou não. Então, por exemplo, se estivermos monitorando o tanque inimigo, talvez
queiramos ir do estado de
busca para o
estado de ataque , dependendo se
o tanque viu o jogador. Isso significa que
a máquina de estado precisa ser capaz de
monitorar um objeto. Por padrão, nossa máquina de
estado monitorará
sua máquina principal porque a máquina de estado sempre
será conectada diretamente ao objeto
que está monitorando. Então, criaremos uma variável
chamada nó monitorado e criaremos uma função, uma função pronta para
nossa máquina de estado. E dentro da máquina de estado, o nó monitorado será
imediatamente atribuído ao pai
da máquina de estado. Então, se adicionássemos nossa
máquina de estado ao tanque inimigo, qual estraga ou
faremos na próxima lição Se o adicionássemos aqui, o método get parent
retornaria o tanque, que é exatamente o que queremos. E então vamos passar esse nó monitorado para
as funções de estado. Então, vamos fazer isso.
Agora que estamos em andamento ou agora podemos
preencher o processo. Se o estado atual
estiver pronto para mudar estado com base em qualquer status
no nó monitorado
, o novo estado será igual a,
bem, ainda não sabemos
disso, não é ? Porque temos bem, na verdade, o estado, definimos
isso? Não, nós não fizemos isso. OK. Portanto, há mais um método que o estado
precisará definir, chamado
Determinar o próximo estado. Então, cada estado
saberá quais são os estados para os quais pode fazer a transição. E vamos
retornar uma string. E a string
será o nome
do novo estado para o
qual queremos fazer a transição. E qual formato será
esse? Bem, veremos em um momento. Então, um padrão, ou melhor,
um, basicamente, esse estado abstrato que nunca
vamos realmente instanciar
retornará a string
padrão por padrão, porque parte do design da
minha máquina de estados em geral
é que eu quero que ela tenha um estado padrão
que seja o estado inicial em que
a máquina de estado está quando é inicializada E definiremos isso em breve. Mas agora que
determinamos o próximo estado definido, podemos dizer: Bem, na verdade, ainda não
temos isso. OK. Então, vamos entender
isso em um momento. Passe. Caso contrário, se o estado não
estiver pronto para mudar de estado, indique o processo com
base em seu nó monitorado. Tudo bem, então o que fazemos aqui? Bem, precisaremos uma lista de estados que a máquina
estatal suporta, bem
como seus nomes. Então, para fazer isso, vamos
exportar um dicionário. E se você nunca usou
um dicionário antes, um dicionário é uma lista de itens, e eu vou te mostrar como
isso funciona em um momento. Basicamente, é uma lista
de pares de valores-chave, e uma chave não está anexada a um valor específico, então
você pode procurá-los. A melhor maneira de descrever isso é
como uma lista telefônica, certo? Estou mostrando minha idade. As listas telefônicas provavelmente não existem mais. Mas digamos que
você tivesse um livro com
todos os
números de telefone nos Estados Unidos, e a chave poderia ser
o nome da pessoa
e, em seguida, o valor seria
seu número de telefone real. Então,
se você soubesse o nome deles , poderia procurá-los pelo nome e recuperar o número de
telefone. Então, nesse caso específico, o
dicionário ficará em branco, mas quando criarmos uma nova máquina de estado
no próximo capítulo,
poderemos preenchê-la. Mas, por enquanto, o que queremos
é que possamos substituir isso agora pela sintaxe de acessar uma string ou acessar um
valor no dicionário Então, o estado será igual
aos estados, e você acessa o valor de uma chave com a notação de colchetes como faria com uma matriz Os estados determinam, na verdade,
não, não são estados. É um estado. É por isso que estamos
obtendo qualquer preenchimento automático. Determine o próximo estado. E se bem me lembro,
sim, tudo bem, devemos fornecer
a ele o objeto monitorado O objeto
monitorado quase sempre
será necessário.
Determine os próximos estados. Porque queremos ser capazes de
fazer isso de forma sofisticada o suficiente para que o estado seja determinado em
vários estados do objeto E estamos recebendo um erro aqui, mas agora que o salvamos,
isso deve desaparecer.
Não vai desaparecer. Lá vamos nós. Tudo bem, agora, infelizmente, não
podemos executar isso ainda, mas há
mais uma coisa que
precisamos fazer antes de passarmos para o próximo capítulo para que eu possa realmente implementar isso e
mostrar como tudo funciona E isso é, precisamos adicionar
um setter ao estado. Em primeiro lugar, o que é um setter? Um setter é uma função
que Gadot chamará, se existir, para
definir a atribuição de um valor
a uma variável específica Então, por exemplo, se eu definir uma função setter aqui e ela sempre
tiver a mesma assinatura, ela sempre assume o valor Sempre que eu tento fazer
algo assim e digo que estado é igual ao que
isso vai ser, Gadot chama
essa função e passa o que quer que ela esteja
como valor Então, a única coisa que
sempre queremos fazer em nosso setter é atribuir a
variável ao valor Mas, nesse caso, também queremos
chamar o manipulador de estado. Então, agora dizemos estado sobre mudança de estado com um objeto
monitorado. Então, sempre que fizermos isso, ele fará isso
automaticamente. Agora, se não
definíssemos o setter aqui, poderíamos facilmente colocar isso aqui Mas, como você pode ver,
vamos
querer atribuir o estado
padrão em pronto, que eu poderia
muito bem fazer agora, estado igual aos estados E como também estou
configurando aqui, se eu não fizesse isso
dentro do setter, teria que
me lembrar de
colocá-lo aqui Então, se houver um
código padronizado que você
precisaria fazer toda
vez que alterasse o valor de uma
variável, configuradores são inestimáveis
e os usaremos muito quando
analisarmos
as interfaces de usuário, e os usaremos muito quando
analisarmos
as interfaces de usuário porque toda vez que
definirmos um valor,
vamos querer
disparar um sinal para notificar a interface do usuário de que
a variável mudou para que os
configuradores são inestimáveis
e os usaremos muito quando
analisarmos
as interfaces de usuário,
porque toda vez que
definirmos um valor,
vamos querer
disparar um sinal para notificar a interface do usuário de que
a variável mudou para
que
podemos atualizar a tela. De qualquer forma, isso agora está feito, mas como não
temos nenhum estado, não
vai nos
fazer nenhum bem, então eu posso realmente executá-lo
e mostrar como funciona. Mas agora podemos passar para
a próxima lição e implementar a máquina de estado
para o tanque inimigo, e eu vou remediar esse
Post Haste. Te vejo lá?
21. Adicionando uma máquina de estado ao tanque inimigo via ECS: Bem vindo de volta. Agora vamos adicionar nossa máquina de
estado ao tanque inimigo e configurar um estado padrão para que o
tanque possa processar seu estado, mesmo que tecnicamente
não esteja fazendo nada E então, uma vez
que tenhamos implementado toda essa estrutura, podemos começar a
criar a
inteligência artificial real que fará com que o tanque funcione. Então, vamos dar uma
olhada no nosso tanque. E a primeira coisa
que vamos
fazer é simplesmente
arrastar nossa máquina de estado para nosso tanque. Boop, e aí está Tecnicamente, o que estamos
fazendo aqui é uma forma
do padrão de programação conhecido como sistema
de componentes de entidades E Godot meio que fala da
boca para fora em sua arquitetura geral, no sentido de que o tanque inimigo
é considerado a entidade, e todas as coisas abaixo dele são Se você está familiarizado com o Unity, ele é mais solidamente estruturado no Unity, onde você tem um objeto de jogo ao qual você pode
adicionar vários componentes E a filosofia é que os componentes não precisam saber nada sobre nada. Eles podem simplesmente lidar
com eles mesmos, e isso será o fim de tudo. E a entidade é
meio responsável por deixá-los fazer suas coisas e também
reagir ao que eles fazem Então, neste caso,
a máquina de estado, é um componente da entidade, que é o tanque inimigo. Além do
fato ler coisas dos dados dos tanques,
a máquina de estado não
precisa realmente se
preocupar com nada do que o tanque esteja fazendo, embora isso possa mudar. Quem sabe? Vamos projetar isso
à medida que avançamos. Mas, em poucas palavras, se você tiver itens
anexados a um item mestre e esses itens estiverem razoavelmente
bem desviados ou isolados,
isolados um do outro Você pode considerar isso um sistema de componentes de
entidades. Dessa forma, não precisamos
, como eu disse, em
nosso último capítulo, não
precisamos que a máquina de estados saiba muito sobre
tudo o que está
ligado, porque seu único propósito é
monitorar estados. Então, vamos criar alguns
estados para ele monitorar. Vamos até a máquina de estado e criaremos um novo script, que
herdará do estado e será
chamado de estado ocioso Ok. Em seguida,
clicaremos duas vezes nele para abri-lo. Agora, o que esse
estado ocioso vai fazer? Não vai
fazer nada. É puramente um
estado reservado para que eu possa mostrar como essa
arquitetura Então, agora que a
máquina de estados existe e
já temos nosso
dicionário de estados definido, podemos preencher essa coisa. Então, o que
faremos é clicar nele, e agora você pode ver que ele me
pedirá uma nova chave
e um novo valor. Então, vou clicar no
pequeno lápis aqui, e a chave será uma corda. E como já o usamos, precisamos definir
a string padrão. Agora, qual será o
valor? Bem, os dicionários em Godot são incríveis porque seus valores
podem ser literalmente Então, nesse caso, queremos que nosso valor seja
o script de estado inativo
que acabamos de criar Mas antes de fazermos isso,
vamos fazer outra coisa. Nosso estado ocioso vai precisar
de alguma coisa. Então, se você se lembra, temos um
método chamado nhange state. Portanto, queremos que nosso estado ocioso relate o fato de que agora
é o estado atual Então, no estado inalterado, vamos adicionar uma declaração
impressa que simplesmente diz estado inativo Então, quando mudamos para o estado, ele
imprime isso no console, e sabemos que
todo esse sistema que
montamos está
realmente funcionando. Portanto, nosso novo valor será um novo objeto. Felizmente para nós,
em Godot, scripts, mesmo scripts que não foram instanciados ou
transformados em nós ou qualquer coisa, apenas os próprios scripts são considerados objetos Mais especificamente, se bem
me lembro, eles são considerados recursos. Então, o que precisamos fazer
aqui é, infelizmente, a única opção
que temos é um novo script GD, e não queremos isso
porque ele
assumirá literalmente um novo script vazio
em branco Então, queremos rolar
até o final aqui, e queremos ir para carregar. Agora, eu também posso fazer uma
carga rápida porque já
fiz isso antes, mas você não,
vamos passar por todo
o processo. Então, ele vai pedir
que abramos um arquivo. Agora, se entrarmos em scripts, máquina de
estado, não teremos Z nada. E isso porque,
curiosamente, um arquivo de script GD não é um tipo de arquivo reconhecido
para esse tipo de coisa Então, queremos ir até o
final e selecionar todos os arquivos, e então podemos selecionar
nosso estado ocioso E a última coisa que
precisamos fazer é clicar em
Adicionar par de valores-chave. Agora, nosso script de estado ocioso é atribuído à string
padrão em nossa lista de estados E isso significa que precisamos fazer mais
uma coisa em
nossa máquina estatal. Em nossa função ready, precisamos realmente
adicionar o ponto Nu porque, como o script GD é basicamente um recurso de classe, precisamos instanciar
um novo em nosso estado porque
nosso objeto de estado é
um estado e
não um recurso de não um Então, se fizermos isso, agora que temos uma máquina de estado
em nosso tanque inimigo, isso significa
que
quando o tanque inimigo entrar na
árvore de cena no início do jogo, ele chamará
sua função pronta e examinará a
lista dos nós dentro dele e
chamará sua função pronta. E quando chegar à
máquina de estado,
a máquina de estado
pegará o pai, que é, obviamente, o
tanque como seu nó monitorado. Em seguida, ele definirá o
estado igual ao estado que definimos em nosso
dicionário em padrão. E nesse caso, é um estado ocioso, então
vamos recuperá-lo, e então vamos
chamar isso de novo, e isso
nos dará um novo objeto de estado E, na verdade, nem
precisamos
imprimir isso lá porque, uma vez atribuído, ele chamará change state, que significa que
devemos ver a palavra estado
ocioso em nosso console Então, vamos ver se isso funciona. E aí está, estado ocioso. Tudo bem, agora
que temos essa estrutura em vigor, podemos realmente começar a
criar estados para o tanque inimigo para que ele
possa realmente fazer coisas Precisaremos adicionar
alguns componentes adicionais. Novamente, essa palavra
se refere à nossa entidade tanque
e, depois de fazermos
isso, podemos trabalhar com ela dentro do estado.
Então, vamos começar. Antes de fazermos, porém,
uma observação rápida, o estado ocioso e os outros estados com os quais trabalharemos fazem uso intenso
da herança do paradigma de
programação orientada
a objetos, do
qual Godot é um grande
usuário, por
assim com os quais trabalharemos fazem uso intenso da herança do paradigma de programação orientada
a objetos, do qual Godot é um grande
usuário Então, o que isso significa é que
se criarmos uma classe base, que fizemos
aqui com um estado, e então criarmos uma
classe filha que estende essa classe, por pura virtude de
estender a classe, obtemos tudo
dentro da Então, se eu não tivesse definido
essa função, o estado ocioso obteria toda essa funcionalidade
gratuitamente, e ainda tem Mas então, se redefinirmos
nosso método de mudança de estado, o
que fizemos, isso é
chamado de substituído por Então, se não tivéssemos feito isso
e simplesmente usado o existente chamado método existing on change state, nada
teria acontecido Então, o que vamos
fazer é criar várias
classes secundárias para substituir a classe estadual
e, em seguida,
substituir a funcionalidade básica
pela funcionalidade secundária herdada E ainda podemos ter
acesso à superclasse ou à
funcionalidade das classes principais usando a palavra-chave super. Então, por exemplo, se
eu quisesse chamar o método base de mudança de estado, eu poderia simplesmente dizer
super em mudar de estado. Claro, eu teria que
passar pelo objeto monitorado. Portanto, podemos estar fazendo
isso em alguns casos, mas provavelmente não
faremos, mas essa funcionalidade
está disponível para nós. Ok, chega de teoria.
Vamos começar a rachar Antes de começarmos, uma nota rápida. Você deve se lembrar que,
na lição anterior, corrigi um pequeno bug
aqui em que precisava adicionar o ponto Nu à configuração
do estado. Eu também tive que fazer
o mesmo no método de processo para quando
mudamos de estado, porque
originalmente isso estava faltando
e, uma vez que mudássemos de
estado, isso
teria causado a falha. Mas isso não causou uma falha
em nossa lição anterior porque nunca
mudamos de estado, mas
agora estamos prestes a mudar. Então, em última análise, nosso tanque terá dois estados. Ou ele
se moverá pelo mapa e
procurará o jogador, que será chamado
de estado de caça, ou atirará
no jogador, que será chamado
de estado de tiro Então, uma das primeiras
coisas que precisamos
fazer é
criar esses estados. Então, criamos um novo script, e eles herdam do estado, e ele será
chamado de estado de disparo. E vamos abrir esse idiota. E então vamos fazer, da
mesma forma, 40 Hunting State. Agora, há algumas coisas que teremos que fazer
para estabelecer as bases para que
tudo isso funcione ,
e faremos tudo isso e depois faremos o
código para os estados A primeira coisa que
precisamos fazer é
adicionar esses dois estados
à nossa máquina estadual. Então, se clicarmos
com o botão esquerdo na máquina de estado, você verá que tínhamos nosso estado ocioso
padrão aqui Então, agora vamos adicionar um novo estado ou uma nova string de par de
valores-chave, e isso
será chamado de disparo. E, claro, o valor
será um objeto
e, em seguida, arrastaremos o estado de
disparo lá e clicaremos para adicionar
o novo par de valores-chave E então faremos o mesmo com nosso estado de caça. Então, vamos chamar isso de caça. E vamos adicionar isso. E agora nossa máquina estatal pode
reconhecer todos os nossos estados. Então, para lidar com
o estado de caça, na verdade
vamos
fazer o estado de tiro primeiro porque é o mais fácil
dos dois de implementar, mas há uma coisa
que teremos
que criar
para fazer o estado de caça Portanto, encontrar caminhos é um tópico extremamente
complicado, e Godot tem sua própria navegação embutida
, mas não vamos
usá-la porque, dado o
fato de estarmos lidando manualmente com
a forma como o tanque se move, ela
produzirá muito mais código
do que eu gostaria de dizer para você aprender o que está acontecendo eu gostaria de dizer para você aprender o que Então, vou fazer uma
versão mais simples do pathfinding, um pouco mais
direta Então, você poderá examinar
as malhas de navegação de
Godot em seu próprio tempo ou apenas pesquisar
caminhos em geral. Mas a maneira como vou
mostrar como fazer isso é definitivamente um dos padrões
do setor, embora vejamos
uma
versão
muito, muito simplificada Então, a primeira coisa
que vamos
fazer é
voltar para nossa arena. E como você pode ver aqui, a arena tem vários obstáculos
diferentes e outros enfeites Então, vamos criar um novo tipo de nó
para a arena. Então, a primeira coisa que
vamos fazer é adicionar um novo nó três D. E a razão pela qual
vamos fazer isso
é que, para evitar que as coisas
fiquem confusas, vamos querer agrupar todos os nós que
estamos prestes a
adicionar sob esse nó três D.
Então, vamos
renomeá-lo para Path nodes adicionar sob esse nó três D. Então, vamos
renomeá-lo para Path E por que estou fazendo
isso? É porque vou criar
um novo tipo de nó, que será chamado de NaPoint e veremos como fazer
isso em cerca de 2 segundos. E o que vai
acontecer é que eu
vou pontilhar o mapa com esses NavPoints
e os tanques, os tanques inimigos
seguirão
esses NavPoints para
se moverem pelo E essa é uma das formas padrão
originais de fazer IA em muitos jogos de tiro em primeira pessoa
e outros jogos como esse É muito
mais simples do que tentar usar uma malha de navegação única, que é o que Godot também
permite que você configure Basicamente, são muito
menos pontos com os quais lidar. E vamos fazer isso
dessa maneira porque
dá uma ideia do que uma
solução mais complicada envolveria. E também nos dá uma
pequena chance de aperfeiçoar nossas crescentes habilidades de matemática
vetorial em vez de deixar
tudo para o Godot Então, vamos criar uma nova cena, e vamos fazer
dela uma cena em três D, e vamos
mudar o tipo da cena para um corpo
estático três D. E vamos
renomear esses três D para Nav Point E, como fizemos antes, adicionaremos uma instância de
malha três D a esse AVPoint para
que possamos vê-la E vamos fazer dela uma malha de cápsulas, porque não? E vamos alterar
o material para que
a
malha de navegação fique realmente
visível , razoavelmente bem visível Nós lhe daremos uma
cor albedo de amarelo. E também expandiremos. Ok, a malha está boa. Vamos mudar a
altura para 1 metro, o que a torna uma esfera. Interessante E então vamos
reduzir o número de anéis, porque quero dizer, no final das contas
, vamos
escondê-los em alguns minutos. Portanto, não precisa
ter uma aparência fantástica. Em seguida, adicionaremos, é claro,
uma colisão em forma de três D, que
será uma esfera porque criamos um objeto
esférico Tudo bem, então nós os temos, e podemos
mudá-los um pouco para
que não fiquem imediatamente
no chão E não precisamos
anexar um script a isso de forma alguma. Mas vamos salvá-lo. Agora, vamos
mudar algumas coisas que
na verdade não mudamos antes. A primeira coisa que
vamos fazer é, claro, definir
a colisão Vamos desmarcar a máscara porque
o próprio NavPoint não precisa verificar
colisões E vamos adicionar uma nova camada e vamos
chamá-la de NAV Points E, é claro,
vamos mudar
a
camada de colisão NavPoints para NavPoints E então vamos
para a Instância Mesh três D, e vamos para camadas da instância visual, e vamos
desmarcar uma e marcar duas E vamos alterar os nomes das camadas para que
a
camada dois seja NavPoints E por que eu fiz isso? Bem, as camadas visuais são semelhantes às
camadas de colisão, pois você pode agrupar e também são
semelhantes aos grupos você pode agrupar coisas
e depois selecioná-las. Então, o que vamos
fazer é, na verdade, ir
até o tanque
e ir para a câmera três D. E
agora
a câmera três D tem
essa máscara de abate aqui E, basicamente, qualquer camada
marcada e
todas marcadas por padrão, a câmera visualizará. Agora, não queremos que essas bagunças de
navegação
apareçam no jogo, e a única câmera que vamos
usar é a
do jogador ou basicamente aquela
conectada a qualquer um dos tanques Então,
vamos simplesmente ir até a camada NavPoints e desmarcá-la E agora, nossos NavPoints não
serão renderizados
pela câmera do jogador Então, agora que
temos um NavPoint, vamos adicionar um pouco à nossa cena Nós os adicionaremos e os
arrastaremos para o nó dos nós do caminho para que sejam anexados
a ele como pais. E vamos garantir que isso
seja direto para cima e para baixo. Vamos diminuir um
pouco o zoom. E o que vamos fazer é basicamente colocar esses pontos, e eu vou apenas duplicá-los
com o Controle V ou o Controle D, e então vamos
colocá-los em vários colocaremos o suficiente deles
para que você tenha a ideia O que vamos fazer é que nosso tanque se mova
de um ponto a outro. Ele procurará todos
os pontos que estão
dentro de sua faixa de movimento. Ele escolherá um
aleatoriamente e depois girará até ficar
voltado para aquele ponto e depois se
moverá em direção a esse ponto. Basicamente, tudo o que queremos
fazer aqui é criar vários
pontos ou criar vários,
criar vários pontos NAB
para dar ao tanque um lugar para se mover Agora, é claro, se tivermos
os NavPoints configurados de forma que haja um obstáculo
entre eles ao longo do caminho, o tanque
colidirá com o Então, queremos espaçá-los
o suficiente para que o tanque possa encontrá-los quando procurar novos pontos
para onde ir, mas não de forma que
seja possível realmente ir Então, por exemplo, se o tanque fosse desse
ponto a esse ponto, queremos ter certeza de
que a linha entre eles não inclua essa rocha. Então, vamos ajustar isso um pouco e vamos fazer isso. Ok. E isso é suficiente para isso é
suficiente para a arena. Então, como você pode ver, você pode realmente ver os NavPoints aqui Mas se fôssemos começar
o jogo, o que eu farei, vamos verificar novamente onde vamos voltar ao jogo. Está bem? Então, o
tanque do jogador está aqui. Agora, se fôssemos
começar o jogo, você veria que nenhum dos
NavPoints está aparecendo na visualização
do jogador porque a câmera os está
retirando, mas eles ainda estão Ok, agora que isso está configurado, vamos modificar
nosso tanque inimigo que ele possa detectar o jogador e depois
tentar atirar nele. A primeira coisa que
precisaremos fazer, obviamente, é ir
até o tanque inimigo. Mas o que queremos
fazer agora é
adicionar o que é chamado de nó D da
área três. Então, vamos até o tanque inimigo. Adicionaremos um nó filho e adicionaremos uma área três D.
E uma área três D requer
uma forma de colisão, assim
como nossa forma de colisão três D. Na verdade, elas são
basicamente a mesma coisa Então, vamos adicionar um nó filho aqui, que é, obviamente,
uma forma de colisão E só nos preocupamos com coisas dentro de um raio XY do tanque Então, podemos simplesmente fazer um cilindro. Agora, isso também pode
ser feito verificando a distância entre as
posições globais dos dois tanques. Mas é menos código
fazer isso dessa maneira e também passa tudo
para o mecanismo de física, que é mais eficiente. Então, a
forma da colisão vai, bem, primeiro de tudo, vamos
reutilizá-la um pouco Na verdade, não
importa a altura, mas apenas para manter as coisas
visualmente consistentes, faremos com que seja quase tão
alto quanto o tanque. E então precisamos mudar seu raio para o raio que queremos que o tanque
possa ver o jogador Então, vamos arrastar esse cara
para fora até cerca de, digamos, 15 Agora, isso é completamente arbitrário É apenas um raio em que
decidi que quero que o tanque seja capaz de
detectar o jogador Você poderia facilmente
fazer dez ou 20. Eu não faria com que fosse
menor do que
a distância que o projétil do tanque disparará ,
porque
você pode aumentá-lo. É perfeitamente normal que
o tanque consiga ver o jogador antes dos
jogadores ao alcance. Mas, você sabe, vamos
ver como isso funciona. Então, agora, vamos
mantê-la em 15, e vamos mudar
a área três D, e vamos
chamá-la de área de alvo E há um bug com Godot que uma área três D não detecta coisas que são estáticas, a
menos que tanto o monitoramento quanto o
monitorável sejam verificados, o que é meio desagradável Porque normalmente você
só quer que o monitoramento seja
verificado para ver se as coisas
entram na área. Então, desmarcaremos a opção
Monitorável para este, mas faremos algo
semelhante para E eu vou revisitar essa discussão quando chegarmos ao
movimento, eu acho Estou meio que me
adiantando aqui. Mas agora que temos
nossa área de mira, o que queremos fazer é, antes de tudo,
mudar a colisão da
área de mira dos tanques inimigos para bem, podemos desligá-la
por uma coisa ou desligar suas
camadas por Na verdade, não
precisa estar em uma camada, mas só queremos que ela colida
com a camada do jogador, que não só rima, mas também significa que a área só vai se importar se
o jogador entrar nela Então, agora vamos para o nó
e para a área três D
e, claro, queremos que o
corpo entre e
saia dos métodos Então, vamos conectá-los
ao tanque inimigo. E por algum motivo,
o botão de conexão não quer cooperar Agora, só para provar que isso realmente funciona,
vamos fazer duas coisas. Vamos
imprimir o nome
do corpo quando ele entrar na
área
e, em seguida, imprimiremos o nome do corpo quando ele
sair da área. E você pode estar pensando neste
momento, bem, como posso visualizar todas essas
coisas que estão acontecendo? Quero dizer, como sabemos a
extensão de nossos lançamentos, nossas áreas de colisão e outras coisas
enquanto depuramos
nosso enquanto depuramos E acho que já
te mostrei isso antes, mas se não o fiz,
mostrarei de novo. Se você for depurado e
fizermos formas de colisão visíveis,
podemos ver as formas de colisão
de todos os Agora, se eu começar o jogo, agora você pode ver que pode ver todas as
formas de colisão que definimos E aqui está o
alcance de mira do tanque inimigo, e aqui está a forma
de colisão de um dos nós de navegação Agora, se eu dirigir
meu tanque para frente, entro na zona de mira dos
tanques inimigos, então diz tanque do jogador,
e agora, se eu sair
da zona de mira,
ele aciona o outro método
e também diz tanque do Portanto, temos um pequeno
problema, pois o corpo está apenas no escopo e, portanto, é
válido dentro desse método. Precisamos ser capazes de acessar qualquer alvo do tanque
fora desse método Então, é claro, isso significa que
precisaremos de uma variável, e a chamaremos de alvo, e será
um tipo de corpo de personagem três D, porque esse é o
tipo de tanque do nosso jogador. Então, o alvo é igual ao corpo. E quando o corpo
sai da área alvo, alvo é igual a nulo Então, se em algum ponto fora
do script do tanque precisarmos acessar uma referência
ao jogador enquanto ele estiver
na zona de mira,
podemos usar essa variável E, de fato, vamos
usá-lo em nossa máquina de estado. Então, vamos ao
nosso estado de tiro. A primeira coisa que
vamos fazer é dar um nome a ele. E enquanto estiver em minha mente, vamos fazer o mesmo com
o estado da caça. E precisamos voltar
à nossa máquina de estado e mudar
seu estado padrão
desse estado ocioso fictício que
criamos para o estado de caça E quando
estivermos lá, precisamos definir algumas coisas. Então, se você se lembra,
tínhamos vários métodos
auxiliares de stub
dentro do estado Então, a primeira coisa é que
precisamos do nosso método de
mudança de estado. Portanto, no estado de caça, queremos sair
do estado de caça se o tanque
encontrar um oponente. Então, o que podemos fazer aqui é devolver o resultado
de um cheque em ouro E a primeira coisa que
vamos fazer. E então isso é realmente válido. Quando você substitui um método, mesmo que não tenhamos definido um tipo de variável para
um parâmetro de entrada, podemos defini-lo
em uma classe secundária E, nesse caso, queremos fazer
isso para ajudar nosso preenchimento automático. Vamos
lançar especificamente o objeto monitorado em um tanque de IA. Agora,
retornaremos o resultado do alvo do objeto
monitorado
ser igual a nulo Portanto, se o
alvo do objeto monitorado não for nulo, isso significa que
devemos mudar do caça para
o estado de disparo porque
encontramos um E, inversamente, queremos
fazer exatamente o oposto
no estado de disparo Portanto, devemos sair do estado de disparo se o
alvo for igual a nulo E então, da mesma forma,
precisamos ser capazes indicar qual
é o próximo estado para cada um dos nossos estados. Então, para o estado de caça
, sempre haverá uma transição
para o estado de tiro E para o estado de tiro, sempre
transferirá a transição
para o estado de caça E só para nos ajudar
com nossa depuração, vamos ecoar porque, de qualquer forma
, substituiremos
a alteração de estado Então,
quando definirmos isso, vamos mostrar qual é
o estado em que estamos Então, no estado de caça, vamos apenas
imprimir o estado de caça. E então, no estado de disparo, opa, precisamos de todo
o método No estado de disparo,
vamos para o estado Echo Firing. E agora podemos verificar
se ambos estão funcionando se
voltarmos ao nosso jogo. Agora, se eu manobrar
em direção ao tanque, temos um problema.
Qual é o nosso problema? Tudo bem, acesso inválido à chave de
propriedade que dispara uma
boneca Ok. Eu não os
configurei corretamente?
Vamos dar uma olhada. Ah, eu não usei a palavra estado. Então, como você pode ver, o erro aqui é que estou
retornando a palavra, bem, esta não foi escrita
corretamente em primeiro lugar,
mas deveria estar apenas no estado de disparo em vez de disparar Então, vamos assim. E então, para o estado de caça, vamos mudá-lo para caça.
Agora, isso deve funcionar. Então, como você pode ver, como já
configuramos nossa máquina de estado para fazer a transição
para o estado padrão, o fato de definirmos
nosso estado padrão para o estado de busca significa que,
uma vez configurada e alterada, Godot repetirá a palavra de busca aqui para mostrar que estamos
lá por Agora, se eu
for, está quebrando de novo. O que eu fiz dessa vez?
Ok, não está na coisa. Por que esses
estados de caça Hunt Aha são determinados como o próximo estado Oh, eu mudei os errados. Ugh. Ok. Determine o próximo estado. Estado de disparo. Determine o
próximo estado. Caçando. Tudo bem. Mais uma vez com
sentimento. Lá vamos nós. Então, desde que entrei
na zona de mira, ela passou
para o estado de tiro Agora, se eu voltar, ele volta ao estado de caça, que é exatamente o que queremos. Tudo bem, agora que
temos nosso alvo e podemos alternar entre os tiro e
os estados de caça, o que queremos fazer a seguir? Bem, como vimos antes, temos um método de processo. E em nossa máquina de estado, basicamente, em seu método de
processo, verificamos se
devemos mudar de estado
e, se não, devemos processar o estado em que
estamos atualmente. Portanto, precisamos substituir
o método de processo para cada um desses estados E como estamos trabalhando
no estado de disparo agora, esse será
o primeiro que faremos Então, primeiro de tudo,
vamos nos certificar de
alterar todas essas
assinaturas de forma que elas convertam especificamente o objeto porque é isso que
queremos fazer E, claro, eventualmente também
teremos que anular o
processo no
estado de caça Então, no estado de tiro, uma vez que tenhamos um alvo,
que é o jogador, vamos querer
girar a torre dos tanques inimigos em direção ao jogador, verificar se ela tem
uma linha de visão clara e depois atirar E para fazer
isso, precisamos adicionar alguns nós extras
ao nosso tanque inimigo. O primeiro nó que
vamos adicionar ao nosso tanque é chamado de lançamento três
D. Um lançamento é basicamente
uma seta que aponta para uma posição alvo dentro do mundo designada
em coordenadas locais, que significa que usa o mesmo espaço de
coordenadas do tanque E vamos apelidar
essa linha de visão. E precisamos que
o tanque inimigo seja capaz modificá-lo e acessá-lo
de dentro de seu próprio script. Então, exportaremos uma variável
chamada sightline, que é, obviamente, uma reformulação
de três
D. E, em seguida,
arrastaremos isso até aqui Então, um molde é basicamente uma linha, e ele traçará desde o ponto de origem até o destino
que você deu a ele, e será capaz de relatar a primeira coisa
que atingir nesse caminho. Então, para nossa linha de visão, se traçarmos uma linha do tanque inimigo até
o tanque do jogador, vamos voltar ao
jogo por um segundo aqui. Então, se traçarmos uma linha, então esta será nossa
linha de visão radiográfica. Se traçarmos uma linha
do
tanque inimigo até o tanque do jogador, se não houver nada no caminho, se dissermos: Ei, o que é o tanque inimigo ou com o
que o raio está
colidindo, recuperaremos nosso alvo Se houvesse, digamos,
uma árvore no caminho, a linha de visão relataria a primeira coisa que
atingiu foi a árvore, que significa que não
temos uma linha de visão para o tanque de nossos jogadores. Então, basicamente, queremos
comparar para onde a linha de
visão dos raios lançados está apontando
e, se for o alvo,
sabemos que temos uma linha de visão clara.
Então, como fazemos isso? A primeira coisa que fazemos é voltar para o tanque inimigo e
ir para a linha de visão, e queremos que nosso
lançamento de raios colida não
apenas com o jogador,
mas também com obstáculos
e tanques inimigos, e não com o solo, sem
projéteis ou sem pontos de navegação Dessa forma, ele pode
detectar se há um tanque inimigo ou uma
árvore no caminho, ou pode encontrar nosso
jogador quando o encontrarmos. Vamos fazer
tudo isso dentro do estado de disparo porque
o estado de disparo
conterá a lógica que determinará
se
o tanque deve
ou não
atirar em seu E a razão pela qual fazemos
isso aqui é porque, se o tanque perder o jogador
de vista
, queremos sair
do estado de tiro e
voltar ao estado de caça E essa informação
está incorreta. Vamos voltar ao tanque inimigo e obteremos a linha correta, obteremos o código correto. Ah, tudo bem. Não é isso. É isso. Ok. Então, o que essas duas
linhas de código fazem? O primeiro pega nosso objeto monitorado,
que é, obviamente, nosso tanque inimigo, que
é a entidade à qual nossa
máquina de estado está conectada, e atualiza sua linha de visão, que é a linha de visão lançada, sua propriedade de posição alvo, que é essa variável aqui, e a define igual à posição
do alvo que o objeto monitorado
está atualmente apontando para. Então, como você se lembra, de
alguns minutos atrás, definimos a meta igual
ao tanque do jogador se ele entrasse no
vamos voltar aqui. Ele define o valor alvo igual ao tanque
do jogador se ele
entrar na área de mira E não precisamos nos
preocupar em verificar valores
nulos nem nada, porque
o tanque não
estará em estado de disparo a
menos que tenha um alvo E precisamos que esse método
seja local porque a posição
alvo do objeto monitorado é local em seu próprio espaço. Então, precisamos convertê-lo para o espaço de coordenadas
do objeto monitorado Caso contrário,
estaria no espaço global e os valores estariam errados. Em seguida, chamamos o método force
cast update
na linha de visão para dizer a Godot que atualize imediatamente o elenco, porque se isso não acontecesse,
Godot atualizaria o
elenco no próximo quadro,
então Godot atualizaria o
elenco no próximo quadro, estaríamos errados Queremos que isso aconteça
imediatamente para que possamos verificar
a coisa certa. Agora, se eu executar o jogo, já que ainda temos nossas variáveis de
colisão ou ainda temos nossas formas de
colisão definidas, na verdade não
obtemos nada Existe uma maneira de
ativar essas coisas. Deixe-me ver se consigo configurá-lo. Ok, eu descobri o
que deu errado. A linha de visão lançada
estava originalmente na base
do tanque porque é aí
que ela cai para zero. Eu originalmente comecei com
menos um Y,
que estava aqui embaixo, então,
na verdade, tivemos que movê-la para cima de forma que você pudesse realmente
vê-la quando ela apontasse para o alvo oposto Então, agora vamos Nat
e rodamos nosso jogo. Agora você pode ver o lançamento
do tanque inimigo
diretamente para o nosso tanque. E o que precisamos fazer a seguir
é verificar se o objeto
está colidindo com
o alvo ou não Então, fazemos isso dizendo que eu monitorei o objeto, a linha de visão, e o método é
chamado Get collider Então, se chamarmos Get collider
na linha de visão, precisaremos ver se ele é igual ao alvo do objeto monitorado,
que é, obviamente,
o tanque do
nosso jogador E, na verdade, antes
mesmo de fazermos isso ,
o que podemos fazer é fazer isso e depois
comentaremos isso. Simplesmente imprimiremos com o
que está colidindo. E não faremos isso dessa maneira.
Nós faremos isso monitorado. Vamos soletrar corretamente o objeto. Siteline dot Get
collider. Nome do ponto. Agora, dirigindo até aqui, você pode ver que está colidindo
com o tanque do jogador Mas se eu for aqui
atrás desta colina, o raio agora está
colidindo com a colina Porque o raio lançado
atravessa a
caixa delimitadora da colina antes de nos atingir Isso significa que o tanque inimigo não tem uma linha de
visão para o jogador. Então, vamos nos livrar disso,
então vamos voltar aqui. Portanto, se o tanque inimigo tiver uma linha de
visão para o jogador, queremos girar a torre até que ela fique voltada para o E para fazer isso,
na verdade precisamos de um segundo raio de projeção. Vamos negociar, vamos
comentar isso novamente. Agora, onde vamos
colocar esse molde de raios? Na verdade
, esse raio será lançado na torre e estará voltado
na
mesma direção do cano,
porque queremos ser capazes de
ver o que quer que a torre esteja Então, adicione outro nó filho aqui, e isso será
um raycast novamente, Hmm E essa
será a linha de mira, e só
colidirá com o jogador, e será tão longa
quanto nossa área de mira
ou área de mira Então, qual era o tamanho da nossa área
de segmentação? Nossa área de alvo tem
um raio de 15 metros. Isso significa que a
linha de mira precisa ser 15. Mas como o tanque
em si é girado, isso significa que também precisamos girar
a linha de mira Agora, como você pode ver, temos uma linha que se estende
da nossa torre
até o raio de mira. E vamos mudar isso um pouco porque não queremos que seja assim antes de partirmos. Ok. Então, agora, se voltarmos
ao nosso roteiro e
pudermos descomentar isso novamente, precisaremos, obviamente, uma referência à nossa
reformulação de metas Tanque inimigo,
linha alvo, linha alvo. E vamos fazer uma
rápida verificação de sanidade para garantir que, se
girarmos a torre, poderemos girar garantir que, se
girarmos a torre,
poderemos girar
o molde corretamente.
Sim, aí vai. Perfeito. Deixe-me
voltar ao nosso roteiro. De volta ao inimigo. Não, de volta ao estado de tiro. E verificamos se a
linha alvo do
objeto monitorado entra no colisor Se não for igual a nulo
, sabemos que estamos
mirando em nosso jogador Mas queremos verificar se é
igual
a nulo porque,
se for igual a nulo, queremos
girar a torre E como giramos nossa torre? Bem, nós já temos um método para isso. Objeto monitorado. Acho que não me
lembro do nome dela. Estava no tanque. Lá vamos nós. E foi definida a velocidade de giro. E nesse caso, novamente
, pode ser um
ou negativo. Então, se eu definir como um, isso
indicará que
sempre vai virar na direção positiva,
o que pode não
ser necessariamente o que queremos. Na verdade, o que
precisaríamos fazer é determinar a orientação
do objeto do jogador para ver se um negativo chegaria lá
mais rápido do que um positivo Mas vou deixar isso
como um exercício para você. Então, deixe-me ver se consigo
esclarecer o problema aqui. Então aqui está nosso tanque visto de cima. E digamos que
o jogador esteja aqui. Bem, se sempre girarmos a torre em uma direção
positiva, ela girará
dessa maneira, o que é Mas se o tanque estivesse aqui
, isso significa que
a torre teria girar totalmente desse jeito
, e nós realmente queremos que ela
gire nessa Então, há um método
chamado ângulo dois, e vamos
ver isso quando
lidamos com o movimento
no modo de caça. E uma vez que tenhamos feito isso, você deve ter
ferramentas suficientes à sua disposição. Se você quiser uma pequena
lição paralela, por assim dizer, você pode modificar esse código para
que a torre gire na direção correta e leve o mínimo de tempo para
girar em direção ao jogador De qualquer forma, precisaremos de outra, porque se ela
estiver realmente colidindo
com o jogador
, queremos ter certeza de
que a velocidade é zero Então, definiremos a velocidade de rotação com o vetor de entrada igual a
zero, o que a interromperá. Agora, se estivermos lá, vamos. Oh, está girando o tanque.
Nós não queremos fazer isso. Queremos girar a torre. Portanto, o método
não define a velocidade de rotação. É uma torre giratória. Então, vamos voltar para lá. E em vez de definir a velocidade de giro, vamos girar a torre
22. Adicionando uma máquina de estado ao tanque inimigo via ECS, parte 2: Mmm, a primeira coisa precisamos fazer é
forçar algumas variáveis de movimento Então, no estado
de mudança do nosso estado de
disparo, que é chamado quando fazemos a
transição para o estado de disparo, queremos que o tanque pare de se mover e
girar e
tudo o mais que esteja Então, definiremos a velocidade de rotação e a
velocidade de avanço iguais a zero Isso significa que, assim que
o tanque avistar um alvo, ele parará tudo
e, em seguida, imediatamente verificará sua mira. E faremos o mesmo
para o estado da caça. Agora, o que é essa propriedade ociosa? Essa é uma variável que
precisamos adicionar ao nosso tanque inimigo. E é um booleano. E indica se o tanque está
ou não movendo de um
ponto
de navegação para outro. Basicamente, se o tanque estiver ocioso, queremos que ele encontre outro ponto de navegação
e se mova em direção a ele, porque nunca queremos que os tanques fiquem completamente ociosos Embora, quero dizer, talvez você saiba. Na verdade, se você estiver sentindo aventureiro depois de
terminarmos esta lição, talvez você possa modificar os
tanques de forma que eles parem
periodicamente e, você
sabe, talvez apenas dê uma olhada Mas, por enquanto, eles
sempre estarão se movendo, patrulhando e
procurando o jogador Então, em nosso estado de caça, novamente, quando estivermos em estado de mudança, forçaremos
o tanque a ficar ocioso, o
que significa que, em sua
primeira passagem de processamento, ele encontrará uma nova
posição para se mover em direção a ele E vamos precisar de uma
lista dessas posições, e eu estou realmente me
adiantando. Então, vamos voltar à cena
do tanque em si, e
precisaremos de outra área. E essa vai
ser nossa área de movimento. E esse é o que deve ser monitorável e
monitorável , porque se
desmarcarmos monitorável, que é uma palavra muito
difícil de dizer mesmo para um falante nativo de
inglês, ele não detectará nossos
pontos de navegação estáticos por algum motivo, que não faz muito
sentido porque monitorável significa
que essa área é detectável
por outras formas de sentido porque monitorável significa
que essa área é detectável que essa área é detectável mas não queremos que seja detectável por outras formas de
colisão. Então, logicamente,
desligaríamos isso. Mas há um bug e o Gadot
em que, se desligarmos isso, ele não detectará
objetos estáticos. Então, vamos deixar isso. E em sua colisão, queremos desligar sua camada e queremos que ela detecte pontos de
navegação Então, vamos mudar isso e adicionar uma forma de
colisão a ele Essa forma, é claro,
é um cilindro. E vamos mover o cilindro um pouco
para cima e, é claro, mudá-lo. Não
precisamos de um aperto para ter a
mesma altura que está, e mudaremos
seu raio para 20 Ally, vamos fazer com que seja 25. E isso é meio arbitrário. Basicamente, esse é
o raio em que procuraremos pontos de
navegação, e queremos que seja
maior do que o alcance de segmentação só porque não queremos ter preencher o mapa com Queremos poder
espaçá-los relativamente longe um
do outro Mas isso é completamente
ajustável. Agora, o que precisamos é que
essa área de movimento
seja capaz de acionar funções
no tanque inimigo. Então, vamos conectar,
novamente, o corpo entrou. E o corpo abandonou os métodos para conectar algumas
funções para nós, e eu não sei por que ele
continua desconectando isso, mas aí está. Estrondo. E agora podemos voltar
aqui e definir uma matriz chamada pontos de navegação
próximos E será uma
matriz do nó três D, embora não precisemos
realmente detalhar isso para
determiná-lo ou declará-lo Podemos simplesmente dizer, e é
uma matriz, ou podemos removê-la completamente e fazer com
que fique assim. Mas, de um
modo geral, você deseja definir os tipos de suas
variáveis, se puder. Então, quando o tanque estiver próximo o suficiente de um ponto de
navegação que esteja dentro
da área de movimento, ele acionará
essa função. E quando isso
acontece, queremos
anexar o corpo aos nossos pontos NAV
próximos E quando sai dessa
faixa, queremos apagar. Do ponto de navegação próximo. Portanto, essa variável sempre
terá uma lista dos nós
corretos dentro dela. Agora, há também um
método chamado get overlapping nodes que também
poderíamos usar, mas isso é um pouco mais claro para fins de instrução Então, agora que temos isso, podemos entrar em nosso estado de
caça. E, basicamente, o que queremos fazer é que,
se o
objeto monitorado estiver inativo , vamos querer fazer algumas
coisas, mas antes disso, nosso tanque inimigo precisará ser capaz de
rastrear o ponto de
navegação mais próximo Também conhecido como Ponto de
Navegação alvo, de qualquer forma. E, na verdade, os NaPoints
são três Ds de corpo estático. Mas, novamente, você não precisa ser tão refinado
com a definição Mas aqui, este,
você provavelmente deveria. Tudo bem. Deixe-me
voltar ao estado da caça. Portanto, se o
objeto monitorado estiver ocioso, queremos fornecer a
ele um NavPoint próximo Portanto, o NavPoint
mais próximo será
igual ao objeto monitorado Ganhe pontos de saída aleatórios. E ainda não definimos
esse método. Então, vamos fazer isso. Pelo menos em um esboço.
Examinaremos todos esses métodos e, em seguida, veremos como
realmente implementá-los. Ah, hein. Muito melhor. Tudo bem, de volta ao Hunting State. E uma vez que temos um ponto de
navegação definido
, na verdade queremos dizer
que ele não está mais ocioso Então, ocioso agora é igual a falso. E no próximo quadro, vamos verificar
se o objeto monitorado ou. Chegou ao seu destino. Bem, vamos
verificar se não
chegou ao destino. Caso contrário,
vamos fazer algumas coisas, e eu vou colocar essas
coisas em um momento. Mas se tiver, então queremos
colocá-lo novamente em marcha lenta para que eu possa escolher um novo ponto de
navegação Ok, então, se ele não
chegou ao seu destino, queremos ver se ele
está voltado para
seu destino. E se não estiver voltado para
seu destino
, queremos girá-lo
até que, eventualmente, esteja Então, cada quadro ele
verificará
para ver se está voltado para
seu destino
e, se não, dissemos que é objeto
monitorado com velocidade de rotação E temos o mesmo problema aqui que tivemos
com a torre, então vamos
definir a velocidade de giro igual
a um para que ela sempre gire a um para que ela sempre positivamente E se estiver de frente para
seu destino
, queremos que ele se mova
em direção ao seu destino. Então, objeto monitorado
Defina a velocidade de movimento um para que ele avance em direção ao seu
destino. OK. Então, agora, uma vez
implementados esses métodos, teremos um tanque móvel. E, claro, também
precisamos ter certeza de que desligamos adequadamente a velocidade de movimento e
a velocidade de rotação Portanto, se ele não chegou ao seu destino e
não está voltado para seu destino
, precisamos definir
sua velocidade de giro, mas se estiver voltado para
seu destino, queremos que ele pare de girar
e defina sua velocidade de movimento E então, é claro, uma vez que
chegou ao seu destino, definimos sua
velocidade de movimento igual a zero. Oh, agora, vamos
implementar esses métodos. Então,
chegamos ao destino. Rich, é claro,
devolve um lingote. E, por enquanto, ele
pode retornar falso. Então temos Está
voltado para o destino. E foram só aqueles dois? Alcançou sua face
e, em seguida, obteve um ponto de navegação aleatório Bem, nós
já fizemos esse. E acho que devo manter as
convenções de nomenclatura consistentes. Disse que sou péssimo com isso. Tudo bem,
então como obtemos um ponto de
navegação aleatório? Tudo bem, então como obtemos um ponto de
navegação aleatório Estrondo. Então, o que estamos
fazendo é o que é isso? Provavelmente é o errado
. Pontos de navegação próximos Tudo bem. Ah. O nome é
um pouco diferente. Pontos de navegação próximos. Certo? O que estou perdendo? Aqui vamos nós. Ok, agora tudo está
alinhado com minhas anotações. Então, nesse método, o que fazemos é declarar um NavPoint e
defini-lo como nulo, e verificar se nossa matriz NavPoints próxima
que estamos mantendo aqui, se o tamanho é
maior Se for, isso significa que
temos NavPoints por perto. E sempre
deve haver NavPoints próximos. Se não houver, então
fizemos algo errado. Mas é só a verificação da sanidade. Então, percorremos bem os
pontos NAV, fazemos um loop
e, basicamente,
verificamos o NavPoint que selecionamos é igual
ao ponto NAV mais próximo
ou, se é nulo, isso significa que
precisamos obter um novo, porque o que queremos
fazer é não
tentar ir para o mesmo
NavPoint em que estávamos tentar ir para o mesmo
NavPoint em que Basicamente, ele continuará
tentando selecionar um novo ponto de navegação
aleatoriamente até obter um que não seja aquele de onde
acabamos de vir ou a primeira vez na
primeira vez no loop, por assim dizer, porque quando a
função for chamada pela primeira vez, o ponto de navegação será igual a nulo Então, no mínimo,
este vai acionar. Então, definimos o ponto de
navegação igual a um valor dos
NavPoints próximos, que é, obviamente, uma matriz, e
usamos a função Randy Range Portanto, o Randy Range assume dois valores, o intervalo inferior e o
intervalo superior, que é inclusivo Então, na verdade, temos que
reduzi-lo em menos um. Então, queremos começar em zero, que é o
índice mais baixo da nossa matriz, e
o índice mais alto da matriz é, obviamente, o tamanho do tamanho
da matriz menos um Então, basicamente,
queremos um número aleatório entre zero e o último
elemento da matriz. Então, uma vez que atribuímos um elemento de
matriz aleatória ao nosso NavPoint, basicamente
verificamos se
é o NavPoint
que já temos ou simplesmente existe? Então, uma vez que temos esse valor, nós o retornamos e, em seguida, teremos um ponto de
navegação aleatório. É muito fácil verificar
se alcançamos nosso
ponto de navegação porque tudo o que precisamos fazer é verificar posição global
do ponto de fazer é verificar a posição global
do ponto de navegação para
o qual
estamos indo, se a distância entre a posição global
do nosso tanque e a posição
global
do ponto de navegação
for menor que 1,1. E 1,1 é um valor arbitrário. Eu o calculei monitorando a posição global
do tanque em cada quadro
à medida que ele é atualizado, e o número mínimo de
unidades que o tanque move na velocidade que
definimos é um
pouco maior que uma. É como 1,08 ou
algo parecido. Então 1,1, se for menor que 1,1
, isso cobre esse intervalo. Então, verifique se usamos o método da distância dois,
que é, obviamente, um método definido
dentro de um vetor
e, claro, a
posição global de um nó é um vetor. Então, verificamos a distância
entre nossa posição global e o ponto de navegação
alvo para o qual vamos. E se estivermos perto o suficiente
para menos de um único
quadro de movimento
, chegaremos ao
nosso destino. E, finalmente, o mais
complexo do grupo. Está voltado para o destino. Então, o que precisamos fazer aqui é
encontrar o vetor entre o que
representa o ângulo que estamos tentando enfrentar Então, deixe-me voltar ao jogo, e vamos definir isso aqui. Agora, o que precisamos
fazer é encontrar o vetor que
representa essa linha, a linha que vai do
tanque ao tanque inimigo,
do tanque do jogador
ao tanque inimigo. E a maneira de obter esse
vetor é
subtraindo a posição do tanque
daquela do tanque inimigo, e isso
nos dará esse E queremos que ele aponte
daqui para aqui. Então, subtraímos isso ou
subtraímos isso disso. E isso é Opa. E é isso que temos aqui.
Então, o ponto NAV mais próximo Tudo bem, eu realmente preciso me
corrigir um pouco. Então, não é o jogador. É o
ponto de navegação para o qual vamos. Então, digamos que o tanque inimigo estava indo daqui para cá. Precisamos obter o vetor
que representa esse caminho. Então, a maneira de obter isso é
subtraindo a origem, que é, obviamente,
o tanque do destino, que
é
o ponto NAV Então, os pontos NAV, a posição
global menos a posição global do tanque,
e nós a normalizamos E normalizar isso
significa que reduzimos o comprimento do vetor
para que o comprimento seja um, que significa que será muito menor porque tudo o que realmente
importa é o ângulo E uma vez que temos esse vetor
normalizado, calculamos o
ângulo usando o método do ângulo dois para a
transformação de pontos com base em Z. E vimos a transformação antes, quando estávamos
movendo nosso tanque O componente Z da transformação representa a
face do tanque. Então, se calcularmos
o ângulo daqui, até a orientação do tanque, obteremos o ângulo
entre esses dois vetores E à medida que giramos em direção
ao ponto de navegação, esse valor vai
ficar cada vez
menor e menor E, eventualmente, se o ângulo entre os dois vetores
for menor que um grau, é bastante seguro
dizer que estamos apontando para
o destino Então, o que fazemos é pegar o
ângulo entre esses dois, entre o componente Z da nossa base e o
vetor oposto, que acabamos de obter. E por uma questão de conveniência, estou usando graus em radianos, o
método de graus em radianos, porque
gosto de pensar em graus e não
sei qual é o radiano
equivalente Então, dizemos graus em
radianos um grau, e isso calculará
o número adequado de radianos porque o ângulo
dois retorna Então, novamente, verificamos
se o ângulo entre essas duas coisas é menor que um
grau e, se
for, está voltado para
seu destino. Então, tudo isso deve
funcionar perfeitamente. Vamos começar nosso jogo. E estamos errados. Então, Rotate Turret é
provavelmente o nome errado
da função. Nenhum tanque inimigo. Sim, é a torre Rotate
Underscore. Tudo bem. Espero que seja
o único que eu quebrei dessa forma. Lá vamos nós. Então, agora o tanque está girando esperançosamente, em direção
a um dos pontos de navegação,
e aí vai E agora, claro, sim. Então eu não fiz isso. Não configurei esses
nomes de funções corretamente novamente. Então, o que temos?
Definimos a velocidade de avanço e definimos a
velocidade de rotação igual a zero Então, sim, é
girar a torre zero. E defina a velocidade de movimento. Então, o que realmente acontece lá é que,
como você pode ver, aqui está a colisão,
a esfera
de colisão do ponto de navegação Então, o tanque vai
girar até atingi-lo
e, em seguida, vai
direto em direção a ele Mas agora estou perto o suficiente para
que o tanque me veja, então ele vai parar de se mover e agora vai
tentar girar,
como vimos antes, e
depois atirar em mim Vamos ver se isso
realmente funciona. E
provavelmente não funciona porque estou fora do alcance. isso provavelmente requer apenas entanto, isso provavelmente requer apenas
um pouco mais de ajustes
nos valores Mas sim, então vou deixar essa lição aqui porque
ela já é muito longa. Se você está acompanhando o projeto deste capítulo
, pode ser um bom desafio tentar
corrigir esses bugs. Se você puder, então você
definitivamente terá dominado os conceitos que estou ensinando ao ser
capaz de solucioná-los Mas é mais provável que esteja
literalmente ajustando os raios da
Área três Ds e as Bem, esse foi um grande problema.
Junte-se a mim na próxima lição e continuaremos
com mais coisas legais.
23. SFX: áudio 3D: Bem-vindo de volta. Vamos ver
o áudio posicional Mas antes disso,
precisamos fazer alguns ajustes
leves em nosso tanque e em nossa máquina de estado para
que possamos realmente fazer
o áudio funcionar corretamente. Então, a primeira coisa que
precisamos fazer é voltar ao nosso script tank dot gd original e adicionaremos uma
variável chamada destroyed E isso vai ser um Bool. E se você se lembra, quando destruímos nossos tanques inimigos ou quando destruímos ou
quando eles nos destroem, simplesmente
liberamos o nodo e excluímos o
tanque da existência E isso é ruim para o áudio porque se você está
tentando reproduzir, por exemplo, uma explosão para
ser destruído, o fato de o nó ser acionado imediatamente significa
que você não ouvirá esse efeito sonoro faremos é que,
em vez de excluir o tanque, vamos simplesmente transformar seu valor
destruído em verdadeiro
e, para o jogador, ignoraremos qualquer entrada adicional E para o inimigo, vamos
colocá-lo em um estado destruído, que criaremos antes de fazermos todo o áudio
posicional. Então, vamos adicionar uma função na parte inferior
aqui e a chamaremos de Hit. E agora, acertar vai ser
apenas um passe. E então, no shell, quando ele atinge um objeto que pode ser bombardeado, em vez de liberá-lo,
vamos chamar sua E agora, no sucesso, simplesmente
transformaremos destruído em verdadeiro E em nosso jogo, podemos ir até o topo aqui
e dizer basicamente: jogador destruído retornar. Isso significa que nenhum
pressionamento de tecla será processado após
a morte do jogador, que é uma chatice
para todos, na verdade E para o
tanque inimigo, como eu disse, precisaremos de um novo
estado porque, basicamente, quando o tanque for
destruído, queremos que ele
vá para um estado em que não
seja mais processado. Então, criaremos um novo script. Ele herdará
de um estado e será chamado
de estado morto, mas está tecnicamente destruído Abra aquele cara e
dê um nome de classe. E, é claro, daremos a
ele seu estado de mudança
e, dessa forma, ele poderá relatar
qual é seu estado atual. E então, é claro,
na máquina de estado do inimigo, precisamos adicionar um novo
estado à máquina. Corda destruída. O valor é, obviamente, um objeto, e então arrastamos nosso
estado morto até aqui. Adicione um par de valores-chave
e agora estamos bem. Agora temos que modificar nossos estados
existentes para ir para esse estado no caso
de a bandeira destruída ter sido virada E, felizmente, o código
é o mesmo para ambos. Então entramos em estado de disparo, e em processo, não,
não em andamento Eu determinei o próximo estado,
não, eu deveria mudar de estado, voltamos, não
precisamos de um extra. Retornamos o alvo do
objeto monitorado igual nulo ou o objeto monitorado
destruído Em qualquer um desses casos
, queremos mudar de estado, e precisamos fazer isso também em
nosso estado de caça. Então, no próximo
estado determinado, para ambos, verificamos se o
objeto monitorado foi destruído e, em
seguida, passamos para destruído. Caso contrário, vamos atirar, pelo
menos no caso do estado
de caça E então, em estado de fogo
, ou será
destruído ou caçado E o que o estado morto faz? Bem, não faz absolutamente
nada. Neste momento. Bem, na verdade
faz mais uma coisa. Vamos
interromper incondicionalmente toda rotação
e todo movimento quando o
objeto estiver nesse estado,
dessa forma, ele realmente
terá parado de se mover e será Tudo bem, então temos a torre
rotativa,
definimos a velocidade de movimento
e precisamos girar definimos a velocidade de movimento e precisamos Bem, eu já tenho os dois. OK. Gire, gire, mova
a velocidade. Tem mais um. Precisamos de velocidade de giro. Esse é o único. Tudo bem. Depois que todos esses três
valores forem definidos como zero, o tanque não se moverá mais e não há como
sair desse estado. Então, quando o tanque está
morto, ele está morto, o que é uma chatice para todos, principalmente para as
pessoas no tanque. Tudo bem, agora que isso foi feito, somos capazes de adicionar
nossos efeitos sonoros Mas vamos
garantir que isso funcione antes de fazermos qualquer outra coisa. Então, vamos até aqui,
vamos atirar no tanque inimigo e pronto, ele foi destruído. E como você pode ver
, estava girando e agora não está
mais girando Não está mais
fazendo mais nada. Perfeito. Tudo bem, vamos
adicionar alguns efeitos sonoros Então, voltaremos ao
nosso tanque original. Bem, na verdade, não, vamos começar em um nível um pouco
mais alto. Bem, há dois tipos
de sons em Gadot. Há
som posicional e
há o que você poderia
chamar de som ambiente. Som ambiente que você ouvirá
de qualquer lugar do jogo e geralmente é usado para
coisas como música de fundo No nosso caso, vamos
adicionar um pouco de
som ambiente à nossa arena Então, adicionaremos um nó filho e usaremos o nó do reprodutor
de fluxo de áudio. Agora, o reprodutor de
fluxo de áudio
sem duas designações D nem
três D é um reprodutor de som simples que sempre reproduz o som no mesmo volume, não
importa onde você esteja Então, vamos renomeá-lo,
chamá-lo de ambiente. E eu já forneci três efeitos sonoros para
você neste projeto. Então, se você baixar o
projeto para a Lição oito, você já deve ter esses
sons importados. Se você quiser
reimportá-los ou
importar seus próprios sons para
praticar a importação para um
GodObject Você pode simplesmente pegar seus
próprios arquivos de áudio, desde que estejam nos formatos wave
Og ou MP three, e simplesmente arrastá-los para a
pasta do projeto, e eles devem ser
importados imediatamente. Então, acessaremos o arquivo de áudio Amazon
Jungle Night e o arrastaremos para
o stream E agora estamos prontos para ir até lá e queremos
verificar a reprodução automática, o que significa que ela
começará assim que o
nó entrar na árvore, o
que significa que funcionará começará assim que o
nó entrar na árvore, o imediatamente. Agora, temos um problema queremos poder
alterar os vários níveis
de áudio dos diferentes
tipos de sons. Então, por exemplo,
não queremos que nossos
ruídos na selva sejam mais altos do que nossos tiros e
explosões E conseguimos isso em
virtude do barramento de áudio. E há
vários barramentos de áudio. Bem, quero dizer, colocamos
um como Master padrão, o que significa que todas as
rotas de áudio passam pelo barramento Master. Se adicionarmos um novo
barramento, por exemplo, e o chamarmos de ambiente, voltaremos ao nosso reprodutor de fluxo de áudio
ambiente Podemos mudar o
ônibus para o ambiente. E agora, se baixarmos
o volume aqui, o ambiente ficará mais silencioso, mesmo que não tenhamos
diminuído o áudio
ou o nível
de volume do nosso Então, vamos adicionar
outro barramento de áudio, e este
será para efeitos sonoros. E esse vai
estar no volume normal. Então, agora, se carregarmos nosso jogo, agora, parece
uma selva nebulosa à
noite, quase
sem árvores E vamos desligar
essas formas de colisão. Não precisamos deles
por enquanto. Ok, agora precisamos que o jogador e
os tanques
inimigos sejam capazes emitir ruídos de disparo quando disparam e
explodam
quando e
explodam Então, vamos para a cena do nosso tanque
base e adicionaremos dois novos nós. Adicionaremos o
reprodutor de fluxo de áudio em três nós D duas vezes. E vamos renomear um, e vamos chamá-lo de Cannon E então vamos chamar
a outra de explosão. Também precisamos ser capazes de
acessá-los no script. Então, voltaremos ao
nosso script de tanque e exportaremos
essas variáveis. E vou criar um novo grupo só porque queremos
manter as coisas organizadas. Exporte para o
reprodutor de stream de áudio Cannon
SFX três D. E precisamos de outro
para a explosão E agora voltamos ao nosso tanque, e simplesmente, primeiro, expandimos a categoria
e depois simplesmente os
arrastamos até aqui para que
tenhamos acesso a eles. E agora, quando
disparamos um método de projétil, tudo o que precisamos fazer
é jogar pontos de canhão E quando morremos,
explosion dot play. E como estão bem,
temos que pegá-los. Temos que acertar os
nomes primeiro. É Cannon SFX
e Explosion SFX. E como esses são
três nós D de áudio , eles
são posicionais, o que significa que
eles se ajustarão à distância
do ouvinte de áudio,
que, neste caso, é sua
câmera por padrão. Ah. Tudo bem, isso não
funcionou. E parte da razão para
isso é porque, bem, eles estão
passando pelo ônibus principal, o que não queremos. Na verdade, queremos que eles
passem pelo ônibus SFX. Isso é um pouco grande.
Vamos arrastar isso para baixo. Toque. Ok, agora
isso deve funcionar. E isso não acontece, vamos
ver o que eu quebrei. Ah, eu vejo o que eu quebrei. Claramente, eu não arrastei os efeitos
sonoros para lá. Vocês provavelmente
perceberam isso antes de mim. Tudo bem, canhão de explosão. OK. Agora que realmente temos áudio,
isso deve funcionar. Claramente, eu preciso de uma xícara de café. Lá vamos nós. Muito melhor. OK. E como você pode ouvir o
kaboom do tanque inimigo E agora também vou me
aproximar para que você possa ouvir
o tanque inimigo atirando em mim. E você pode ver que não
vai ser tão alto quanto era antes. E aí está.
Temos áudio posicional, três áudios D em Gado. E esse é o fim
desta lição. Eu te disse que seria muito
mais rápido do que o outro. Portanto, sinta-se à vontade para
brincar adicionando seus próprios sons. E se você quiser,
pegue o que aprendemos adicionando NavPoints
e talvez adicione algumas entidades do mapa à
sua arena que possam reproduzir sons e repeti-los
quando chegarem perto de você Caso contrário, nos
vemos na próxima lição.
24. Camadas básicas de UI: Bem vindo de volta. Nesta lição, aprenderemos os
conceitos básicos da interface do usuário e não
haverá codificação envolvida Portanto, é um pouco mais
de férias à quantidade de trabalho que
fizemos nas
últimas duas aulas. Então, no iGado, uma das coisas mais
úteis que você pode fazer é combinar dois ativos D e três D
na mesma cena E uma maneira de
fazer isso,
obviamente, é com o
uso de nós de controle, que permitirão sobrepor uma interface de usuário de dois D no
topo do seu campo de jogo Então, aqui está nossa visão em três D. E também temos outra
guia aqui para dois D. Agora, é
claro, ainda não fizemos nada com dois D, então ela ficará vazia. Mas
ao mudar para essa guia, você verá que tem um espaço de coordenadas de dois D com a origem no canto superior
esquerdo aqui E esse retângulo roxo será o limite
da sua tela E você pode alterar o tamanho
desse retângulo acessando as configurações
do projeto do projeto E então janela, e ela
é mapeada especificamente para a largura da janela de visualização e
a altura da janela de visualização
da janela do seu jogo O GaDo usa uma coordenada
um por um
em escala de pixels quando faz
suas interfaces de usuário Mas também é possível
escalá-los para sua janela. Mas nós realmente não
vamos fazer isso. O que vamos fazer
é colocar nossos ativos diretamente em nossa interface de usuário e partir daí.
Então, vamos fazer isso. Temos nossa cena de jogo aqui
e, claro, temos nossos
três ativos D nela. Então, agora vamos
adicionar uma interface de usuário
adicionando um nó filho e
adicionando um controle. Um controle é o nó de
nível mais básico das interfaces de usuário. E simplesmente por ser um controle, ele sempre será renderizado em cima dos três D. Então, o que queremos fazer aqui é
realmente
querer nosso controle esteja alinhado com a parte inferior
da tela Então, vamos clicar
nessas predefinições de âncora e clicar nesta
, que está na parte inferior Então, o que ele vai
fazer é
forçar o alinhamento
e a ancoragem desse controle na parte inferior
da tela e esticá-lo
por toda
a tela Poderíamos
agarrar essas alças e arrastá-las para cima para
torná-las maiores ou menores Podemos até
movê-lo porque controle não está
bloqueado em nada. Um controle pode ter
o tamanho que você quiser, em qualquer
posição que você quiser. Acontece que, em
muitos casos, você realmente
deseja fixá-lo nos cantos
da tela
por vários motivos,
geralmente para que, se
você alterar sua resolução, seja em tempo real ou se for criar
versões diferentes do seu jogo, poderá ter problemas com o
dimensionamento incorreto da interface do usuário Então, por exemplo, se eu aqui estão os
pontos de ancoragem, na verdade Se eu os alterasse para
que ficassem assim, e então eu fizesse o
controle assim, bem, ele está ancorado
nesse ponto específico E se fôssemos aumentar
a tela, talvez ela não se
alinhasse corretamente. Na verdade, pode ser assim porque tudo mudou. Então, vamos orientar. Mas, felizmente, não
precisaremos nos preocupar com isso por enquanto. Nós só vamos
construir para uma resolução. Então, vamos
realinhá-lo na parte inferior da
tela desta forma, e vamos adicionar
um nó destruído de textura E um fragmento de textura faz exatamente
o que diz na lata. Ele tem uma textura. E neste projeto, forneci a você
uma textura singular e fontes
tou que
usaremos
para criar nossa interface de usuário muito básica. Então, vamos
arrastar o arquivo PNG até a textura,
e aí está. E agora, devido à
orientação que fizemos, na verdade
ela está na
parte inferior da tela. Então, vamos ver se não podemos
realinhar essa coisa corretamente. Não, você vai ser
assim, não é? Tudo bem. Vamos fazer assim. Uma das
coisas gloriosas de trabalhar com
interfaces de usuário no Gadot é que embora seja infinitamente
mais fácil de usar do que a maioria dos outros mecanismos de jogo e tenha muito menos peculiaridades que
você precisa contornar,
as peculiaridades que ele tem, às vezes
você se
vê lutando contra ,
embora seja infinitamente
mais fácil de usar do que a
maioria dos outros mecanismos de jogo e
tenha muito menos peculiaridades que
você precisa contornar,
as peculiaridades que ele tem, às vezes
você se
vê lutando contra elas. Você fica tipo, Oh, isso
funciona do jeito que eu acho que funciona? Sim, não, talvez. Eu não sei Ok, então vamos mudar o retângulo de
textura para isso, e ele deve realmente funcionar Na verdade, isso OK,
sim, vamos voltar. Vamos tentar isso de forma diferente.
Vamos passar pelo controle e não fazemos isso. Em vez disso, usaremos tela cheia
ou janela inteira. E então, dessa forma, o retângulo de
textura, se o definirmos para a largura inferior, agora
ele será dimensionado corretamente e deverá estar do
jeito que queremos E não precisamos nos
preocupar com o modo de
expansão nem nada, mas vamos mudar isso. Na verdade, não,
não vamos ignorar isso. Mas se
mudássemos o tamanho dessa textura ou o
tamanho do controle, poderíamos alterar a escala da
textura aqui E também
usaremos um contêiner de margem,
que, a longo prazo,
é provavelmente um
dos contêineres
mais úteis disponíveis para interfaces de usuário,
junto com os
contêineres VBox e
HBox Os contêineres de painel também
são incríveis. E o que
vamos fazer aqui é o contêiner de margem
ficará totalmente destruído Mas como eu coloquei o contêiner de
margem como filho da textura rect, quando digo totalmente destruído, para o contêiner de margem, ele será totalmente
destruído de seu pai será totalmente
destruído Então, no caso do controle,
quando eu disse totalmente destruído, seu pai era a tela, então era o
tamanho total da Mas o contêiner
de margem será do tamanho total
do fragmento de textura E o que um contêiner de margem faz é nos permitir fornecer margens para
nossa interface de usuário E isso está em layout, o
tema substitui as constantes. Então, vamos com
20 para a esquerda, 20 para a direita, dez para
cima, dez para baixo. Novamente, esses são valores de pixels. Agora, é claro, não
vamos ver nada porque o contêiner de margem
não tem filhos. Então, vamos
dar um. Vamos dar a ele o contêiner VBox contêiner VBox, como mostra
o ícone, pegará todos os seus
filhos e os
organizará de forma que fiquem orientados
verticalmente Então, se eu fosse adicionar, digamos, um monte de rótulos,
temos um rótulo aqui. Vamos colocar uma mensagem de texto. E então, se eu
duplicasse isso algumas vezes, você pode ver que
eles se
empilham automaticamente um sobre o outro, que é incrivelmente
útil para No entanto, em nosso contêiner
VBox, usaremos
um contêiner HBox E o contêiner HBox faz exatamente
a
mesma coisa que o contêiner VBox, mas na direção
horizontal Agora, também uma palavra de nota: maioria dos contêineres
redimensiona todos os
seus filhos de forma
que
ocupem todo o
espaço disponível neles. Então, como você pode ver, o
contêiner de margem é desse tamanho. E então, quando coloquei o contêiner
VBox
nele, ele se redimensionou automaticamente para ocupar tanto espaço quanto o tamanho do
contêiner de margem menos as Então aqui está nossa margem de 20 pixels, e eu realmente não
gosto desses dez. Acho que vou mudar
isso em um segundo. Mas aqui está nossa margem de 20 pixels e aqui está nossa margem de dez pixels. Se não tivéssemos essas margens
, o contêiner VBox
seria do tamanho do contêiner de
margem E não seríamos capazes
de alterar esse tamanho. Não conseguiríamos
torná-lo menor do que isso porque é
assim que os contêineres funcionam. Então, voltaremos ao nosso contêiner de
margem e
aumentaremos essas
margens só porque E agora, dentro do contêiner
HBox, forneceremos uma etiqueta E o rótulo, como você pode ver, você não pode realmente
ver nada nele, então vamos
dar a ele um texto. O que isso vai
fazer é na verdade, criar
um indicador aqui, que vamos conectar
ao código na próxima lição, que mostrará se
nosso tanque está pronto para disparar ou não. Então, temos status
e vamos
mudar a cor da fonte e
todas as outras coisas boas. Então, queremos ir para substituições de
temas,
cores, e queremos
mudar a cor da fonte para que
fique preta, e vamos
mudar a fonte em si
para a fonte estêncil que eu forneci para
você no projeto,
porque é bonita porque é E então vamos para os tamanhos de fonte, e vamos fazer com que sejam 25. E isso não é bom. Vamos
fazer isso 45. Muito melhor. Agora, está justificado à esquerda
no canto superior esquerdo
e, na verdade, queremos
que fique à direita. Portanto, há duas maneiras de corrigir isso. A primeira é que
vamos mandar nosso contêiner HBox
se alinhar até o final, e isso resolve nosso
problema Na verdade, sim, resolve a maior parte do nosso problema porque nosso rótulo
está onde precisamos que esteja E agora, em vez de
adicionar outro rótulo, vamos adicionar
um rótulo de rich text. etiqueta Rich Text é uma versão sofisticada da etiqueta que tem muitas funcionalidades
extras Você pode usá-los quase de forma
intercambiável. Há algumas vantagens em
usar um em relação ao uso do outro. A maior desvantagem que
encontrei ao usar o rótulo de
rich text é que ele nem sempre é dimensionado
verticalmente com precisão, dependendo da
hierarquia de controle em que você o usa Mas, como estamos prestes a ver, ele tem muitas outras habilidades que o tornam muito legal. Então, a primeira coisa que
vamos fazer é descer
para o layout
e a transformação. Não, na verdade, não somos.
Vamos ao layout. E aqui, você pode ver
o tamanho mínimo personalizado. Agora, na maioria dos controles
, o padrão será 00. O que Gadot faz é
começar com esse tamanho mínimo. É exatamente o que
você pode pensar. Então, no momento, o tamanho
mínimo é zero. Portanto, tanto na direção horizontal
quanto na vertical, esse controle é tratado como zero. No entanto, verticalmente, ele está
se estendendo até a altura
do contêiner
principal, é
claro, o controlador HBox Mas vertical ou horizontalmente, não
há nada aqui. Então, para horizontalmente
na direção X, digamos que nosso
mínimo seja 200 Então, agora você pode ver,
no mínimo, expandido
para 200 pixels E vamos
ficar um pouco mais sofisticados. Vamos abordar as substituições
de temas e temos muito mais opções
para o rótulo de rich text E o que queremos
são estilos, normais. Tudo bem, não podemos verificar
porque não temos nada lá. Mas se estendermos isso, temos a opção
de caixas de estilo. Então, vamos
para a caixa de estilo plana, e agora você pode ver que o fundo da
etiqueta está colorido. No entanto, não queremos essa cor
excelente. Vamos mudar para preto. E vamos colocar um texto aqui. E, claro, esse texto tem a fonte e
o tamanho errados. Então, a primeira coisa
que vamos fazer é mudar o onde está? Fontes. Vamos
mudar a fonte normal. E, mais uma vez, não podemos clicar nele porque não
temos nenhuma fonte nele. Vamos usar a fonte LCD N, que tem uma aparência muito legal. Agora você pode ver que temos
uma boa fonte com aparência de LCD. Vamos mudar
o tamanho, normal. Oh, estou usando o errado. Não é de admirar. Tamanho normal da fonte, 24. Lá vamos nós. É um pouco grande
demais. Isso é bom. Agora, temos um pequeno
problema aqui, pois a fonte
do estêncil está meio desajustada na direção
vertical
e a fonte LCD está E não há absolutamente
nada que possamos fazer sobre isso. Então, nós meio que teremos
que tolerar isso. Se estivéssemos usando apenas o layout
manual com cada controle diretamente
sob o controle, poderíamos ajustar perfeitamente o X
e o Ys,
mas, nesta lição,
quero mostrar como os
contêineres interagem Então, agora queremos
usar cores, e acho que a cor padrão, queremos que seja amarela. Portanto, é bonito e tem uma aparência
computadorizada. E agora, esse é o principal
poder do rótulo de rich text. Temos o que é chamado de código BB. E se verificarmos isso, o código BB nos
permite usar HTML como
formatação em nosso rótulo Então, por exemplo, embora
definamos a cor do nosso rótulo como amarelo, se eu colocasse um par
de etiquetas coloridas aqui, elas usariam colchetes
e não colchetes
angulares como HTML Então, se você tentar fazer
isso, não funcionará. Então, continue com isso. Cor Eu tenho dois deles lá.
A cor é igual ao vermelho. E agora temos
texto em vermelho. E há muita formatação
que o BB Code pode fazer Infelizmente, não
poderei entrar em tudo isso,
mas se você estiver curioso, mas se você estiver curioso, pode simplesmente pesquisar no Google o código
BB Gadot four, e ele o levará direto à documentação
do Gado e mostrará todas
as tags suportadas O que vamos usar
vai justificar nosso
texto dentro do rótulo Então,
vamos simplesmente dizer, certo. E agora a recarga está
onde precisa estar. Felizmente, está meio amontoado na
borda da coisa, então vou preenchê-lo com
alguns espaços extras E agora isso parece muito bom. Obviamente, podemos adicionar
vários
outros indicadores e rabiscos
à nossa interface de usuário Mas isso é o suficiente
para nos ajudar. Então, se rodarmos o jogo agora,
teremos uma barra de status. E na próxima lição, mostrarei como conectar
a barra de status ao código e usar sinais para atualizar
seus valores. Te vejo lá?
25. Eventos e sinais de UI - Score: Mamãe, hmm. Mamãe, hmm. Bem vindo de volta. Antes de começarmos, vamos
duplicar o contêiner HBox para nosso indicador de status com o
Controle D. E a razão pela qual
vamos
fazer isso é porque
queremos ter um segundo indicador
para nossa contagem de mortes Embora
tenhamos apenas um tanque
no tabuleiro no momento,
teremos mais. E agora que temos vários contêineres HBox aqui,
vamos renomeá-los Então você carrega o status
e conta de mortes. E também é uma boa ideia
renomear os
próprios rótulos de rich text , porque
vamos
usá-los como referências diretas Portanto, precisamos saber o que são para sermos capazes
de diferenciar. E a convenção de nomenclatura que
eu geralmente uso
nesse caso é o nome
do controle e valor, porque
isso o
diferencia
de qualquer rótulo que estamos usando para designar a coisa
porque temos um rótulo, mas também temos Então, como podemos saber a
diferença entre os dois? Bem, este é estático
e este tem valor. E então, é claro, alteramos o recarregamento do
texto para zero, e também devemos alterar
o status de recarregamento
do outro para pronto porque é com isso que
vamos começar Embora possa ser
um pouco mais inteligente refatorar isso
posteriormente para
configurá-lo para qualquer que seja o status atual ou inicial do tanque , mas não
vamos fazer isso Vamos apenas
configurá-lo como pronto. Ok, agora que tudo está pronto, precisamos adicionar
alguns scripts
e, em seguida, podemos
conectar todos os nossos sinais. Então, o primeiro script que
vamos adicionar é um ao
controle real, que, é
claro, deve
ser renomeado agora que penso nisso,
porque é nossa interface E anexaremos um script, o que, é claro, pode ser
feito aqui ou aqui. E nós realmente não
precisamos dar a ela seu próprio nome de classe, mas
vamos fazer isso de qualquer maneira. E na interface do usuário, devemos
obter referências aos valores que
vamos alterar. Que é um rótulo de texto rico. OK. E então, como de costume, vamos arrastá-los até aqui. Precisamos desses rótulos para responder aos sinais de
dois lugares diferentes. O valor da contagem de mortes
precisa responder a um sinal
de qualquer um dos tanques inimigos
e, em primeiro lugar, temos apenas um tanque
inimigo aqui, mas vamos
reestruturar o cenário em futuro próximo para que os tanques inimigos estejam
em lugares diferentes , só passará por um nó
secundário para inimigos, Provavelmente, só passará por um nó
secundário para inimigos, ou
talvez para o gerador. Queimaremos aquela ponte
quando chegarmos até O problema é que, se
mudarmos nossa hierarquia, seja como
for, nosso tanque
inimigo poderá mudar a menos que façamos uma referência
aos tanques
do jogo, na verdade não queremos fazer isso Da mesma forma, precisamos obter o status
de recarga do jogador, e o jogador onde
ele está está bem, mas, você sabe, mesmo assim Então, o que vamos
fazer é adicionar
o que é chamado de carregamento automático. Então, vamos
para nossa pasta Scripts e vamos
criar um novo script, e vamos
chamá-lo de Messenger. E isso é exatamente o que eu
chamo de todas as minhas cargas automáticas. Você pode chamá-lo do
que quiser. Então, o mensageiro, aí está. O mensageiro
não precisa de um nome de classe porque vamos
até as configurações do projeto, acessamos Globals, clicamos no ícone da pasta, escrevemos o messenger para adicioná-la
e, em seguida, clicamos no botão de anúncio E agora, o que
aconteceu é que Gadot carregará esse script e instanciará como filho
da cena raiz jogo junto com
a
cena que criamos E a
maneira mais fácil de ilustrar isso é seguir
em frente e fazer isso Então, se rodarmos nosso jogo
e usarmos o controle remoto, podemos ver que
temos a cena raiz. Aqui está nossa cena de jogo, e agora também
temos nosso mensageiro. Isso significa que podemos
acessar nosso mensageiro a partir de qualquer script em nosso jogo
simplesmente usando seu nome Então, vamos fazer isso. Antes disso, porém,
precisamos configurar algumas funções auxiliares
em nossa interface Então, o que queremos fazer aqui? O que queremos fazer
é que a interface
responda a dois sinais
diferentes. Um, quando o status de
recarga do jogador muda e outro quando o valor da
contagem de mortes muda Então, precisaremos
fornecer um par de
funções para fazer isso. E dentro desse método, tudo o
que queremos fazer é alterar o status de recarregamento como texto com base no texto de status ou não, com base no status. O
status é booleano Então, se for verdade, isso
significa que estamos recarregando. Se for falso,
significa que não somos. E normalmente, poderíamos
dizer que estou aqui, mas na verdade é um pouco mais ilustrativo do
que estamos testando Na verdade, poderíamos mudar
isso para o status de recarga. E isso simplesmente
esclareceria ainda mais, na verdade. Portanto, se o status de recarga
for igual a verdadeiro, o valor do status de recarregamento terá uma E o que queremos definir
para isso vai ficar um
pouco complicado. Então, vamos
voltar para cá por um segundo. Portanto, temos várias sequências de caracteres
que precisaremos. Então, vamos começar
aqui por um segundo. Ou vai estar recarregando
ou vai estar pronto. No entanto, se você se lembra, tínhamos o código BB aqui. E não queremos
ter que digitar esse código BB toda vez. Poderíamos facilmente fazer isso, mas teremos que
fazer isso com as duas cordas, e é um
pouco irritante Então, o que vamos
fazer é definir uma constante. Agora, as constantes são
como variáveis, exceto que você não tem permissão para alterar seu valor
depois de definidas E, como convenção de nomenclatura, eu sempre gosto de colocar meus nomes
constantes em maiúsculas Portanto, nosso const
será recarregado. Formato de texto. E isso é,
claro, uma corda. E o que isso vai ser é que vai ser nosso código BB. Os dois espaços que precisamos para
garantir que tudo esteja
devidamente espaçado e uma porcentagem s. E esse é um símbolo que vamos usar
para formatação de strings, e veremos como
isso funciona em um Então,
acertamos e pronto. Então, agora o que queremos fazer
aqui é definir
nosso texto para essa string de formato de
recarga
e, em seguida, usar o sinal de
porcentagem para dizer, vamos
formatar essa string com qualquer string que fornecermos Então, obtivemos o formato de
recarga de texto
e, em seguida, Godot verá
automaticamente esse símbolo e substituirá a porcentagem s
pela palavra Isso significa que obteremos essa string como nosso resultado e faremos a mesma
coisa aqui embaixo. Mas, honestamente, isso também pode ser
reduzido um pouco mais Quero dizer, tecnicamente,
podemos fazer isso assim. Mas agora só precisamos fazer isso uma vez. E então faremos o mesmo
com nossa contagem de mortes. Agora, nesse caso específico, não
precisamos fornecer
a nova contagem de mortes. Poderíamos facilmente colocá-lo
no player e depois passar o valor aqui como
parte do sinal. Mas, para simplificar, vamos deixar isso como parte
da própria interface do usuário. Então, a contagem de mortes é um número inteiro, é igual a zero E então, quando a contagem de
mortes mudar, simplesmente
aumentaremos nossa variável um e, em seguida, definiremos o valor
da contagem de mortes Igual aos formatos de
texto de recarga, e substituiremos
as contagens de mortes E vamos fazer isso corretamente com o apropriado. Lá vamos nós. Ok, agora vamos
conectar nossos sinais. O primeiro sinal que
vamos usar é o sinal de
destruição do tanque inimigo. Então, voltamos ao nosso
mensageiro e definiremos um sinal e ele não requer nenhum parâmetro. E então, se formos
até nosso tanque inimigo, o tanque inimigo, se você se lembra, nosso tanque base tem uma
função chamada hit, e essa função é chamada quando qualquer tanque é
atingido por um projétil
e, portanto, o destruirá e reproduzirá o efeito
sonoro de explosão. Queremos que o tanque inimigo também
emita esse sinal. Então é aqui que fazemos uso da herança porque
o tanque inimigo, que é da classe AI, estende o
tanque, que significa que ele já
tem seu método de tanque definido Portanto, não precisamos, se não
redefinirmos isso
e simplesmente o chamarmos de, o tanque inimigo
terá essa funcionalidade Mas se a
redefinirmos, agora podemos adicionar nossa
própria funcionalidade O que queremos fazer é querer a
funcionalidade das classes básicas. Então, usamos a superpalavra-chave. Então, dizemos super dot Hit. E isso chamaremos as classes
básicas de método Hit. Além disso,
queremos que o mensageiro e o tanque
inimigo sejam destruídos. Emissão de pontos. Agora, sempre que qualquer
tanque inimigo for destruído, ele dirá à
classe de mensageiros que emita esse sinal Agora, nossa interface de usuário,
em seu próprio método pronto, pode se conectar a esse
sinal porque, novamente, essa classe de mensageiro
está disponível para qualquer classe em qualquer lugar e a qualquer momento. Então, nós apenas
conectamos o Messenger, o tanque
inimigo destruído e fornecemos o método que
queremos conectar. E agora, para o jogador, queremos fazer duas coisas. Então, podemos fazer isso. Podemos
fazer isso em dois lugares. Queremos que o jogador
emita um sinal que
indique que seu status de
recarga mudou No entanto, o jogador é
um tanque, não um tanque de IA. Então, se
colocarmos isso no tanque, ele poderia estar disponível
para qualquer tanque do jogo, que é realmente bom,
porque só precisamos nos conectar
à
emissão desse sinal pelo jogador. Não sei por que meu boné gosta
de
se desligar quando eu uso meu
sublinhado, mas aí está Agora, queremos nos conectar
a esse sinal, e faremos isso no jogo porque o jogo tem acesso a
tudo o que precisamos. Então, já nos conectamos jogador
que o projétil disparou aqui. Agora vamos nos conectar a o. Não sei
por que não é
preenchimento automático, mas de qualquer forma. E qual é o método ao qual
queremos conectá-lo? Bem, precisamos do nosso nó de interface de usuário, então faremos o que fizemos
aqui para pegar o tanque inimigo. Também podemos fornecer uma
referência à interface do usuário do jogo. E, na verdade, também
faremos outras coisas
com a interface do usuário. Então, vamos fazer uma exportação. E é um controle. Sim, sabemos que você está
quebrado agora. Ok, agora o player
vai se conectar às interfaces de usuário. Na verdade, isso não está correto. Deveria ser UI porque,
na verdade, temos uma classe para UI. Tudo bem.
Ambos devem estar bem, e agora podemos usar o Auto Connect. Então, agora temos o status de
recarga do jogador alterado. E aqui está algo com o qual você
deve ter cuidado. Sempre que você
tenta usar ou sempre que permite que o Gadot preencha automaticamente o nome
de uma função
no método connect,
ele sempre adiciona
os parênteses de chamada
ao método,
e você não quer isso porque isso
quebra as coisas nome
de uma função
no método connect, ele sempre adiciona
os parênteses de chamada
ao método, e você não quer isso porque isso E então, se você
tentar excluí-los, Gadot exclui todos os
parênteses Ok, agora os dois
devem estar conectados. Então, se entrarmos em nosso jogo, você pode ver que nosso
status está pronto. Se eu atirar, nada acontece. Tudo bem, vamos
ter que depurar isso. Mas se eu atirar no
tanque inimigo, eu deveria pegar um kit. Aí está. Tanque destruído. Agora temos que
matar a contagem de um. Ah hein, eu vejo o problema. Na verdade, nunca
emitimos o sinal. Então, voltar ao tanque deveria ter sido a
primeira coisa que fiz. Em seguida, vamos para o Fire Shell, e a última coisa que
fazemos depois que o projétil dispara é simplesmente emitir o sinal com o valor da variável de
recarga Agora devemos ter corrigido. Sim. Na verdade, não,
não, eu estava errado. Eu não seria a primeira
vez. Portanto, o problema aqui é que, quando o tempo de
recarga atinge o tempo limite, precisamos mudar, precisamos
informar à interface do usuário que o
status mudou E isso é irritante porque
agora teríamos que ir a todos os lugares do
jogo mudar essa variável
e emitir esse sinal Então, precisamos fazer isso de forma inteligente. E é por isso que, mais uma vez, precisamos de uma variável setter
ou de um método setter Então, definimos um setter
para o recarregador. E, claro, recarregar
é igual ao valor, e então emitimos um sinal, e agora deve ser ótimo Perfeito. Agora temos uma interface de usuário totalmente
funcional. Então, a próxima coisa que vamos
fazer é dar uma olhada em como utilizar alguns truques inteligentes e componentes da interface do usuário
para criar um minimapa
26. Criando um minimapa: Bem vindo de volta. Nesta lição, vamos adicionar um
minimapa à nossa interface do jogo, e é muito mais simples do
que você imagina Vamos usar os nós Gado
incrivelmente úteis conhecidos como subjanelas de visualização Se você está familiarizado com as versões
anteriores do Gado, elas costumavam ser
chamadas apenas de janelas de visualização, mas acho que confundi
muitas pessoas Então, a primeira coisa que
vamos
fazer é voltar à
nossa visualização em dois D para que possamos ver nossa interface de usuário aqui. E queremos adicionar um minimapa no
canto superior direito da tela Para fazer isso, precisamos controle da interface
do usuário conhecido como contêiner da janela de
subvisualização Como o nome sugere, esse é um contêiner, que é basicamente
apenas um controle que conterá uma subjanela de visualização Vamos esticá-lo até
o tamanho que
queremos
e, em seguida, justificá-lo corretamente com as predefinições de
âncora corretas Também vamos
garantir que seja quadrado, defina o
tamanho da transformação 230 por 190. Isso não vai funcionar. Digamos que
200 por 200. Muito melhor. E então vamos deslizar um
pouco para que
seja perfeitamente justificado. Lá vamos nós. Agora, para usar um contêiner de subjanela de visualização,
como você pode ver aqui, temos um pequeno
aviso que diz que ele não tem uma janela de subvisualização,
então vamos Adicionaremos uma subjanela de visualização. Uma porta de subvisualização é basicamente uma nova janela
para o seu mundo de jogo. Ele renderizará tudo o que estiver visível dentro desse
pequeno subespaço E, no nosso caso, o que
queremos que seja visível é uma
visão secundária da câmera do nosso mundo existente. E não se preocupe,
na verdade é muito menos
complicado do que parece. Então, o que vamos
fazer é adicionar outra câmera tridimensional
ao nosso mundo principal do jogo. E essa não
precisa ser atual porque já
teremos uma câmera atual em nosso player. No entanto, vamos renomear isso. Vamos chamá-la de câmera
espiã porque ela flutuará
acima do nosso mundo de jogo Então, vamos trazer isso aqui
e não vamos fazer isso. Vamos voltar aqui.
Vamos ver duas janelas de visualização Agora podemos ver
o que nossa câmera vê. Vá lá. Clique. Lá vamos nós. Às vezes, meu computador está lento
e mal-humorado e não gosta fazer coisas. OK. Se agora descermos e
girarmos a câmera, vamos fazer
dessa maneira. É mais fácil. Se girarmos a câmera, forma que ela fique voltada para baixo, 90 graus,
acho que não fiz isso direito As rotações sempre me confundem. Para onde estamos olhando aqui? Oh, eu estou olhando para o céu. Ok, é menos 90.
Sempre me pega. Tudo bem, agora basta arrastar
isso para cima até que possamos ver a totalidade do mapa ou pelo menos o máximo possível
do mapa E isso é bom, eu acho. Ou podemos sempre
fazer isso para que possamos ver
essas coisas lá. Isso é bom o suficiente, eu
acho. Você notará por padrão, que ele está renderizando
nossos pontos de navegação Então, é claro,
temos que voltar à nossa máscara de chamada e clicar
na camada NavPoints para que não
os vejamos dentro da câmera Agora, tudo o que precisamos fazer é arrastar nossa câmera espiã para
nossa janela secundária E agora, se você for para dois D, poderá ver uma bagunça feia
porque o que está acontecendo aqui
é que a porta
de subvisualização, que tem 512 pixels por
512 pixels, não está sendo esticada
corretamente até o tamanho do
contêiner da poderá ver uma bagunça feia
porque o que está acontecendo aqui
é que a porta
de subvisualização, que tem 512 pixels por
512 pixels,
não está sendo esticada
corretamente até o tamanho do
contêiner da subjanela de visualização. Felizmente, podemos corrigir isso simplesmente marcando
a opção de alongamento, e agora temos uma
pequena porta de visualização. Então, a única outra coisa que
precisamos fazer agora é atualizar a câmera espiã
quando nosso jogador se move. E normalmente você
pensaria que simplesmente
colocaria a câmera
espiã no jogador. Mas se você fizer isso,
o player teria que estar
na janela de exibição
e, na verdade, não queremos
mudar nossa hierarquia aqui Então, o que podemos fazer é simplesmente dar à câmera seu próprio roteiro. E como o jogador
sempre existirá, tudo o que precisamos fazer é exportar
uma referência para o jogador, chamá-la de alvo
e torná-la um pouco mais genérica pois pode suportar três D de qualquer corpo
físico, mas só vamos
usá-la para o jogador. E então arrastaremos
o player até aqui. E agora, no método de processo Spy
CAMs, que aparentemente não consigo
soletrar. Lá vamos nós. Tudo o que precisamos fazer
é atualizar as posições X e Z da câmera
para que sejam as do jogador. Não atualizamos o valor
Y porque
o valor Y representa
a altura,
o valor para cima ou para baixo, e queremos
que isso permaneça consistente. Literalmente,
queremos que ele vá
nas direções X ou Z
com base no tanque. Portanto, a posição global
da nossa câmera, tanto X
quanto Z, são iguais
ao ponto X da
posição global do alvo
e à posição
global do alvo Z. E isso deve funcionar. Vamos ver. Sim. Agora, se
eu mover meu tanque, você pode ver que ele está
atualizando tudo isso. Um outro ajuste que provavelmente
devemos fazer é
orientar a câmera de forma
que, quando o player
gire, a câmera Mas vou deixar
isso como um exercício para você ver se você
dominou esta lição janelas de visualização são incrivelmente
úteis em três D. Você pode até usá-las para renderizar na superfície
de outro objeto E se tivermos tempo
no final do curso, talvez eu fale sobre isso como um material bônus. Nos vemos na
próxima lição.
27. UI 3D com nós Label3D: Bem-vindo de volta. Esta lição será bastante curta, e o que vamos
fazer é examinar uma maneira rápida de adicionar uma interface de usuário
tridimensional, também conhecida como
diagética em nosso ambiente tridimensional E vamos fazer isso
colocando um nome no estilo World of Warcraft
acima de todos os nossos tanques Então, como você pode imaginar, isso requer a adição de
um nó filho, e o nó filho que
vamos procurar é o rótulo três D.
Agora, é claro, precisamos
orientar adequadamente nosso rótulo três D, então vamos trazê-lo até aqui e
movê-lo um pouco para trás para que
fique sobre nossa torre Lá vamos nós. E então
vamos abrir seu texto. E, como você pode ver,
há algumas configurações semelhantes
às que você obteria em sua
etiqueta e etiqueta de rich text. Então, vamos simplesmente colocar um texto
de
espaço reservado aqui, nome do tanque Agora, como você pode ver, só podemos ver o nome do tanque pela
frente e por trás. Se olharmos para o lado
, não veremos nada porque esse é
um verdadeiro objeto de três D. E às vezes você
pode querer isso, às vezes você pode não. Talvez não estejamos na variedade. Então, o que vamos fazer
é estender as
bandeiras e
mudar a Billboard para outdoor significa que o
objeto sempre estará voltado para a câmera,
independentemente de sua orientação Agora, também queremos estender um pouco
nosso script de tanque, e vamos fazer isso
adicionando uma variável de exportação. Mamãe. E, claro, vamos arrastar nosso
rótulo três D para lá. E em nosso objeto de jogo, vamos mudar
o nome do jogador e
o nome dos tanques inimigos
para valores apropriados. Como já temos, já que já temos uma
referência ao nosso jogador, podemos simplesmente pegar a propriedade do rótulo do nome do tanque e definir seu texto
igual ao jogador. E então pegamos nosso
tanque inimigo da mesma forma
que fizemos quando nos conectamos como sinal e fazemos
exatamente a mesma coisa. Mas com o número apropriado
de períodos, vamos lá. Agora você pode ver que
o jogador tem um poço, tanto o jogador quanto o
tanque inimigo têm uma etiqueta acima deles. Agora,
percebi, ao brincar com
a construção,
que há algo
na inteligência
artificial do
usuário dos tanques inimigos inteligência
artificial do
usuário dos tanques inimigos que está causando
um loop infinito Então você deve ter
notado isso sozinho. Vou investigar isso
e, antes de prosseguirmos
para a próxima lição, vou corrigi-lo
e depois dizer a vocês mesmos
como consertá-lo
antes de continuarmos Mas esse é o fim
do capítulo nove. Então, apesar desse
bug, muito bem.
28. Menu inicial: Bem vindo de volta. Conforme prometido, depurei um pouco o sistema de
pontos de navegação e descobri que
basicamente não tínhamos pontos de navegação
suficientes dentro da faixa de movimento
do tanque, de modo que, quando ele chegava a um ponto
em que só podia selecionar um
ponto específico, ficasse E nunca queremos
que isso aconteça. Então, adicionei alguns
pontos extras
no mapa apenas para evitar
que isso acontecesse. modo geral,
você deseja ajustar sua camada
de pontos de navegação que os objetos não
se movam uns pelos outros, e também haja pontos
suficientes para que ela
não fique presa assim. Uh, eu também forneci
um pouco de código
extra na função get
random NabPoint, basicamente, e isso nunca deve acontecer se você configurar seus pontos de
navegação corretamente Mas se chegar ao
ponto o tanque só tenha um
ponto para escolher, ele basicamente ficará preso
próximo ao ponto em que está mais próximo e não tem outros
alvos para onde ir. Então, imprimi um aviso e defini o ponto de navegação que ele selecionaria igual
ao NavPoint existente
mais próximo E essa não é a solução
ideal, mas evita que o
jogo seja bloqueado E nesse ponto,
você perceberá que
algo deu errado e precisará adicionar mais
alguns nós à sua grade de navegação. Ok, com isso esclarecido, vamos agora falar sobre o que
estamos aqui para
falar no Capítulo dez. Nesta lição,
vamos começar a
aprimorar nosso jogo e adicionar todos os
componentes semelhantes a ele que o
tornarão um jogo e não
tanto um E a primeira coisa
que
precisaremos é de um menu Iniciar. Então, é claro,
voltaremos à nossa cena de jogo. E já
temos uma interface de usuário no jogo, o que é ótimo, mas agora podemos
adicionar uma interface de início de jogo a ela. E vamos ser bastante
simples e preguiçosos em relação a isso. Basicamente, vamos deixar
a cena principal do jogo
lidar com todos os componentes internos e externos da interface do usuário e simplesmente ligá-los e desligá-los
conforme necessário, em
vez de mudar para cenas externas. Para um jogo maior e mais
complicado, isso definitivamente
seria uma boa ideia, mas estamos mantendo as coisas simples. Então, se adicionarmos um nó filho, poderíamos adicionar um controle,
mas, em vez disso,
adicionaremos um contêiner de painel. E o que é um contêiner de painel? Um contêiner de painel
é um contêiner semelhante aos contêineres VBox, H box e margin
que usamos anteriormente No entanto, ele contém
uma imagem de fundo que será dimensionada com base
no tamanho do seu controle. E podemos mudar
essa imagem de fundo
para que ela realmente
pareça com algo texturizado Mas para o que estamos fazendo aqui, padrão
é um fundo preto
semitransparente, e é
exatamente isso que queremos, porque basicamente queremos que o jogo desapareça quando
o Então, podemos fazer isso completamente e
obter o que temos lá.
Vamos renomeá-lo. E, novamente, verifique se você está
nas duas guias D ao
editar interfaces de usuário. Então, agora vamos usar
outro novo contêiner, e este é chamado
de contêiner central. E o que um contêiner
central faz? Um contêiner central pega
tudo que está dentro dele, o comprime até o menor tamanho
possível
e, em seguida, o força a ser
centralizado em qualquer
controle ao qual esteja conectado Então, neste caso, ele está
anexado ao menu Iniciar, então ele vai centralizar todos os controles dentro
dele. Por aqui. E
manterá essa força nesse tamanho específico, independentemente do tamanho para tamanho específico, independentemente do tamanho o qual redimensionamos
o menu Iniciar Então, dentro do nosso contêiner central, vamos usar nosso bom
amigo, o contêiner VBox, e dentro dele,
vamos adicionar um rótulo Esse rótulo será o título
do nosso jogo, que é Zone Battle. Garantiremos
que esteja centralizado, mesmo que a fonte
que estamos prestes a usar não esteja muito bem
centralizada O tamanho da fonte será 100, e a fonte em si será
nossa amiga, o estêncil Então, em vez de
localizá-lo aqui, podemos simplesmente acessar o
Quick Load, já que o
carregamos antes, e
clicar nele aqui
e, pronto, temos um estêncil Agora, vou
te mostrar um truque muito legal. Na pasta do seu projeto, forneci uma textura de camuflagem com um
nome muito horrível E vamos usar isso para um efeito especial em nosso título. Então, a primeira coisa que
vamos fazer é adicionar uma textura destruída como filha de nossa etiqueta E também vamos renomear esse rótulo apenas para que possamos ou
apenas para sabermos o que é E nossa textura estragada, precisamos que seja do
tamanho da nossa etiqueta Então, como observamos anteriormente, como é
filha da etiqueta, se dissermos totalmente
destruída, ela se forçará a atingir o
tamanho da Agora precisamos
fornecer uma textura. Então, vamos arrastar nossa textura
de camuflagem até o slot de textura,
e agora ela está muito grande. Então vamos para o modo de expansão
e dizemos Ignorar tamanho. Infelizmente, está esmagado. Então, mudamos o
modo de alongamento para ladrilho e agora parece muito bom. Mas vamos invertê-lo um pouco só para ver se podemos obter uma orientação um
pouco melhor Uh, também podemos
mudar isso para Sim, isso não vai
funcionar. A, é Tile. Ok, isso parece muito bom. E agora aqui está a parte chique. Se descermos,
voltamos para se
selecionarmos novamente o título do jogo e
diminuirmos para a visibilidade, temos uma opção
chamada Clip Children E se mudarmos isso para apenas um
clipe, quão legal é isso? Ele prende a
textura subjacente ao próprio rótulo. Agora, é claro, não é
perfeito porque alguns
desses valores obscuros meio
que obscurecem um pouco, mas podemos mudar a cor do nosso plano de fundo
masculino inicial acessando estilos substituídos por temas
e mudando
para um
novo estilo box flat,
que tem uma que Então, vamos mudar isso
e torná-lo mais escuro. E também vamos soltar um
pouco
o Alpha para que possamos ver o
fundo através dele. Isso não vai resolver
nosso problema perfeitamente. A escuridão do E
ainda existe um pouco,
mas, você sabe, parece
muito boa de qualquer maneira. Na verdade, não tente isso. Vamos movê-lo para, tipo,
um peixe verde mais escuro. Sim, não é perfeito, mas parece um pouco
melhor. Eu não sei De qualquer forma, não posso dizer isso de verdade, perto o suficiente. Você entendeu a ideia. Então, a partir daqui, precisamos
adicionar mais alguns itens. Queremos deixar o jogador
configurar o número de tanques
inimigos com os quais ele
começa o jogo. Então, para fazer
isso, precisamos
adicionar outro contêiner HBox, que fornecerá outra
linha para trabalharmos E dentro desse contêiner HBox, novamente, vamos
adicionar um rótulo E esse rótulo
vai dizer inimigos. E, claro, teremos que
mudar a fonte
e o tamanho da fonte. Vamos transformar a fonte em 50 e faremos outro
carregamento rápido para recuperar nosso estêncil. Também poderíamos definir um tema
aqui para usar no menu, mas como
vamos alterar apenas o texto
e é apenas um item
extra a ser alterado, normalmente temos que
colocar o tema no rótulo de qualquer maneira. Então, qual é a diferença
entre colocar um tema
na etiqueta e soltar a fonte e o tamanho da fonte
na etiqueta, sabe Então, além
disso, precisamos ter outro elemento no
contêiner HBox, e esse é
chamado de caixa giratória E também o faremos, então não
queremos a caixa giratória aqui. E, na verdade, agora que
estou vendo,
é quase completamente
invisível contra o pano de fundo verde, então
vamos mudar isso novamente. Mas com o rótulo destacado, vamos ao dimensionamento do
contêiner do layout E então temos valores horizontais e verticais aqui. Portanto, em geral, um controle só
ocupará o espaço necessário. E isso pode ser alterado. E uma forma de alterá-lo
é clicando em Expandir, que significa que ele ocupará o máximo de
espaço
possível dentro do espaço disponível. Então, nesse caso, o
contêiner VBox que estamos usando só será tão largo
quanto o texto do título Isso significa que temos muito espaço disponível para trabalhar. E então, é claro,
verticalmente, o
HBox será tão
alto quanto o texto e o
controle, o que for Mas falando horizontalmente,
se não fizéssemos isso
, nenhum desses objetos ocuparia toda a
largura do controle, o que é bom, mesmo que
o controle ocupe toda
a largura
do controle pai Então, o que queremos
fazer, como vimos, é ampliar isso para que
ocupe todo o espaço disponível e nos deixe
a
pequena caixa giratória ali mesmo Agora, infelizmente,
a única parte da caixa giratória que podemos alterar é a cor do
texto e os botões de seta. E só podemos fazer isso
por meio da definição do tema, o que é meio desagradável Então, vamos
deixar como está. Mas faremos algumas alterações na própria caixa giratória. Vamos
mudar o alinhamento do texto para o centro
e vamos
mudar o valor
mínimo para um, e vamos
mudar o valor
mínimo para caso contrário,
seria um jogo chato E vamos
alterar o valor máximo para sete porque isso é
quase o máximo que nosso mapa
pode suportar confortavelmente Sempre poderíamos mudar
isso se quiséssemos, e faremos o arredondamento
para que ele inclua apenas valores
inteiros inteiros O valor é um, o valor máximo é sete. Ok, isso parece bom. Agora vamos mudar essa cor novamente porque ela não está
funcionando para nós agora. Eu sempre faço isso.
Eu sempre tento arrastar as setas em vez
do OK, é um pouco mais parecido E, finalmente,
precisaremos de dois botões. Então, adicione o nó filho novamente e usaremos um botão. O primeiro botão
será nosso botão para iniciar o jogo. E vamos renomeá-lo como tal. É sempre uma boa ideia
renomear seus controles importantes da interface
do usuário,
porque, como você pode ver aqui,
a hierarquia da interface do usuário tende a ficar muito
confusa muito rápido Por isso, é sempre bom poder
ver o que você está fazendo
a qualquer momento. E adicionaremos mais um botão. E este nos permitirá
sair do jogo. Deus me livre E agora, é claro,
teremos que
acessar as substituições
e alterar as fontes novamente Portanto, o tamanho da fonte é 50. A fonte em si é,
novamente, estêncil. E então faremos o
mesmo para começar. Se estivéssemos fazendo
algo
mais complexo do que apenas mudar a
fonte e o tamanho, eu definitivamente já teria
criado um tema. Mas, sim. Tudo bem. Então, esta é a nossa tela de título. E na próxima lição, vamos utilizar o que
aprendemos aqui para criar uma tela de pausa que aparecerá
no meio do jogo E então, na
lição seguinte, nós os
conectaremos ao código para
que funcionem. Te vejo lá.
29. Menu de pausa: Bem vindo de volta. Nesta lição, vamos construir um menu de pausa que podemos usar para
pausar o jogo Como você deve ter adivinhado, nossa interface de usuário está ficando
um pouco confusa aqui, então vamos clicar
no globo ocular ao lado do menu Iniciar para desativar sua visibilidade Agora podemos trabalhar sem impedimentos. Vamos adicionar
outro nó filho. E este
será um contêiner central. E a razão pela qual queremos um contêiner
central é porque nosso menu de pausa não
ocupará toda a tela Então, queremos que ele seja centralizado
no centro da tela. Então, se fizermos o Full Wrecked aqui,
mudaremos isso para o menu de pausa Agora, dentro disso, vamos usar outro contêiner de painel. Agora, é claro,
observe que você não consegue ver o contêiner do painel,
porque, como mencionei na lição anterior,
o contêiner central comprime tudo até seu tamanho mínimo
absoluto Portanto, há duas maneiras de corrigir isso. A primeira é que podemos usar
o layout e transformar. Não, não está em transformação. Está sob o layout.
Tamanho mínimo personalizado. Se mudássemos isso
, você pode ver que o controle
estaria impondo um tamanho mínimo
absoluto, mas não precisamos fazer isso Clique aqui e redefina-o para zero, porque
tudo o que
vamos colocar dentro
do contêiner
do painel será dimensionado para nós. Dessa forma, não
precisamos nos
preocupar em reajustar esse
tamanho mínimo personalizado toda vez que
alteramos o tamanho do contêiner do
painel Então, a primeira coisa que
vamos adicionar é um contêiner de margem. E, como mencionamos anteriormente, um contêiner de margem
literalmente fornece a capacidade adicionar margens
à periferia
do nosso conteúdo existente, que se ajustarão quando realmente colocarmos algumas coisas lá, porque na
verdade
existem maneiras de lidar com
essa bobagem, em que a fonte
do estêncil que estamos
usando é um pouco desajustada fonte
do estêncil que estamos
usando é usando Não podemos fazer nada
sobre isso nos botões, mas podemos fazer
algo sobre isso no cabeçalho
do menu, para o qual
vamos usá-lo. Vamos adicionar
outro nó filho, e este será
um contêiner VBox E dentro do contêiner VBox, vamos
adicionar outro rótulo E, claro, esse rótulo
vai dizer Menu de pausa. E vamos centralizá-lo,
e depois vamos descer para os hemovídeos, é claro, o tamanho
da fonte será 45 e a fonte, novamente, é Parece meio decente. Agora, vamos
ficar um pouco sofisticados e vamos
pegar um novo tipo de controle chamado
separador H. E o separador H é incrivelmente útil
porque basicamente fornece a capacidade de adicionar linhas que
separarão seu conteúdo, e você pode controlar a aparência dessas linhas
de várias maneiras diferentes Então, a forma como
vamos fazer isso é usar o modo novamente, e vamos mudar
o estilo do separador,
e será
um novo estilo de linha,
que é um tipo de estilo que ainda não
vimos E então, ao abri-la,
a cor da linha, vamos
mudá-la para branco para que corresponda ao nosso texto. E vamos dar a ele uma espessura de dois,
porque não? E vamos mudar as margens
do conteúdo. E vamos mudar
a margem de conteúdo superior para cerca de 16. E, como você pode
ver, ele aumenta. Mesmo que o controle
esteja tecnicamente aqui, ele eleva as linhas
para que
pareça que está mais próximo da nossa fonte E agora que temos isso agora que temos
a fonte aqui, podemos realmente alterar nossas margens um pouco que pareçam um pouco melhores Então, se voltarmos ao
nosso contêiner de margem e usarmos as constantes de
Themoides, agora
podemos alterar as Então, vamos começar com uns bons
dez pixels em todos os lugares, e isso parece
muito bom até agora. Assim, podemos ajustá-lo ainda mais quando tivermos
nossos outros botões e
adicionaremos três novos botões. Ou vamos
adicionar dois novos botões? Acho que vamos
adicionar dois novos botões. Originalmente, eu estava pensando em sair do desktop, mas podemos sair do título. Portanto, nosso primeiro botão
será simplesmente um botão de zoom, que nos levará de
volta ao jogo, e nosso segundo botão
será um botão para sair do título. Então, é claro, o
Zoom vai dizer, Zoom, e sair do título
vai dizer sair do título. E agora, aqui está um truque
muito inteligente. Se você pressionar a tecla Control e clicar com o botão
esquerdo para
selecionar vários nós, se eles tiverem
propriedades em comum, você poderá alterá-los todos de uma vez. Então, com esses dois selecionados, agora
vamos até
eles durante viagens, e podemos alterar
as fontes e os tamanhos das
fontes sem precisar
fazer isso individualmente Então, carga rápida, estêncil. Boom, quão legal é isso?
E agora vamos até aqui. E vamos com 40. Parece que está certo. E clicaremos
duas vezes aqui
para recentrá-lo. E isso realmente
parece muito bom. Uh, as margens são, as margens são boas. Ok. Esse é o nosso menu de pausa. Assim, podemos clicar na
visibilidade para ocultá-la. E agora, na próxima lição, vamos
conectá-lo ao código e adicionar a capacidade de
iniciar e pausar o jogo E sim, te vejo lá.
30. Gerenciador de jogos: estados de início/fim: Bem vindo de volta. Nesta lição, escreveremos
o código que
conectará nossos menus de início
e pausa, bem
como adicionaremos a
habilidade de o jogador
morrer e ser expulso de volta ao menu Iniciar para
que ele possa tentar Para fazer isso, porém, precisamos configurar um
pouco de estrutura. Então, a primeira coisa
que precisamos fazer, obviamente, é criar scripts para
o menu de início e de pausa E agora que nossa pasta de scripts está ficando um pouco confusa, adicionaremos uma nova pasta para
colocar nossos scripts de interface nela E também devemos criar referências ao nosso menu inicial e nosso menu de pausa em
nosso jogo E, obviamente,
queremos que o menu
Iniciar seja exibido quando
o jogo for carregado pela primeira vez. Portanto, no método pronto
para nosso objeto de jogo, podemos fazer com que nosso
menu inicial se mostre. Agora, temos um pequeno problema. Mesmo que o
menu Iniciar esteja sendo exibido, o jogador ainda pode se mover e o tanque inimigo ainda
pode se mover. E isso ocorre porque,
na verdade, não pausamos nenhum processamento que
aconteceria enquanto o jogo em execução porque o
menu está sendo exibido E queremos fazer isso
tanto para o menu de pausa
quanto para o menu iniciar Agora, poderíamos examinar os métodos de processo nossos tanques, de nosso
jogo e de todo o
resto e da entrada de teclas
não manipulada e, basicamente, verificar
se algum dos
menus está sendo exibido e seguida, retornar
prematuramente dessas funções Mas isso dá muito
trabalho. E a marca de um bom programador de jogos é uma
maior sensação Então, o que vamos fazer
é usar o que é chamado de
propriedade pausada da árvore de cenas Opa. Também
vamos matar um monte de carneiros
aleatórios que não
têm absolutamente nada
a ver com o que estamos
fazendo. Tudo bem. Então, para ter
acesso à árvore de cenas, usamos o método get tree. E há uma propriedade da árvore
de cenas chamada pausada. Agora, se definirmos como verdadeiro, isso significa que nenhum
processamento ocorrerá. Então, agora, se fôssemos
rodar nosso jogo, você pode ver que absolutamente
nada está acontecendo. Se eu pressionar qualquer uma das teclas, o jogo não funcionará ou o
tanque não se moverá. O único problema é que, se
eu clicar em qualquer um dos dois, quero dizer, ainda não
colocamos nenhum
código por trás deles, mas deixe-me fazer isso
para fins de ilustração. Então, vamos ao nosso menu Iniciar e conectaremos
o botão de saída,
e faremos isso
indo até a
guia de sinais e obtendo
o sinal pressionado. E se clicarmos em Ir para a fonte
, ele irá direto
para o objeto que está transmitindo o sinal Queremos rolar um
pouco para cima porque, na verdade queremos anexá-la ao script
do menu Iniciar. Agora, digamos que
imprima, pare de pressionar. Então, agora, se tentarmos sair
para o desktop, você notará que
não estamos vendo nada nosso lado aqui, do nosso lado aqui,
e isso porque, é claro,
nossa interface de usuário também
não está sendo processada. Então, a maneira de mudar
isso é clicar no
componente da interface do usuário, o controle. E isso funciona para
qualquer nó, na verdade, mas só vamos usá-lo
para nossos menus de início e
pausa E você quer
entrar em processo. E então mudamos
o modo do processo de herdar para sempre E isso significa que, mesmo que
a árvore de cenas seja pausada, esse objeto
continuará sendo processado Então, agora, se começarmos
nosso jogo novamente e tentarmos
sair, você verá que o método de encerramento pressionado foi acionado e a mensagem
apareceu no console. Então, para sair do nosso jogo, só
precisamos obter uma
referência à nossa árvore. E então simplesmente diga “desista”. Agora, em um jogo mais sofisticado, você gostaria de adicionar um diálogo que diz: Você
realmente quer sair Sim ou não.
Na verdade, você deve ter ferramentas
suficientes à sua
disposição para criar uma. Então, se você decidir que quer fazer um pouco
mais de programação para aprender, eu pediria que nesta lição você
adicionasse uma caixa de
diálogo de confirmação que aparece quando o botão de saída é pressionado e só sairemos do jogo se
o botão sim
do diálogo confirmado
tiver sido pressionado Então, agora também queremos
conectar o botão Iniciar. E podemos muito bem
fornecer os dois menus, nomes das
classes e soletrá-los
corretamente, é claro E, claro, também
queremos conectar
os dois botões no menu de
pausa E no caso do menu de
pausa, queremos retomar o
jogo quando ele for retomado Então, naturalmente, neste caso, vamos
retomá-lo e, na verdade, precisamos definir o processo em nosso
menu de pausa para sempre Então, é claro, quando retomamos, pausa é igual a falsa e ocultaremos o menu de pausa Agora que temos nossos
stubs todos conectados, precisamos realmente adicionar
funcionalidade a eles Portanto, no menu Iniciar, temos nosso método
pressionado pelo botão Iniciar. E, como você pode ver, o menu Iniciar é
filho do jogo, e
precisaremos que o jogo
reaja ao botão do menu Iniciar pressionado, porque queremos que o jogo faça toda
a contabilidade necessária para iniciar o jogo quando esse botão for
pressionado Godot tem um lema que é uma diretriz para ditar como pais e filhos devem interagir E essa diretriz é
chamada de call down signal Up. Isso significa que
o jogo pode manipular
o menu Iniciar diretamente, como
vimos aqui ao chamar o método
Start Men's show, mas o menu Iniciar
deve enviar um sinal e permitir que outros nós decidam
o que fazer com ele E como o jogo é o
pai do menu Iniciar
, ele naturalmente reagiria a esse sinal, porque estamos essencialmente subindo
na hierarquia Portanto, o menu Iniciar deve disparar um sinal para
o jogo reagir. Agora, o problema é
que o jogo será pausado quando o
menu Iniciar for exibido, então o menu do jogo não será
realmente capaz de reagir Então, na verdade,
temos que fazer duas coisas. Na verdade, temos que
colocar uma pausa da árvore no próprio objeto do
botão Iniciar, o que é bom E então temos que enviar
uma mensagem para que o jogo e quaisquer outros objetos interessados saibam que um novo jogo
foi iniciado. E então faremos isso.
Temos uma árvore pausada, igual a falsa E então entraremos em nosso mensageiro e
definiremos um novo sinal. Mamãe, hmm. E nosso menu Iniciar
disparará esse sinal. E, na verdade, outra coisa que ele precisa fazer é se esconder. Então, atualmente, o jogo realmente
não fará
nada quando o jogo começar, mas conectará
o sinal de qualquer maneira. Oh, fiz isso errado.
É conectar Como eu disse,
agora, não faz nada. Então, vamos ver se isso
realmente funciona. Opa, temos um erro. E eu já me deparei com
esse erro antes. Não tenho certeza do
que se trata, mas basicamente o que está acontecendo
é que, por algum motivo, o NavPoint
fica nulo quando o tanque sai
do estado ocioso,
e isso é e isso é Então, se voltarmos ao
nosso estado de caça, se o
objeto monitorado estiver ocioso, verificaremos se
há um NavPoint Obteremos o NavPoint e seguida, o
objeto monitorado ocioso será Mas isso pressupõe que
isso realmente funcione. Agora, se isso não funcionar,
chegará ao
ponto em
que presume que o NaPoint foi definido Então, o que temos que
fazer aqui é fazer uma pequena
salvaguarda que diz: se os objetos monitorados mais próximos do
NavPoint forem iguais a nulos, bem, na verdade, não,
não precisamos fazer isso Vamos fazer isso aqui em cima. Portanto, se os objetos monitorados
mais próximos do NaPoint não forem nulos, pode definir idle Caso contrário, no próximo
ciclo, queremos tentar novamente. Agora, também é possível que precisemos ajustar nosso nível de
navegação novamente. Vou analisar isso com mais
alguns testes após esta aula para
ver se é esse o caso. Mas isso definitivamente
nos salvará de alguns problemas, porque se o
tanque nunca realmente se mover, então sabemos
que esse é o problema. Isso não é capaz de
encontrar um ponto Av. Isso pode ser apenas
uma falha que tem algo a ver com a pausa do
jogo. Mas sim. Então, vamos voltar a isso, e veremos se isso
funciona, e deveria. E ele e o tanque inimigo estão
se movendo e assim
por diante. Tudo bem, agora queremos abrir o menu de pausa quando a tecla
escape é pressionada, e atualmente estamos inserindo todas as teclas na entrada de teclas
não manipuladas do jogo, mas também podemos fazer isso
no Se a memória serve apenas porque não está visível,
não significa que não receberá eventos de pressionamento de teclas Então, vamos testar essa teoria. E se eu estiver errado,
então vamos colocá-lo onde
originalmente íamos colocá-lo. Se a entrada for pressionada por uma tecla física, escape e não
estiver visível, queremos pausar o jogo e simplesmente fazer isso
novamente obtendo a árvore, pausando como igual a verdadeiro Ok, acabei de perceber que
acabei de perceber um pequeno bug. Portanto, ainda não estamos verificando se o
jogo está rodando. Então, se eu clicar em Escape agora,
teremos um menu de pausa.
E nós não queremos isso. Então, só queremos que isso
aconteça se não estiver visível, mas também,
na verdade, em vez de, se não estiver visível, vamos verificar se a árvore já
foi pausada Se a árvore não estiver pausada
, queremos fazer isso. E lá vamos nós.
Então, agora vamos começar o jogo e agora podemos fazer uma pausa Então, já manuseamos
nosso botão Zoom,
então, em seguida, temos que usar
nosso botão de sair para o título E, claro, a maneira
mais fácil de fazer isso é adicionar outro sinal. E emitiremos esse
sinal do nosso menu de pausa. E queremos que o
menu Iniciar monitore esse sinal. Tudo bem Onde está meu
começo? Aí está. Portanto, no método pronto do nosso menu Iniciar, nos
conectaremos a ele. Na verdade, podemos fazer um
pequeno atalho aqui. Então, o que
faríamos é fornecer um nome de
função aqui
e, em seguida, fornecer
uma função aqui embaixo. Mas tudo o que a função fará é simplesmente mostrar
o menu Iniciar, e há uma maneira muito
mais rápida de fazer isso Vamos usar o que é
chamado de função Lambda. E uma função Lambda
é literalmente apenas uma função definida
em linha sem um nome Portanto, podemos fornecer uma definição completa
da função aqui, em vez do nome da função. E fazemos isso
simplesmente fornecendo a palavra-chave funk e os argumentos da função,
como faríamos aqui, mas não damos um nome a
ela e, em seguida simplesmente
adicionamos o
código Então, neste caso, o código literalmente será apenas
para mostrar o menu Iniciar. Agora, estamos em pausa
ou estamos no menu Iniciar. E vamos para Start.
O jogo está rodando. Pausa. Saia do título. Esqueci de esconder o menu de pausa. Mas, sim, é
assim que isso funciona. E agora, se estivéssemos bem, não
poderíamos jogar um novo jogo porque
o menu de pausa ainda está Tudo bem, então pare com o título, emita. Esconda-se E agora
devemos ser dourados. E nós somos. É muito legal. Tudo bem, quando sairmos do título, saímos do desktop. O jogo acabou. Ok, agora que podemos ter um menu
iniciar e um menu de pausa, precisamos configurar os estados do jogo de forma
que o jogo saia o jogo mostre uma
mensagem e depois volte ao menu inicial
depois que o jogador morrer E, novamente, a
maneira mais fácil de fazer isso é fornecer uma função global. Na verdade, não,
o tanque ainda não tem? Não, fizemos isso, fizemos
isso com casca. Bem, podemos colocá-lo aqui. Assim, podemos fornecer um sinal de quando um tanque
foi destruído. E se abrirmos
nosso script de projétil, já que já estamos lidando com
a colisão do tanque aqui, sim, poderíamos fazer isso Nós podemos fazer isso aqui. Podemos fazer isso aqui ou
podemos fazer isso dentro
do método hit. Qualquer um deles é
perfeitamente aceitável. Mas se nós realmente,
você sabe o que? A maneira mais lógica de fazer isso. Desculpe, eu continuo
pulando por aqui. Mas se voltarmos para o tanque, teremos uma
variável destruída e, mais uma vez, setters Destroyed é igual Messenger, na verdade, precisamos mudar isso
porque é para qualquer tanque. Tanque mensageiro
destruído, emitido por si mesmo. Self é uma palavra-chave especial que indica o objeto que está executando o script no momento. OK. Sim. Ajuda se eu soletrar as coisas corretamente.
Estrondo. Lá vamos nós. Ok, agora, novamente, o único
tanque cuja mensagem nos
importa é o tanque do jogador. Embora isso seja realmente
meio redundante, já que em nosso tanque inimigo,
temos, uh hein OK. Tudo bem. Sim, temos alguns sinais
redundantes aqui, que normalmente você quer
evitar, mas neste caso, queremos diferenciar
entre o tanque inimigo
e ser destruído e
apenas um tanque em geral
sendo destruído em geral Então, neste caso, queremos nos conectar ao método de destruição de tanques do
jogador. Embora, você sabe,
se for esse o caso, não
precisemos colocá-lo aqui. Porque já temos
vários sinais aqui. E então vamos voltar
aqui e está um pouco
destruído. E então, dessa forma, o
jogo pode se conectar
ao método destruído do jogador. O que desencadeará o final do jogo. E, claro, isso
significa que precisaremos de um pouco mais de interface de usuário. Então, vamos criar isso agora. Vamos ao jogo, e isso realmente
fará parte da interface do usuário. Então, podemos jogar isso aqui. Será um contêiner de painel, vamos
torná-lo um contêiner. Sim. Será
do tamanho mais ou menos, e vamos centralizá-lo,
o que é outra forma. Essa é outra maneira de
centralizar as coisas além usar um contêiner central No entanto, se você alterar o tamanho posteriormente,
precisará recentrá-lo Então, se eu for assim,
agora está errado,
então eu teria que recentrá-lo então eu teria que recentrá-lo Diálogo de fim de jogo. Etiqueta do nó filho. Na verdade, não. Queremos um painel, queremos
um contêiner de margem. Vou aumentar um pouco essas
margens. Constantes de Themoides. Vamos dar a todos eles quinze. Recipiente de margem. Rótulo. O alinhamento horizontal agora
está centralizado. E eles substituem. Carregue rapidamente nossa fonte de estêncil, altere o tamanho do
texto para muito maior Lá vamos nós. E agora podemos adicionar o código para fazer isso e
pausar por alguns instantes e depois
voltar ao menu Iniciar Então, é claro,
precisaremos voltar ao nosso jogo e exportar
outra referência. Tudo bem E quando o diálogo do game
over é exibido, precisamos pausar o jogo
e terminar o jogo após,
digamos, cerca de 2 segundos. Então, no método
destruído por um jogador, usamos a palavra-chave Awet E o que isso significa
é que ele vai
pausar o processamento desse script em particular,
neste caso, do jogo até qualquer sinal que
você indicar seja disparado Então, o que queremos fazer é pegar nossa árvore
e
chamaremos Create Ti, que é
o equivalente a
criar um nó temporizador, como fizemos
com o cronômetro de recarga dos tanques, mas é meio que feito de forma Basicamente, ele cria
um novo nó temporizador e o anexa à árvore principal com esse número de atraso de
contagem regressiva em segundos
e, em seguida, e, em seguida E queremos indicar
que estamos
aguardando o
método de tempo limite ou o sinal de tempo limite desse cronômetro, que é chamado quando
o cronômetro acaba E também queremos
conectar a esse sinal nosso método de manipulação de
final de jogo. Agora, infelizmente, isso
não congela o jogo. Isso não faz com que a árvore de
cenas seja pausada, como fizemos
para pausar o jogo E queremos isso porque
não queremos pausar o jogo porque se pausássemos
o jogo
assim que o
diálogo do game over surgisse
, isso interromperia a
reprodução do som Então, o jogador morreria. O som da explosão ocorreria. Mas então o diálogo
surgia e a árvore fazia uma pausa e não
ouvíamos realmente a explosão É por isso que não queremos
fazer nossa chamada universal de árvore
igual pausada por pontos Getree quando
destruímos o jogador No entanto, precisamos colocar algumas
salvaguardas em jogo para evitar que as coisas aconteçam enquanto o jogador
estiver morto, porque,
por exemplo, se não mandarmos os tanques inimigos pararem de
atirar no jogador morto, eles continuarão atirando nele, que só piora a
injúria Então, no estado de disparo, corrigimos isso, em vez de disparar
incondicionalmente um projétil, adicionamos uma verificação para ver se o objeto monitorado,
que é, obviamente, o tanque inimigo, se é
o alvo,
que é o jogador, está destruído ou se
não foi destruído, não destruído, então
disparamos E se for destruído,
nós o ignoramos. Também precisamos corrigir um pequeno bug
no setter destruído do nosso tanque porque o que estava acontecendo aqui era que estávamos emitindo o sinal destruído, independentemente do status da variável
destruída E só queremos admitir o sinal destruído quando o tanque
foi realmente destruído, que significa que quando destruído
é igual a verdadeiro. Então, fizemos um cheque aqui. E a razão pela qual isso
importa é que se o jogador
morresse e nós
voltássemos ao menu principal
e depois
voltássemos para começar um novo jogo, o
jogador ainda estaria morto. Então, agora no início do jogo, adicionamos um jogador destruído
Eagles False para o jogador em um estado ativo para que possamos jogar um novo Infelizmente, nenhuma
das outras variáveis que definimos será igual ao
que foi redefinido. Assim, o jogador manterá sua
antiga contagem de mortes e tal. E podemos realmente mudar isso. Então, se usarmos a UI, Kill count, podemos
redefinir isso para zero. Também pode ser uma boa ideia
simplesmente Sim, vamos fazer isso. Portanto, uma ideia melhor é,
na verdade, fazer com que a contagem de mortes ou a interface do usuário se conecte
ao método de início do jogo. Porque várias coisas podem
se conectar ao mesmo sinal. E, na verdade, não
queremos fazer isso aqui. Queremos fazer isso dentro da própria
interface de usuário
, pois isso mantém tudo
independente. Então, mensageiro, inicie o jogo, conecte-se ao Iniciar jogo. E então, no jogo OnStart, queremos reduzir a
contagem de mortes para zero Agora, infelizmente,
as posições iniciais dos tanques dos jogadores e dos tanques
inimigos não
serão redefinidas, mas vamos corrigir isso
na próxima lição, quando implementarmos
um sistema de desova real Agora, deixe-me ter certeza de que não
estou esquecendo nada. Portanto, o estado de disparo é bom. O tanque destruído é bom. Fizemos nossas coisas no jogo. Então, é claro, vamos conectar o final do jogo
e, no final do jogo,
ocultar o jogo sobre o
diálogo e simplesmente emitir o sinal de saída para o E, claro,
precisamos congelar o jogo novamente quando ele voltar
para a tela de título, e acho que não
fiz isso. Vamos verificar. Ok, jogo de carrinhos. Deixe o inimigo me matar. Ok, então
o jogador não vai se mover, mas como você pode ouvir,
na verdade não pausamos a árvore Então,
precisaremos fazer isso. Então, no final do jogo, deixamos o
Messenger para Title Amit. Isso significa que
o jogo Bem, o menu Iniciar se conectou
rapidamente ao Title it Funk Show E aqui, então,
na verdade, queremos adicionar outra linha ao nosso Lambda aqui, que pausará a árvore Assim, podemos formatar isso um pouco melhor simplesmente
pressionando Enter Godot não vai se importar. E então faremos Get
Tree Almost equal true. E isso deve
resolver o problema. E isso acontece. OK. Agora que temos, há mais uma coisa que
precisamos fazer, obviamente, e precisamos verificar se o jogador matou
todos os tanques inimigos
e, se o fez, o jogo deve
terminar nesse aspecto. Ou, pelo menos, ele deve reiniciar e reaparecer um
determinado número de tanques Mas não vamos
fazer isso agora. Vamos fazer
isso como parte do
desenvolvimento do gerador de inimigos, o que
faremos na próxima lição
31. Sistema de aparecimento de inimigos: Bem vindo de volta. Nesta lição, vamos codificar um sistema de
geração que vai
lidar com a inserção do nosso jogador
e dos nossos inimigos no mapa Mas antes de começarmos a programar
, precisamos fazer algumas tarefas domésticas Então, a primeira coisa
que devemos fazer é ir à nossa arena e adicionar um novo NavPoint porque também precisamos indicar onde o jogador
aparece Então, já temos
nossa cena do NavPoint e vamos arrastá-la
para a lista Quando estiver lá, vamos
renomeá-lo como player spawn. Vamos usar o nome
do spawn para indicar
que esse é o ponto de desova em que
o jogador deve aparecer Além disso,
queremos mudar a cor
dos pontos de desova que
saibamos que são
especificamente para o jogador Portanto, se clicarmos com o botão direito do mouse
e
selecionarmos Filhos editáveis, agora teremos acesso aos
filhos do objeto Como mencionei em
uma lição anterior, a malha é um recurso
e, como todos os pontos de desova
vêm da mesma cena, todos
compartilham o
mesmo recurso, que significa que se eu
mudar essa malha, isso mudará todos
eles, então não queremos isso Então, expandimos o menu
suspenso e dizemos tornar
único, recursivo E a razão pela qual dizemos recursivo e não apenas tornamos
único é que também queremos que o material dentro da malha
seja único Agora podemos expandir
isso e ir até o material, alterar seu albedo e torná-lo da cor
que você quiser Eu escolhi verde. E então temos que mover o
spawn dos jogadores para outro lugar. Vou colocá-lo
bem no canto do mapa para
que o jogador não apareça em cima dos oponentes E também vou mudar a rotação
do ponto de desova para que possamos indicar
a origem em que o jogador vai
aparecer Então, eles aparecerão no local com
a rotação desse ponto de desova específico E então a próxima coisa
que precisamos fazer é modificar nosso jogo para levar em conta
o fato de que
vamos usar
um nó gerador Então, a primeira coisa que devemos fazer é excluir o tanque
do jogador e o tanque inimigo,
porque o gerador os adicionará à cena E também precisaremos
adicionar um spawner. Além disso,
seria uma boa ideia,
neste momento , subdividir o objeto do jogo na jogável e
na seção de interface
do usuário Então, vamos adicionar um nó filho, e vamos
chamá-lo de playfield, que será do tipo node Node é o tipo de objeto padrão
de
nível mais baixo que você pode ter em Godot E é muito útil
quando você quer dizer, eu quero algo em uma cena, mas eu não quero
que seja nada. Os nós são ótimos para agrupar coisas como estamos prestes a ver Então, renomearemos esse
nó para campo de jogo e arrastaremos a arena para baixo dele de forma que seja
filha do campo de E o campo de jogo também
precisará de um gerador, que também será
um E, claro, o spawner precisará
de um
script E mudará o nome
da classe para spawner. E agora estamos prontos para começar a
criar nosso sistema de spawn. A primeira coisa que precisaremos fazer é detalhar o espaço O gerador precisa
lidar com várias coisas. Ele precisa configurar alguns sinais. Então, é claro,
forneceremos uma função pronta. Isso vai gerar tanques inimigos. E isso não só
gerará o tanque do jogador, mas também
retornará o tanque do jogador ao nodo de chamada, porque queremos poder
colocá-lo no mundo do jogo E não queremos apenas
colocá-lo no mundo do jogo, mas também precisamos
conectar alguns sinais e outras coisas ao objeto do jogo. Portanto, é um pouco mais fácil fazer isso retornando
o objeto do jogador. Mas também podemos passar
o objeto de conexão, que faremos com
os tanques inimigos de qualquer maneira. Agora temos nossos três
métodos e, claro, isso vai
reclamar
porque quer retornar um valor, e ainda não temos um valor Então, agora nós
os temos inseridos. E, claro, precisaremos referências aos arquivos de cena que vamos instanciar,
que, é claro, são o
tanque e o tanque de IA Portanto, o player tank prefab
é um cenário lotado. E o tanque inimigo pré-fabricado também
é um cenário lotado. Também precisamos saber o número
de tanques inimigos que
vamos gerar porque temos esse botão giratório no menu Iniciar E o padrão será um. E isso deve ser
suficiente para começarmos. Então, se entrarmos no jogo, na verdade, devemos
entrar no roteiro do jogo. Então, já temos um monte de coisas aqui que preparamos
para o roteiro
do jogo,
que presume que o jogador e o tanque
inimigo
já estejam em cena
quando o jogo começa Esse não é mais o caso, mas ainda precisamos desse código. Então, em vez de
tentar lembrar de tudo, vamos controlar
K e comentar tudo. E no início do nosso jogo, agora
temos informações que
precisam ser tratadas. Então, vamos passar por aí. E então
voltaremos a isso. Você pode ignorar esse erro
se estiver recebendo. É algum tipo de
inseto estranho que Godot vomita. Ele não apareceu nas edições
anteriores,
então, presumivelmente,
será corrigido Isso não afeta nada do
que estamos fazendo agora. Ok, então no spawner,
o que precisamos fazer? Bem, novamente, precisamos
gerar o tanque do jogador, e a maneira mais fácil
de fazer isso, é claro, é
criar um novo Então, o jogador
vai ser um tanque. E
será uma instância do
player tank prefab Portanto, o player tank
prefab instancia e, só para
especificar demais,
podemos lançá-lo dizendo como podemos lançá-lo E agora temos uma cópia de um tanque que podemos
usar como nosso jogador. Assim, podemos devolver o jogador. Mas precisaremos
fazer mais do que isso. Também precisaremos fornecer
uma referência ao campo de jogo,
especificamente ao objeto da arena, porque precisaremos ser capazes de
consultar seus pontos de desova E não queremos simplesmente pegar o nó de pontos de desova
diretamente, porque também
precisaremos acessar o
pai da arena Então, vamos fazer da arena A
uma variável aqui. Gerador. Ok, então também
temos que atribuir esses valores. Então, o terreno do campo de jogo será
uma arena. O tanque
pré-fabricado do jogador é, obviamente,
tanque, e o tanque
pré-fabricado inimigo é tanque inimigo Então, entre outras coisas
que temos que fazer pelo jogador,
temos que definir seu nome, sua rotação e
sua posição. Portanto, o nome, tanto o nome do nó quanto o valor do rótulo
são bem fáceis. Se quisermos definir o
nome do nodo, que é o que aparece
aqui na árvore da cena, simplesmente dizemos nome do ponto do
jogador
e o chamaremos de jogador porque se
deixássemos como é para o tanque, seria tanque, e não
queremos isso. Então, queremos indicar
que esse é o jogador. Agora, se você se lembra, o
tanque tem uma etiqueta de três D, que acredito que
chamamos de etiqueta com o nome do tanque, acordo com o preenchimento automático. Ok. Aí está. Etiqueta com o nome do tanque. Então, sim. O texto também é igual ao jogador. Em seguida, precisamos obter o ponto de desova
do qual o jogador vai
desovar E a maneira mais fácil
de fazer isso é
simplesmente ocupar o terreno do nosso
campo de jogo E obteremos o nó
Nav Points. Oh, na verdade, há
uma maneira um pouco mais fácil fazer isso do que eu fiz
originalmente. Então, o que eu fiz na
primeira vez que fiz isso foi pegar
o nó NAV Points
e escrevê-lo corretamente, o
que eu nunca faço nas filmagens que eu nunca faço E então eu usei o método
find child e dei a ele o
nome player spawn Mas não precisamos
fazer isso porque
sabemos que sempre haverá um spawn de
um jogador associado
aos NavPoints, então eu deveria ser
capaz de especificar diretamente
seu caminho dessa forma E saberemos em breve se
isso realmente não funciona, porque veremos um acidente Tudo bem. Depois de
fazer tudo isso , precisamos adicionar o
jogador ao campo de jogo Porque, se você se lembra, não
estávamos adicionando nenhum objeto móvel
à arena, mas sim
à raiz do jogo Quero dizer, poderíamos
adicioná-los à arena, mas eu gosto de manter minhas
malhas de terreno separadas dos objetos
móveis É por isso que temos um campo de jogo. Então, opa. Portanto, o campo de jogo é o
pai do terreno do campo de jogo. Então, nós apenas compramos um
jogador pai-filho. E temos que fazer isso
antes de tentarmos definir a posição
ou rotação do jogador. Se não cometermos um erro, e este é um que não
devemos ignorar. Então, quando o jogador estiver
no terreno do campo de jogo, podemos mudar sua rotação e sua rotação
será
igual à rotação dos pontos de desova E a posição
global do jogador será igual à posição global dos pontos de
desova Agora, se
você usa ou não a posição ou posição
global geralmente
depende dos sistemas de coordenadas em
que você está trabalhando Às vezes importa,
às vezes nem sempre
usa a posição
global apenas para que eu não
tenha nenhuma surpresa rude Mas, você sabe, vamos tentar posição e ver se ela
realmente funciona. Deveria. E agora que tudo isso está feito, podemos voltar ao nosso jogo. E, claro, quando
o novo jogo começa, temos que realmente gerar
o jogador e gerar os inimigos e fazer um pouco mais de inicialização da
configuração antes que o jogo Então, como já
temos uma referência ao jogador em nosso jogo, o que faremos aqui é
dizer que o jogador é igual a Oh, temos um pequeno problema porque não temos uma
referência ao gerador. Então, vamos pegar um desses. Tudo bem, o spater é um nodo, é claro E comentaremos tudo
isso para que
possamos realmente atribuir a
variável de chorar em voz alta Lá vamos nós. Ok, Spanor Estrondo. Agora temos o Spawner Ok, agora podemos
voltar e fazer isso. O jogador é igual ao spawner Dot. Então, na verdade, definimos um nome de classe? Demos a ele um nome de
classe, certo? Sim, nós fizemos. Então, vamos realmente voltar
ao script do jogo que
possamos usar o preenchimento automático Spawner não é um nodo. Spawner é um spawner. Ok, agora vamos voltar aqui, Spawner spawn E assim que tivermos
o tanque do jogador, podemos conectar todos os sinais
deles aqui. Portanto, não precisamos mudar o rótulo
dos tanques dos jogadores. Já fizemos
isso, mas
precisamos conectar
esses três métodos. Tudo bem. E agora, quando
o jogo começar, devemos ser capazes de
ver nosso jogador. E não podemos. ocorre porque nosso
ponto de desova é nulo, o que significa que algo deu errado quando tentei
obter o ponto de desova Então, vamos ver o que eu fiz de errado
aqui. De volta em um momento. E, claro, a
resposta foi que eu tinha o nome errado para o nó
NavPoints na arena Então, no meu
rascunho original do jogo, eu o chamei de NavPoints E então, é claro, era
aí que meu cérebro estava. Mas nessa versão,
para a aula, eu o
chamei de Path nodes. Então, eu simplesmente renomeei o
nó e a vida estava boa. Então, temos mais uma coisa
que precisamos fazer aqui no GameStart para evitar que o jogo
trave e
fique com raiva de E isso é,
claro, configurar o alvo da nossa câmera espiã, porque se você se
lembra, nosso minimapa usa uma câmera secundária
acoplada ao player Então, como removemos o
jogador da cena, precisamos adicionar o jogador de
volta à Spy Cam. Então, a câmera espiã é que não temos uma referência à câmera espiã porque nunca
precisávamos dela antes, então vamos adicionar uma
dessas também. E se você está coçando a
cabeça se perguntando: Ei, é realmente tão comum ter tantas exportações em uma
aula? Sim, sim, é. Em alguns dos estúdios
profissionais anteriores em
que trabalhei, utilizaram Godot Ah, você ficaria
surpreso com quantas exportações tivemos, especialmente no que diz respeito às
interfaces de usuário. Isso foi na época
dos três pontos
O de Godot , quando não era
possível arrastar e soltar Portanto, embora tivéssemos as variáveis
exportáveis, ainda
precisávamos
fazer como getObject com base no nó em cima dela Então, na verdade, foi ainda pior. Há outras maneiras de
acessar os nós diretamente, como usar o nome exclusivo. Mas, na prática, descobri que um nome exclusivo é
quebrado na maioria das vezes. Portanto,
a maneira mais confiável de obter um objeto, independentemente de onde ele esteja, porque especialmente quando você está
desenvolvendo sua hierarquia, você
moverá muito seus objetos Portanto, geralmente não é bom usar caminhos de
objetos, como
fazemos método spawn, para
obter o objeto,
porque as
referências do objeto são atualizadas quando o objeto se move e os caminhos
codificados não Portanto, geralmente é o caso da ferramenta
certa para o trabalho certo. De qualquer forma, nosso espião Cam e eu nunca demos um nome de classe
ao Spicam Aqui vamos nós. Jogo. Câmera espiã. Jogo. Ah, claro, agora que temos
um erro,
vai ser um problema? Bem, sim, isso vai
ser um problema. Tudo bem, deixe-me
recarregar o projeto, e eu estarei de volta em um segundo Ok, através da magia da edição de pós-processamento, agora
estamos de volta. Agora vamos voltar ao contêiner da porta de
subvisualização da interface do usuário SpyCam. Nós arrastamos isso até
aqui para que tenhamos nossa SpyCam e possamos
removê-la agora E então, agora que o
player foi adicionado, SpyCamt Target é
igual ao jogador, e agora tudo deve estar perfeitamente bem do ponto de vista do
jogador E é. Temos um jogador. No entanto, não tenho certeza
se o jogador está realmente surgindo
onde deveria estar Ok, então eu comecei a olhar para esses dois objetos. Bem,
há uma maneira de saber. Se eu girar totalmente, posso ver se estou realmente
no canto do mapa, e parece que não estou Parece que estou
no centro do mapa. Então, vamos voltar para a arena e verificaremos novamente onde está spawn do
nosso jogador E nós o colocamos lá. Verifique a transformação. Ok, vamos voltar
para o gerador. E em vez de posição, vamos colocá-la em posição
global. Esse pode ser um daqueles
casos em que isso realmente importa. Oh, eu vejo o problema. A posição global do jogador é
igual à posição do jogador. Tem o formato de si mesmo,
como diria Shakespeare. Queremos a posição do ponto de desova além da rotação do ponto de
desova Isso deve resolver o problema. Muito melhor. Agora, os jogadores estão
realmente na borda
do mapa a que pertencem. Parece que eles estão voltados para
a direção errada, no entanto. Tudo bem, toque seu spawn. Rotação amarela.
Queremos que seja assim. Provavelmente é uma questão de a
rotação em Y estar acontecendo dessa maneira, mas o tanque
girou para os lados Então, simplesmente giraremos o tanque na direção
oposta Também podemos inverter o
sinal da rotação. Uh, tudo bem. Não sei por que
isso não está funcionando. Deixe em zero, digamos, 180. Ok, isso é melhor. De qualquer forma, você entendeu. Você pode adicionar dados
ao spawn do jogador para alterar a
forma como
o jogador desova Então, agora o jogador
está fazendo seu trabalho. Ele pode disparar projéteis novamente. Mas, na verdade, falando
em disparar projéteis, temos que mudar uma coisa : quando
o projétil é disparado, ainda
o
estamos adicionando ao jogo e não
queremos fazer isso Queremos adicioná-lo ao Playfield. E o campo de
jogo chama Oh, nós não, hein Não adicionamos uma referência
ao campo de jogo. Então, tecnicamente, não
precisamos, pois já sabemos que o campo de jogo
existe no jogo, então podemos simplesmente fazer Coloque um ponto no campo Ad child
e, em seguida, adicione isso
colocará a concha
no local correto Mas você também pode
, obviamente, exportar uma variável do tipo node e, em seguida, arrastar o
campo de jogo para ela Na verdade, isso
seria um pouco melhor. Seria mais eficiente
porque ainda há alguma sobrecarga quando você
obtém o node. Então, faremos isso. O. Ok. E esse é
o roteiro errado. Lá vamos nós. Agora temos que
gerar os tanques inimigos Para fazer isso,
precisamos saber quantos tanques precisamos gerar E se você se lembra, colocamos uma caixa giratória para lidar com isso
em nosso menu Iniciar. Aqui mesmo. Então, temos
que conectar essa caixa giratória, e fazemos isso indo para
baixo do contêiner HBox E é por isso que
você precisa rotular seus nós de forma
mais inteligente Então eu vou fazer isso. Portanto, a caixa de rotação, sempre que
você altera
o valor na caixa de rotação, digitando diretamente
ou usando as setas, ela dispara um sinal
chamado Então, queremos conectar isso e conectá-lo
ao nosso menu inicial. E queremos que esse valor
vá basicamente para onde
for necessário. Então, vamos fornecer outro sinal em nosso mensageiro. Mas isso é um pouco exagerado Ok, e é claro,
precisamos fornecer um valor da quantidade que foi alterada para quem está se conectando
a esse sinal Então, em nosso menu inicial, descemos aqui e dizemos messenger, e a contagem de spas
mudou e passamos o valor que é
passado para o método. E nós fizemos isso errado.
Na verdade, é emitido, o que não consigo
soletrar. Lá vamos nós. Tudo bem, agora, qualquer pessoa que precise
se preocupar com a
alteração ou não da contagem de spawn do inimigo se da contagem de spawn do inimigo se inscreverá nesta
mensagem E isso, é claro,
inclui nosso criador. Então, quando estiver pronto, a contagem de descendentes de inimigos com
pontos mensageiros foi alterada. Conectar. E esse é outro caso em a função é tão pequena
que podemos usar um Lambda Então, vamos apenas dizer que a
quantidade de tanques inimigos igual E isso significa que sempre
que esse valor mudar, o gerador saberá disso Agora, sempre que
geramos tanques inimigos
, a primeira coisa que
precisamos fazer é fornecer duas variáveis Um deles será para o tanque inimigo que
criamos. E isso vai ser
um tanque de IA, é claro. E então também
precisaremos de uma variável de ponto de desova. E precisaremos de
uma variável de ponto de desova porque cada tanque será
atribuído a um ponto de desova
aleatoriamente no mapa, exceto pelo
ponto do jogador Agora, seria uma boa
ideia armazenar esse valor em cache. E com isso, quero dizer,
precisaremos duplicar
a matriz de qualquer maneira, mas não precisamos
obter a matriz duas vezes, embora isso só seja feito uma vez por vez, então não é muito ineficiente
se não o fizermos, sim, vamos colocá-la E os pontos de desova serão uma matriz de nós três Ds. E será o nosso
campo de jogo. Consiga um pai. Espere, não, não seja pai, porque terreno do
campo de jogo é, na verdade a arena que tem os pontos de
navegação diretamente nela Sim. Então, o que
vamos fazer é obter pontos de navegação do Node E não queremos obter
o nó NavPoints em si. O que queremos
é que sejam filhos, que é uma matriz que inclui
todos esses NavPoints Então, queremos que as
crianças sejam duplicadas. E a razão pela qual queremos
duplicá-la é que
queremos modificar a
lista que obtemos, e isso ficará
claro em um momento E provavelmente também podemos
fazer uma previsão aqui como array Node three D, não que isso realmente importe,
mas tudo Ok, e
também
precisaremos fornecer o que
chamo de retorno de chamada Não sei se tecnicamente
conta como um retorno de chamada, mas é basicamente
um método que
precisamos conectar a
cada tanque inimigo,
e esse é,
obviamente, o método de
disparo de projéteis do nosso jogo Então, se você se lembra, subimos aqui, todo tanque inimigo que aparece, ou pelo menos o tanque inimigo
que geramos, tinha que
se conectar ao método de
disparo onsel do jogo Então, felizmente para nós, em Godot, funções são objetos e são objetos
do tipo chamável Então, podemos passar a
função diretamente aqui. Então, vamos chamá-lo de manipulador de
shell, eu acho, manipulador de
shell do tipo callable e agora poderemos
conectá-lo corretamente Tudo bem, então temos
nossos pontos de desova e temos nossos tanques inimigos Então, a primeira coisa que
vamos fazer poderíamos realmente fazer isso uma
forma um pouco diferente. Pode ser um pouco mais
eficiente fazer isso dessa forma, mas vamos fazer
dessa maneira de qualquer maneira Antes de gerarmos os tanques, queremos ter certeza de que o número de tanques inimigos
que vamos
gerar seja menor que o número
de NavPoints no mapa E também
deveríamos ter limitado
o valor máximo
do spinner porque
atualmente ele está definido como sete E, quero dizer, temos
mais NavPoints do que isso, mas e se criássemos um mapa
com menos NavPoints E, por exemplo, se você é
um desenvolvedor solo, é fácil manter
esse tipo de coisa em mente, mas às vezes você só quer
algumas salvaguardas extras Provavelmente seria
uma boa ideia, por exemplo, assim que o jogo
começar, consultar o mapa e definir
automaticamente esse valor. E quanto mais
penso nisso, mais
é uma boa ideia. Vamos dar uma olhada na
rapidez com que isso pode ser feito. Já temos
nosso menu inicial. Já temos nosso gerador. Então, sim, vamos fazer isso aqui. Ah, sim, eles estão acessíveis
porque, caso contrário, não
conseguiríamos
mostrar Comece aqui. Então, vamos até aqui e definiremos o menu Iniciar. E precisaremos
obter o nó correto. Então, vamos precisar do caminho para o nó, e
não sabemos disso. Então, se entrarmos no jogo, no menu
Iniciar, girar a caixa, clicar com o botão
direito, onde está? Copie o caminho do nó. Então, podemos remover menu
Iniciar porque é
aí que estamos começando. Menu Iniciar, caixa de rotação e valor máximo
das caixas de rotação,
a propriedade é chamada de valor máximo de
sublinhado. Então, vamos simplesmente: o valor
máximo é igual a playfield dot get Node Oops Já colocou isso entre aspas. Eu
tenho pontos para contar crianças porque
vou calcular quantos menos um para contabilizar o nó do jogador, porque não
queremos poder
aparecer no nó do jogador Então, esse é um trecho de código longo e
feio. Você provavelmente não deveria fazer
isso em um jogo real, mas só para
colocar as coisas em funcionamento aqui com o mínimo de dor, vamos
fazer assim. Então, de volta ao nosso spawner, temos um erro.
Qual é o nosso erro? Esse é o nosso erro porque
não terminamos essa linha. Então,
primeiro de tudo, vamos
garantir que isso realmente funcione. E, claro, ele obtém
Child Count em um valor nulo. Arena de campo de jogos. Pontos de navegação O problema é que
temos um caminho redundante aqui. Não precisamos
começar com o campo de jogo
porque estamos no campo de jogo Só precisamos ganhar pontos
Ana Nav. Agora isso deve funcionar.
E aí estamos. Então, agora devemos ser capazes
de mudar isso para dez, que é o número de
NapPoints que temos Perfeito. Agora nunca mais
vamos ultrapassar, o que significa que, no spawner, podemos ignorar essa linha.
Nós não vamos precisar disso. E só para que
possamos validar isso, vamos colocar isso
aqui por enquanto Então, queremos
analisar o número de tanques
inimigos que
vamos gerar Então, vamos
fazer isso com o Tank. Vamos
definir um loop de quatro. A variável é
chamada de índice do tanque, está dentro e há uma
função muito útil chamada range E se fornecermos o valor, fornecermos uma
quantidade singular como valor, isso nos dará uma
matriz de números de
zero a esse número menos um, o
que é incrivelmente útil
para percorrer zero a esse número menos um, matrizes Então, se nossos tanques inimigos forem
realmente iguais a 11, alcance nos
dará de zero a dez, que é exatamente o que queremos. Ou pelo menos perto o suficiente. É o número certo de valores. Então, o tanque inimigo é igual a, e isso é a mesma coisa
que fizemos com o jogador. Então, o
ponto pré-fabricado do tanque inimigo é instanciado. Como tanque de IA. E, claro, você tem que soletrar
a palavra As corretamente Acho que é um novo recorde para mim ao digitar incorretamente uma palavra de
duas letras Oi. Bem, é por isso que sou cientista da computação e não
professor de inglês. Tudo bem. E quando tivermos
um tanque inimigo
, precisamos configurar
alguns de seus detalhes. E, claro, esses
detalhes são o nome, o nome do nó e
o ponto de desova E como já temos uma referência ao
campo de jogo, sim, tudo bem. Então, no mínimo, podemos simplesmente dizer
jogar em um terreno de campo,
pegar um pai, adicionar tanque inimigo
infantil, e
isso seria ótimo Mas isso não é suficiente. Então, a primeira coisa que
precisamos fazer, obviamente, é conectar
o sinal de disparo de projétil à nossa chamada e, em seguida, precisamos
renomear o tanque inimigo O nome do ponto do tanque inimigo é igual a. E vamos
chamá-lo de submarino inimigo ou inimigo com esse token E, é claro, vimos
em uma lição anterior que esse token nos permite fazer
a substituição de strings. Então, já que estamos tentando
substituí-lo por um número, na verdade, ele deve
funcionar sem uma conversão de cordas Vamos experimentá-lo. E
o número do inimigo é simplesmente o índice do tanque mais um, porque queremos que
eles sejam de um a qualquer coisa e não de
zero a qualquer coisa. E então
faremos o mesmo com Well, então o tanque inimigo que
chamaremos de tanque inimigo com isso. Mas o nome de exibição Seremos apenas o número do inimigo. E esses são arbitrários. Sou
só eu decidindo que
isso é o que é Você pode fazer o que
quiser. E agora, é
claro, temos que
encontrar um ponto de desova Mas antes disso,
seria um pouco mais eficiente ou, pelo
menos, mais, eu acho,
menos complicado, porque o criador e o campo de jogo ou
o terreno do
campo de jogo têm exatamente o mesmo pai, então podemos apenas dizer Tudo bem, agora que
o tanque foi adicionado ao campo de jogo,
podemos definir um ponto de desova E, claro, quando o tanque aparece
pela primeira vez no mundo, sua posição é igual
ao ponto vetorial zero, que é uma constante
que indica que o vetor é
zero, zero, zero Então, enquanto for
esse o caso. Portanto, desde que o inimigo
enquanto a posição do tanque inimigo
seja igual ao vetor 30, isso significa que ele não está atribuído E o que queremos fazer
aqui é continuar escolhendo novos pontos de desova
até obtermos um válido E a única vez que o ponto de
desova não será válido é se for o ponto de desova
do jogador Então, ponto de desova Whoops. Curt, maldito, você preenche automaticamente. O ponto de desova é igual a, e já temos
nossa matriz de pontos de desova Portanto, é igual a
pontos de desova com o índice de um número aleatório de zero ao tamanho dos pontos de
desova menos Então, isso nos dará qualquer
índice de zero até o final do ponto de
desova, porque o máximo de pontos de desova ou o índice máximo de uma matriz é sempre igual ao
seu tamanho menos Então, quando tivermos um ponto de
desova definido, queremos removê-lo
da matriz de pontos de desova porque
já o escolhemos Então, simplesmente dizemos pontos de desova, apagamos
pontos de desova. Queremos apagá-lo, seja válido ou não,
porque o que vai acontecer é que, como
já estamos procurando os tanques, depois de definirmos esse ponto de desova
do tanque, voltaremos ao topo,
criaremos um novo tanque
e, em seguida, queremos selecionar entre os
pontos de E não queremos incluir
o que acabamos de escolher. Então, se sempre excluirmos o ponto de desova que
acabamos de escolher
, nunca
obteremos um ponto de desova duplicado E é por isso que
duplicamos a
matriz G children do nó NavPoints porque vamos
excluir coisas dela. E se usássemos a matriz
original dos filhos originais, excluiríamos pontos de NavPoints do nosso mapa e não
queremos fazer isso Então, para algo
assim, sempre trabalhe em uma cópia duplicada Então, os pontos de desova são apagados. E queremos verificar o ponto de
desova se o nome do ponto de desova é igual ao início do jogador,
porque se é ou foi o
spawn desse jogador, não me lembro Vamos dar uma olhada. Spawn do jogador Dizem que a memória é a primeira coisa que
desaparece quando se envelhece. Pelo menos eu acho que
eles sabem. Eu esqueço. Tudo bem, então se o nome do ponto de
desova não
for igual ao desova do jogador, o que fazemos é que a posição do tanque inimigo
seja igual à posição do ponto de desova E isso deve bastar para
nós. Vamos dar uma olhada. Bem, na verdade, não.
Não poderemos testar isso porque, quando
estamos começando o jogo, na verdade não
estamos
gerando nenhum tanque Então, temos que voltar ao jogo. E agora que eles foram resolvidos,
podemos removê-los. E então voltamos para
Iniciar o jogo. Então, criamos nosso jogador. Configuramos nossa câmera espiã. Agora temos que dizer ao
gerador que gere tanques inimigos
e passar
a função que
vamos anexar, e passar
a que é, obviamente,
disparar um projétil E agora devemos ser capazes gerar um determinado número de
tanques em nosso mundo Vamos começar com dois
e temos um erro. Tudo bem Tentando
atribuir o tipo, blá, blá, blá, tipo Oh, ok Então, o problema aqui é que ele está tentando atribuir
um tipo de nó de matriz a uma variável do tipo
nó três D.
Especificamos nossa
matriz de pontos de desova como um nó três D, mas por causa da
magia do polimorfismo, na verdade
ela está tentando retornar um nó
e você não pode lançar
para e você não pode Então, se mudarmos isso de forma que, bem, não precisemos
dizer que é um nó três D, podemos removê-lo e
mudaremos isso para simplesmente nó Agora, vamos tentar novamente. Crie dois tanques, comece o
jogo. Tudo bem Temos um jogador e
temos dois tanques. E, claro, eles estão se movendo
individualmente. E como você pode ver, Godot está lidando com a
física para eles. Portanto, você nem precisa se
preocupar com eles se
contornando, mesmo que, se
os dois estiverem tentando fazer isso no mesmo ponto,
eles simplesmente colidirão Portanto, temos um jogo funcional. A única coisa que nos
falta é uma condição de
fim de jogo, uma condição de vitória para o jogador. Então, isso é muito fácil e rápido de adicionar, considerando tudo o
que já configuramos. Vou desafiá-lo a fazer isso como um complemento
a esta lição Mas você faz uma pausa se
quiser, pausa o vídeo, experimenta você mesmo e
continua assistindo ao vídeo, e eu mostrarei como fiz isso Tudo bem. Mas antes de
entrar nisso, temos um
bug muito grande que precisa ser
corrigido, a menos que você goste que seu
jogo seja realmente desafiador. Então, se você notar ou talvez tenha notado que está
brincando com isso, se você começar um jogo
e depois morrer, e depois começar outro jogo, haverá mais tanques gerados do que você
mandou E isso porque nenhum dos objetos
do jogo
anterior está sendo removido pelo gerador antes de realmente
começarmos o Então, a maneira mais rápida de fazer
isso é fazer isso é que o patrocinador faça isso
ou podemos fazer com que o jogo faça isso Podemos simplesmente fazer isso no
jogo. É bastante fácil. Então, todos os nossos objetos, todos os nossos tanques estão sendo
acoplados ao campo de jogo Então, queremos entrar no campo
de jogo. E
não queremos fazer isso. Então, quatro crianças no
campo de jogos Pegue crianças. Isso percorrerá
todas as crianças
do campo de jogo e as colocará
na variável child para que
possamos fazer algo com E tudo o que precisamos fazer
é ver se
a criança está no grupo
vendável, porque
colocamos todos os objetos que podem ser removidos
do jogo nesse grupo, pois
eles podem ser Portanto, se child dot estiver no grupo Shellable, child dot free E isso deve
resolver nosso problema. Tudo bem Agora, vamos configurar
nosso jogo de acordo com as condições. Então, a primeira coisa que
precisamos fazer é acompanhar o número
de tanques que foram mortos
versus o número de tanques que ainda restam. E a maneira mais rápida e fácil fazer isso é voltar à interface
do usuário, porque
a interface do usuário já está acompanhando a contagem de mortes Então, tudo o que precisamos fazer é também acompanhar o
valor do gerador. E a maneira
mais fácil de fazer isso é adicionar outra variável chamada
Kill count target. Que também é um número inteiro. E como já
temos uma configuração de sinal, podemos simplesmente monitorar se a
contagem de desova do inimigo mudou E, mais uma vez, podemos
usar uma função Lambda, que simplesmente dirá que o alvo da
contagem de mortes é igual
ao novo valor E agora, toda vez que a contagem de
mortes muda, queremos verificar esse valor. E se a contagem de mortes for igual a esse
valor alvo, então vencemos. Obviamente, vamos
mudar isso em um momento. Mas a próxima coisa que
precisamos fazer, obviamente, é fornecer um estado de fim de jogo para
o jogador que venceu, e também precisamos poder
relatar ao jogador
que ele venceu. Então, vamos mudar
um pouco as coisas. Também temos um bug antigo.
Deixe-me ver se consigo encontrá-lo. Portanto, o problema aqui é que
sempre que um tanque é atingido, destruído ou não, ele emitirá o sinal de
tanque inimigo destruído, que é ruim porque significa
que você pode
continuar acumulando mortes
atirando no mesmo Então, se voltarmos para nossa concha, se o corpo estiver em grupo
e o corpo
não for destruído,
podemos chamar Para indicar que o
projétil atingiu o tanque. Quero dizer, está batendo de qualquer maneira. Isso é meio
impróprio, eu acho. Já está verificando e
disparando se há uma colisão. É
basicamente a contabilidade que
acontece quando o tanque é atingido E não precisamos
continuar fazendo isso repetidamente se o tanque já
tiver sido destruído. Então isso resolverá isso.
E agora só precisamos adicionar a estrutura
para finalizar o jogo. Portanto, em jogo, podemos
fornecer uma nova função para mostrar o
diálogo do fim do jogo , porque o que
podemos fazer é fazer com que o diálogo do fim do jogo relate se o
jogador ganhou ou perdeu. A maneira mais fácil de fazer isso
é fornecer uma função. E essa função basicamente mostrará o diálogo do game
over, e o mostrará
com uma mensagem de sucesso ou uma mensagem de falha, dependendo do valor dessa variável de
sucesso. Então, se for um sucesso, pegamos nossa caixa de diálogo de interface de usuário
que já temos e pegamos o rótulo do
contêiner
de margem, que é, obviamente, esse rótulo aqui. E mudamos seu texto com base no fato de o
jogador ganhar ou perder. E então, é claro,
fazemos o mesmo código que fizemos aqui, onde
mostramos o diálogo, esperamos 2 segundos
e depois nos conectamos ao final do jogo. Então, agora que um jogador é destruído, tudo o que precisamos fazer é mostrar a caixa de diálogo do jogo com
a variável falsa. E precisamos fornecer uma maneira para o jogador mostrar
esse diálogo e vencer. Então, precisamos de outro sinal em nosso mensageiro e
precisamos disparar esse sinal
da interface do usuário aqui. E antes de continuarmos, há uma pequena
otimização que podemos fazer. Então, na verdade, queremos atualizar a exibição sempre que a contagem de mortes mudar. Então, novamente, precisaremos de um setter. Porque quando o jogo começar, a contagem de mortes será igual a zero,
mas, nesse momento, não
chamamos o código que estava
aqui originalmente para alterar a contagem de mortes. Então, sim, faremos isso sempre que esse
valor realmente mudar. Então, isso deve resolver
esse problema. Ok. E agora precisamos ouvir
um sinal do player. Normalmente,
seria um pouco mais lógico fazer com que o diálogo do
GameOver ouvisse um sinal do
jogador, mas na verdade nunca criamos um script para o diálogo do
GameOver, então também podemos fazer isso aqui Há várias maneiras
de otimizar e refatorar esse código para
torná-lo melhor em geral Mas, na verd
32. Múltiplos ângulos de câmera: Mamãe. Bem-vindo de volta. Vamos analisar a criação de
um sistema dinâmico de câmeras, ou acho que a melhor maneira de
colocá-lo seria um sistema de várias
câmeras. Então, chegamos ao
ponto em que
ampliamos a funcionalidade de nosso tanque o suficiente para que um simples
tanque não funcione mais , porque queremos adicionar um
sistema de câmera ao nosso tanque, mas não queremos
adicioná-lo ao tanque inimigo que é derivado do tanque. Então, teremos que criar
uma nova cena herdada, herdar de Tank
e salvar essa, e vamos
chamá-la de
tanque de jogador
e tanque de
jogador é, bem,
temos que voltar ao nosso gerador e
atualizar nosso tanque de jogador pré-fabricado
para
realmente usar o tanque do jogador em vez do tanque agora bem,
temos que voltar ao nosso gerador e
atualizar nosso tanque de jogador pré-fabricado
para realmente usar o tanque do jogador realmente usar E agora, nada
vai mudar porque eles são
exatamente da mesma classe. Mas no tanque do jogador, queremos adicionar um equipamento de câmera Então, temos nossa câmera existente três D, mas queremos mais. Então, voltaremos aqui e
mudaremos , ou melhor
, adicionaremos um nó, e esse
será um nó três D. Vamos chamá-lo. Câmeras. E vamos mover a câmera
existente para baixo das câmeras, e isso não vai funcionar. E há uma razão para
isso. Portanto, simplesmente adicionaremos câmeras
adicionais
diretamente aqui, em vez de preocuparmos em torná-las sofisticadas
e adicionar um equipamento extra Posso renomear a câmera? Não. OK. E tudo isso faz sentido. Você não quer,
na verdade, não pode alterar nenhuma
das informações subjacentes
do nó. Então, tudo bem. Então, vamos simplesmente adicionar
algumas câmeras extras. Bem, eu adiciono outra câmera três D. E esse nome
dará um nome a, ou melhor, daremos um índice
adicional dois. Então temos a câmera três D dois
e a câmera três D três. Então, câmera três D dois, eu sempre
quis uma câmera
na torre para que você pudesse ver onde a câmera está realmente girando, embora isso realmente não nos
faça bem, não é Na verdade, não,
podemos colocar a
câmera na torre Fizemos isso com o
marcador três D anteriormente. Então, adicione a câmera três D lá. E então vamos nos certificar de que está voltado na direção certa. Sim, isso parece bom. Prévia.
Oh, está de cabeça para baixo. E só para constar, essa
é a seta roxa para mostrar a
orientação correta do tanque. Então, nesse caso,
queremos que seja zero. E agora podemos ver nossa
torre em nossa torre. E queremos que o terceiro seja, digamos, bem, está tudo
bem onde está. É uma câmera traseira. E na verdade, você
sabe o que? Podemos adicionar , então teremos que
fazer isso de forma um pouco diferente da maneira que eu planejei
originalmente. Mas vamos adicionar um nó
em vez de um nó três D, e isso será um equipamento de câmera E,
literalmente, teremos um roteiro com referências
às nossas câmeras existentes. E agora, não estamos
criando um novo nó. Estamos adicionando um
script. E vamos exportar câmeras automotivas. E as câmeras serão
um conjunto de câmeras de três Ds. E, sim, ajuda se você não adicionar sua própria pequena notação
boba Ok, agora temos uma matriz e podemos indicar
o tamanho da matriz. Portanto, temos três
câmeras no total. Um, dois, três. E agora podemos arrastar
as referências às nossas câmeras existentes
para essa matriz. E tudo o que precisamos é um único método que
processe entradas de chave não manipuladas E vamos verificar
se uma, duas ou três teclas
foram pressionadas. E se tiverem, mudaremos para a câmera
correta. É
pressionada a tecla física. Chave um. E vamos
criar um método chamado switch to camera e forneceremos o índice correto. Então, neste caso, podemos chamá-lo de que podemos usar o
mesmo índice da câmera, mas
precisaremos alterar os índices porque ele
estará desligado em um E depois faremos outra coisa. Mamãe. Na verdade, vamos usar
um LF aqui. F. Tudo bem. L F. Câmera um, câmera dois, câmera
três, câmera três E temos um I
redundante lá dentro. Excluir. Tudo bem. E, claro, não
precisamos mudar para a
câmera. Então funk Whoops E isso é bem
simples. Tudo o que precisamos fazer é dizer índice da
câmera da câmera menos um, porque temos
que compensar o fato de que
os índices começam em zero, mas estamos começando em um aqui, e poderíamos
facilmente tornar isso Quero dizer, certo, por que não? Menos confuso
dessa forma, eu acho. OK. Atual igual a verdadeiro. E como Godot se
preocupará apenas com a última câmera que
foi configurada como atual
, não devemos nos preocupar em rastrear
qual câmera é atual Então, vamos ver se isso
realmente funciona. E se isso não acontecer,
faremos algumas modificações. Jogador e aí está. Agora temos um sistema
multicâmera. E isso foi muito fácil. Ok, terminamos de programar
por enquanto, então vamos para
o próximo capítulo e começaremos a falar
sobre atualizações gráficas Vamos revisitar os materiais e examinar as malhas e todas as outras
coisas boas Nos vemos lá.
33. Melhores explosões com efeitos de partículas: Bem-vindo de volta. Nesta lição, vamos
remediar o fato de que quando qualquer tanque é baleado, ele simplesmente para.
Simplesmente está lá. Faz barulho e
é muito chato. Então, vamos melhorar as explosões de nossos tanques com
alguns Agora, o melhor
dos sistemas de partículas é que eles parecem complicados
na superfície, mas depois de aprender um ou dois pequenos
truques sobre eles, você pode basicamente jogar com
eles o quanto quiser,
sem nem mesmo
entender o que a grande maioria
dos recursos E como tudo isso é atualizado em tempo real na janela
do GadoEditor, você pode basicamente jogar
com todas as configurações
e, quando conseguir
algo de que
goste, pode rolar com Portanto, um sistema de partículas é um nó, assim como qualquer outro
nó no GADO Então, vamos
adicionar uma nova cena. Vamos
selecionar outro nó
e vamos usar as partículas de
GPU três D.
Agora, há uma diferença
entre partículas Agora, há uma diferença de GPU
e partículas de CPU As partículas da GPU são processadas na
placa gráfica na GPU As partículas da CPU são processadas pelo processador
principal do seu computador. A diferença
entre os dois é que
as partículas de GPU têm mais desempenho em um sistema acelerado de
três D. Além disso, e isso é algo dos bastidores,
a equipe de Godot está basicamente
deixando
as partículas da CPU para trás, no sentido de
que não as está priorizando
sobre as Portanto, eles não estão adicionando
nenhum recurso novo,
mas estão dispostos a permitir que as pessoas o igualem às
partículas da GPU Então, basicamente, use partículas de
GPU, a menos que elas simplesmente não funcionem
no hardware que você está
tentando atingir É uma boa regra prática. Então, vamos criar uma nova
GPU com partículas de três D
e, claro, ela não faz nada Porque na verdade ainda não
configuramos nada. Então, as duas
coisas principais e você
verá um pouco: você
verá um aviso e um
erro aqui. Diz que nada é
visível porque as malhas não foram
designadas para desenhar passagens e um material para processar as
partículas não foi atribuído,
portanto, nenhum comportamento é impresso Isso significa que
precisamos atribuir
essas duas coisas para que nossas partículas
façam qualquer coisa. A primeira coisa que
adicionaremos são os passes de empate. O sorteio passa
e você precisa adicionar pelo
menos uma para determinar
a aparência de suas partículas. Portanto, precisamos dar a ele algum tipo de
nova malha. E vamos usar partículas texturizadas com bitmap Então, vamos usar uma malha quádrupla. E agora você pode ver que
na verdade temos uma partícula aqui Na verdade, temos um
monte de partículas aqui, mas como elas não têm comportamento, elas não estão realmente se movendo. Observe também que eu reorganizei duas coisas no projeto nesta lição Eu o
reorganizei para que tivéssemos várias subpastas, estamos chegando ao
ponto de
adicionar muito mais
recursos ao nosso projeto e não queremos que as coisas
fiquem confusas Então eu coloquei todas as
fontes, os gráficos, as cenas e os
efeitos sonoros em suas próprias pastas. Falando nisso,
adicionei algumas texturas de
partículas ao projeto para você usar
ao criar
seus próprios sistemas de partículas Tudo isso está
disponível gratuitamente opengameart.org Existem outros lugares onde
você pode obtê-los
na Internet ou até mesmo criar
seus próprios, se desejar. Depois de clicar na passagem
e na malha e estendê-la, agora
temos a oportunidade de
alterar sua aparência, da
mesma forma que faríamos com as outras
malhas com as quais trabalhamos Na verdade, como você pode ver, podemos usar qualquer tipo
de malha que quisermos. Então, se quiséssemos uma caixa ou
uma cápsula ou qualquer outra coisa, para dar uma aparência mais tridimensional às nossas partículas,
poderíamos fazer isso. Mas
vamos usar uma malha quádrupla
e, em seguida, temos que
fornecer um material, e devemos ser especialistas
nisso neste momento Então, vamos usar
um novo material padrão e podemos abri-lo. Agora, existem várias
configurações extras para um material particulado do
que para materiais comuns E também há
alguns interruptores extras que, se você não girá-los, três quartos das configurações do
sistema de partículas não funcionarão e você passará
duas ou 3 horas batendo a cabeça contra a parede se perguntando por que nenhuma das configurações
está E eu definitivamente não estou falando por experiência
nesse assunto. Então, a primeira coisa que vamos
fazer é ir até
Albedo, é claro, e vamos
adicionar uma de nossas Então, vou mostrar como
criar dois sistemas de
partículas diferentes, um explosivo
e um constante E também forneci
o sistema de partículas que
criei para o tanque e anexei ao
tanque neste projeto Então, você pode
acompanhar esta lição para ver como todas
essas configurações funcionam, e então você pode tentar criar as suas próprias,
e então você também pode inspecionar as que eu
criei para o tanque Também mostrarei como
usar os scripts para acionar as explosões e usar
o script
GD para acionar as explosões no
final da lição Então, agora que voltamos aqui, precisamos de uma textura, novamente. Então, isso vai ser
uma espécie de fogo, sim, espécie de
textura ardente ou um sistema de
partículas de fogo Então, vamos
usar a explosão
na textura certa e
trazê-la aqui. Agora, como você pode ver, não
há transparência, então precisamos habilitar a
transparência. E também precisamos
expandir a cor do vértice e clicar e
ativar o uso como albedo E é isso que nos permite
mudar as cores a transparência e todas as coisas
boas da nossa textura. E como essa é
uma textura de três D, mas estamos usando uma textura, você pode ver que, quando
você gira, a textura se inclina e desaparece porque está mapeada em
uma coisa no espaço de três Então, para mudar isso, precisamos divulgar a textura
e habilitar
o outdoor de
partículas E o que isso faz é
sempre fazer com que
a textura fique voltada para nós independentemente
da orientação em que a câmera esteja. E nesse caso, é
exatamente isso que queremos. E também precisamos, bem, não
precisamos, mas
seria uma boa ideia
clicar em manter escala dessa forma, se quisermos mudar a
escala das partículas,
e provavelmente o fazemos, também
permitirá
que isso aconteça. Caso contrário, e alterássemos
qualquer uma das curvas de escala, nada disso teria efeito Tudo bem, então
temos um material. Nós temos um passe. Agora vamos
ao material do processo. material do processo
determina o que realmente acontece com as partículas ao longo do
tempo e muitas outras coisas Portanto, precisamos de um novo material de
processamento de partículas. Agora que temos uma,
você pode ver, por padrão, nossas partículas estão surgindo
e caindo E isso porque
a funcionalidade padrão do
processo de partículas é
simplesmente dar um tapa na
gravidade e encerrar o dia.
Mas não queremos isso. O que realmente queremos
são algumas coisas. Então, vamos voltar para a seção de três
partículas D da GPU e deixaremos a
emissão ligada por enquanto Mas o que vamos fazer
eventualmente é ativar um disparo,
porque um disparo basicamente significa que um
conjunto de partículas vai emitir, e então
pronto Isso é exatamente o que
queremos para uma explosão. Então, vamos desligar isso por enquanto ,
apenas para que possamos ver
o que está acontecendo. Então temos o que é
chamado de explosividade, e isso é exatamente o
que diz na lata Quanto mais explosivo for, mais instantaneamente
as partículas aparecerão E é meio difícil de ver
agora porque, novamente, todos
eles estão surgindo com a mesma velocidade e todos
estão sendo afetados pela Então, vamos aumentar o número
de partículas para, tipo, 25. E a explosividade é boa, e não
precisamos nos preocupar com a aleatoriedade Aleatoriedade Se não estivéssemos
usando explosividade, aleatoriedade determinaria a aleatoriedade
da frequência Portanto, não precisamos nos preocupar com colisões, desenhos ou trilhas Essas são opções
sofisticadas com as quais não
vamos lidar Então, normalmente, as partículas não colidem
com o meio ambiente. Se você quisesse,
precisaria adicionar um nó especial chamado colisor
de partículas de GPU
ao seu sistema de partículas E isso está relacionado a isso. E não precisamos nos
preocupar nem um pouco com o desenho. Então, uma das coisas sobre sistemas de
partículas é que
eles são extremamente nerds, e há muitas
configurações que você nunca precisará, a menos certeza absoluta de que
precisará Então, se você olhar para uma configuração
específica, você pensa, por que
eu usaria isso? Então você não
precisa. É ótimo. Então, em material processado, é
aqui que
podemos começar a fazer nossas partículas fazerem coisas. Então, usamos bandeiras de partículas. E nós realmente não precisamos nos
preocupar com nada disso. Então, eles ditarão como a partícula se alinha em
suas várias direções Também podemos adicionar
amortecimento como atrito, que retarda as partículas
ao longo do tempo até desova e a velocidade de
desova e a exibição são como as três Então, se ficarmos sob a posição, você pode ver que
temos a oportunidade de
definir a forma a partir da qual as
partículas são geradas Então, agora eles estão
girando a partir de um ponto, o que significa que todos estão surgindo exatamente
no mesmo
ponto do mundo,
mas podemos alterá-lo para que
eles apareçam dentro mas podemos alterá-lo para que
eles apareçam Agora você pode ver que está surgindo dentro de uma área circular aqui, e podemos alterar o tamanho da
esfera para obter muito mais partículas
espalhadas ou uma caixa ou assim por
diante, até mesmo um anel O anel pode ser divertido,
especialmente para fogo. meio difícil, então você pode alterar o eixo do anel para
alterar o tamanho do anel, a altura do
anel, o
raio do anel e o erro do anel Sim, eu não sei se eu realmente quero fazer isso.
Vamos deixar como a. Então temos ângulo e velocidade,
e esses dois são
extremamente importantes Então, você vai
se acostumar muito com esse controle em Gadot pelo menos quando estiver usando
os sistemas de partículas Este é o único lugar em que eu
realmente o vi usado em Gdo
e, basicamente, fornece
um alcance que você pode expandir arrastando essas pequenas flechas específicas
. Essa é a palavra que estou
procurando. E você também pode deslocar todo
o intervalo em si,
alterando clicando e
arrastando o retângulo E isso indica o intervalo, mínimo e máximo que as
várias configurações podem ter. Portanto, no caso de um ângulo,
quando uma partícula é gerada, ela pode ter um ângulo que varia entre esse valor e esse
valor No entanto, não queremos ser tão
específicos ou loucos, então vamos configurá-lo de
0 a 360, e tudo bem Isso significa que a partícula pode potencialmente aparecer em qualquer orientação
angular O divertido é a velocidade. velocidade determina a rapidez suas partículas
explodirão de onde estão, e a propagação determina Em um ângulo ao redor dela. Então, se você quiser uma coisa mais
parecida com uma fonte
, diminuirá a
propagação, e se quiser uma com mais aparência de explosão,
você pode aumentar a extensão Infelizmente, no momento,
não parece nada porque, novamente, não
temos nenhuma velocidade Então, vamos adicionar um pouco de velocidade. Vamos fazer com que nossa
velocidade seja igual a duas. Agora você pode ver que
temos um pouco mais disso. E agora, se eu
mudasse a dispersão, você pode ver que
eles estão explodindo em um ângulo maior Ok, então não queremos que
nossas partículas caiam porque não é
assim que uma explosão funciona. Então, está subanimado? Não, está sob
acelerações. OK. Então, para evitar que as partículas
caiam para baixo, temos que desligar a gravidade E a gravidade está sob
acelerações. E como você pode ver,
já está definido para menos 9,8, o
que é, obviamente, a
gravidade da Terra puxando Se mudarmos isso para zero, Boom. Agora temos partículas que simplesmente explodem em qualquer direção Agora você pode ver como a
dispersão funciona um pouco melhor devido ao
fato de a gravidade estar desligada. Então, vamos
deixá-lo em 180, e agora temos uma
explosão que vai para fora. No entanto, as partículas em
si não parecem muito boas. Então, temos dois problemas. A explosão
desaparece muito rapidamente, então vamos aumentar a vida útil de cada partícula para 2 segundos. E outra grande coisa
sobre esse sistema é que quase todas as propriedades
em um sistema de partículas, junto com todas as
propriedades que existem em
Godot em geral, têm uma dica de ferramenta
muito informativa Então, se você não sabe o que
uma configuração específica faz, basta passar o mouse sobre ela
e ela lhe dirá Infelizmente, quando
você começa a se
debruçar sobre coisas assim, você
não vai conseguir nada. Só vai
dizer: Essa propriedade só
pode ser definida
no inspetor Bem, eu estou no inspetor,
então deixe-me fazer isso. Então, alguns deles você meio
que tem que brincar. Mas Godot, na verdade, tem uma documentação
incrivelmente boa
sobre os sistemas de partículas, e vou vinculá-la aos
materiais complementares deste curso Portanto, temos a gravidade e também
temos a
capacidade de alterar
as acelerações lineares radiais e tangenciais
das partículas, mas não as usaremos No entanto, poderíamos.
Poderíamos simplesmente aumentar isso, e isso mudaria
a forma como as partículas
realmente aceleram. Não sei, eu meio que gosto
desse. Vamos deixar as coisas assim. aceleração radial
basicamente determina como as partículas
se acelerarão a partir de seu raio, o que não faz muito sentido, a menos que você a
veja em Então, aqui está. E vamos aumentar um
pouco o amortecimento para ver o que acontece Basicamente, o amortecimento
diminuirá gradualmente suas partículas
até que elas parem Sim, não sou fã,
não sou fã disso, na verdade. Vou
desligar o amortecimento Ascensão. Agora, a
mais divertida é a exibição. A exibição é como você
pode alterar e ajustar a aparência geral
de suas partículas Então, vou mostrar como basicamente as
curvas de cores e as escalas funcionam, e então você pode aplicar isso à maior parte
de todas as outras. Então, de um modo geral,
as partículas serão controladas por
um intervalo individual. Então, nesse caso, escala
significa a
escala literal da textura Então, se levantarmos isso, um pouco da gritaria,
é muito grande. Algumas das partículas podem ser maiores do que outras porque
elas surgirão com um valor de escala entre
esse intervalo Então, vamos realmente
fazer isso 0,25. Então, agora podemos pegar alguns
pequenos. Pode florescer. Então também temos o que é chamado
de curva, e curvas são divertidas Não é muito ilustrativo
fazer a curva de escala, então vou mostrar a cor Eu vou te mostrar
as curvas de cores. Mais especificamente,
a curva Alpha. E, novamente, nada disso funcionará a menos que você ative a cor
do albedo ou use um albedo e
a cor do vértice nas configurações do material Então, se formos para a curva Alpha, podemos selecionar uma
nova textura de curva. E, claro, por algum motivo, meu inspetor volta até
o topo
sempre que eu expando qualquer um deles Não sei por que isso acontece. Mas então, se clicarmos nele, agora
temos a oportunidade de
definir uma curva. Então, se você mudar
isso para uma nova curva, agora temos uma
curva, clicamos em uma curva e
podemos ver a curva. Com o tempo, a configuração
normal das texturas para esse valor será multiplicada pelo
valor nessa curva Agora, é claro, dado que
acabei de adicionar uma curva, você não pode mais ver minhas
texturas porque todas elas estão
sendo multiplicadas o Alpha está sendo
multiplicado por zero ao longo da vida útil da
textura, e não é isso que nós Se arrastarmos isso para um, agora voltaremos para
onde estávamos antes, que significa que o
Alfa básico da textura, que é, obviamente,
um, é multiplicado por, novamente, um ao
longo da vida útil Então é aqui que tudo começa. É aqui que a
partícula nasce. É aqui que a partícula morre. Não há nenhuma metáfora
aí. Então, se mudarmos isso, se clicarmos aqui e adicionarmos outro ponto e
arrastarmos isso para zero, agora você pode ver que, com o tempo, as partículas desaparecerão Portanto, ao longo de sua vida, o Alpha
diminuirá gradualmente até desaparecer. E podemos até somar mais pontos. Então, o que eu gosto de fazer para que
as texturas não
apareçam tão rapidamente é trazer
meu valor inicial para zero e, em meu valor inicial para zero e seguida, arrastar esse ponto médio até aqui
para que
elas realmente
desapareçam tempo e depois desapareçam
gradualmente com o E isso é muito legal. E você pode até fazer
isso com as cores. Então, se você quiser mudar
a cor da textura, você pode adicionar um poço, você adicionaria um gradiente
à rampa de cores Então, vamos fazer com que os gradientes sejam
ligeiramente diferentes das curvas Mas muitos desses recursos têm curvas disponíveis. Então, como você pode ver aqui,
temos uma curva angular e assim por diante. Então, certo, vamos encerrar
isso. Onde estávamos? Ok, temos um gradiente de rampa de
cores. Boom, então abrimos isso, e
agora temos um gradiente. E se você nunca trabalhou com gradientes em Godot antes, basicamente você pode adicionar
pontos dentro do gradiente,
e estamos prestes a
fazer isso e, em seguida alterar o valor do valor da cor em cada ponto para que
as cores
se misturem suavemente entre eles ao longo da
distância do Então, aqui, temos preto em uma extremidade e
branco na outra, o que nos dá um bom
desbotamento na propriedade É por isso que agora você pode ver que a
textura começa
preta e depois
fica branca ao longo da
vida útil da textura Então, vamos adicionar
mais alguns pontos aqui e
clicar duas vezes neste. E tudo que fiz foi clicar com o botão esquerdo
aqui para adicionar esses pontos. Agora, se eu mudar esse
preto para amarelo, significa
que a textura
começará em amarelo e depois desaparecerá até ficar
meio enegrecida E então vamos mudar isso para laranja para, tipo,
um laranja brilhante. E então este para um vermelho. Agora você pode ver que
as texturas estão basicamente começando
com uma tonalidade amarela e depois
indo para uma tonalidade laranja e
depois indo para uma tonalidade vermelha e depois desaparecendo até a cor original
da Agora, para uma explosão, nós realmente
não queremos fazer isso, mas se estivéssemos fazendo fogo, que vou
mostrar a vocês em um momento, algo assim
é muito útil. Então, na verdade, essa é uma textura meio
ruim para uma explosão Então, deixe-me te dar uma melhor. Na verdade, consegui
criar algumas configurações para
fazer com que isso parecesse uma explosão real,
mas demorou
uma eternidade e não me lembro
quais são as configurações Hum, eu poderia verificá-los novamente, mas seria melhor
eu realmente mudar o material porque eu
quero te mostrar, na verdade, vamos transformar isso
em fumaça e depois eu farei
o da explosão. Então, vamos mudar
a textura novamente. Vamos mudar para fumaça preta. Opa, tenho que abri-lo primeiro. Aqui vamos lá, material. Textura de fumaça preta. Estrondo. E vamos esclarecer isso simplesmente indo para o
menu suspenso e clicando em Limpar. Vamos sair nas curvas Alpha. Vamos desligar a explosividade. Aumentaremos o valor para cerca 1:50 e mudaremos
a distribuição do ângulo para, como 20, e mudaremos a direção
de X para zero para Y um, que significa que agora
ele vai subir Então, agora temos uma boa partícula de fumaça
raivosa. Eles estão meio que
subindo um pouco demais. Então, vamos com a velocidade
inicial de 0,5. Como é essa aparência?
Meio que melhor. Ah. Ok, poderia ser pior. Nada mal. E agora vamos fazer um segundo
que é meio explosivo. E eu vou realmente
cuidar dela. Não, não, eu não sou. Vou adicionar um nó filho e adicionarei um nó
três D porque assim que fiz o sistema de partículas
original Então eu tinha um nó
três D e Opa. Você não pode fazer isso dessa maneira.
O que você precisa fazer é mudar esse Não. No nó três D,
clique com o botão direito do mouse em Criar raiz da cena. Lá vamos nós. Isso
os inverte Agora adicionamos um, então queremos que
este esteja sempre em execução. E então adicionamos outro sistema de partículas de
GPU. E este vai
disparar alguns detritos em explosão quando
o tanque Assim, podemos voltar no tempo
e, eventualmente, daremos uma
chance. Mas queremos que nossa
explosividade chegue a uma. Queremos desligar isso por enquanto para que
possamos ver o que estamos fazendo. A aleatoriedade é boa. Então, é claro, precisamos de
outro material de processo e um passe de empate com
um novo material. Vamos fazer esse material como um prisma porque eles se parecem adequadamente com
estilhaços Então, vamos mudar a
aparência. Vamos reduzir o tamanho apenas para que
não seja um bloco gigante. Então, é claro,
precisamos de um material. Agora, nesse caso, não
vamos usar transparência ou
cores malucas nem nada, então simplesmente usamos um albedo Não vou dar uma textura, mas o que vou
fazer é deixá-lo cinza para que pareça um pedaço de metal lançado do tanque, e eles também não precisem de cartazes ou algo parecido E agora vamos ao nosso processador de
partículas. As bandeiras de partículas estão
bem, posição de desova. Faremos com que eles
emitam a partir de um ponto. O ângulo vai ser uma
boa pergunta, na verdade. Qual será o ângulo? Bem, a direção
novamente será ascendente. E vamos fazer
um spread de cerca de 75. E vamos dar uma velocidade
inicial. Digamos que a velocidade. Não queremos que ninguém
não tenha velocidade. Então, vamos de,
tipo, cinco para 20. E agora, sem
nenhuma mudança, na verdade
temos uma explosão de aparência bastante
decente. Então, vamos
mudar isso um pouco. Queremos mudar os ângulos
potenciais deles. Então, vamos de 0 a 360. E então, dessa forma,
sempre que eles aparecerem, eles aparecerão com
um ângulo aleatório E podemos alinhar o eixo Y da partícula
com sua direção, e isso também é muito legal Na verdade, agora eles realmente
giram no ar, mais ou menos. Tudo bem, então se eu voltar a emitir e
ativar uma foto, você pode ver que a emissão
será desligada E isso porque um único tiro é exatamente o que
significa. É um tiro único. Vamos aumentar o
número de partículas aqui. Estrondo. Lá vamos nós. Agora, um único tiro
literalmente dispara todas as
suas partículas de uma vez
e depois encerra o dia, e então não dispara mais. Então, se você indicar, digamos, 200 partículas aqui, e não tivesse explosividade
aumentada para uma como eu,
isso meio que
vazaria aquelas 200 partículas,
uma, duas, três, quatro,
cinco, seis, sete E então, quando tudo
estivesse pronto, seria o fim de tudo. Com a explosividade
ativada, como a nossa, todos
disparam ao mesmo tempo e
depois não disparam Então é isso que nos permitirá misturar todos esses efeitos
diferentes ou esses diferentes sistemas de
partículas, isso é o que nos permite
criar efeitos de explosão Então, deixe-me mostrar o
que eu fiz para o tanque. Então, emitindo, aqui está a explosão
inicial, Kaboom. E então aqui estão os escombros. Opa. Kaboom. Literalmente
, o que acabei de te mostrar. Fume também da mesma forma. E então eu também adicionei um para fogo que
na verdade não tem textura. Literalmente, são
apenas partículas quadradas. E isso é porque eu não tenho uma textura de
fogo decente em mãos. De qualquer forma,
desligo todos
eles porque só queremos que todos
estejam habilitados e façam suas coisas quando
o tanque explodir Então, adicionei esse
sistema de partículas ao meu tanque
e, no script do
tanque em nossa função de impacto,
obtenho uma referência às partículas de explosão,
crianças, porque
queremos
as Crianças,
que são os sistemas de partículas reais e não o nó E então percorremos cada criança e dissemos que ela está
emitindo uma propriedade para verdadeira E então, uma vez que
tenhamos feito isso, teremos uma boa explosão. E vou te mostrar como fica em ação, porque
eu realmente gosto. Então, adicione mais alguns
inimigos, caso contrário, não
conseguiremos realmente ver
a explosão antes que
o jogo termine. Agora, se eu me aproximar sorrateiramente
desse cara aqui, muito legal. E isso é muito mais gratificante do que apenas
ver os tanques pararem E agora vai
queimar e soltar fumaça por toda a eternidade, pelo
menos até o jogo terminar Ok, eram sistemas de partículas. E na próxima lição, faremos
outro mergulho profundo ou melhor nos materiais para fazer com que nossos tanques não pareçam tão planos.
Te vejo lá.
34. Como texturizar seus tanques: revisitando materiais: Bem vindo de volta. Nesta lição,
vamos dar uma olhada nas opções adicionais
que você tem disponíveis ao criar um material para
as várias partes do seu tanque ou qualquer outra malha ou material disponível
em seu projeto. Eu forneci todos os arquivos
relevantes como parte do arquivo
do projeto
no diretório de
texturas de metal da barra gráfica, mas também fornecerei links nos materiais complementares
deste curso para você mesmo obter alguns, porque
você mesmo pode criar esses mapas,
se souber como fazer ou não conseguiu obtê-los de vários repositórios ou até mesmo use
ferramentas on-line para criá-las. Portanto, um bom lugar para obter essas texturas
seria ambientcg.com Novamente, forneci um link para os materiais
complementares E se você quiser
fazê-los você mesmo a partir de uma textura individual
que você criou, você também pode acessar
normalmpline.com E, novamente,
forneci um link para isso nos materiais
complementares Ah, como você pode ver, eu já comecei a brincar
com alguns materiais, mas vamos criar um, ou melhor, modificar um diretamente. Então, vamos para a frente do nosso tanque, que é, obviamente, entrelaçado desde 387, e expandiremos a malha e expandiremos o material Agora, neste momento, é meio chato porque é literalmente apenas uma cor individual
singular Então, queremos mudar isso. Então, vamos para o albedo, e temos um espaço
para textura aqui Então, vamos arrastar uma
textura para lá. Arrastaremos o arquivo
de cores dos fornecidos. E agora você pode ver que,
na verdade, substitui ou sobrepõe uma textura em nosso material tingindo-a com a
cor que fornecemos Então, deixe-me pegar essa cor. Se mudássemos isso e colocassemos tudo de
volta em branco
, você poderia ver que a textura em si
não é realmente afetada. E então, se quisermos colorir,
basta dar a cor novamente. Mas podemos fazer
mais do que isso porque temos vários
arquivos aqui. Nós podemos mudar a metalicidade. E, claro, isso também
tem uma textura. Portanto, se fornecermos a
textura metálica, isso pode alterar a
aparência metálica do material Também podemos alterar
a rugosidade, que é a textura da rugosidade E você pode ver agora
que isso está dando um pouco mais de profundidade e
sensação à textura. Então, antes que esses solavancos não
existissem, eles
realmente não pareciam três D e nem existiam de
verdade Na verdade, deixe-me
limpar essa textura, e eu vou fazer com que você possa ver que a
diferença agora é que, ok, parece um
monte de manchas coloridas E agora, se colocarmos a
rugosidade de volta aqui, você pode ver que realmente
parece algo,
você sabe, que você poderia passar a
mão e sentir Então, também temos mapas normais. Agora, existem dois
tipos diferentes de mapas normais, mapas
normais, em
formato DX ou GL. Godot trabalha com o formato GL. Então, vamos
usar o GL normal. E esse é um
pouco confuso. Portanto, Godot tem suporte
para um mapa de altura
e, em outros motores e
em outros tipos de ferramentas, isso geralmente é chamado de mapa
de deslocamento E você realmente não pode ver
muita diferença com essa
configuração de iluminação específica, mas ela existe. Agora, se você não
gostar da forma a textura se estende
no objeto específico em
que está trabalhando, você pode ir novamente,
embaixo do material, e ir para a opção de escala
UV E deixe-me reinicializar este só para que você
possa ver a diferença. Então, porque às vezes , como não
estamos realmente usando modelos
reais que têm o mapeamento UV feito nos
três softwares de modelagem D, Godot basicamente
estica a textura em toda a superfície do objeto, da maneira que achar melhor,
mas isso pode não funcionar para nós, então podemos reduzi-la alterando
o zoom da Tudo bem, agora temos um poço,
temos um tanque muito diferente e com aparência
mais texturizada E se entrarmos em nosso jogo, você pode definitivamente
ver a diferença, especialmente como a luz está passando por ele e
como ela parece diferente. E, claro, como fizemos
isso em nossa cena de tanques base, os tanques inimigos parecem
exatamente os mesmos. E você também pode ver como
a luz está mudando devido à
refletividade dos tanques Oh, temos um erro. Tudo
bem Eu quebrei alguma coisa. Então, isso é algo que será corrigido
na próxima lição, mas seja o que for,
garanto que é irrelevante para esta lição
em particular, então não vamos nos preocupar com isso De qualquer forma, eram os materiais
e seus vários mapas. Nos vemos na
próxima lição.
35. Decalques: Bem vindo de volta. Estamos
na reta final. Antes de continuarmos,
quero apenas mencionar que, sim, corrigi o erro que surgiu no final
da última lição. Basicamente, quando reorganizamos as coisas no capítulo em que
criamos o gerador inimigo, o tanque inimigo básico não tinha um conjunto pré-fabricado de projéteis porque
o tanque que
colocamos diretamente no jogo estava onde realmente instalamos esse pré-fabricado Então, por algum motivo, ele
nunca foi propagado. E então, quando o movemos
para o spawner, é
claro, já que estávamos
trabalhando com base no modelo,
e o shell prefab E então, é claro, eu
nunca permiti nenhum dos tanques e das aulas que
nenhum dos tanques e das aulas
posteriores atirassem de volta contra mim, então nunca apareceu. De qualquer forma, resumindo
, voltei
e consertei a cena dos tanques inimigos
para ver todas as aulas de, acho que é 104, capítulo
dez, lição quatro em diante Portanto, o erro deve ser corrigido
retroativamente, mesmo que tenha
aparecido no vídeo Ei, para coisas mais
interessantes. Vamos falar sobre decalques. Os decalques são muito legais. Eles são uma forma de
adicionar mais detalhes de textura ao seu jogo sem precisar
incorporá-los aos seus modelos. Então, por exemplo, eu criei uma pequena cratera de projétil de explosão que aparece como um decalque no chão aqui
onde o projétil atinge Agora, eu não gostei o
suficiente para colocá-lo em árvores ou algo assim Então, se você atirar em uma árvore,
você não a verá. Mas esse é um decalque em
seu nível mais básico. E vamos ver como fazer um. Decalques são nós, In Gado. Então, se você criar uma nova cena e fornecer a ela uma
base de tipo de decalque, criaremos uma
nova bem rápido
para que você possa ver como é feito, outro nó,
decalque Então, se você criar um novo
decalque, livre-se dele. E você lhe dá uma
textura para seu albedo. No mínimo,
isso é tudo que você precisa. Então, no nosso caso, não
precisamos fazer mais nada. O que normalmente faríamos é girar a
orientação dos decalques de forma que corresponda à superfície normal da malha à qual os
estávamos fixando Mas não precisamos fazer isso porque estamos apenas
fixando-o ao solo,
então a orientação padrão da superfície está perfeitamente correta Então, acessamos nosso
script de shell e, claro,
dentro de nosso shell, como fizemos antes para outras coisas semelhantes, adicionamos uma variável de exportação do tipo packed scene
para o decalque prefab
e, em seguida, arrastamos cratera de
concha E então, quando a concha
impacta com alguma coisa, instanciamos uma cópia
do decalque pré-fabricado Nós o adicionamos ao pai da
concha quando
crianças porque o pai da concha é o campo de jogo e, em seguida,
ajustamos
a cratera, o
decalque, que é a cratera, a posição global da
cratera
para a posição global da E obviamente temos fazer isso nessa ordem,
porque se
definíssemos a posição global
antes de adicionarmos a criança,
receberíamos uma mensagem de erro. Mas, sim, isso são decalques. Você pode usar decalques para
coisas como respingos de sangue, sujeira, todo tipo de
coisas assim. Hum, estamos fazendo isso
dinamicamente aqui por causa da forma como
as conchas funcionam, mas você também pode usá-las para
adicionar textura ao seu terreno E quando melhorarmos nosso
terreno em uma aula posterior, que pode na verdade ser a
próxima lição, exclua o cheque De qualquer forma,
depois de
melhorarmos o terreno, faremos isso lá para
ver como adicionar alguma variedade De qualquer forma, isso são decalques. Nos vemos na
próxima lição.
36. Importando modelos externos: Bem vindo de volta. Nesta lição,
mostrarei algumas maneiras de importar
modelos externos para o Godot Infelizmente, dado
o fato de que Godot suporta uma grande
variedade de formatos de modelos, e também muitas vezes, se você quiser comprar modelos
gratuitos da Internet, o quase posso
garantir
que acontecerá nos primeiros jogos, a menos que você seja
ou conheça
um modelador
de três D, muitas vezes
você terá
alguns jogos, a menos que você seja
ou conheça
um modelador
de acontecerá nos primeiros jogos, a menos que você seja
ou conheça
um modelador
de três D, problemas Neste ponto, para o GaDo 43, é possível
importar quase
sempre sem problemas os tipos de arquivo GLTF Mas às vezes os ativos
que você deseja não estão nesses
formatos ou, mesmo que estejam, o artista não tomou
todas as medidas necessárias para
disponibilizar o recurso corretamente no GADO. Então, o que vamos
fazer é importar alguns ativos e vou mostrar
algumas maneiras comuns de corrigir alguns erros básicos que
podem surgir
durante suas importações Portanto, todos os recursos serão fornecidos como parte
deste projeto de aulas. Além disso, forneci alguns ativos
não fixos para você jogar
e tentar se
consertar depois de eu
mostrar o que fazer Então, primeiro, deixe-me encerrar
um monte
dessas cenas porque
não vamos usá-las. E a primeira coisa que
vamos fazer é consertar nossa rocha porque ela tem uma aparência
muito redonda. Então, temos um conjunto de
pedras disponível para nós, e elas foram baixadas
da arte do Open Game. E como você pode ver,
eles foram fornecidos em vários formatos compatíveis,
incluindo Kalata, que é
DAE OBJ e até mesmo Godot Mas se você abrir o Godot, verá que faltam
algumas dependências e outras coisas por
vários motivos Portanto, não vamos corrigir
essa dependência quebrada. O que vamos fazer é
criar
uma nova cena a partir de
um arquivo existente. Então, temos nosso arquivo DAE aqui, clicaremos com o botão direito nele
e criaremos uma nova cena herdada Então, isso nos dará um novo Godot com essa malha como uma
instância de malha dentro dela E na verdade, você
sabe, isso é bom. Então, vamos copiar a instância de malha. E, na verdade, deixe-me
ver se isso vai funcionar. Deixe-me voltar para a rocha aqui. Já temos uma malha. E nós temos um OBJ vamos ver se podemos
inserir isso lá Isso vai funcionar? Não.
Que tal isso? Sim, isso vai funcionar. Portanto, a instância
de malha três Ds usará ObJs de pontos
como um recurso de malha E se você não tem um OBJ,
se você tem apenas, tipo,
um DAE ou qualquer outra coisa, então você pode simplesmente
fazer o que eu fiz e clicar com o botão direito
do mouse e
obter uma cena herdada, e então você pode copiar aquela instância
Mesh três D. Qual é o caminho aqui? Sim, ainda é o DAE. Interessante. De qualquer forma, Godot
fará algumas importações nos
bastidores De qualquer forma, podemos
clicar com o botão direito do mouse e copiar esse nó. E volte para nossa rocha, embora realmente não precisemos
porque já a importamos. Então, sim, então temos nossa malha. O problema é que as
texturas da malha não estavam vinculadas Felizmente, as texturas
foram fornecidas para nós, que possamos definir manualmente o
material para nossa malha Infelizmente, para um DAE, isso não indica especificamente o recurso de
malha, mas muitos
dos formatos de arquivo de malha importados terão seu material oculto sob o que é
chamado de superfície. Você também pode fornecer
um material existente ou novo sob a substituição do material de
superfície Portanto, a superfície é o
material real da rocha. Agora, o que podemos fazer é tornar nossa malha única e
depois dizer única recursiva, e isso nos permitirá
mudar o material E nesse caso, eles
já forneceram um material, então podemos simplesmente arrastá-lo. E por alguma razão, isso não atualizou as texturas. Então, tudo bem. Mas ele nos forneceu
algumas configurações de material, e nós mesmos temos as
texturas Então, vamos arrastar nossa rocha
PNG para o albedo, e isso já está
parecendo E agora temos um,
não parece que temos
um metal aqui, mas temos uma rugosidade
e temos um E temos um especular, que pode realmente
ser metálico Vamos tentar isso. Isso
parece muito bom. Então, agora temos uma rocha de aparência bastante
decente aqui, e podemos fechar
isso. Não salve. Agora, se salvarmos
nossa rocha e
voltarmos à cena da arena, veremos algumas rochas muito
mais bonitas aqui. E lá vamos nós. Temos
algumas pedras bonitas. Então, vamos fazer o
mesmo com as árvores. E, nesse caso, as árvores. Então, novamente, eu forneci
vários tipos de pedras para você jogar e
fazer algo semelhante. Agora, para as árvores,
temos um problema semelhante as árvores
fornecidas estão no formato FBX Agora, a partir de quatro pontos e três de Godot, você pode importar
arquivos FBX diretamente para
Godot, por volta
da era dos quatro E se você estiver
trabalhando em quatro pontos dois, talvez ainda
precise fazer isso. Mas há um
conversor FBX externo que Godot usa. E, por exemplo, se eu clicar
duas vezes
nisso, se você clicar
duas vezes nele, verá que o material não foi
configurado corretamente. E você também pode
ver que tinha a opção de usar um importador
específico Agora, o UFBX é, obviamente, o importador que agora vem incluído em 43 com Godot, então você deve ser Então, o problema aqui é
que, novamente, o material, mesmo que eles tenham
fornecido um material, ele não tem uma textura, mas eles forneceram
a textura para nós. Então, o que eu já
fiz foi criar um novo material padrão e, para fazer isso
, para fazer isso
, basta
clicar com o botão direito do mouse em
criar novo recurso
e, em seguida, no material padrão. Por isso, criamos arquivos de material
padrão em nossos
modelos existentes até agora. Então, esta é a primeira vez
que estamos realmente usando um arquivo de material externo. Mas o que eu fiz foi pegar
a pele existente fornecida e arrastá-la
até aqui até o albedo Então, felizmente, a árvore
em si foi mapeada corretamente, então tudo o que foi
necessário foi vinculá-la novamente Então, se formos até Young Tree e fizermos uma nova cena herdada, selecionaremos várias vezes para obter tudo
isso E então abrimos as malhas, podemos. Novamente, temos um
material sob a superfície, que não é o que queremos Portanto, podemos configurá-los para torná-los recursivos
exclusivos novamente. E então, sob a superfície, podemos mudar o material para
nosso novo material padrão. E agora OK, parece que esse
modelo em particular não está funcionando bem. Mas de qualquer forma, aqui está
um
que eu acompanhei todo esse processo anteriormente com um dos outros
modelos, e aqui está. Então isso realmente funcionou. Então, a moral da
história é que, infelizmente, às vezes você
precisa fazer um pouco de massagem para que modelos disponíveis
gratuitamente funcionem em Godot Mas os problemas mais comuns são materiais quebrados
ou texturas quebradas, e acabei de mostrar
duas maneiras de corrigir isso Então, boa sorte. Vamos, hum, vamos realmente colocar essa árvore que atualmente funciona
em nossa cena de árvore. Então, vamos clicar
duas vezes nele para abri-lo. Vamos nos livrar dessas
duas instâncias de malha. E então vamos
Onde estava nossa árvore? Vamos arrastar aquela árvore até
aqui agora que temos uma árvore. Então, se
guardarmos isso e voltarmos para nossa arena, novamente, as árvores
parecerão bem lindas Então, vamos nos livrar dessa
causa que não funciona. Ok, então é assim que se exporta ou importa
modelos para Godot E em nossa próxima aula, vamos
embelezar um pouco a arena, e esse será o
fim do curso. Então eu vou te ver lá.
37. Como aprimorar o terreno de nível: Mamãe, hmm. Mamãe, hmm. Bem vindo de volta. Nesta lição,
nossa lição final, faremos
algumas coisas. A primeira coisa que
vamos fazer é mudar nosso Skybox Então, você deve se lembrar,
e eu já deletei
aqui que tínhamos uma skybox que vinha das configurações de céu padrão
produzidas pelo Godot Nós podemos mudar isso. Então, se voltarmos para nossa
arena e formos para o
nó do Meio Ambiente Mundial que
criamos há muitas, muitas lições, podemos clicar nele para expandi-lo
e, em seguida, clicar
no céu. E eu já o
expandi aqui. Agora, antes havia uma textura celeste
processual nesta caixa, que eu
já limpei Podemos mudar isso para
várias coisas. Então, vamos dar a ele outro novo
céu, e vamos abri-lo. E agora temos a opção de
definir um material celeste. Agora, antes de ser configurado para
um material celeste processual, assim que o tínhamos aqui Mas também podemos fornecer o que é
chamado de material panorâmico do céu. E o céu panorâmico é como você adiciona caixas celestes gráficas reais Agora, criar uma textura panorâmica está além do escopo do que
estamos tentando fazer aqui, mas eu
forneci uma do pacote All Sky de Richard Whitlock, que está disponível na Godot Asset
Library Ele fornece várias cenas
existentes do Godot Skybox e dez texturas diferentes do
skybox Então, eu forneci um aqui. E se você clicar
no Skybox para abri-lo, verá que
tem a opção fornecer um panorama Agora, por algum motivo,
bem, tudo bem, agora vai funcionar. Ótimo. Mas antes eu tinha um
problema em arrastar isso Então, se você arrastar a textura para esse slot,
agora você receberá uma skybox A outra opção, é
claro, é clicar e
carregar ou carregar rapidamente. Mas uma vez que você tenha feito isso, você pode ver agora que você tem
um lindo céu panorâmico, e eu preciso Woop, lá vamos nós Lindo, aí vamos nós. Bem, você entendeu.
Mas de qualquer forma, sim, esse céu agora cobre toda
a nossa cena
ambiental e parece muito bom Parece muito melhor do que
o original. Então, a seguir, vamos
consertar a serena. A primeira coisa que
vamos fazer é adicionar limites
reais. Então, se você se lembra de quando provavelmente testava
coisas e brincava antes. É possível
sair da borda da arena
e, como não estamos
aplicando nenhuma gravidade, isso significa que nossos tanques
vão flutuar para o espaço Isso não acontecerá com os
tanques inimigos porque eles só podem
ir ou só podem ir
de NavPoint para NavPoint, mas definitivamente pode acontecer o jogador, e isso é Então, vamos corrigir isso.
A maneira
mais fácil corrigir isso é simplesmente fornecer algumas colinas de colisão ao redor
da borda do monte Então, vamos pegar uma colina. Vamos clicar com o botão direito do mouse
e duplicar essa colina
e, em seguida, precisamos de
Editable Children E então precisamos
tornar as malhas únicas. E a colisão é única para
que possamos alterá-las. Agora, vamos
renomear esta colina para fazer
fronteira com a colina norte E vamos mover isso para cá. Vamos Whoa,
isso é interessante. Mudaremos a orientação
desta colina de tal forma que Onde está nossa transformação.
Onde está nossa transformação. Precisamos dos 90 graus dessa forma. Sim. Ok. E vamos sim, vamos
falar um pouco sobre isso. Aumente um pouco. E agora podemos mudar
a malha real. Então, se formos aqui, temos XYZ. Vamos mudar a
direção X para 100, que é o Whoa,
isso não está certo Vamos mudar o fogo,
é porque ele é girado. Tudo bem, vamos mudar
a direção Z lá. Vamos trazer isso aqui. E nós temos um
desses. E então vamos duplicar tudo
isso Mude para Sul. Arraste-o para baixo. Opa. Border Hill South. E podemos simplesmente
duplicar os dois e
girá-los de forma
que fiquem para leste e oeste E eu esqueci de
mudar a colisão, então vamos corrigir isso em um momento Faça essa rotação. Negativo 90. A orientação está um pouco errada. Podemos resolver isso com bastante facilidade. Também pode simplesmente
esticá-los para que
fiquem melhores Z um em cinco. Sim. E então faremos
o mesmo para East Hill. Sim, tudo bem, eu acho que eles são. Tudo bem, parece que
temos uma pequena lacuna lá. Isso não está certo. Ok. Isso é melhor. E agora temos que
consertar as colisões. Então, voltamos às nossas formas de
colisão
e, felizmente, podemos
simplesmente editá-las aqui. E, claro,
teremos que redefinir suas transformações E a orientação está um
pouco errada, mas tudo bem. Vamos simplesmente prolongar
isso desse jeito. Arraste isso aqui e
arraste isso aqui. E então faça o mesmo com
os outros três. Essa está correta. Só temos que girá-lo novamente agora. E reoriente-o um pouco. Faça o mesmo com os outros dois. Sim, parece que os dois
são bons. Só temos que
mudar a rotação. Zero. E eles estão
errados em termos de Z, então vamos corrigir isso. Ok. Agora, não devemos
mais ser capazes de viajar para o espaço. Agora, vamos consertar esse terreno que parece
meio feio Então, da mesma forma que fizemos antes, forneci um conjunto extra de texturas para este projeto na pasta Graphics Desert
Textures Então, agora podemos simplesmente
criar um novo material, criar um novo material
padrão de recurso. Sim, vamos chamá-lo.
Deserto. Para onde foi isso? Aí está. Tudo bem, e agora que podemos, não
precisaremos de sombreamento, mas não precisaremos da cor
do vértice Precisaremos do nosso albedo. E isso não vai arrastar o
Rock 29 até lá. Ok, você vai me dar
você vai me dar dor. Rock 29 Albedo Rock Drag. Lá vamos nós. E não precisamos, realmente
não precisamos de metal Precisamos de aspereza
e precisamos de normalidade. Então, aqui está nossa rugosidade. Por que isso continua desaparecendo? Mapa normal. Ativado. E, novamente, temos que ter certeza de
usar o correto,
que é o GL normal E, na verdade, temos um
para oclusão ambiental, então vamos ativá-lo
e ver o que Pare. As alegrias do software de código
aberto, às vezes ele só
quer agir de forma boba Tudo bem E temos um mapa de deslocamento, então
ele habilita a altura E eu vou fazer isso
da maneira normal desta vez. Gráficos,
texturas do deserto, deslocamento. Ok, Dan,
voltaremos para nossa arena e queremos definir
o material da nossa malha terrestre. Instância
três D. Então abra nossa malha e trocaremos o material. Podemos clicar em carregá-lo? Não. Velho. Árvores do deserto. Lá vamos nós. Ok, então é
meio grande. E a maneira mais rápida de corrigir isso é alterar a
escala do UV Então, se abrirmos a textura
e descermos para UV, podemos mudar a escala aqui. Então, vamos configurá-lo para 0,5. E isso não é bom.
Vamos configurá-lo para 1,5. Isso é um pouco melhor. A iluminação é meio estranha. Provavelmente tem
algo a ver com o pôr do sol, eu acho Vamos desligar isso.
Não, não é o sol Hmm. Ok, aí está para que possamos ver, na verdade, há algo
interessante acontecendo aqui. Então, o que temos? Ok, então parece que a textura do
Rock 29 estava ruim. Vamos usar a cor Rock 29. Veja se isso resolve o problema.
Sim, muito melhor. Ok. Eu gosto disso. Tudo bem, agora que
temos uma boa aparência, podemos fornecer o mesmo
material novamente para nossas colinas E vamos fazer isso
diretamente na própria colina, é por isso
que usar
cenas herdadas é maravilhoso Então, vamos voltar para
Hill, expandir nossa malha. E substitua nosso recurso, e agora podemos carregá-lo rapidamente porque já o
usamos, abra, boom. Tudo bem. Essas
colinas parecem melhores. Pelo menos em termos de textura.
Quero dizer, obviamente, ainda
estamos usando uma malha
muito inadequada Mas, tudo bem,
e, claro,
nossas malhas de borda não estão usando o mesmo material porque as
tornamos únicas,
então temos que
configurá-las então temos que
configurá-las E, claro, eles
parecem terríveis. Então, temos que mudar o dimensionamento da
nossa interface de usuário novamente. Nós redefinimos isso para um.
Ainda parece uma porcaria Vamos para Não. Ok, então, neste momento, teremos que alterar a escala
da textura em
apenas uma direção Então, há um pequeno ícone de
link aqui. Então, se você clicar
nele, isso significa que se você mudar e se
certificar de que é branco. Se você mudar todos eles, isso significa
que todos
eles serão alterados. Mas se você não quiser
que seja esse o caso, clique nele novamente para
que pareça quebrado. E nesse caso,
acho que só
queremos mudar o X e o Z. Então, vamos lá, está
mudando tudo, não é? E nós
não queremos isso. Ah, certo, obviamente,
porque estamos usando as mesmas texturas que usamos antes ou para as outras malhas Então, teremos que
torná-los únicos novamente. E, felizmente, podemos fazer isso simplesmente clicando com o botão direito do mouse
em todos eles, expandindo, acessando o material
e, em seguida, fazendo make Unique. E agora devemos ser capazes de
consertá-los sem quebrar
todo o resto. Mas vamos voltar ao
nosso deserto original. Verifique se as
balanças estão corretas. Sim, eles eram originalmente
1,5, o que era bom. E agora podemos mudar
tudo isso, espero. Material B. Agora, esses materiais
devem ser únicos. Um UV. Lá vamos nós. Essa é a coisa
cinco. Lá vamos nós. Isso está começando a
parecer um pouco melhor. Tudo bem. Não é perfeito. Talvez possamos fazer 15? Sim, isso parece
infinitamente melhor. Tudo bem. Agora, vamos rodar nosso
jogo e ver como fica. Tudo bem Acho que neste
momento, talvez
queiramos
desligá-lo da neblina Mas onde está o
tanque inimigo? Aí está ele. O dimensionamento da textura ainda
é um pouco pequeno. Gostaríamos do material. Tudo bem, vamos desligar a
neblina na câmera ou no ambiente
. Nevoeiro. Ah, isso mesmo. Porque está ativado na
câmera. Nós fizemos isso. Então, vamos voltar à nossa cena
original do tanque ir até a câmera
e desligar uma névoa Z. Tudo bem, agora vamos tentar
isso de novo. Certo. Parece muito melhor.
Obviamente, queremos brincar com o sol direcional porque agora tudo
está na escuridão total Então, vamos fazer isso. Vamos
voltar à nossa cena de jogo. E, na verdade, está no mundo
da arena Environment
Directional Light E podemos levantar isso Tudo bem, então onde está
o Oh, aí está Aí está a pequena
flecha. Lá vamos nós. Então, se girarmos para baixo, agora o mapa está mais
diretamente na luz do sol, vamos arrastá-lo até
aqui para que possamos alguma sombra acontecendo Ok, isso deve parecer
infinitamente melhor. Sim. Então, neste momento, você pode
brincar com ela para obter, na verdade, eu sinto que essa textura ainda tem uma aparência
muito desagradável. Vamos voltar para aqui. E vamos mudar a escala
UV para três. Ok. Está parecendo melhor. Neste ponto, é
apenas uma questão de ajustar até que fique do jeito que você
gostaria Como você pode ver, a textura parece infinitamente
melhor no minimapa, mas está meio
achatada e inclinada aqui por causa do tamanho da arena Mas se você realmente
for para as colinas, parece muito melhor. Embora, sim, ainda seja
meio estranho lá embaixo. De qualquer forma, isso nos leva
ao final do nosso curso. Sinta-se à vontade para continuar
brincando com as configurações de texturas, iluminação e tudo mais até conseguir
algo de que goste, porque neste
momento, como eu disse, é literalmente apenas um
ajuste Espero que você tenha gostado deste
curso e se junte
a mim para analisar os fundamentos do desenvolvimento de
três D em Godot, e nos vemos
na próxima vez
38. Como exportar seu jogo: Vamos dar uma
olhada rápida em como exportar seu jogo para que outras pessoas
possam jogar sua obra-prima Você exportará seu jogo
em Project Export e precisará baixar as predefinições relevantes
para o seu sistema Então, por exemplo, se eu quisesse exportar
para a área de trabalho do Windows, clicaria no botão Adicionar
e selecionaria Área de trabalho do Windows. E então, é claro, se não
tivermos nenhuma
predefinição disponível, isso nos dirá que
não há modelos de exportação disponíveis
no caminho esperado Portanto, teríamos que
baixá-los, gerenciar modelos de exportação, baixar e instalar
a partir do melhor espelho disponível. E uma vez feito isso, você deve ser capaz de
exportar seu projeto. Você pode alterar qualquer uma das configurações disponíveis,
se necessário. Por exemplo, você pode
adicionar um ícone ou alterar
qualquer outra coisa. Mas se você realmente não sabe o que
essas configurações significam
, não há problema em
deixá-las como padrão.
39. Projeto do curso: crie seu próprio jogo 3D: É hora de colocar em prática tudo o que
você aprendeu. Para o projeto de classe, você
criará sua própria versão
do jogo Zone Battle usando os sistemas que desenvolvemos
ao longo deste curso. O objetivo não é copiar
tudo perfeitamente, mas aplicar os conceitos básicos e tornar o projeto seu. Seu projeto pode incluir um tanque jogável com controles de movimento
e torre,
um ambiente em três D
com iluminação, inimigos com comportamento básico de IA, inimigos com comportamento básico de IA efeitos
sonoros e elementos de interface do usuário,
como pontuação ou Você está convidado a
personalizar o projeto. Na verdade, você é encorajado a fazê-lo. Mude o layout do nível,
ajuste o comportamento do inimigo. Experimente com materiais ou
adicione seus próprios pequenos recursos. Quando estiver pronto,
envie capturas de tela ou um pequeno clipe de jogabilidade do seu projeto para a galeria do
projeto Você também pode incluir uma breve
descrição do que você construiu e quais peças você
achou mais interessantes
ou desafiadoras. Vou verificar os projetos
e deixar um feedback. Estou ansioso
para ver seus jogos.
40. Parabéns! O que vem a seguir?: Parabéns. Você
chegou ao final do curso. Você aprendeu
a trabalhar dentro do Gdo, navegar em três espaços D,
criar ambientes,
implementar física, controles, IA,
áudio, interface do usuário e
sistemas de jogos. Certamente muito. E você
juntou todas essas peças em um jogo
completo de três D. Mais importante ainda, agora você
entende como os GidObjects são estruturados e como diferentes sistemas se comunicam entre si Essa base é
o que permite que você
continue aprendendo e
experimentando por conta própria Obrigado por fazer este curso e por criar ao meu lado. Estou empolgado em ver o futuro sua
jornada de desenvolvimento de jogos. Boa sorte e boa criação.