Como Criar Inteligência Artificial para um Slime Inimigo

Nota: Um arquivo de projeto concluído para este tutorial pode ser encontrado no final deste artigo.
Introdução
Neste tutorial, criaremos a inteligência artificial (IA) para um craba de lama inimiga convincente para um jogo do tipo plataforma. Cobriremos alguns recursos e comportamentos mais avançados no hyperPad, portanto, este tutorial assume algum conhecimento básico com o editor hyperPad. Se você acha que precisa se familiarizar mais com a criação de um jogo do zero, você pode primeiro verificar o Guia Completo - Criando um Jogo de Plataforma.
Para fazer o slime parecer "inteligente", ele deve fazer mais do que simplesmente se mover para frente e para trás, e deve estar um pouco ciente de seu entorno.
Isso parece emocionante! Mas antes de começarmos, devemos primeiro detalhar como o slime inimigo deve se comportar:
- Em vez de andar, o slime vai pular para a esquerda ou para a direita para se mover.
- O slime saltará na direção do jogador.
- Se o jogador estiver muito longe, o slime não se moverá (parado).
- O slime removerá a saúde do jogador ao contato.
- O slime é derrotado se o jogador saltar em cima dele.
Agora que sabemos o que queremos fazer, vamos começar!
Parte 1: Configuração do Projeto
Neste tutorial, começaremos um novo projeto do zero para manter as coisas simples. Crie um novo projeto e defina-o como "Visão Lateral", você pode deixar as outras configurações com seus valores padrão.
Com o seu novo projeto criado, vá à Biblioteca de Recursos e pegue o "Pacote Inicial de Plataforma" do hyperPad na loja de ativos. (É grátis!)
Agora que temos alguns ativos para trabalhar, vá em frente e coloque alguns blocos de chão e crie seu mundo. Se você ainda não estiver lá, vá para a Biblioteca de Recursos e toque em "Downloads", depois "Pacote Inicial de Plataforma".
Na imagem abaixo, alguns blocos de chão (pasta "Mundo de Grama") foram colocados e um fundo (pasta "Fundos") foi definido.
Agora que temos uma ótima cena para trabalhar, vamos adicionar os objetos Jogador e Slime. Vá para a Biblioteca de Recursos e abra sua pasta "Downloads", depois a pasta "Pacote Inicial de Plataforma" se ainda não estiver aberta.
Usaremos o "Espacial Verde" como jogador, então toque no ativo do espacial verde para ver todos os seus ciclos de animação. Por padrão, queremos que o jogador simplesmente fique parado, então toque na animação "Parado" e coloque-a na cena.
Na mesma pasta da Biblioteca de Recursos, também há um personagem animado chamado "Slime Rosa". Perfeito para usarmos como um slime inimigo! Toque no ativo do slime e escolha a animação "Mover" e coloque um slime na sua cena com seu personagem jogador.
Até agora, tudo bem! Agora temos nosso objeto jogador e nosso objeto slime, prontos para usarmos. Mas, se jogássemos nosso projeto agora, não conseguiríamos interagir com o jogo. Portanto, teremos que criar alguma lógica para dar vida ao nosso jogo.
Parte 2: Controles do Jogador
Antes de podermos trabalhar para dar algum movimento à nossa slime inimiga, devemos primeiro ter alguns controles para o espacial verde.
Toque no espacial verde e defina seu modo de física de Parede para Física, o que permitirá que o jogador se mova livremente. Depois, toque no botão "Comportamentos" para abrir o editor de Comportamentos para nosso personagem jogador, para que possamos adicionar alguns controles.
No editor de comportamento do nosso personagem jogador, você já deverá ver um solitário Reproduzir Animação comportamento. Podemos deixar esse comportamento de lado, mas podemos dar alguns amigos a ele.
Na seção Interação, coloque qualquer lugar um comportamento Controlado por Joystick e um comportamento Saltar com Botão. Com esses comportamentos, nosso jogador agora está pronto para controle. Mas, está faltando um pouco de animação.
Toque no comportamento Controlado por Joystick e defina a "Animação do Joystick Esquerdo" para o ciclo de animação "Andar" no ativo do Espacial Verde. Faça o mesmo com a "Animação do Joystick Direito".
Agora nosso personagem jogador anda, mas ainda não anima quando salta.
Toque no comportamento Saltar com Botão e altere tanto a "Animação de Queda" quanto a "Animação de Salto" para o ciclo de animação "Saltar".
Se jogarmos nosso jogo agora, podemos nos mover e pular! Em seguida, podemos trabalhar na nossa slime inimiga.
Parte 3: Movimento do Slime
Como detalhamos na seção de introdução deste tutorial, queremos que nosso slime pule em direção ao jogador. Para fazer isso, nosso slime precisa saber onde o jogador está no mundo. Por causa disso, devemos adicionar uma Tag ao nosso personagem jogador, assim nossos comportamentos podem recuperar nosso personagem jogador em qualquer cena.
Toque no personagem jogador e selecione a aba Tags na parte inferior da visão de propriedades. Digite "Jogador" no campo de texto na parte superior do menu de tags e pressione o botão adicionar (+) ao lado. Agora nosso personagem jogador está tagueado com a tag "Jogador".
Semelhante ao que fizemos com o personagem jogador, toque no slime e defina seu modo de física de Parede para Física. Então, toque no botão Comportamentos para abrir o editor de comportamento do slime.
No editor de comportamento, vá para a seção de Personalizado e arraste um comportamento Timer para o editor.
Toque no comportamento Timer e defina seu intervalo para 2 segundos.
Este será o início de nossa lógica para a inteligência artificial do slime.
A ideia aqui é que a cada 2 segundos, nosso slime "pense" no que fazer a seguir, como: O slime deve pular? Se decidir pular, em que direção deve pular?
Em seguida, vá para a seção de Transformar e coloque um comportamento Obter Posição. Toque nele e defina seu alvo para a tag "Jogador" que criamos anteriormente, tocando na aba Tags na parte inferior de sua visão de propriedades e selecionando "Jogador". Agora conecte o Timer ao comportamento Obter Posição.
Agora sabemos onde o nosso jogador está no mundo! Para determinar se o jogador está à esquerda ou à direita do slime, também precisamos saber onde o slime está no mundo.
Arraste outro comportamento Obter Posição para o editor. Por padrão, o comportamento já está direcionado ao nosso slime, então não precisamos fazer nada além de conectá-lo ao nosso ramo lógico. Vá em frente e conecte o Obter Posição do jogador ao Obter Posição do slime.
Opcional: Para facilitar a compreensão, eu renomeei meus comportamentos Obter Posição para indicar claramente o que eles estão rastreando: "Obter Posição Jogador" e "Obter Posição Slime". Isso é opcional, mas se você também quiser mudar os nomes dos comportamentos, pode fazê-lo tocando no comportamento e tocando em seu nome na parte superior da visão de propriedades.
Até agora, o que temos é que a cada 2 segundos, o slime obtêm a posição do personagem jogador e de si mesmo. Agora que temos essa informação, podemos determinar se o slime deve pular para a esquerda ou para a direita.
Debaixo da aba Lógica, arraste e conecte um comportamento Se. Nas suas propriedades, defina o primeiro valor para a posição x do primeiro Obter Posição (tag "Jogador") arrastando o valor de saída do comportamento para o campo nas propriedades do Se. Para o segundo valor, defina para a posição x do segundo Obter Posição (slime). Por fim, defina o estado da condição do comportamento Se para "É Menor Que" (<).
Nota: A posição x de um objeto é o valor que representa onde o objeto está no mundo em seu eixo x. (Esquerda e direita)
Então, o que tudo isso significa? O comportamento Se verificará se a posição x do jogador é menor que a posição x do slime. Se o acima for verdadeiro, ele executará o próximo comportamento conectado. O que isso significa essencialmente, é que se o jogador estiver mais à esquerda que o slime, então a execução do comportamento continuará.
Ok, agora temos a lógica configurada para fazer o slime pular para a esquerda, então vamos fazer o slime fazer exatamente isso!
Debaixo da aba Física, arraste e conecte um comportamento Aplicar Força ao comportamento Se. Nas suas propriedades, defina a Força para: x = -0.5, y = 1. Depois, defina o multiplicador para um número considerável, 200 deve servir.
O que temos agora é que, se o slime encontrar o jogador mais à esquerda que ele, ele pulará para cima (y = 1 × 200) e um pouco para a esquerda (x = -0.5 × 200).
Experimente! Jogue o jogo e teste para se certificar de que tudo está funcionando. O que você deve ver é o slime pulando para a esquerda a cada 2 segundos, enquanto o jogador estiver à esquerda dele. Se você mover o jogador para a direita do slime, ele deverá parar de pular até que você se mova para a esquerda novamente.
Nota: Se o seu slime não estiver se movendo, reveja os passos anteriores para se certificar de que não perdeu nada. Certifique-se de que os comportamentos estão conectados corretamente e que o modo de física do seu slime está definido para Física (móvel) em vez de Parede (não móvel). Também, em breve resolveremos o problema em que o slime às vezes fica de lado ou de cabeça para baixo.
Ótimo progresso até agora! Se o seu slime está pulando como esperado, então estamos prontos para continuar. Vamos terminar os comportamentos de movimento permitindo que o slime também pule para a direita.
De volta ao editor de comportamento do slime, duplique o comportamento Se. Arraste e encaixe o novo comportamento Se à direita do comportamento Se original. Isso o transformará em um comportamento "Senão Se".
Duplique também o comportamento Aplicar Força e conecte isso ao novo comportamento Senão Se.
Nas propriedades do Senão Se, altere a condição de "É Menor Que" (<) para "É Maior Que" (>). Isso terá o efeito oposto do primeiro Se. Se o primeiro comportamento Se não for verdadeiro, ele verificará se o Senão Se é verdadeiro. Isso significa que, se o jogador não estiver à esquerda do slime, ele verificará se o jogador está à direita do slime e continuará executando os comportamentos conectados ao Senão Se.
Agora você deve ter um ramo de comportamento que se parece com isso:
No segundo Aplicar Força (sob o Senão Se), altere suas propriedades para que sua força seja x = 0.5, em vez de x = -0.5. Agora, em vez de pular para a esquerda, o slime pulará para a direita.
Jogue o projeto e experimente novamente! Agora você deve ver o slime pulando na direção que o jogador está. Excelente!
Uma coisa que você pode ter notado enquanto testava é que, se você colidir com o slime, ele pode às vezes cair de lado ou ficar de cabeça para baixo. Queremos que o slime fique na posição vertical, então vamos corrigir isso rapidamente.
De volta ao editor de comportamento do slime, vá para a seção de comportamento Transformar e arraste um Bloquear Rotação para o editor. Não é necessário conectá-lo a outro comportamento, queremos bloquear sua rotação assim que o slime for criado, então você pode deixá-lo assim. Depois de fazer isso, experimente o jogo novamente. Desta vez você terá um trabalho difícil tentando derrubar o slime de lado.
Você também pode ter notado que a animação do slime está sendo reproduzida muito rapidamente. Se isso estiver acontecendo, toque no comportamento Reproduzir Animação no editor de comportamento do slime e mude os Quadros Por Segundo para um número muito menor. 6 quadros por segundo parece muito bom.
Ótimo! Agora nosso slime não está apenas se movendo bem, mas também parece ótimo. Na maior parte, a lógica de movimento do slime está completa.
No entanto, também queremos que o slime só pule se o jogador estiver por perto. Dessa forma, se construirmos um mundo maior, slimes muito longe não tentarão imediatamente pular em direção ao jogador e atacá-lo. Na próxima parte, iremos adicionar outra condição para bloquear a lógica de salto se o jogador estiver muito longe.
Parte 4: Slime Parado
Nesta parte, implementaremos alguns comportamentos do slime que o farão ficar parado (ou seja, não se mover) quando o jogador estiver muito longe.
Para conseguir isso, precisamos encontrar uma maneira de medir a distância do nosso slime até o jogador. Convenientemente, existem comportamentos disponíveis para fazer exatamente isso! Vamos trabalhar.
Abra o editor de comportamento do slime e arraste um Calcular Distância para o editor a partir da seção Lógica. Nas propriedades do comportamento, o primeiro objeto já está definido para nosso slime. Para o segundo objeto, vá para o menu de Abas e selecione a tag "Jogador".
Esse comportamento, quando executado, calculará a distância em metros do nosso slime até o jogador. Com essas informações, podemos verificar se o jogador está muito longe verificando se está além de uma determinada distância.
Coloque um comportamento Se a partir da seção Lógica e conecte-o abaixo do comportamento Calcular Distância. Nas propriedades do comportamento Se, defina o primeiro valor para o valor de saída do comportamento Calcular Distância. Defina a condição para "É Menor Que" e o segundo valor para 15.
Agora o que temos é uma maneira de verificar se o jogador está muito longe, verificando se a distância entre o slime e o jogador é menor que 15 (metros). Se essa condição for falsa, então o jogador está muito longe e o comportamento Se não executará o próximo comportamento.
Agora que temos nossa nova condição pronta para uso, desconecte o Obter Posição (slime) e o antigo comportamento Se da parte anterior do tutorial e faça um espaço para nossa nova condição. Você pode desconectar comportamentos tocando e segurando as conexões entre os comportamentos.
Com a nova condição de distância no lugar, conecte o Obter Posição (slime) ao comportamento Calcular Distância e, em seguida, conecte o novo comportamento Se ao comportamento Se antigo. Você deve agora ter algo assim:
Está começando a parecer bem complicado agora, mas a ideia é relativamente simples. Agora o que temos é que antes de verificarmos qual direção o slime deve pular, primeiramente verificamos se a distância entre o slime e o jogador é menor que 15 (metros).
Se o jogador estiver mais perto de 15 metros, então continuará e verificará em qual direção devemos pular, como de costume. Se o jogador estiver mais distante de 15 metros, não continuamos e a lógica termina até a próxima vez que o slime "pensar" novamente (daqui a 2 segundos).
Dê uma chance ao jogo! Se você se aproximar muito do slime, ele deve começar a pular em direção a você, mas se você se afastar demais, ele deve parar de se mover e esperar até que você se aproxime novamente.
Nosso slime está começando a parecer bastante ameaçador agora, mas ainda está faltando uma maneira de causar dano ao jogador. Na próxima parte deste tutorial, daremos ao jogador uma barra de saúde e implementaremos alguma lógica para causar dano ao jogador.
Parte 5: Atacando o Jogador
Como detalhado na seção de introdução, implementaremos ataques do slime fazendo com que o slime machuque o jogador quando tocar o jogador. Para começar a implementar uma forma de o slime atacar o jogador, primeiro precisamos dar ao jogador alguma saúde.
Na editor principal, selecione a camada da UI da Cena e crie um novo objeto com o botão Objetos Especiais. Toque em "Barra de Saúde" para criar uma barra de saúde para nosso jogador.
Como está colocada na camada UI da Cena, se escolhermos expandir nosso mundo e fazer a tela seguir o jogador, ela permanecerá na mesma posição na tela.
Você pode colocá-la onde quiser na tela. Eu coloquei a minha no centro da tela perto da parte inferior.
Quando você terminar de encontrar um bom lugar para sua barra de saúde, podemos trabalhar para adicionar uma maneira de remover saúde da barra de saúde. Retorne à camada Principal onde está seu slime e abra novamente o editor de comportamento dele.
Em um local vazio no editor de comportamentos do seu slime, arraste um comportamento Colidido encontrado na seção Objeto. Nas suas propriedades, defina o segundo objeto para a tag "Jogador".
Abaixo da seção de comportamento Personalizado, arraste um comportamento Enviar Mensagem e conecte-o abaixo do comportamento Colidido. Nas propriedades do comportamento Enviar Mensagem, defina a Chave do Evento como "jogador atingido", e defina o valor como -10.
Lembre-se: Chaves de eventos diferenciam maiúsculas de minúsculas! Para simplicidade, este tutorial usará letras minúsculas para chaves de eventos. Você pode escolher usar letras maiúsculas se preferir, mas certifique-se de lembrar quais letras são maiúsculas para depois.
Agora temos uma maneira de detectar quando o jogador deve perder saúde. Quando o jogador colidir com o slime, uma mensagem para o evento "jogador atingido" será enviada com um valor de -10. Usaremos o -10 para dizer à barra de saúde para "adicionar" -10 de saúde, e já que o valor é negativo, removerá 10 de saúde.
Ainda precisamos adicionar essa lógica à barra de saúde, então vamos fazer isso agora. Saia do editor de comportamento do slime e então, no editor principal, toque na camada UI da Cena e depois toque na barra de saúde. Abra o editor de comportamento da barra de saúde.
Na barra de saúde, arraste um comportamento Receber Mensagem da seção Personalizada. Nas suas propriedades, defina a Chave do Evento como "jogador atingido". (Lembre-se de que é sensível a maiúsculas!)
Esse comportamento será nosso receptor da mensagem "jogador atingido" enviada sempre que o jogador atinge o slime. Quando este comportamento detectar uma mensagem de transmissão para "jogador atingido" em qualquer lugar do jogo, ele irá executar.
Agora, adicione um comportamento Adicionar à Barra de Saúde abaixo da seção de comportamento UI e conecte-o abaixo do comportamento Receber Mensagem.
Nas propriedades do Adicionar à Barra de Saúde, arraste o valor de saída de Receber Mensagem para o campo "Valor a adicionar". Esse valor será o valor -10 que configuramos anteriormente no comportamento Enviar Mensagem no slime. Assim, se decidirmos fazer com que outros inimigos causem diferentes quantidades de dano, tudo o que precisamos fazer é alterar o valor na transmissão para o que queremos, e a barra de saúde usará esse valor em vez disso!
Certifique-se de que " Evento Quando Cheio" esteja desligado e "Evento Quando Vazio" esteja ligado. Isso significa que se a barra de saúde chegar a zero, ela executará o próximo comportamento.
Abaixo da seção de comportamento Cena, arraste um comportamento Carregar Sobreposição e conecte-o ao comportamento Adicionar à Barra de Saúde.
Nas configurações de Carregar Sobreposição, altere a sobreposição selecionada para a sobreposição "Game Over" que é criada automaticamente para você quando você faz um novo projeto.
Jogue o jogo e experimente! Agora, sempre que você entrar em contato com o slime, ele deve esvaziar sua barra de saúde. Quando a barra de saúde atinge zero, é o fim do jogo.
Legal! Agora temos uma maneira de causar dano ao jogador e perder o jogo.
Algo parece um pouco fora, porém. Não estamos dando muito feedback ao jogador de que ele foi atingido, além de remover saúde da barra de saúde.
Podemos corrigir isso impulsionando o jogador e o slime um do outro, deixando claro que eles colidiram, além de impedir que o jogador receba dano muito rapidamente ao colidir com o slime repetidamente.
Vá para o editor de comportamento do slime (você pode precisar selecionar a camada Principal primeiro) e arraste um comportamento Impulsionar Objeto sob a seção Física. Conecte-o abaixo do comportamento Enviar Mensagem de antes e abra suas propriedades.
Nas propriedades, altere o segundo objeto para a tag "Jogador" abrindo a aba de Tags e selecionando "Jogador". Altere o valor da Força para 200, o Multiplicador do Objeto A para 0.25 e o Multiplicador do Objeto B para 1.
Agora, quando o jogador colidir com o slime, ele será empurrado para longe do slime com uma força de 200 (1 × 200 força) e o slime será empurrado para longe do jogador com uma força de 50 (0.25 × 200 força).
Nosso jogo está começando a ficar muito bom agora! Apenas um problema agora é que temos um slime invencível e nosso jogador não tem como derrotá-lo. Na próxima parte, implementaremos uma maneira de nosso jogador revidar.
Parte 6: Derrotando o Slime
Para permitir que nosso jogador ataque o slime pulando em cima dele, teremos que mudar como estamos lidando com a colisão ao fazer com que o slime ignore a parte inferior do jogador (os pés do jogador) ao causar dano.
Abra o editor de comportamento do slime e toque no comportamento Colidido que criamos na parte anterior do tutorial. Desative a opção "Na Parte Inferior", que ignorará colisões se o slime colidir com a base da caixa de colisão do jogador.
Agora, nosso slime não machucará o jogador se o jogador pular em cima dele. Em vez disso, queremos realizar uma lógica diferente quando isso acontecer.
Com o evento Colidido selecionado, duplique-o e reverta todas as opções no novo comportamento Colidido para que apenas o evento "Na Parte Inferior" esteja habilitado.
Isso servirá como nosso ponto de entrada quando o jogador salta em cima do slime.
Em seguida, arraste e conecte um comportamento Destruir Objeto da seção de comportamento Objeto. Ele já deve estar configurado para destruir nosso objeto slime por padrão.
Agora, quando jogarmos nosso jogo, saltar em cima do slime o destrói. Mas, novamente, como fez com receber dano do slime antes, isso não parece muito satisfatório.
Como fizemos na parte anterior do tutorial, vamos adicionar outro comportamento Impulsionar Objeto. Duplique o comportamento de Impulsionar Objeto mais antigo da lógica de dano ao jogador e conecte-o abaixo do comportamento Destruir Objeto. Suas propriedades do comportamento de Impulsionar Objeto mais antigo podem permanecer as mesmas.
Agora, quando jogarmos o jogo, haverá um bonito e satisfatório impulso ao pular em cima do slime.
Conclusão & Exercícios
E isso é praticamente tudo! Conferimos todos os itens feitos na seção de introdução:
- Em vez de andar, o slime irá pular para a esquerda ou para a direita para se mover. Verificado!
- O slime saltará na direção do jogador. Verificado!
- Se o jogador estiver muito longe, o slime não se movimentará (parado). Verificado!
- O slime removerá a saúde do jogador ao contato. Verificado!
- O slime é derrotado se o jogador pular em cima dele. Verificado!
Se você chegou até aqui, agora deve ter uma compreensão decente de como pode dar inteligência a seus inimigos e fazê-los pensar e tomar decisões por conta própria. Muito bem!
No entanto, sempre há mais coisas que podem ser feitas. Como exercício, tente fazer o seguinte por conta própria:
- Reproduzir uma animação de "atingido/morto" quando o slime for pulado pelo jogador.
- Reproduzir uma animação de "atingido" quando o slime atacar o jogador.
- Adicionar um pouco de aleatoriedade a quão longe o slime pulou cada vez.
Um arquivo de projeto concluído para este tutorial pode ser encontrado aqui: Baixar Projeto do Tutorial

