Masterclass de desenvolvimento de jogos Godot 3D: crie um jogo de batalha de tanques | Skillademia Academy | Skillshare

Velocidade de reprodução


1.0x


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

Masterclass de desenvolvimento de jogos Godot 3D: crie um jogo de batalha de tanques

teacher avatar Skillademia Academy, Creative Skills for the Future

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Aulas neste curso

    • 1.

      Sejam bem-vindos à masterclass de Godot 3D!

      1:02

    • 2.

      Instalando o Godot

      1:40

    • 3.

      Visão geral do projeto: Batalha de zona

      3:44

    • 4.

      Navegando no Godot: a janela principal, a árvore de cenário e o inspetor

      4:46

    • 5.

      Como navegar no Godot: a janela do jogo e navegação básica no espaço 3D

      5:37

    • 6.

      Primitivos e espaço 3D — rotação, escala, tradução

      14:36

    • 7.

      Materiais

      7:51

    • 8.

      Como criar objetos complexos a partir de primitivos: o tanque

      26:30

    • 9.

      Como criar o campo de jogo

      16:03

    • 10.

      O nó Camera3D

      8:44

    • 11.

      Vetores

      12:11

    • 12.

      O nó CharacterBody3D

      10:44

    • 13.

      Reação à entrada do jogador: movimento

      26:53

    • 14.

      Reação à entrada do jogador: controlando a torre

      10:54

    • 15.

      Colisão

      13:25

    • 16.

      O nó RigidBody — disparando uma concha

      53:09

    • 17.

      Ambiente: iluminação mundial e sol global

      6:35

    • 18.

      Jogabilidade: adicionando tanques inimigos por meio de cenas herdadas

      5:13

    • 19.

      Como destruir os tanques

      6:46

    • 20.

      IA: máquinas de estado

      16:33

    • 21.

      Adicionando uma máquina de estado ao tanque inimigo via ECS

      50:35

    • 22.

      Adicionando uma máquina de estado ao tanque inimigo via ECS, parte 2

      22:19

    • 23.

      SFX: áudio 3D

      12:49

    • 24.

      Camadas básicas de UI

      14:34

    • 25.

      Eventos e sinais de UI - Score

      18:27

    • 26.

      Criando um minimapa

      6:52

    • 27.

      UI 3D com nós Label3D

      3:42

    • 28.

      Menu inicial

      12:54

    • 29.

      Menu de pausa

      6:37

    • 30.

      Gerenciador de jogos: estados de início/fim

      31:37

    • 31.

      Sistema de aparecimento de inimigos

      53:16

    • 32.

      Múltiplos ângulos de câmera

      8:33

    • 33.

      Melhores explosões com efeitos de partículas

      28:49

    • 34.

      Como texturizar seus tanques: revisitando materiais

      5:30

    • 35.

      Decalques

      4:01

    • 36.

      Importando modelos externos

      9:45

    • 37.

      Como aprimorar o terreno de nível

      21:15

    • 38.

      Como exportar seu jogo

      1:28

    • 39.

      Projeto do curso: crie seu próprio jogo 3D

      0:47

    • 40.

      Parabéns! O que vem a seguir?

      0:32

  • --
  • Nível iniciante
  • Nível intermediário
  • Nível avançado
  • Todos os níveis

Gerado pela comunidade

O nível é determinado pela opinião da maioria dos estudantes que avaliaram este curso. Mostramos a recomendação do professor até que sejam coletadas as respostas de pelo menos 5 estudantes.

9

Estudantes

1

Projeto

Sobre este curso

O Godot se tornou um dos motores de jogos de código aberto mais interessantes disponíveis atualmente — poderoso, flexível e completamente gratuito. Com o lançamento do Godot 4, o desenvolvimento 3D em tempo real é mais capaz do que nunca, abrindo as portas para a criação de jogos completos sem depender de ferramentas proprietárias.

Neste curso, você vai aprender o desenvolvimento de jogos 3D do zero, construindo um projeto completo para jogo chamado Zone Battle. Em vez de demonstrações isoladas, este curso se concentra em sistemas reais usados em jogos reais — desde movimento e combate até UI, IA, áudio e exportação.

Começaremos instalando o Godot e se familiarizando com o editor, cenas, nós e navegação 3D. A partir daí, você construirá recursos de jogos usando primitivas, criará materiais, configurará câmeras, iluminação e ambientes, e dará vida a tudo com física e controles do jogador.

À medida que o projeto cresce, você vai implementar sistemas de jogo, como spawning de inimigos, IA de tanques usando máquinas estatais, mecânica de colisão e de disparo, pontuação, menus, minimapas, efeitos sonoros e explosões de partículas. Você também vai aprender a estruturar um jogo corretamente usando gerenciadores, cenas herdadas e componentes reutilizáveis.

Este curso é ministrado usando a versão 4.3 estável do Godot, mas as técnicas que você vai aprender — organização de cenas, física, lógica de IA, sistemas de UI e arquitetura de jogo são habilidades fundamentais que se aplicam em diferentes versões do Godot.

Ao final do curso, você não entenderá apenas como o Godot funciona, terá criado e exportado seu próprio jogo 3D completo e obtido uma base sólida para continuar a desenvolver seus próprios projetos.


O que você aprenderá

  • Como navegar e usar o editor Godot para projetos 3D
  • Conceitos 3D principais: transformações, materiais, câmeras, iluminação e física
  • Como construir objetos e ambientes complexos a partir de primitivos simples
  • Movimento do jogador, controle de torre, filmagem e sistemas de colisão
  • Como criar IA inimiga usando máquinas de estado e lógica no estilo ECS
  • Adicionando efeitos sonoros, UI, sistemas de pontuação, minimapas e menus
  • Trabalhando com partículas, adesivos, modelos externos e aprimoramentos de terrenos
  • Estruturando um jogo completo com gerentes, spawners e estados
  • Como exportar seu jogo 3D finalizado

Requisitos

  • Um computador capaz de executar o Godot 4.x
  • Godot instalado (download gratuito)
  • Não é necessário ter experiência anterior com o Godot
  • Programação básica ou curiosidade de desenvolvimento de jogos é útil, mas não obrigatória

Para quem é este curso

  • Iniciantes que querem aprender o desenvolvimento de jogos 3D do zero
  • Usuários do Godot fazendo a transição de 2D para 3D
  • Desenvolvedores independentes explorando o Godot 4
  • Estudantes e entusiastas de design de jogos
  • Desenvolvedores que procuram uma experiência de aprendizagem completa baseada em projetos

Conheça seu professor

Teacher Profile Image

Skillademia Academy

Creative Skills for the Future

Professor

NEW CLASS: Figma Beginner Masterclass: Learn UI Design Step by Step

Figma can feel intimidating when you first open it.

There are so many tools, panels, and features that many beginners don't know where to start, or what actually matters when designing an interface.

That's exactly what this class is designed to solve.

In this beginner-friendly class, we'll build a complete UI project together while learning the fundamentals of Figma step by step. You'll learn how to structure layouts, work with typography and colors, organize your designs, and create simple interactive prototypes.

The focus isn't just on learning the software, but on understanding the workflow behind modern UI design in a practical and approachable way.

If you'... Visualizar o perfil completo

Level: Beginner

Nota do curso

As expectativas foram atingidas?
    Superou!
  • 0%
  • Sim
  • 0%
  • Um pouco
  • 0%
  • Não
  • 0%

Por que fazer parte da Skillshare?

Faça cursos premiados Skillshare Original

Cada curso possui aulas curtas e projetos práticos

Sua assinatura apoia os professores da Skillshare

Aprenda em qualquer lugar

Faça cursos em qualquer lugar com o aplicativo da Skillshare. Assista no avião, no metrô ou em qualquer lugar que funcione melhor para você, por streaming ou download.

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.