Neste curso completo e gratuito, você vai aprender a criar o seu primeiro jogo 2D com a Godot.
Um jogo de plataforma inspirado em Mario com níveis, moedas, um jogador que você controla
com a habilidade de matar inimigos ao pular sobre eles, passar de fase, como você verá agora.
E muito mais
Você vai aprender boas práticas programando jogos com a Godot engine.
Este é um curso para iniciantes em programação, onde nós vamos, bem  passo a passo, aos poucos
te mostrar cada pedaço, pra você começar a desenvolver jogos,
mas ainda assim mostrar boas práticas ao criar jogos com a Godot ou programando jogos em geral.
Se você não tem qualquer experiência com programação, o convido a assistir à nossa introdução ao GDScript para iniciantes.
É totalmente grátis. Link na descrição abaixo.
Nesta primeira parte, que tem duas horas de duração, você vai aprender a fazer o jogador e o inimigo do zero.
Cada etapa até o final. Para fazer a câmera suave que você vê na tela. Uma fase base.
E tudo isso com muitos detalhes sobre como a Godot funciona.
Na próxima parte nós vamos fazer o design das fases. Criar moedas, criar portais que mudam de fase.
E, mais importante. Aprender mais como trabalhar com a câmera, fazer transição de cena. Esse tipo de coisa.
Antes de começarmos, gostaria de dizer que essa série é patrocinada pelo nosso curso premium.
Se você quer ir mais fundo no desenvolvimento de jogos, criar jogos mais polidos  ou apenas apoiar nosso trabalho.
Nós temos um curso mais avançado sobre personagens vistos de lado e que já está disponível.
Esta série para iniciantes também tem uma versão extendida que inclui conteúdo bônus
como essa aula de como adicionar rampas. Exercícios, desafios, perguntas, mais informação no geral.
As vendas desses cursos nos permitem criar todo esse conteúdo gratuito. Se você está interessado, os links estão na descrição.
Mas agora, vamos começar a criar o projeto. Aproveite.
O código fonte deste projeto, junto com os recursos para começar estão no github, link na descrição.
Você deve fazer o download o arquivo startassets.zip e então ir ao seu gerenciador de arquivos.
Botão direito e "extrair aqui", para ter as imagens que você vai precisar para fazer o jogo.
Você pode criar suas próprias, mas isso vai te ajudar a começar mais rápido.
Então eu vou voltar e renomear essa pasta para "assets".
Então eu vou criar uma nova pasta para guardar o meu projeto da Godot.
Vamos chamar de "platformer" e copiar o caminho até ele. Eu vou abrir a Godot.
Criar um novo projeto. E vamos chamá-lo de "Platformer" também.
Só vou incluir um lembrete de que é um tutorial.
E colar o caminho para a pasta onde eu quero guardar esse projeto.
Você pode também clicar no botão "browse" e navegar o seu computador
até a pasta na qual você quer criar o projeto. Ela deve estar vazia.
Então clique em "Select Current Folder". E você pode "criar e editar" seu projeto.
Isso vai abrir a visão 3D. Nós queremos trabalhar na 2D, aqui.
Então clique em "2D" no topo da tela. E nós vamos voltar ao gerenciador de arquivos.
Eu vou voltar à pasta onde eu tenho minha pasta "assets"
E então arrastar e soltar a pasta "assets" dentro da pasta do projeto "Platformer".
Para que nossas imagens fiquem acessíveis dentro do editor da Godot.
Uma vez que você faça isso e volte para a Godot. Você vai ver na aba "FileSystem" a pasta "assets" com as imagens dentro.
Nós vamos começar o projeto criando o personagem e começar com a movimentação de personagem.
Nós queremos uma nova pasta na aba "FileSystem" para guardar nossas cenas.
Os personagens que criaremos e o código que escreveremos.
Eu recomendo que usemos uma pasta chamada "source" para representar o código fonte para isso.
Então clique com o botão direito em "res://", essa é a raíz do seu projeto
E em "Nova Pasta" (New Folder).
Chame a pasta de "source" ou abrevie para "src".
Aqui nós vamos guardar cada arquivo GDScript e também cada cena que criarmos
uma vez que eles são parte do código do seu jogo.
Então vamos começar a fazer o personagem, o "player".
Nós queremos criar uma cena 2D, mas nós usaremos um nó personalizado para isso.
Então, clique em Nó Personalizado (Custom Node). A princípio queremos criar um KinematicBody2D.
KinematicBody2D é um nó que podemos controlar, mover pelo mapa
e que detecta colisões, bater em uma parede, no chão, essas coisas.
Vamos renomear como "Player", nesse caso.
E um nó como este precisa de um forma de colisão.
Uma forma geométrica para detectar colisões com o mundo.
Então nós vamos adicionar uma. Selecione o nó "Player" clique no + ao topo.
E, dessa vez, você procura por "CollisionShape2D". Então comece digitando "collision".
E você vai encontrá-lo na parte debaixo da janela. Crie um desses.
E nele você deve adicionar uma forma geométrica, um recurso, ao nó.
Para fazer isso, temos que ir para o lado direito, ao "Inspetor" (Inspector).
Do lado de "Shape". Clique no texto "Empty" e então crie um novo RectangleShape2D.
Uma vez criado você verá um pequeno retângulo que apareceu na tela.
Então você pode aproximar a visão com a roda do mouse.
E então clique e arraste os pontos para editar a forma.
Note que, para fazer isso, você precisa ter o modo de seleção ativado no canto superior esquerdo da interface.
Para definir o tamanho deste retângulo, nós primeiro vamos adicionar a imagem do jogador.
Então selecione o nó do jogador no topo. Nós vamos adicionar uma Sprite como filha dele.
Nós precisamos dele selecionado para fazer isso e então clique para expandir a pasta "assets".
Procure pelo arquivo "player.png" e então clique e arraste para dentro da tela.
Ele vai ser automaticamente adicionado com o tipo que você selecionar aqui. Escolha Sprite.
Clique em "Ok" para adicionar a Sprite e você a verá adicionada como filha do nó "Player" logo abaixo do CollisionPlayer2D.
Agora, o nó que estiver mais em baixo na lista vai ser desenhado por cima dos outros.
A ordem de desenho é de cima para baixo, por padrão.
Então você pode clicar e arrastar o "Player" para cima do CollisionShape2D para que a gente veja o retângulo na frente dele.
Então, nós queremos mover o jogador de forma que os dois eixos que cruzam aqui
Estejam na parte de baixo da Sprite. Nós vamos usá-los para representar a origem do jogador.
Você pode clicar e arrastar, com o modo de seleção ativado, para mover a Sprite.
Quando você faz isso, a princípio é um pouco impreciso, porque você pode mover livremente.
Mas nós queremos posicionar nosso personagem precisamente na origem.
Para fazer isso, precisamos usar a funcionalidade de "snap".
Então, na barra de ferramentas, clique no ímã para ativar o snap.
E então clique nos três pontos para configurá-lo. Por padrão nós temos "Encaixar na Grade" (Snap to grid) ativado.
Você pode ativar ou desagivar com a tecla G.
Como você pode ver, ele desenha a grade e quando você move o personagem
o centro dele vai encaixar na grade.
O problema é que não é e isso que a gente quer ainda.
Nós queremos alinhar a parte de baixo do personagem com a origem da cena.
Então clique nos três pontos e desative "Encaixar na Grade".
Nós vamos ativar "Usar Snap de Píxel" (Use pixel snap) em vez disso.
Pressione G de novo para esconder a grade. E então clique e arraste.
E você verá que o personagem se move em pequenos intervalos de um pixel de cada vez.
E então você posicioná-lo de forma que e ele se alinhe com o eixo x que temos aqui desenhado em vermelho.
Você deve selecionar o CollisionShape2D e então movê-lo de forma que ele fique centralizado ao personagem.
Então mova-o para cima. Você pode segurar a tecla shift para limitar o movimento a apenas um eixo.
E então alinhá-lo ao centro do personagem.
Clique e arraste em uma bolinha para aumentá-lo.
Você vai ver que ele expande para os dois lados ao mesmo tempo.
Ele aumenta a extensão do seu retângulo, não apenas um lado.
E você deve fazer o mesmo para o eixo y.
O problema é que não queremos que ele cubra todo o personagem.
Isso representa a colisão do jogador, a parte que vai parar em paredes.
E, no geral, a gente "trapaceia" um pouco. Fazemos com que a colisão seja um pouco menor que a imagem
pra que o personagem não fique preso quando uma parte que está na parte arredondada acerte alguma coisa.
Então nós vamos fazer ele ser um pouco menor que a imagem. Pode fazer algo parecido com isso.
E, finalmente, vamos adicionar um script ao personagem. Só pra começar.
Nós vamos adicionar dois scripts ao projeto.
Um específico para o jogador e outro que será compartilhado pelo inimigo e o jogador.
O jogador e o inimigo irão se mover pelo jogo. Então terão código em comum. Lógica.
Nós podemos criar um script pai que eles irão herdar ou estender
e isso vai nos permitir compartilhar código entre os dois em vez de repeti-lo duas vezes.
Uma vez no script do player e outra no script do inimigo.
Enfim, para começar, vamos salvar a cena. Então pressione ctrl-s para fazer isso.
Vá para a pasta raíz e nós vamos criar uma nova pasta chamada "Actors"
onde nós vamos guardar todos os "actors" do nosso jogo. O jogador e o inimigo, nesse caso.
Clique em OK. Você vai parar dentro da pasta Actors e então salve seu arquivo como "Player.tscn".
E então, com o Player selecionado, clique no ícone "Adicionar script" no topo da árvore de nós.
Clique e o caminho do script vai estar dentro da pasta Actors automaticamente.
E o nome do script vai ser o mesmo do nó "Player.gd"
Nós vamos usar a linguagem GDScript. Automaticamente ele vai herdar o tipo KinematicBody2D
E para o "Modelo" (Template) nós vamos usar o modelo "Empty".
Clique no botão "Criar" (Create) para criar o arquivo do script.
Vamos aproximar um pouquinho aqui e nós temos o script do jogador.
Nós vamos criar um segundo script através editor de scripts.
Como pode ver, nós estamos na visão de script no topo do editor.
Vá para o menu "Arquivo" (File) e crie um novo script.
Nós vamos mudar a pasta. Clique no ícone de pasta para fazer isso.
Mude para a pasta Actors e chame-o "Actor.gd".
Essa será a classe base que tanto o jogador quanto o inimigo vão estender.
Clique no botão "Avrir" (Open) para definir esse caminho e crie o script Actor.
Automaticamente é aberto o script Actor.gd no editor de scripts.
Nós podemos registar esse arquivo como uma classe que podemos usar, após a palavra reservada "extends".
A palavra "extends" quer dizer: esse script vai ter todas as funcionalidades do que está logo após ela. Nesse caso, Node.
Para registrar nosso script Actor como um script que poderemos usar no jogador e no inimigo
use a palavra reservada class_name logo abaixo da linha que tem "extends".
E então você pode digitar o nome que quer usar. No nosso caso "Actor".
Salve, e depois disso volte para o script do jogador Player.gd.
E no lugar de "extends KinematicBody2D" você vai digitar "extends Actor".
Agora tenho que fazer uma mudança na nossa classe Actor. O tipo que essa classe estende é muito importante.
Se o seu nó é do tipo KinematicBody2D, seu script deve estender KinematicBody2D ou uma classe filha.
Nós devemos digitar "extends KinematicBody2D" aqui, no topo do nosso script Actor.gd.
Dessa forma, nós estamos criando uma nova classe Actor que é do tipo KinematicBody2D
e que possui todas as suas funcionalidades. Se nós formos na documentação podemos ver
que esse nó e todos os seus ancestrais, aqui após "Herda de" (Inherits)
PhysicsBody2D < CollisionObject2D < Node2D e etc, até Object
então ele terá todas as funcionalidades de todas essas classes, mais o que nós escreveremos no script Actor.gd
Vou fechar o KinematicBody2D por agora
e nós podemos começar a programar o Actor.gd. Vou fechar o Player.gd também, por enquanto.
Vamos começar a programar a movimentação. Vamos passo a passo bem devagar.
Então, primeiro vamos fazer nosso personagem se mover, de alguma forma, e depois nós melhoramos isso.
Como nosso jogador estende o script Actor ele também vai executar todo o código que escrevermos no Actor.gd
Nós vamos começar adicionando uma função que é própria da Godot, que vem junto com a engine chamada _physics_process
Digite a palavra reservada func, para definir uma função, e então digite _physics_process.
Se o seu autocompletar não está como o meu, com ": float" e a seta logo após isso, é por causa das suas configurações de editor
Vá em Editor e em Configurações do Editor (Editor Settings) e procure por "type".
Na categoria "Completion", "Add Type Hints" deve estar ativado.
Uma vez feito isso, quando começar a digitar o nome da função, você vai ter o autocompletar com tipagem.
Nós vamos trabalhar dessa forma, então o convido a ativar aquela configuração.
_physics_process é uma função que, se você definí-la em um dos seus nós, a Godot vai executá-la automaticamente a cada frame do seu jogo.
Normalmente entre 30 e 60 vezes por segundo. É onde, geralmente, você quer definir a movimentação do jogador.
Note que existem dois. Um é chamado _process e o outro _physics_process.
Para personagens como o seu jogador, ou qualquer coisa que envolve física, que vai colidir, detectar o chão,
ou as paparedes, você deve usar _physics_process.
Agora nós vamos fazer o personagem se mover aqui. E para isso nós temos uma função que é definida no KinematicBody2D
é chamada move_and_slide.
Essa função pede por linear_velocity (velocidade linear), do tipo Vector2, então nós vamos criar esse Vector2
Acima do move_and_slide em uma nova variável
Você pode apertar ctrl-shift-enter para criar uma nova linha acima da que você estava.
Nós vamos criar uma nova variável aqui, que vamos chamar de "velocity", nossa velocidade linear.
Ela vai ser um Vector2. Então você pode digitar : =
para informar à Godot que o tipo dessa variável será o mesmo do que será digitado depois.
Nesse caso, será um Vector2.
Um Vector2 possui dois valores. Um no eixo x e outro no eixo y, que representam uma posição ou uma distância, se você quiser.
No nosso caso, uma velocidade.
No eixo x nós vamos colocar 300 e no y 0.
Isso significa que nós queremos que nosso personagem ande 300 píxeis por segundo no eixo x
E 0 píxeis por segundo no eixo y.
E no nosso move_and_slide, digite "velocity" entre os parênteses
Nós vamos mover o nosso personagem usando esse valor guardado na variável "velocity"
Voltando para a nossa cena, nós podemos rodá-la apertando F6 para ver o resultado.
O problema é que se você olhar o personagem, ele está fora do retângulo que representa o que podemos ver.
Então nós vamos mover o personagem para dentro da tela.
Para isso pressione a tecla W ou ative o modo "mover" na barra de ferramentas e então arreste-o para dentro da tela.
E então pressione F6 para rodar a cena e você verá o personagem movendo-se para a direita em velocidade constante.
Agora clique em Script no topo ou pressione F3 que é um atalho pra isso.
F1, F2, F3 e F4 são atalhos para mudar as visões e abrir a documentação.
F3 para o editor de script e nós vamos melhorar o nosso código um pouco.
Nós não queremos que o nosso personagem se mova para a direita o tempo todo, isso seria meio bobo.
Em vez disso, nós queremos aplicar alguma gravidade a ele.
Nós poderíamos colocar o valor diretamente aqui em "velocity", mas em vez disso, vamos guardar a gravidade em uma variável.
E nós não vamos declarar essa variável dentro de _physics_process. Quando se declara uma variável aqui, ela existe apenas dentro desta função.
E você não consegue acessar a variável dentro de outras funções que vamos adicionar depois
Então, selecione "velocity", aperte ctrl-x para cortar e então cole fora da função _physics_process
E você vai ver que não da erro, esta tudo bem usá-la nesta chamada de move_and_slide aqui.
Nossa velocidade vai ser um Vector2 de tamanho zero por padrão. Então, por padrão, o personagem não vai se mover.
E então, adicionaremos algumas variáveis para atualizar a velocidade a cada frame.
Então vou criar uma nova chamada "gravity".
E esta será um valor decimal. A gravidade só vai ser aplicada no eixo vertical no nosso jogo.
E ela é uma aceleração. Uma aceleração vertical. Então, digamos, 3000.
Vou adicionar ".0" no final, para informar à Godot que eu quero que ela seja um valor decimal e não um número inteiro.
Então essa é a gravidade. E o que podemos fazer aqui é
na nossa função _physics_process, nós vamos adicionar a aceleração da gravidade ao eixo y da velocidade.
Então fazemos "velocity.y" e, para adicionar a ela, em vez de usar =, podemos usar +=
que é um atalho para "adicione ao que está à esquerda", aqui.
Adicione "gravity * delta".
delta é um valor que a engine vai nos dar a cada chamada dessa função _physics_process
Ela representa o tempo que passou desde o último frame.
Então, você quer usar esse valor "delta", para fazer seu código não depender do framerate.
Em outras palavras. Se o jogo ficar mais lento, o personagem ainda se moverá na mesma velocidade.
Se alguém tiver um computador lento, ou então alguma cena está bem pesada e você não sabe o que está acontecendo.
Você quer que o movimento do personagem seja constante. Então você pode fazer isso com o valor delta aqui.
Um detalhe técnico é que "velocity" é um vetor que representa uma velocidade.
Ou seja, quantos pixeis você quer mover por segundo em uma determinada direção.
Para obter um movimento na quantidade de pixeis que queremos mover o personagem em 1 frame nós precisamos multiplicar "velocity" por delta.
Mas, a engine faz isso por nós no método move_and_slide.
É por isso que não multiplicaremos velocity por delta.
Okay, isso vai fazer o personagem se mover para baixo. Você pode pressionar F6 para executar a cena e vê-lo cair.
Nós podemos tornar nossa gravidade configurável. Para fazer isso, adicione a palavra reservada "export" antes da variável.
Depois de fazer isso, você verá "gravity" aparecer no lado direito, no inspetor. Se você tiver selecionado o nó Player.
E então você pode modificar a gravidade. Digamos, 500 pixeis por segundo ao quadrado.
Aperte F6 e agora o personagem cairá devagar.
Você pode notar que a nossa gravidade é um tipo de aceleração.
Nós vamos, talvez, definir uma velocidade máxima para o personagem.
Provavelmente não queremos que ele acelere infinitamente. Que é o que acontece atualmente.
Então nós vamos fazer duas coisas. Primeiro, vamos adicionar uma variável "speed".
Que vamos usar "export" já. Vamos chamar de "speed".
E ela também será um Vector2.
Por quê? Porque termos uma rapidez no eixo horizontal, quando o jogador pressionar as setas para a esquerda e direita.
E você quer uma outra para o eixo y, para velocidades máximas de queda ou pulo.
Entre parêntesis. No eixo x, nós vamos definir 300.0 pixeis por segundo e, no eixo y, vamos definir 1000.0
E quando você salvar, vai ver os valores atualizarem no lado direito, no inspetor. Então você poderá personalizar isso no seu jogador.
Então você pode usar "speed" desta forma: se "velocity.y" for maior que "speed.y", ou seja, se for maior que 1000, aqui.
Nós vamos definir "velocity.y" de volta a "speed.y".
Uma outra forma de escrever isso, com uma função matemática, em uma única linha.
É dizer que "velocity.y" é igual ao max ("max" é uma função matemática embutida)
O maior entre "velocity.y" e "speed.y". Desta forma você não precisa adicionar um novo bloco de código.
Isso vai limitar a velocidade de querda e então nós usamos move_and_slide com o vetor "velocity".
E esta função vai calcular uma nova velocidade para o personagem.
Se ele atingir uma parede, uma rampa ou algo assim. Ela vai retornar um novo Vector2.
Você pode clicar segurando ctrl no move_and_slide para ver sua documentação.
Você pode ver que é um pouco complexa e faz bastante coisa.
Mas na parte de baixo você verá "retorna o vetor de velocidade linear rotacionado ou escalado se uma colisão ocorrer".
Isso significa que, se seu personagem bater em algo, a Godot tentará movê-lo suavemente ao longo da superfície que ele atingiu.
E, isso modificará a velocidade do personagem. Então nós queremos adicionar
"velocity =" e nós obteremos o valor retornado por esta chamada de função.
Note um último detale: esta linha, que temos aqui
pode ser que a gente a mova para os scripts e lógica específicos do jogador e do inimigo.
Então nós vamos removê-la daqui, por enquanto, e talvez nós vamos colocá-la em outro lugar depois.
Então, se você rodar o jogo, vai ver apenas o seu personagem caindo.
Nós queremos que ele caia em algo, em algum chão.
E, pra isso, vamos voltar à visão 2D. Cliquem em 2D ou pressione F1.
Nós vamos colocar o jogador de volta para a origem.
Selecione o Player e, no inspetor, vá para baixo na categoria "Transform"
e clique no ícone de redefinir próximo a "position". Vai redefini-lo para zero.
E nós vamos criar nossa fase. Vá em Cena (Scene), Nova Cena (New Scene).
Será um... vamos começar com um Node2D, por enquanto.
E nós vamos chamá-lo de, LevelTemplate, (modelo de fase), TestLevel (fase teste) ou algo assim.
Salve com ctrl-s. Crie uma nova pasta na pasta raíz, chame-a de Levels (fases).
Clique em Ok e salve seu modelo de fase lá.
Nós vamos adicionar um TileMap à nossa fase, então selecione LevelTemplate
clique no botão + ou use o atalho ctrl-a, para adicionar um nó e procure por TileMap.
Pressione enter para adicioná-lo e você verá que, com o TileMap selecionado
o editor se transforma em um editor de TileMap.
Um TileMap precisa de um recurso tileset que você verá no inspetor.
Nós temos um preparado para você na pasta assets, que você pode clicar e arrastar.
Se você quiser criá-lo, no entanto, você quer limpar isso...
Clique no tileset aqui, crie um Novo Tileset (New Tileset).
E clique no recurso para abrir o editor de tileset, que se parece com isto.
Neste editor nós temos que carregar uma texture (imagem) que ele vai cortar em pedaços
que podemos, então, usar para criar fases em uma grade.
Clique no botão +, vá para assets e carregue o arquivo tileset.png
Você verá que, no centro do editor, você terá a sua imagem aberta.
Então, nós queremos clicar em "New Single Tile". E, quando fizer isso, aparecerá um ícone de snap.
Vou clicar e arrastar apenas para começar a definir uma região, para então poder ativar o snap, a grade aqui.
Então, uma vez ativado, você poderá ver a grade de snap.
Você pode expandir as opções de snap no inspector à direita.
E nós vamos definir "step" para 80 por 80.
E então, com a ferramenta de seleção ativa, clique na região
criada anteriormente e ele vai grudar automaticamente na grade.
Se você voltar ao TileMap e clicar e arrastar, você pode começar a desenhar sua fase.
Você verá que nossa imagem é um pouco mair que o quadrado da grade.
Nós vamos mudar isso em breve, mas antes, vamos clicar no nosso recurso tileset para terminar de editá-lo.
Selecione a imagem, o pedaço, o tile único que você tem aqui.
Nós vamos adicionar uma colisão a ele.
Isso vai fazer nosso personagem parar se atingir a parede ou o chão.
Clique na aba de Collision, selecione o ícone "Create a new rectangle"
E isso vai, automaticamente, quando você clicar dentro do tile
criar um retângulo que preenche o tile instantaneamente.
Agora você pode minimizar o tileset aqui, o editor.
Volte ao TileMap e, quando você clicar e arrastar, você estará criando paredes que o personagem pode colidir.
Agora nós precisamos mudar o tamanho da célula para combinar com o do nosso tileset.
No inspector, com o TileMap selecionado, expanda a categoria Cell.
O tamanho está 64 por 64, você quer que esteja 80 por 80 assim como a nossa imagem.
E então você pode clicar e arrastar para criar paredes e chão que vão parar o jogador.
Eu vou contrair a pasta assets e expandir as pastas src e Actors.
E agora você pode pegar o Player.tscn aqui e clicar e arrastar para qualquer lugar da cena. Vou colocar ele no alto.
Vou clicar e arrastar o jogador para que ele seja filho do LevelTemplate e não do TileMap.
E então, pressione F6 para jogar o jogo. Você verá o personagem caindo e ele vai parar no chão.
Então, isso é algo legal que temos aqui.
Este é um bom começo. Antes de fazermos nosso personagem se mover e adicionar mais lógica
nós vamos mudar as configurações do nosso projeto.
Nós temos colisão que acontece automaticamente
mas quando começarmos a adicionar o inimigo e mais lógica no jogo, teremos alguns problemas
se não organizarmos as nossas camadas de física.
E também, o tamanho da tela é um pouco pequena se comparado com a arte. Você pode notar que o personagem está bem grande na tela.
Nós queremos mudar isso para que fique mais legal.
Para fazer isso, nós vamos para Projeto (Project), Configurações de Projeto (Project Settings ).
E nesta janela nós vamos lá para baixo, primeiro para as camadas de física (2d Physics).
Nós resolveremos isso e depois o tamanho da tela.
Você quer ir para baixo do menu da esquerda e clicar em 2d Physics.
Aqui você pode nomear suas camadas de física no lado direito.
Por exemplo, camada 1 pode ser o player (jogador), o 2 pode ser os enemies (inimigos)
E o layer 3 poderia ser, bem, no próximo tutorial teremos coins (moedas), então você chamá-lo de coins.
E o layer 4, não da pra chamar de chão... vamos chamar de world (mundo).
Então tudo, tipo, as paredes, plataformas, chão, todas essas coisas ficarão na camada mundo.
Feche as configurações de projeto por agora. Vou abaixar a janela de Ouput.
Quando você selecionar o TileMap, na categoria Collision você tem Layer e Mask.
Layer é onde este TileMap está, qual camada ele pertence.
Você tem 20 camadas, se você clicar nos dois pontos à direita
você verá uma lista de checkboxes que têm os nomes de camada que você acabou de criar.
Então, nosso TileMap, nós não queremos que ele esteja na camada do player, clique para deselecionar.
E nós vamos definir que ele está na camada world.
E Mask representa as camadas de física que esse TileMap vai detectar
e que você poderá usar ou processar via código.
O TileMap em si não precisa detectar nada então nós vamos deselecionar a Mask aqui.
Usar esses Layer e Mask vão te ajudar não apenas a evitar bugs
mas também vão melhorar a performance dos seus jogos.
Porque quando a Godot tenta detectar colisões entre nós
ela apenas verifica entre Layers e Maks que combinam, entre nós.
Por exemplo, nosso personagem aqui. Vou expandir Collision, logo abaixo PhysicsBody2D.
Ele está na camada player e apenas detecta colisão com o que estão na camada player, o que não é muito útil.
Em vez disso, nós precisamos voltar à cena do Player.tscn fazer isso, mudar as configurações globalmente no nosso projeto.
Com o nós Player selecionado, você quer mudar a Mask. Ele vai detectar o world aqui.
O que significa que o Player esta na camada player e ele colide com tudo o que está na camada world.
Salve com ctrl-s, volte para o LevelTemplate, pressione F6 para ver que nada mudou.
Nosso jogador ainda colide com o chão.
Agora, se eu mudar as colisões no jogador e fazer ele detectar outra camada.
Você verá que ele atravessa o chão. Não colide com ele mais.
Então nós queremos que ele colida com o chão.
Note que eu disse que nós precisávamos voltar ao Player.tscn para mudar as configurações de colisão.
Isso é porque essa é a definição do nosso jogador.
Quando você adiciona o jogador a qualquer cena, serão estes os valores padrão que teremos.
Então, quando você muda uma instância, ou uma cópia do jogador
como você tem na cena LevelTemplate, você sobrescreve o valor.
Você o torna diferente apenas para aquela cópia do jogador e não para todo o projeto.
Agora nós vamos fazer o nosso jogador reagir a entrada de dados.
Pressionar para esquerda ou direita para se mover horizontalmente. E barra de espaço para pular, por exemplo.
Para fazer isso nós temos que começar definindo input mappings (mapeamento de entrada).
Vá para Projeto, Configuraçẽso do Projeto (Project Settings) para a aba Mapa de Entrada (Input Map).
O mapa de entrada te permite mapear teclas do teclado ou de um controle para um rótulo
que você pode então reutilizar no seu código para referenciar essas teclas.
Você tem alguns definidos por padrão pela Godot para a interface de usuário e nós vamos adicionar aluns.
Então clique na barra ao lado de Action e você quer digitar o nome da sua ação.
Vamos começar com "move_left", clique em Adicionar (Add).
Então vamos fazer essa primeira ação. Você pode vê-la na parte de baixo da lista.
À direita você vê um ícone +, onde você pode adicionar mapeamentos de entrada.
Clique nele, vamos adicionar uma tecla do teclado, então você deve pressionar essa tecla.
Vamos começar com WASD, então A, para mover o personagem para a esquerda.
Você pode adicionar outra tecla, vamos dizer que o jogador quer usar as setas. Então, seta para esquerda.
E deve ser isso, por agora. Você pode também adicionar o controle
então Eixo do Joystick (Joy Axis), nesse caso.
E, você pode pegar, "Axis 0 - Left Stick Left", o com "-".
Dessa forma, se você pressionar A, seta para esquerda, ou pressionar em um controle de xbox, dualshock ou playstation
você obterá a mesma entrada "move_left" no código para reagir a essas entradas.
Vamos fazer o mesmo para "move_right". Nós vamos criar essa ação, então
tecla D, seta para direita e, finalmente, eixo do joystick. Dessa vez será Axis 0 +: analógico esquerdo para a direita.
Então adicione esses e nós vamos adicionar uma ação para pular. "jump" será a tecla W
a seta para cima ou Botão do joystick (Joy Button) Xbox A.
Com isso nós temos as ações que precisamos para começar a programar a movimentação do jogador.
Clique no script perto do nó Player para abrir o editor de script.
Nós vamos adicionar aquela função _physics_process novamente.
função _physics_process
E nós vamos escrever algum código nela.
Essa callback é especial, essa função, como eu disse
é definida pela engine. É específica da Godot, ela não existe em outras engines.
E ela funciona dessa forma: quando você tem uma classe que estende outra, o Actor
a Godot vai executar essa função _physics_process, mas também vai executar o _physics_process da classe pai.
Então ela vai executar esse código assim como tudo o que nós vamos escrever aqui, automaticamente.
Aqui nós vamos, primeiramente, calcular a direção em que o jogador está tentando mover a cada frame usando o nosso Input.
Para fazer isso, nós temos que usar a classe Input na Godot dentro da _physics_process.
É uma classe disponível globalmente que te permite checar as entradas a cada frame do jogo.
Por exemplo, quando você digita o nome de uma classe que é acessível dessa forma
você pode pressionar . para então acessar suas propriedades e métodos
que você pode ver com os parêntesis.
Note que, apertar . e acessar as propriedades é semelhante às propriedades que você tem listado no inspetor do editor.
Se passar o mouse por cima de alguma dessas você verá o nome sublinhado. Nesse caso "gravity" em minúsculo.
Certo, se você clicar em Input segurando ctrl, vai abrir sua documentação no editor de script.
E então você pode ver todos os métodos que ele tem na sessão "Methods" (métodos), aqui.
E nós vamos usar métodos que nos dizem, a cada frame, se o jogador está pressionando uma tecla.
Deixa eu fechar essas documentações aqui...
O que nós vamos fazer aqui é chamar um método chamado get_action_strength na classe Input.
E então nós podemos passar uma das ações de entrada que nós definimos
nas configurações de projeto. A Godot fornece auto completar pra você.
Então vamos começar com "move_right".
Esta função, get_action_strength, vai retornar um float, um valor decimal.
E, se a tecla estiver pressionada totalmente para a direita, ele vai retornar 1.
Se a tecla não estiver pressionada, ele vai retornar 0.
Isso é útil porque, em se tratando de direções, você quer que mover-se para a direita seja 1 e mover-se para a esquerda seja -1.
Você verá daqui e apouco como isso funciona.
Você pode clicar segurando ctrl neste método para ir à sua documentação.
E você vai ver que a linha começa com "float".
Esse é o tipo de retorno da função. Ela vai retornar um valor decimal, nesse caso.
E a documentação explica um pouco melhor. "Retorna um valor entre 0 e 1, representando a intensidade da ação fornecida".
A razão dessa função é que, se você não mover o analógico até o fim, você terá um valor decimal.
Por exemplo, se você mover o analógico até a metade, você vai obter um valor de 0.5.
Para calcular a direção de entrada do jogador, nós vamos fazer um cálculo com os valores retornados por get_action_strength.
Então vamos adicionar uma linha acima disso. Nós vamos guardar essa direção em uma variável.
E também vou pressionar ctrl-shift-F11 para expandir a área de script.
Nós vamos criar uma variável chamada "direction" e ela será um Vector2.
A razão para escolhermos Vector2 é, novamente, porque nós podemos ter um movimento horizontal e outro vertical.
Duas direções para levar em conta.
Coloque o cursor entre os parêntesis e pressione enter para adicionar uma nova linha
para ter as direções x e y alinhadas uma com a outra aqui.
Nós vamos calcular a direção x assim:
Eu vou adicionar uma vírgula e, em uma nova linha, definir o componente y do Vector2 para 0, por enquanto.
Mover-se para a direita, no jogo, deve ser um valor de 1.0. Nós vamos representá-lo dessa forma.
E, mover-se para a esquerda será um valor de -1.0. Deste jeito.
Certo? Então, ao fazer esse cálculo, se nós pressionarmos a tecla para a direita
nós obteremos o valor 1.0. O que nos fará mover para a direita.
E nós subtraímos o valor retornado por "move_left" de forma que a gente obtenha
-1.0 se nós pressionarmos apenas a ação "move_left".
Se você pressionar ambos, "move_left" e "move_right", ao mesmo tempo, nós obteremos 0.0.
Da mesma forma se você não pressionar nenhum deles.
Nós podemos usar essa direção para definir a velocidade do personagem. Então "velocity"
A velocidade que definimos no script Actor.gd.
Agora, voltando para Player.gd, podemos dizer
"velocity = speed * direction"
E, com isso, podemos executar o jogo.
Você verá o personagem mover-se devagar.
E você pode pressionar para a direita e para a esquerda para movê-lo. E ainda não conseguimos pular.
Definimos a direção vertical como zero que, vezes speed, deveríamos ter uma velocidade vertical zero.
Em vez disso o personagem está se movendo. Isso se deve ao script Actor.gd.
É isso que expliquei antes sobre o _physics_process.
Nós definimos um comportamento no script Player.gd, mas a Godot vai executar o _physics_process no script pai antes.
Então ela vai adicionar "gravity * delta" à "velocity" e então vai mover o personagem.
Depois, nós mudamos a velocidade e, finalmente, o personagem só vai se mover para a direita ou esquerda no pŕoximo frame.
Mais tarde do que o que estamos fazendo aqui.
O que podemos fazer nesse momento é remover esta linha do _physics_process do Actor.gd
e mover o personagem no script do jogador (Player.gd).
Dessa forma, você vai ver que ele não vai cair. Por quê?
Porque nós estamos definindo a direção vertical como 0.0
Uma coisa que podemos fazer é definir como 1.0, por padrão
(nós mudaremos isso se o personagem pular)
para que o personagem caia e fique no chão.
Com isso, você tem a habilidade de cair e de se mover para a direita e esquerda.
Nós vamos modificar a velocidade do jogador
Porque essa velocidade é boa para algum monstro ou alguma I.A.
que o personagem tenha que matar, de forma que seja fácil pular na I.A., como vermos depois
mas para o jogodor é um pouco lento. Então vamos aumentar a rapidez em x do jogador.
Você precisa ter selecionado o nó Player para fazer isso.
Pressionando F5 agora o personagem anda mais rápido no eixo x.
Nós vamos adicionar a lógica de pulo do nosso personagem agora.
Onde nós calculamos a direção, nós queremos que o valor aqui seja -1.0, quando queremos que o personagem pule.
Mas nos outros momentos, nós queremos que ele caia, então queremos que o valor seja 1.0
A razão para qual nós queremos que o valor seja -1.0 para ir para cima é que o eixo y, no jogo
na engine, aponta para baixo, como na maioria das engines.
Então nós vamos usar algo chamado operador ternário (ternary operator).
É semalhante a usar if : e então fazer algo e então ter um bloco "else".
Exceto que nós podemos escrevê-lo em uma linha só. Funciona assim:
nós queremos que o valor seja 
-1.0 se o jogador acabou de pressionar a tecla "jump"
do contrário nós queremos que o personagem  caia.
-1.0 "if" acabou de pressionar (just_pressed) a tecla "jump", se não 1.0, que fará o personagem cair
E nós queremos fazer um pouco além disso. Porque com essa condição apenas o personagem pode pular a qualquer momento no meio do ar.
Então queremos adicionar "and is_on_floor()" (e está no chão).
is_on_floor é uma função que você tem em um KinematicBody2D. Clique segurando ctrl nela.
Você verá na documentação do KinematicBody2D. "Retorna verdadeiro se o corpo estiver no chão".
E "Atualiza apenas após a chamada de move_and_slide"
É por isso que nós queremos ter move_and_slide aqui no script Player.gd.
Para que a gente tenha controle sobre quando moveremos o personagem.
Para que is_on_floor e is_on_ceiling, esse tipo de função, funcione.
Certo, então isso nos da a direção de pulo.
Agora nós vamos fazer uma coisinha para deixar nosso código mais fácil de manter e de ler no futuro.
Nós vamos mover esse Vector2 aqui para uma função.
Para ter uma função que calcula a direção para nós.
Eu explicarei daqui a pouco o porquê nós faremos isso.
Nós vamos criar uma função chamada "get_direction", que vai retornar um Vector2
E nós vamos retornar esse valor que nós estamos atribuindo à variável "direction". Selecione tudo.
Ctrl-x para cortar e, na função "get_direction" vou colocar a palavra reservada "return"
Esse é o valor que a função vai retornar. E vou colar o nosso cálculo.
E, na variável "direction" nós vamos obter a direção, vamos chamar essa função
Nós vamos fazer isso para manter nosso código fácil de ler no futuro
Por exemplo, se um colega de equipe quiser entender como o jogador se move
Se usarmos funções como estas, só é necessária a função _physics_process
e algumas linhas para entender o tipo de movimento que o personagem faz.
E então, se precisar entrar em detalhes, se quiser mudar o código da direção, ele está nessa função "get_direction"
Isso não parece muito já que nosso jogador é simples, mas você verá, no fim do tutorial, que nós teremos adicionado bastante linhas de código
e que isso tornará o código mais fácil de ler do que jogar tudo em _physics_process.
Vamos trabalhar no pulo a seguir
porque o jogador pode ser mover horizontalmente, mas ainda não consegue pular
Para isso nós vamos modificar a forma que calculamos nossa velocidade a cada frame.
Nós vamos deixar isso um pouco mais complexo, já que vamos adicionar a habilidade de cancelar o pulo, como você verá em breve.
Mas nós vamos fazer o mesmo que fizemos com a função get_direction. Nós vamos criar uma função que calcula a velocidade.
E nós podemos chamá-la de "calculate_move_velocity".
Então, na parte de baixo do script, vamos adicionar "calculate_move_velocity"
Ela vai retornar um Vector2, o tipo da velocity. E, por enquanto, podemos retornar
"speed * direction".
Nós teremos algumas formas de lidar com essa função.
Como você pode ver nós obtemos um erro porque "direction" não está definida no escopo atual.
"O escopo atual" significa a função, cada bloco, que você pode colapsar, você pode considerar um escopo.
Quando você cria uma variável, como "direction" dentro de uma função ela está limitada a essa função.
Se você criá-la fora da função, vamos fazer dessa forma. Variável "direction
É um Vector2 vazio, desse jeito. Então ela vai se tornar disponível em todas as funções
neste arquivo ou nessa classe, porque este arquivo representa uma classe.
O negócio é, você não quer ter muitas variáveis do lado de fora das funções porque,
ter esses valores que pessoas podem modificar (você, seus colegas de trabalho) nó código é uma grande fonte de  bugs
É difícil manter o controle de como esses valores são modificados e, colocar um valor aqui
te permite modificar uma variável de fora do script do jogador.
De outro script, um script "game", um script de "score" ou qualquer um. É perigoso, nesse sentido.
É por isso que, sempre que pudermos, nós vamos deixar a variável em um escopo, criá-la em uma função específica.
Agora, para a velocidade de movimento, nós vamos passar estes valores como parâmetros da função
Então, nós vamos precisar de quatro... bem, vamos começar com três
Nós vamos precisar de "linear_velocity". Este é o nome que as funções da Godot dão à variável de velocidade.
No move_and_slide, o primeiro parâmetro é chamado "linear_velocity"
na documentação então nós vamos usar a mesma convenção.
Eu vou mudar a formatação para os parâmetros. Eu vou alinhá-los verticalmente
então após cada parâmetro você quer colocar uma vírgula, para separá-los
E nós vamos adicionar "speed", como um Vector2. Nós vamos passar cada parâmetro explicitamente.
Nós teremos "direction", também um Vector2. Vamos ordená-los dessa forma e, por enquanto, vamos ter só esses três.
Este é um estilo de programação onde nós passamos cada parâmetro explicitamente para a função
para garantir que nós abemos exatamente quais valores a função usará para fazer seus cálculos.
E, de novo, nós fazemos isso para evitar bugs no nosso programa.
Então nós vamos calcular a nova velocidade. Vamos criar uma variável "new_velocity" na função.
E ela vai começar como a nossa "linear_velocity"
Então essa função vai pegar a velocidade inicial, fazer alguns cálculos com os outros parâmetros e retornar um novo valor
Um novo valor que você pode então atribuir à nossa velocidade, guardar ou processar como quisermos.
Então vamos fazer dessa forma. Nós vamos pegar a velocidade original
vamos atribuir à "new_velocity.x" o valor de "speed.x" vezes "direction.x"
E para o eixo y será um pouco diferente.
Então, nós vamos pegar a lógica que tínhamos no script Actor.gd e nós vamos removê-la do _physics_process aqui.
Nós vamos pegar essa linha, onde nós adicionamos a velocidade
e nós vamos colocá-la na nossa função de calcular a velocidade.
Então, "new_velocity.y".
Nós vamos adicionar "gravity * delta" para fazer o personagem se mover para baixo.
Nós não temos acesso ao valor de "delta" aqui. Nós podemos ou passar para função
ou usar uma função chamada "get_physics_process"
Vamos ver, "get_physics_process_delta_time"
Estou procurando na documentação para ver o nome da função, que vou copiar aqui.
Você pode usar F4 para mostrar essa janela de busca.
E então você pode procurar por delta_time para achar a função "get_physics_process_delta_time".
Então eu vou copiá-la, fechar a documentação e colá-la com ctrl-v
no script e adicionar os parêntesis para chamar a função.
Então isso vai retornar o valor delta que tínhamos no _physics_process.
Dessa forma não precisamos adicionar um novo parâmetro à função.
Então nós adicionamos a gravidade. Agora nós vamos adicionar uma condição se pularmos.
Então, se nós estivermos pulando a direção em y será -1.0.
Nós podemos dizer que, se a "direction.y" é igual a -1.0
nós vamos sobrescrever "velocity".
Nós vamos fazer o personagem pular instantaneamente.
"velocity.y" será igual a "speed.y * direction.y". Vezes esse -1.0.
Isso vai aplicar a velocidade do jogador. Deixa eu retornar à cena do jogador e selecioná-lo.
Nossa velocidade em y, aqui. Ela será aplicada indo para cima.
E substituir "velocity.y" com ela. Então isso fará o personagem pular.
E, por enquanto, deve estar bom o suficiente então nós podemos voltar
à função _physics_process e usar nosso "calculate_move_velocity" aqui.
Então "velocity = calculate_move_velocity(" e nós vamos passar
A "velocity" , primeiro parâmetro da função, aqui.
Seguido de "direction" que será o valor desta variável aqui. E "speed".
Novamente, nós estamos passando explicitamente cada parâmetro para a função
para garantir que ela seja uma função pura, como chamamos na programação.
É uma função que apenas pega alguns parâmetros, executa alguns cálculos e retorna um novo valor.
Ela não modifica diretamente alguma propriedade do nosso personagem, o que chamamos de mutar os valores.
Nós vamos agrupar todas essas mutações, todas essas mudanças nas propriedades do personagem
(nesse caso "velocity"), na função _physics_process
para que seja fácil manter o controle de onde nós estamos modificando a velocidade do jogador ou personagem.
Certo, nós podemos executar o jogo.
E o personagem ainda não consegue pular...
Tem uma linha que esqueci que precisamos mudar.
Nós não vamos retornar "speed * direction", claro. Nós queremos retornar "new_velocity"
dessa nossa função "calculate_move_velocity"
Certo, agora com isso, nós podemos executar o jogo e veremos que o personagem não consegue pular mesmo que pressionemos a tecla W.
Por que isso esta acontecendo?
Essa é uma pegadinha aqui. Isso se deve a como "move_and_slide" funciona na Godot.
Como KinematicBody2D funciona.
Esse nó é feito para ser bastante flexível e te permitir a criar todo tipo de jogo.
Um jogo visto de cima como Zelda, assim como um jogo visto de lado.
Por causa disso, vou clicar segurando ctrl para ir à documentação
Essa função tem bastante parâmetros opcionais.
E um que é muito importante é "floor_normal" (normal do chão).
Isso é um Vector2 que é perpendicular ao chão e aponta para longe dele.
Nós precisamos que "floor_normal" seja fornecido para que a Godot nos diga o que é chão e o que não é.
Para a função "is_on_floor", que estamos usando na função "get_direction", funcione.
Então nós precisamos passar esse segundo parâmetro "floor_normal", aqui e ele será um Vector2 apontando para cima.
Então você pode usar Vector2.UP, que é uma constante definida na classe Vector2
É um Vector2 com os valores (0, -1). Dessa forma.
Nós podemos usar essa constante Vector2.UP em todos os nossos personagens quando usarmos "move_and_slide"
Ou nós podemos definir uma nova constante na classe Actor.gd é por sua conta
Então você pode ia até Actor.gd, criar uma constante com a palavra reservada "const"
Isso é como as outras variáveis abaixo. Te permite
colocar um rótulo em um valor, mas você não pode modificá-lo depois, é um valor constante.
E você pode dizer FLOOR_NORMAL será igual a Vector2.UP
A vantagem de ter esse tipo de rótulo é que, quando voltarmos ao nosso jogador
nós podemos ver que o segundo parâmetro na função move_and_slide é o "floor_normal"
Eu digitei errado aqui, algo que pode acontecer. Eu digitei "velocity" em vez de "new_velocity" na função "calculate_move_velocity".
Fazendo com que o cálculo não funcione. Com isso concertado o personagem pode agora pular
como é esperado
Ele não pula muito alto. A altura do pulo e o impulso do pulo são controlados pelo valor de "speed.y".
Então eu posso aumentá-lo para 1400, por exemplo e pressionar para cima.
Você pode notar que agora o personagem pula bem mais alto.
Nós vamos adicionar a opção de interromper o pulo e fazer o pulo ser mais como você vê no Mario
onde, se você pressionar por mais tempo, o personagem vai pular mais alto.
Para fazer isso, nós vamos adicionar uma nova variável no _physics_process do Player.gd
chamada "is_jump_interrupted".
Ela vai ser "bool", como o nome sugere. Então, um valor que pode ser "true" ou "false".
Ela vai usar uma expressão um pouco parecida com a que temos em "get_direction"
Nós queremos checar se acabamos de soltar a tecla de pular
Então se 
Input.is_action_just_released("jump
")
e se o jogador está pulando mesmo. Então, se velocity.y é menor que 0.
Se "velocity.y" é negativa o personagem está indo para cima então ele está pulando.
E nós vamos passar esse valor para a função "calculate_velocity", para que nós possamos usá-lo lá.
"is_jump_interrupted" vai ser o nosso quarto parâmetro.
Agora nós temos que descer para "calculate_move_velocity", adicionar nosso "is_jump_interrupted" aqui em baixo.
E será um valor "bool", para que no fim da função a gente possa adicionar uma condição
Se o pulo foi interrompido nós vamos definir "new_velocity.y" como 0.0.
E então nós retornamos essa nova velocidade.
Isso vai fazer com que, se eu manter a tecla pressionada, o personagem pula até a altura máxima.
Mas, se eu soltá-la rapidamente o personagem para de ir para cima e começa a cair instantâneamente.
Então, baseado em quanto tempo você manter a tecla pressionada você pode modular a altura do pulo.
Uma pequena nota sobre nomes de variável:
No momento, na nossa função "calculate_move_velocity"
Nós chamamos essa variável de "new_velocity". Vamos dizer que você acha ela um pouco longa
Como nós já temos o nome da função, nós sabemos que estamos calculando a velocidade de movimento
É isso que obteremos como saída da função. Nós podemos renomear essa variável
Você pode dar double click para selecioná-la, apertar ctrl-r
para abrir a funcionalidade de procurar e substituir do editor
E nós vamos procurar por "new_velocity", no primeiro campo. O segundo campo nos permite definir um texto substituto.
Nós podemos chamá-la de "out", a saída da função.
E, nós só usamos "new_velocity" dentro dessa função aqui, então nós podemos clicar em "Replace All"
para substituir todas as cópias desse nome
Chamá-la de "new_velocity" me levou ao erro de escrever "velocity" no lugar.
Outra coisa que gostaria de introduzir aqui são variáveis "públicas" e "privadas"
Nós temos algumas convenções, como desenvolvedores, sobre como nomeados as variáveis.
Se nós colocarmos um underline no começo da variável, nós a chamamos de "privada"
Isso significa que ela deve ser usada apenas dentro deste script desta classe.
Nesse caso, como estamos estendendo Actor, isso inclui as classes Actor e do jogador
Variáveis "públicas", por outro lado, indicam aos nossos colegas de equipe que eles podem modificá-la
de outro script. De outro nó no jogo.
Esse é o caso da "velocity" no momento, porque ela não começa com underline
E alguém, em outro script, poderia fazer algo como "velocity =" alguma outra coisa. Um novo Vector2.
E nós não necessariamente queremos que isso aconteça, é por isso que nós vamos renomeá-la para colocar um underline no início.
O problema é que nós definimos "velocity" no script Actor.gd e nós estamos usando-o também no script Player.gd
Nós a temos em dois arquivos diferentes.
Nós podemos procurar por um texto como esse, um nome, no projeto inteiro e substituí-lo em todos os nossos arquivos de script
usando ctrl-shift-f para procurar nos arquivos.
Nós temos uma opção para procurar em uma pasta ou para procurar no projeto inteiro.
Ele utilizará o texto que você selecionar, então se você clicar duas vezes em "velocity" e apertar ctrl-shift-f ele vai procurar por "velocity" no projeto
Então nós podemos clicar no botão Substituir (Replace) para procurar e substituir no projeto inteiro.
E eu tenho que sair do modo sem distrações. Eu vou fechar a barra de procurar e substituir no script aqui.
E você verá que ele encontra várias cópias de "velocity" no projeto e também o encontra dentro da função "calculate_velocity"
Um lugar onde nós não queremos substituí-la
Então nós vamos ter que recomeçar a nossa busca. Ctrl-shift-f
E garantir que nós estamos buscando apenas Palavras Inteiras (Whole Words)
Nós estamos procurando por "velocity" apenas quando ela é uma palavra única por si só.
Então, quando nós clicarmos em substituir nós acharemos "velocity" apenas como o nome da variável e como um parâmetro separado.
Então nós podemos ver que ele está encontrando ocorrências do texto em dois arquivos: Actor.gd e Player.gd
No campo Substituir (Replace) na parte de baixo, nós podemos digitar "_velocity".
Certifique-se de salvar seus arquivos antes de fazer isso
E então clique em "Replace All" (substituir todos)
Está escrito que você não poderá desfazer isso as mudanças serão salvas instantâneamente
Então, vamos fazer isso, no nosso caso. E podemos ver que nos dois scripts Actor.gd e Player.gd nós temos "_velocity"
E o jogo ainda funciona, certo? Porque nós substituímos tudo de uma vez.
Mas, você quer estar ciente de que, quando você usa essa funcionalidade ele vai substituir tudo e salvar
E a forma de não perder progresso ao fazer isso é usar um sistema de controle de versão, como git
Isso é um tópico para outro vídeo, outra série, mas vale a pena dizer que, se você cometer um erro
e estiver usando um sistema de versionamento, você pode reverter as mudanças.
De qualquer forma, por enquanto, nós temos nosso nome de variável.
Vamos trabalhar no nosso inimigo a seguir.
O inimigo será um pouco semelhante ao jogador em sua base. Então nós vamos à pasta raíz
pasta Actors, selecionar Player.tscn, clicar com o botão direito e duplicá-lo
Nós vamos chamá-lo de Enemy.tscn, voilá!
Dois cliques na nova cena para abrí-la
No momento nosso inimigo é igual ao jogador.
Nós vamos selecionar o primeiro nó e chamá-lo de "Enemy"
O segundo nó, a Sprite do jogador, nós vamos chamá-la de "enemy" também
E, no sistema de arquivos, nós vamos procurar por "enemy"
Você verá, na pasta assets um arquivo enemy.png
Então você pode expandir a pasta assets e, com a Sprite "enemy" selecionada, clique e arraste "enemy.png" para o slot "texture"
Substituindo o jogador pelo inimigo.
Nós vamos ajustar a forma de colisão para o monstro,
Fazê-la, vamos dizer, um pouco menor na base
Talvez um pouco mais larga também.
Essa é a parte do monstro que irá colidir com paredes
Isso vai bloquear o jogador também ou acertar e matar o jogador.
Isso deve bastar
Agora, vamos selecionar o nó raíz "Enemy"
Como nós duplicamos a cena do jogador o inimigo ainda tem o script do jogador anexado a ele.
Então nós vamos clicar com o botão direito no Enemy
E nós vamos escolher Estender Script
Nós vamos mudar, no campo Herda (Inherits), o script que o Enemy vai estender.
Então, clique no ícone de pasta e dê dois cliques em Actor.gd
Modelo (Template) deve ser Empty e o Caminho (Path), por padrão deve ser "Enemy.gd" na pasta Actors
Clique em Criar (Create) para ter o script do inimigo.
 
De volta à cena do inimigo, nós temos que mudar uma última coisa para as colisões
Lembra-se de Layer e Mask?
Se você selecionar o nó Enemy, ele ainda está configurado para estar na camada player
Em vez disso, vamos colocá-lo na camada enemy. E ele vai colidir com world
Então a propriedade Mask te permite controlar isso
E com o jogador
Com isso nós podemos começar a programar o nosso inimigo
Salvea  cena, clique para abrir o script Enemy.gd
Vou fechar a documentação do KinematicBody2D
E nós faremos com que o inimigo mude de direção ao bater em uma parede.
Para programar o movimento nós vamos adicionar, de novo, aquela função _physics_process.
Para o inimigo, nós vamos fazê-lo se mover a uma velocidade constante, como o jogador
e nós vamos fazer com que, se ele bater em uma parede, ele muda de direção. Então é assim que faremos:
Lembra-se de que temos nossa propriedade "_velocity" no inimigo da mesma forma que no jogador
porque eles estendem o script Actor.gd
Nós vamos mudar a velocidade em x do nosso inimigo quando ele bate em uma parede
No KinematicBody2D nós temos uma função "is_on_wall" assim como "is_on_floor"
que nós podemos chamar e, se o inimigo está na parede, nós vamos multiplicar a velocidade em x por -1.0
Você pode usar esse atalho par dizer "multiplique _velocity.x por -1.0" se usar "*="
Para que você não precise repetir, "_velocity.x" é igual a "_velocity.x" vezes -1.0
Nós também vamos mover o inimigo a todo frame
A pegadinha aqui é que para decidir se nós vamos movê-lo antes de fazer essa verificação ou depois
Você tem que saber que esses métodos "_is_on_wall" e "_is_on_floor" só atualizam depois de você mover o inimigo
Então nós podemos movê-lo primeiro e então, no próximo frame ele vai mudar de direção
Bem, nesse caso, se nós vamos mover antes ou depois da verificação não vai fazer muita diferença
mas vamos colocá-lo depois. Então nós podemos dizer "_velocity" é igual ao resultado da chamada de "move_and_slide"
Para qual nós passamos a nossa velocidade, como nós queremos que o nosso monstro funcione
E "FLOOR_NORMAL", dessa forma
Nós vamos fazer uma última coisa
Nós vamos garantir que o inimigo sempre se mova em direção ao jogador no início do jogo.
No nosso jogo o jogador deverá se mover para a direita, assim como um jogo do Mario
o que significa que o inimigo sempre deve se mover para a esquerda no início do jogo. É isso que queremos.
Então vou pressionar F3 para voltar para o editor de scripts.
E eu vou adicionar uma nova função. É outra função definida pela própria Godot.
É chamada "_ready".
A função "_ready" é chamada pela Godot em cada nó na cena, no seu jogo.
Começando pelo nó mais ao fundo da árvore.
No caso do nosso inimigo. Ela olharia para Enemy, veria que ele tem nós filhos, então ela iria para os seus filhos
O Sprite enemy e o CollisionShape2D e chamaria a função "_ready" ali
Uma vez que eles estejam prontos (ready) ela vai chamar "_ready" no nó pai
Se nós tomarmos o LevelTemplate como exemplo
A Godot engine verá que LevelTemplate possui nós filhos, o TileMap e o Player
Então ela desceria até o TileMap, chamaria a sua função "_ready"
Depois desceria ao Player, chamaria a função "_ready" nos nós filhos do Player e então no Player e etc
Então ela vai de cima para baixo na ordem da árvore da cena e do nó no nível mais fundo até o nível mais alto.
Então, essa função "_ready" nos permite preparar o nosso inimigo, nesse caso.
Nós podemos dizer, na função "_ready", "_velocity.x" é igual a "-speed.x"
Em outras palavras, ele irá para a esquerda na velocidade definida pela componente x  do vetor "speed"
Nós vamos testar nosso inimigo no nosso LevelTemplate, então vamos voltar à cena do LevelTemplate
Procurar pelo arquivo Enemy.tscn e arrastá-lo e soltar para dentro do jogo.
Então você pode executar o jogo e ver que o inimigo se move para a esquerda
Bem, ele não está caindo, então nós queremos adicionar ao script Enemy.gd
a aplicação da gravidade a todo frame.
Então nós faremos "_velocity.y". Nós vamos adicionar "gravity * delta"
Como o script do inimigo é bem mais simples que o do jogador, nós não vamos criar uma função para calcular a velocidade
porque ela teria apenas duas linhas de código.
Agora, com o código que nós temos, se nós colocarmos o inimigo próximo à parede no nosso LevelTemplate.
Você verá que o inimigo fica preso na parede.
A razão para isso é que, esse código é chamado, mas o problema é que
quando nós atribuímos o resultado de "move_and_slide" à "_velocity"
quando o inimigo bate na parede isso redefine a velocidade de volta a zero.
Então nós queremos garantir que, para o "move_and_slide" nós usemos apenas a velocidade em y aqui.
"_velocity.y" é igual a, e então chamamos "move_and_slide" e pegamos apenas o componente y do Vector2 resultante.
E, com isso, o inimigo vai agora rebater em paredes
Você verá que ele também faz isso quando bate no jogador, porque por enquanto nós não matamos o jogador quando o inimigo bate nele.
Não estamos fazendo isso ainda, mas faremos em breve
Mas primeiro, nós vamos fazer algumas otimizações para o inimigo.
Uma coisa que vai acontecer nos seus jogos é que
digamos que nós colocamos o inimigo fora da tela.
Eu vou aumentar a fase um pouco
para que o inimigo esteja fora da tela no começo.
Se eu rodar o jogo você verá que o inimigo entra na tela.
Em outras palavras a I.A. está executando, está se movendo, mesmo quando ela está longe do jogador.
Isso é problemático se você tem uma fase grande com vários inimigos se movendo.
Isso vai bagunçar a sua fase porque eles vão se mover para todos os lados e...
talvez cair em um buraco ou andar sobre espinhos e morrer, esse tipo de coisa.
Você não controla as interações.
Além disso, isso será calculado o tempo todo, diminuindo a performance do seu jogo.
Então, uma das melhores otimizações que podemos fazer nos nossos jogos é fazer com que a
I.A não execute quando está muito longe do jogador.
Nós temos um nó na Godot feito exatamente para isso. É chamado VisibilityEnabler2D.
Selecione o nó Enemy na cena do inimigo
Pressione ctrl-A e procure por VisibilityEnabler2D.
Crie esse nó. Não o VisibilityNotifier2D, o VisibilityEnabler2D
Ele tê uma caixa pequena, como você pode ver.
Por padrão ele vai pausar a animação congelar a física, esse tipo de coisa, se o nó estiver fora da tela.
Uma coisa que podemos fazer é ativar a caixa Physics Process Parent
para que, quando o nó estiver fora de vista ele pare o _physics_process
e você pode fazer isos para _process também.
Podemos testar isso executando o jogo.
O inimigo tem _physics_process ativado por padrão então ele vai entrar na tela
Agora, vamos voltar ao LevelTemplate
Eu vou mover o TileMap com a tecla W, deixa eu ver se consigo fazer isso.
Eu vou movê-lo para a esquerda, menos duzentos
quatrocentos, okay.
Vou fazer com que o inimigo possa sair da tela.
Vou colocar o inimigo dentro da tela no começo do jogo, deixá-lo andar para a esquerda
E você verá que ele não vai voltar para a direita
Vamos começar o jogo, o inimigo sai da tela e ele nunca volta
porque, assim que ele saiu da tela o nosso VisibilityEnabler2D parou o _physics_process no inimigo.
E isso é algo que podemos controle via código.
Você viu que, por outro lado, se o inimigo começar fora da tela, ele vai se mover.
Esse VisibilityEnabler2D só vai ser ativado quando o inimigo sai da tela.
Então nós vamos voltar ao script Enemy.gd
e, na nossa função "_ready", nós podemos chamar um método chamado
_set_physics_process.
E nós devemos passar um valor bool para ele, nós temos que passar false.
Isso vai desativar o inimigo no começo do jogo.
Você verá que o inimigo nunca entra na tela.
Então agora esse código não vai executar até que o inimigo entre na tela
Nós queremos mudar o retângulo de visibilidade. O retângulo rosa que temos no inimigo
Que é a caixa que deve estar dentro ou fora da tela para que as funcionalidades do VisibilityEnabled2D funcionem
Então nós vamos mudar o tamanho do retângulo mudando a propriedade Rect no nó
Vamos movê-lo para -80, é um pouco grande de mais.
Estou tentando ver qual é o tamanho do inimigo.
Nós não conseguimos mudar o tamanho com o mouse.
-50 parece ser o suficiente.
Então você tem a posição em x e em y da origem do retângulo
e então você tem a largura e a altura do retângulo. Eu vou pôr 100 e 50
vamos tentar um pouco mais, 60, okay
para a parte de baixo ficar na base do inimigo.
Então, quando esse retângulo rosa entrar na tela o inimigo vai ativar
Agora está na hora de adicionar uma câmera, para que a gente veja o VisibilityEnabler2D funcionar
Nós vamos para a cena do jogador
Você pode pressionar ctrl-shift-O e começar a digitar Player para abrí-la facilmente
ctrl-shift-O é um atalho para abrir rapidamente uma cena
pressione enter
E nós vamos selecionar o nó Player, ctrl-A, e adicionar um Camera2D.
Pressione enter para adicioná-lo ao Player.
Por padrão ele não vai fazer nada.
Nós temos a câmera selecionada, para ir ao inspetor e ativar a opção "current" para ativá-la
Essa opção "current" é interessante
A última câmera a ativá-la será a câmera ativa pela qual nós veremos o jogo.
Nós só temos uma no nosso jogo então
será essa. Essa que está anexada ao jogador é que será usada para vermos o jogo
mas isso nos da uma câmera bem legal que vai seguir o jogador
e você pode ver que, assim que nós vemos o jogador e passamos dele, ele vai parar de se mover.
Quando nos afastamos dele, nós não vemos, mas ele para de se mover.
Você vai para longe do inimigo, ele para de se mover e está fora da tela.
Você volta pro inimigo e ele começa a andar novamente.
Interessante, né?
Então, isso ajuda com performance no nosso jogo.
Nós vamos melhorar a câmera depois para que ela não centralize o personagem na tela.
Por enquanto, você pode selecionar a câmera, pressionar W, ou clicar no ícone Modo Mover (Move Tool) na barra de ferramentas
para entrar no modo mover e clique segurando shift para mover a câmera para cima no eixo y.
Para que o jogador esteja mais para baixo na tela por enquanto.
Isso vai nos ajudar a jogar e testar o jogo um pouco melhor.
Vamos adicionar a habilidade de matar inimigos ao pular sobre eles.
Fazer algo como, se o jogador pular e cair sobre o inimigo ele pula de novo usando a cabeça do inimigo como base.
Para fazer isso, nós teremos a lógica dividida entre o jogador e o inimigo.
Geralmente, quando você programa, se você quer programar a morte do inimigo
o código que corresponde a isso deve estar dentro da cena do inimigo.
E, o código de pisar, os ataques do jogador
devem estar na cena do jogador.
Logicamente, nós mantemos código relacionado a uma certa área do jogo
dentro da cena correspondente a essa área.
Então, eu vou à cena do inimigo primeiro para permitir que ele morra quando o jogador pisa nele.
Para detectar isso nós vamos adicionar uma nova área
um novo retângulo aqui, acima do inimigo, para que, quando o jogador caia dentro dela
o inimigo vai detectar que ele foi pisado.
Nós vamos criar isso agora.
Vamos criar um novo nó Area2D.
Então, selecione Enemy, pressione ctrl-A para adicionar um nó e procure por Area2D,
Essa Area2D nós vamos chamar de StompDetector.
Ele vai detectar quando o jogador pisar no inimigo.
Na aba de colisão nós vamos mudar a camada.
Nós não queremos que isso esteja em alguma camada, a área não vai ser monitorável.
Você pode também desativar a propriedade "monitorable" aqui.
E ela vai detectar a camada do jogador, a primeira camada.
Então, quando o jogador entra na área, nós sabemos que o inimigo foi pisado
Agora nós precismos de uma forma de colisão para detectar algo entrando na área.
Selecione StompDetector, ctrl-A, e procure, novamente, CollisionShape2D.
Para Shape, adicione um novo retângulo, como sempre
Eles são precisos o suficiente eu gosto de usá-los porque
eles são praticamente livres de bugs e algumas formas possuem comportamento inconsistente.
Agora, dimensione a forma para que seja um pouco mais larga que a colisão do inimigo.
Nós precisamos ser generosos com o jogador, para que o jogo fique legal e seja fácil matar inimigos.
E nós vamos, na verdade, fazer algo.
No momento, nosso nó StompDetector está na base do inimigo.
Eu vou selecioná-lo, apertar W para entrar no modo mover e clicar segurando shift
para mover a área exatamente acima da colisão do inimigo.
Você verá que usaremos isso no código para que, quando o jogador entrar no StompDetector vindo por baixo do inimigo
isso não matá-lo, porque isso seria meio estranho
E então nós queremos fazer o mesmo, mover o CollisionShape2D de volta para que ele se alinhe com o colisor do inimigo.
Nós podemos mudar a cor do nosso StompDetector.
Para fazer isso, selecione o StompDetector ou o CollisionShape2D
desça até a categoria CanvasItem no inspetor.
Visibility.
E você quer mudar a propriedade Modulate.
Ela vai multiplicar a cor pela cor que selecionarmos com o seletor de cores.
Então, azul costuma funcionar muito bem. Nós podemos fazer nosso StompDetector ficar azul escuro.
Podemos selecionar um roxo ou verde.
Essa...
multiplicação da cor base (esse azul transparente), sempre vai deixar a cor mais escura.
E é por isso que algumas cores como vermelho, por exemplo
o dão um tom escuro e turvo.
É por isso que você quer escolher algo que se alinhe com o azul original.
Azul ou verde vão funcionar bem para essa modulação.
Isso é útil junto com a opção Depurar (Debug)
Formas de Colisão Visíveis (Visible Collision Shapes) no menu de depuração do projeto.
Que faz com que, quando você executar o jogo, você verá as formas de colisão, assim.
Certo, agora nós precisamos adicionar código para que, quando o jogador entrar no StompDetector
a gente reaja a esse evento.
A Godot tem uma funcionalidade chamada "signals" (sinais) para isso.
Quando você seleciona algum nó, como o StompDetector.
Na aba Node, próximo ao Inspetor
você vai encontrar uma lista de sinais que são emitidos quando um determinado evento acontece
Por exemplo, você pode detectar quando um corpo entra na área.
Um corpo, como qualquer KinematicBody2D, o inimigo e o jogador
Então nós vamos clicar duas vezes nesse sinal "body_entered"
e uma janela se abre. Ela nos permite conectar aquele sinal a uma nova função em um determinado nó
que tenha um script anexado.
Então nós vamos selecionar Enemy. Nós queremos que o script do inimigo reaja aqui.
E a Godot vai criar um novo método pra gente chamado _on "nome do nó" e "nome do sinal".
_on_StompDetector_body_entered nesse caso
Clique em Conectar (Conect) para criar a função e abrir o script do inimigo.
Uma nova função é adicionada na parte de baixo do script.
Nós vamos selecioná-la, cortá-la com ctrl-x
e colá-la logo abaixo da função "_ready"
É assim que fazemos na GDQuest, nós colocamos essas (nós as chamamos de callbacks)
essa funções que são chamadas de volta quando um determinado evento ocorre.
Nós as colocamos logo abaixo da função "_ready"
porque pode acontecer de você definir sinais, conexões como essas, na função "_ready".
E desse jeito você terá a reação logo abaixo da definição.
Agora, nós queremos substituir a linha "pass".
Esse comentário nos diz que temos que  substituí-la.
Por código que faça o inimigo morrer.
Quando algo entra na área do StompDetector nós faremos duas coisas:
primeiro, nós vamos verificar se esse "body", o jogador no caso, está abaixo da área.
Então, se "body.global_position.y"
é menor que "get_node", nós queremos pegar nosso StompDetector
.global_position.y
Nós estamos comparando a posição no eixo y do StompDetector no mundo do jogo
com a posição do jogador, que entrará na área.
Vou voltar ao script do inimigo.
Se essa condição for verdadeira
o personagem... me desculpe, deve ser maior que
a posição global do StompDetector.
Se o jogador está abaixo do StompDetector nós vamos retornar da função.
"return" é uma palavra reservada que retorna um valor, nesse caso "void", o que significa que ele não retorna nada
mas ela para a função aqui, então todo o código que escrevermos depois disso não será executado.
E, se nós não retornarmos da função
nós podemos chamar um método chamado "queue_free"
que vai deletar o inimigo, digamos assim.
E nós queremos fazer um pouco mais que isso.
Uma coisa que podemos fazer é desativar  as colisões no inimigo
porque "queue_free" é, essencialmente, matar o inimigo. Ele vai deletar o nó.
Com isso nós podemos executar o jogo
e agora, você deve ser capaz de pular sobre o inimigo e matá-lo, desse jeito.
Note que existe um pequeno atraso entre a chamada de"queue_free" e o inimigo morrer.
Nós queremos garantir que, quando o jogador entre na área do StompDetector
quando ele toca o inimigo, ele não vai ser morto por ele ou colidir com ele.
Então, uma coisa extra que podemos fazer aqui é chamar "get_node".
"get_node" é uma função para ter acesso a um dos nós na árvore.
Nós vamos pegar o CollisionShape2D.
Certo, nós estamos pegando esse nó CollisionShape2D
e nós vamos definir essa propriedade "disabled" como true
para que não se possa mais colidir com o inimigo.
.disabled é igual a true.
E, com isso, quando você pular no inimigo  não deve ser possível você colidir com ele.
Nós vamos ter que verificar se isso funciona como esperado depois
mas, em geral, nos seus jogos você precisará de algumas checagens de segurança para garantir que o jogador não vai morrer quando ele mata o inimigo.
Isso depende de como você programar o código de morte.
Vamos agora adicionar a pisada ao jogador.
Então abra a cena do jogador
e...
na cena do jogador, nós precisamos adicionar alguma coisa para que ele também detecte o inimigo.
No jogo final nós usamos uma área aqui também.
Uma área chamada EnemyDetector.
Selecione o nó do jogador, ctrl-A, vamos adicionar uma Area2D.
E nós vamos chamá-la de EnemyDetector.
Essa irá detectar especificamente o inimigo.
Então nós definimos Mask para a segunda camada, a "enemy".
E nós não vamos colocá-la em nenhuma camada.
Você pode também torná-la Non Monitorable (não monitorável), isso tem o mesmo efeito.
Agora...
Nosso EnemyDetector terá um formato que é maior que o nosso jogador.
Selecione o nó EnemyDetector
adicione um novo CollisionShape2D.
E, novamente, essa forma será um retângulo (RectangleShape2D).
E então nós queremos mover a forma para cima, centralizá-la com o jogador.
Para isso você pode usar a tecla W para mover e clicar e arrastar para mover a forma para cima.
Note que, se você tiver "snapping" ativado
você pode ativar ou desativar pressionando S
o nó deve automaticamente grudar no...
CollisionShape2D aqui.
Então ele vai se centralizar, se alinhar automaticamente com o outro CollisionShape2D.
Agora eu vou expandir esse detector de inimigos para fazê-lo um pouco maior
mas não muito. Nós vamos usar essa área para pisar no inimigo então...
no eixo y nós o faremos ter uma pequena margem abaixo do personagem
para que posamos pisar no inimigo.
E essa área também vai ser a área de morte para o nosso jogador nessa demo.
Por isso você quer deixá-la um pouco maior que a forma de colisão do jogador.
Agora nós vamos mudar a cor também. Então, com EnemyDetector selecionado
eu vou para a aba "Visibility", ou categoria
mudar a cor de modulação para, vamos dizer, algo azul também.
Isso ainda é o que funciona melhor.
Certo...
Com isso, nós vamos conectar o detector de inimigos com o jogador.
Então, o detector de inimigos detecta tudo que estiver na camada "enemy".
Na verdade, nós temos que voltar à cena do inimigo
e fazer com que o StompDetector
esteja na camada "enemy" e seja monitorável.
Nós vamos precisar disso para detectar quando pisarmos no inimigo.
Então vamos fazer dessa forma
nós vamos salvar e voltar para a cena do jogador
e, quando detectarmos uma área, ela vai ser, necessariamente, o StompDetector.
Então, nós vamos fazer o personagem pular nesse momento.
E, se a área detectar um corpo
ele vai ser, necessariamente, o inimigo que tocou o jogador.
Então o jogador deve morrer.
Vamos fazer dessa forma.
Então, EnemyDetector
Nós vamos para a aba Node.
Em "area_entered", nós vamos clicar duas vezes nisso
e criar _on_EnemyDetector_area_entered no jogador.
Vamos criar essa função.
Lembre-se, ele abre o script do jogador e cria a função na parte de baixo do script
Então nós vamos movê-la para cima
e colocá-la acima do nosso "_physics_process", aqui.
Agora, quando a área entrar, nós queremos pisar
então, nós podemos fazer...
"_velocity" é igual
nós vamos adicionar uma nova função chamada "calculate_stomp_velocity"
similar a como nós calculamos a velocidade de movimento ali embaixo.
Então, vamos escrever "calculate_move_velocity", mas eu vou substituir "move" por "stomp".
Expandir o editor de script e nós vamos passar duas variáveis para ela.
Uma será "_velocity"
e a outra será uma nova propriedade "stomp_impulse".
E  "stomp_impulse" será uma variável configurável que é específica ao jogador.
Então, no script do jogador fora de qualquer função
nós vamos exportar uma nova variável
chamada "stomp_impulse"
e nós podemos atribuir a ela, vamos dizer, 1000 pixeis
por segundo.
Agora nós temos que criar nossa função "calculate_stomp_velocity".
Eu vou adicioná-la na parte de baixo do meu script aqui
nova...
função "calculate_stomp_velocity".
Nós vamos usar dois parâmetros, "linear_velocity" é o primeiro
e o segundo é "stomp" ou "impulse", vamos dizer
e ele será um valor float (decimal).
Assim como a função "calculate_move_velocity" nós vamos retornar um Vector2.
Agora, na função  nós vamos criar a variável "new_velocity" ou "out".
Ela vai começar em "_linear_velocity"
e ela vai ser uma cópia da nossa velocidade inicial.
E o...
out.y será igual a "-impulse"
aqui
E nós vamos retornar nossa saída aqui.
Então o que isso faz é bem simples, na verdade
ele só substitui o componente y da nossa velocidade linear por "-impulse"
É como pular, mas "stomp_impulse" é um valor diferente do pulo normal.
Note que, nós estamos preparando tudo isso porque, mais tarde no jogo, nós podemos ter diferentes tipos de inimigo.
Você pode querer um inimigo com uma mola ou algo assim.
Separar essa lógica em uma função faz com que seja um pouco mais fácil
fazer o personagem pular em diferentes alturas ao pisar em um inimigo.
Você pode também usar essa função para fazer cálculos complexos para como o pulo funciona.
É por isso que nós, de novo, separamos o nosso código em funções.
Isso também ajuda a ler o código.
Certo, aqui nós calculamos a velocidade de pisada e fazemos o personagem pular.
E esse "stomp_impulse" que temos no jogador é configurável.
Então quando você clica no Player no editor.
Você tem agora a variável "stomp_impulse" que você pode mudar para fazer o personagem
pular mais alto ao pisar em um inimigo.
Nós podemos testar o jogo agora.
E ver que o jogador, quando você vai em um inimigo pula graças àquela nova função.
Nós vamos ao EnemyDetector para adicionar a habilidade do jogador morrer.
Então, selecione EnemyDetector
vá para a aba Node e quando o corpo entrar nessa área nós vamos fazer o jogador morrer.
Então clique duas vezes no sinal "body_entered".
Vamos conectá-lo ao jogador
e pegar essa função criada na parte de baixo do script
cortá-la, mover para cima e adicioná-la logo abaixo da nossa função anterior.
Vou expandir o editor de script mais uma vez
e nós vamos pôr o personagem na fila para liberar
quando o inimigo entrar na área EnemyDetector.
Agora, se você rodar o jogo com F5
e o inimigo tocar o jogador ele vai matar o jogador
como você pode ver.
Mas, se você pisar no inimigo você mata nele.
Isso é, digamos, uma forma relativamente fácil de programar o sistema.
Você verá que, se a área é pequena de mais aqui ou se você movê-la para baixo para muito perto do colisor do inimigo
bem, o jogador vai morrer e, algumas vezes os dois vão morrer ao mesmo tempo.
O jogador e o inimigo. Então você deve estar ciente disso.
De que a área deve ser grande o suficiente para que o jogador não toque no inimigo
e não morra quando cai sobre a área do StompDetector.
É por isso que eu fiz ela ser meio grande e a coloquei acima da caixa de colisão do inimigo aqui.
Para finalizar as coisas, nós vamos melhorar o jogo, fazer nossa câmera se mover suavemente e uma fase um pouco maior.
Então eu vou selecionar TileMap, vou redefinir sua posição
eu o movi apenas para demonstrar
e eu vou adicionar algumas paredes.
Como antes, como o TileMap selecionado
ctrl-shift clique e arraste para adicionar partes de tiles aqui e ali.
Vamos adicionar plataformas onde nós podemos colocar os inimigos para que eles
patrulhem para trás e pra frente esperando pelo jogador.
Desas forma.
Eu quero que a fase seja mais ou menos do tamanho de duas telas
Ahm... e...
assim deve estar bom.
Nós vamos fazer duas coisas aqui.
Nós vamos adicionar algo no fundo para fazer o jogo ficar mais bonito
e não ter esse cinza feio que temos.
E nós vamos também forçar a câmera a ficar dentro dos limites da fase.
E eu também vou adicionar um tile a mais em baixo para garantir que
nós não vejamos cinza abaixo do chão.
Então, para fazer isso eu vou até a cena do jogador e selecionar a Camera2D.
A câmera tem parâmetros que nos permitem limitar como ela se move.
Ela vai se manter em uma certa posição no jogo.
Então, com Camera2D selecionada você quer expandir a categoria Limit
e nós queremos garantir que, primeiro
ela para em 0 no lado esquerdo (Left) no mundo do jogo.
Então você pode ver que, com isso nossa câmera é empurrada para o lado direito do nosso eixo y.
Se você rodar o jogo você verá que a câmera vai parar à esquerda do mapa.
E então, no topo (Top), nós queremos fazer a mesma coisa:
fazê-la parar em 0.
Isso nos força, no LevelTemplate, a fazer nosso nível em baixo do eixo x.
Se você posicionasse a sua fase e o seu jogo acima da origem do mundo do jogo
você teria que fazer a parte de baixo (bottom) da câmera parar em 0
mas não é isso que queremos, nós queremos manter como está agora.
Voltando ao jogador.
Agora ele vai seguir o eixo x.
Ele vai se mover ao longo do eixo x, esse limite superior
e ele não vai passar do limite esquerdo, do eixo y aqui.
E nós podemos suavizar o limite da câmera para que ela não pare abruptamente nas bordas da tela.
Em alguns casos.
Agora, quando movemos o personagem
a câmera ainda se move junto com ele e nós temos uma margem no meio
na qual, se o personagem se mover em uma pequena caixa a câmera não vai se mover.
Nós podemos mudar isso com Drag Margin aqui, a propriedade que cria essa caixa.
Essa caixa é uma fração da área total da câmera 0.2 em todos os lados.
Nós faremos com que haja um pouco de margem no eixo vertical, então nas propriedades Top e Bottom.
Mas, a câmera sempre centraliza no personagem no eixo da esquerda para a direita, nos lados esquerdo e direito
e para fazer isso nós temos que reduzir Drag Margin para zero em Left e zero em Right.
E então, você também vai querer garantir que Drag Margin H e V estejam ativados.
Do contrário, essas propriedades do Drag Margin não fazer nada.
Então, quando você faz isso, assim que você mover o personagem
a câmera vai se centralizar nele o tempo todo.
Finalmente, nós podemos suavizar esse movimento para que
a câmera não siga o personagem de uma vez, mas tenha um pouco de atraso.
Clique na caixa Enabled para ativar a suavização.
Vou pressionar F5 para rodar o jogo.
Para que você possa ver que agora suavemente para no jogador.
Você pode mudar essa propriedade , vou fazer a janela ficar sempre por cima
para que agora eu possa mudar a propriedade a qualquer momento.
E se você abrir o menu de depuração você tem duas opções
para sincronizar mudanças que estão ativadas por padrão.
Quando você faz uma mudança no editor, como diminuir o valor Speed para a suavização e salva
você verá a câmera se mover bem mais devagar atrás do personagem.
E se você aumentar o valor. Agora a câmera segue o jogador bem rápido.
Ela tem um pouco de suavização, mas é bem sutil.
Eu vou selecionar o valor 7.
Voilá!
Então isso é algo legal de saber, você pode manter a sua janela por cima do editor como uma janela de jogo
e mudar qualquer valor no editor ou eu posso voltar  para a minha fase
aqui e selecionar o TileMap, adicionar tiles.
Onde está o jogador? está mais ou menos nessa área.
Você pode ver que, quando eu adiciono tiles no editor, eles aparecem instantaneamente no jogo também.
Essa é uma funcionalidade bem legal da Godot que você pode usar para
fazer um bom design de fase enquanto você está trabalhando.
Então agora nós vamos criar alguns inimigos a mais aqui.
Eu vou selecionar o inimigo.
Eu vou movê-lo para dentro
desses buracos, você pode ver que a posição do inimigo atualiza instantaneamente.
Selecionar Enemy na árvore da cena
apertar ctrl-D para duplicá-lo
e mover o segundo inimigo um pouco mais para longe.
E agora, nós temos dois inimigos andando na nossa fase.
Nós podemos pular sobre os inimigos para matá-los.
Ou nós podemos morrer miseravelmente. É disso que eu estava falando.
Nós queremos garantir que a StompArea no inimigo é grande o suficiente
para que não ocorra essa situação
onde o jogador morre antes de matar o inimigo.
Então vou torná-la um pouco maior aqui
e talvez voltar à cena do jogador.
Eu farei com que o EnemyDetector
alinhe-se com o eixo x, com a base da caixa de colisão do jogador e isso deve ser o suficiente para evitar esse bug.
Sim, parece estar funcionando bem.
E, com isso você tem uma pequena fase maneira.
Você pode também fazer a câmera parar no fim da fase.
O problema disso é que você tem que configurar a câmera para fazer isso para cada fase
baseado no quão grande a fase é.
Vamos ver como fazer isso para o nosso LevelTemplate.
Então eu vou à cena LevelTemplate, vou afastar a visão.
E nós queremos que a nossa câmera pare no canto direito do nosso TileMap aqui, no último tile.
Você pode ver que temos réguas na tela que você pode clicar e arrastar guias delas.
Nós vamos pôr o mouse sobre a régua da esquerda e clicar e arrastar para colocar uma guia no lado direito da fase.
Você ainda pode usar a roda do mouse para ser mais preciso e alinhar a guia com o final do tile.
A vantagem é que, você pode ver, enquanto arrasta a guia
quantos pixeis ela está comparada com a origem do eixo x.
Você pode também pôr o mouse sobre uma guia que já existe em um dado eixo.
Então, por exemplo, para mover uma guia que já existe, vocẽ quer ir à guia
para o topo da tela aqui e clicar e arrastar de lá.
Você não pode arrastar de dentro da tela, você precisa ir para dentro da régua e clicar e arrastar.
E nós podemos ver que a fase termina em 3600 pixeis.
Agora, nós não queremos mudar os limites da câmera na cena do jogador
porque isso vai ser aplicado a todas as fases na qual colocarmos o jogador.
Em vez disso, nós queremos mudar esse valor, o fim da fase, apenas no nosso LevelTemplate aqui.
Nós podemos fazer isso clicando com o botão direito no jogador
selecionando Filhos Editáveis (Editable Children).
E você quer descer até a Camera2D
expandir a categoria Limit e, para Right, você deve colocar 3600 pixeis
Uma vez feito isso. Vou mover o jogador um pouco mais pra frente para que a gente veja.
Quando você move o jogador para a direita da fase a câmera para na parte mais a direita da fase.
Essa funcionalidade Limit é bem legal porque você pode ver como
quando você move o jogador pelo mundo do jogo
a câmera se limita, ela para nos limites que definimos.
Com isso, nos falta uma coisa para fazer: adicionar o nosso fundo.
O fundo será uma imagem que você pode encontrar na pasta assets chamada Background.png.
Nós vamos clicar e arrastá-la para dentro do jogo.
E nós queremos...
que ela seja um TextureRectangle.
Agora, garanta que, quando você fizer isso, você está com o nó LevelTemplate selecionado
para que o fundo seja adicionado como filho dele.
Agora, o TextureRectangle é uma imagem que pode se adaptar à tela.
É um nó feito para criar interface de usuário
mas as vezes é útil para fazer imagens que repetem
ou para imagens que ocupam toda a tela.
Você verá que o seu ícone é verde.
Quando você o seleciona, uma nova opção aparece na barra de ferramentas chamada Layout.
Isso é uma opção, uma ferramenta que você pode usar para rapidamente
ancorar e redimensionar a sua imagem
baseado na janela do jogo.
Então, clique no menu Layout e selecione a opção Full Rect.
Quando você fizer isso o fundo vai cobrir totalmente a tela do jogo.
Clique e arraste Background para o topo da lista para que ele apareça ao fundo
e agora, quando você rodar o jogo, ele vai ficar preso à esquerda, ele não vai se cobrir toda a cena do jogo.
Nós podemos mudar isso criando um CanvasLayer.
É como as camadas em um programa como Krita ou Gimp.
Então, com LevelTemplate selecionado pressione ctrl-A para adicionar um nó
e procure por CanvasLayer.
Adicione um nó CanvasLayer eu vou posicioná-lo no topo.
Logo abaixo LevelTemplate e adicionar Background como filho dele.
Agora nosso CanvasLayer, se você selecionar o nó, tem uma propriedade Layer Index
isso define em que ordem essas camadas ou as Sprites são desenhadas no jogo
Layer 1 será acima das Sprites que colocarmos na nossa árvore de cena.
Então nós queremos usar um número negativo aqui.
Você pode colocar qualquer coisa, vamos dizer -100, para dizer que está bem longe no fundo.
Isso vai fazer o Layer ser desenhado por trâs de tudo.
E então, você pode pressionar F5 para ver que agora
esse CanvasLayer permanece atrás do jogador o tempo todo.
É como uma imagem fixa do céu, se preferir.
A última coisa que nós vamos até Depurar
Esconda as formas de colisão clicando em Formas de Colisão Visíveis (Visible Collision Shapes) aqui.
Desativando a opção para que a gente possa ver o jogo em sua forma final.
