lukanpeixe / projetocastleroid

Trabalhando em códigos para o mod/mapa de aventura para Terraria produzido pelo Idealizador e seguidores do canal Press key to play.
Apache License 2.0
8 stars 7 forks source link

16- Inteligencia Artificial #29

Open Kemado opened 7 years ago

Kemado commented 7 years ago

Achei este tutorial http://forums.terraria.org/index.php?threads/tutorial-custom-bosses-npc-ai-and-server-syncing.10474/

Não está do jeito que queríamos mas já ajuda a ter uma noção de como criar um boss do zero

lukanpeixe commented 7 years ago

É legal para ter uma base. Por enquanto estou sem tempo para atualizar/acompanhar as coisas aqui, mas pretendo inicialmente usar os bosses do Terraria mesmo, apenas com alteração em cor dos sprites, danos causados e velocidade. Em alguns casos, usar até um monstro normal adulterado como boss, ex.: paladin, "Morthra", Pigron, etc.

Kemado commented 7 years ago

Eita então esquece esse npc ele ignora blocos, mas acho que se fizer a verificação certa ficara perfeito

lukanpeixe commented 7 years ago

Ignorar blocos pode ser bom, depende da situação :)

Gurigraphics commented 7 years ago

A "aiStyle" e o controle dos NPCs ficam neste arquivo: NPC.cs

Kemado commented 7 years ago

baixado vlw... FBI na bota né kkkkkkkkkkk

Kemado commented 7 years ago

Que coisa Linda...Cara você me deu um diamante bruto Agradeço msm....

Gurigraphics commented 7 years ago

Tudo aqui fica disponível nas buscas do Google. Melhor nem dar ideia neh. kkk Flws

lukanpeixe commented 7 years ago

Eita peste! Tem um pouco de código nisso dai O_O Da para ficar lendo e fuçando isso dai por uns dois anos HUhauHA Seguindo a lógica da regeneração de vida, realizar trocas na AI com base nesses códigos usando o tmodloader seria algo descomplicado de fazer né?

Kemado commented 7 years ago

Algo do tipo se o personagem morrer ele da uma rodada e some? Se for isso dá sim, caso se estenda muito sinto em cortar suas asas Lukan

Gurigraphics commented 7 years ago

50.000 linhas de código. E tem mais uns 100 arquivos como esse. Quem só repara o pixel art do Terraria não imagina que é tão complexo.

Seguindo a lógica da regeneração de vida, realizar trocas na AI com base nesses códigos usando o tmodloader seria algo descomplicado de fazer né?

aiStyle tu define quando cria um NPC. Mas deve dar pra alterar durante o jogo.

Eu coloquei npc.aiStyle = 1 naquele NPC, ele saiu pulando igual um slime. Depois coloquei 20 e ele virou uma daquelas bola de aço com corrente. kkk

Kemado commented 7 years ago

Ex npc.aiStyle = 666. Essa animação seria personalizada por exemplo voar por 4frams ou segundos e cair... Minha intensão é criar uma aiStyle unica que pertença ao projeto, desta forma podemos criar animações de forma mais rapida. Mas vou revisar todo o codigo ou parte dele...

Gurigraphics commented 7 years ago

Os NPCs de Castlevania e Metroid praticamente não tem AI. O máximo que fazem é andar de um lado para outro em uma plataforma, pular, abaixar e disparar projeteis. E os que voam, eles apenas atrapalham o pulo.

Pela distancia X e Y da estátua de spawn tu consegue controlar esses limites? E isso aí vai ser igual as tochas invisíveis do Lukan para posicionar eles no mapa?

Kemado commented 7 years ago

Revisei minha lógica e conclui que basta eu simular se a próxima posição (x,y) existe um bloco sólido, caso exista ele colide... Agora vou fazer a função me desejem sorte!

Gurigraphics commented 7 years ago

Revisei minha lógica e conclui que basta eu simular se a próxima posição (x,y) existe um bloco sólido, caso exista ele colide... Agora vou fazer a função me desejem sorte!

Boa lógica e boa sorte. ^^

lukanpeixe commented 7 years ago

sinto em cortar suas asas Lukan

:disappointed: haha

50.000 linhas de código. E tem mais uns 100 arquivos como esse. Quem só repara o pixel art do Terraria não imagina que é tão complexo.

Definitivamente, os códigos do jogo são tão, ou mais, arte que os próprios sprites.

Depois coloquei 20 e ele virou uma daquelas bola de aço com corrente.

Fico pensando na sua reação de ver aquilo hahaha

Mas ainda eu acho que podemos sobrescrever as informações/funções dos mobs/AIs normais do jogo através do tmodLoader. Os itens pelo menos, eu tenho certeza que podem ser alterados, como deixar uma Terra Blade com 2000 de dano.

Revisei minha lógica e conclui que basta eu simular se a próxima posição (x,y) existe um bloco sólido, caso exista ele colide... Agora vou fazer a função me desejem sorte!

Espero que dê certo, buena suerte!

Kemado commented 7 years ago

using Terraria; using Terraria.ID; using Terraria.ModLoader; using Terraria.ObjectData; using Microsoft.Xna.Framework;

namespace Castleroid.NPCs { public class gosma : ModNPC { int contador = 0; int segundos = 0; public override void SetDefaults() { npc.name = "Gosma"; npc.displayName = "Gosma"; npc.width = 18; npc.height = 40; npc.damage = 14; npc.defense = 6; npc.lifeMax = 200; npc.soundHit = 1; npc.soundKilled = 2; npc.value = 60f; npc.knockBackResist = 0.000009f;//1.0f sem resistencia - 0.0000... quanto mais zeros mais resitente npc.aiStyle = -1;//Zerada a ai }

    public override float CanSpawn(NPCSpawnInfo spawnInfo)
    {
        return spawnInfo.spawnTileY < Main.rockLayer && !Main.dayTime ? 0.5f : 0f;
    }

    public override void AI()
    {
        npc.collideX = true;
        npc.collideY = true;
        contador += 1;

        float vel_x = npc.position.X;
        float vel_y = npc.position.Y;
        if(contador > 60){//60 numero de fps do jogo 60quadros por segundo
            segundos++;
            contador = 0;
        }
            if(segundos > 3){
                //vel_x += 16;
                vel_y -= 64;//plano cartesiano o ponto de horigem é diferente - 4 blocos altura
                segundos = 0;
            }
        //string s = segundos.ToString();// converte variavel segundos para o formato de texto
        npc.position = new Vector2(vel_x,vel_y);
        //Main.NewText(s, 255, 240, 20, false);// Texto com posicao x

    }

}

}

Kemado commented 7 years ago

@lukanpeixe copie o código acima e teste a nova gosma quando der...

lukanpeixe commented 7 years ago

copie o código acima e teste a nova gosma quando der...

Testei e constei a ausência de Knockback e códigos :) Embora o Stardust ainda possa gerar um knockback deslizante na gosma huAhuha Mas não se preocupe que a armadura Stardust não estará na aventura.

Eu estava pensando, para dar a ilusão de pulo, poderia ser programado uma série de teleportes até o ponto mais alto. Eu até ia tentar editar o código para isso, mas (acho que) não manjo nada de plano cartesiano.

Cannoner commented 7 years ago

se conseguir encontrar o codigo do Mimic, da para usar a parte do codigo q deixa ele parado para fazer NPCs parados

lukanpeixe commented 7 years ago

se conseguir encontrar o codigo do Mimic, da para usar a parte do codigo q deixa ele parado para fazer NPCs parados

Deve dar certo, mas nãos erá necessário, descobrimos como resolver isso, simplesmente desligando a Inteligencia Artificial (deixando no 0 ou -1) e o monstro fica parado. Obrigado pela dica :)

lukanpeixe commented 7 years ago

E só atualizando o tópico, coisas que já conseguimos referente a IA's:

IA é uma coisa que vamos trabalhar o tempo todo aqui, mas vou listar alguns dos que devem ser nosso próximos desafios:

Para ir finalizando a primeira parte, o Jardim, o que exige mais atenção é o 3º e o 4º item da lista.

Obs.: Ainda não atualizei a pasta com os novos arquivo (incluindo npc que dispara para direção fixa e ou bloco que quebra com a espada). Vou tentar fazer isso amanhã. Desculpe pela demora.

lukanpeixe commented 7 years ago

@Kemado Testei a NPC Rosaria, e esta bem legal o conceito. Existem dois bugs:

  1. O movimento meio esta desequilibrado (ela anda mais para esquerda, devido virar rosa antes do término do ciclo).
  2. Ao morrer para a sua versão "Rosa" um segundo após o respawn o jogo crasha.

Enfim, observações que devem ser estudadas durante o aprimoramento da NPC.

Kemado commented 7 years ago

Me manda o erro que aparece no log, pois aqui esta normal

lukanpeixe commented 7 years ago

Não tem log pq crash o jogo direto. A não ser que eu depure o Terraria com o Visual Studio depois do aviso da parada súbita emitida pelo Windows...

Detalhe, meu mundo esta pré hardmode e não é expert, talvez influencie...

Kemado commented 7 years ago

Primeiro peço desculpas pela minha ausência ou falta de pronunciamento. Não consegui identificar o motivo pelo qual o jogo crash, porem descobri como implementar diferentes AI personalizadas e a parte chata é que temos que codificar("definir como o npc deve agir"). Sobre os Boss ainda não descobri como identificar colisões com paredes. Lógica: Quando descobrir como são feitas colisões possibilita a mudança de direção do npc, desta forma o npc seria mais "inteligente". Enfim este é apenas um relato espero subir novidades em breve...

lukanpeixe commented 7 years ago

Primeiro peço desculpas pela minha ausência ou falta de pronunciamento.

De boa manolo, estamos todos ausentes na verdade ;/

Não consegui identificar o motivo pelo qual o jogo crash

Pode ser coisa do meu mapa, depois eu te passo ele para testar o crash.

ainda não descobri como identificar colisões com paredes

Uma dica que posso te dar, é dar uma olhada nas postagens do tópico do tmodloader, já vi lá IA inteiras de monstros de mods. É bom para pescar referências.

lukanpeixe commented 7 years ago

Um presente para o @Kemado Encontre no fórum do tmodloader uma IA que é uma réplica do Demon Eye, não sei se já viu, mas estudando este código, pode ser que você encontre umas dicas para a parte de colisão. Eu ainda estudei muito o código, e nem testei, mas meus conhecimentos são limitados apra fazer um aproveitamento 100%.

Enfim, segura esta manteiga:

public override void PreAI()
{
    npc.noGravity = true;
    // The following handles the collision:
    if (!npc.noTileCollide)
    {
        if (npc.collideX)
        {
            npc.velocity.X = npc.oldVelocity.X * -0.5f;
            if (npc.direction == -1 && (double) npc.velocity.X > 0.0 && (double) npc.velocity.X < 2.0)
                npc.velocity.X = 2f;
            if (npc.direction == 1 && (double) npc.velocity.X < 0.0 && (double) npc.velocity.X > -2.0)
                npc.velocity.X = -2f;
        }
        if (npc.collideY)
        {
            npc.velocity.Y = npc.oldVelocity.Y * -0.5f;
            if ((double) npc.velocity.Y > 0.0 && (double) npc.velocity.Y < 1.0)
                npc.velocity.Y = 1f;
            if ((double) npc.velocity.Y < 0.0 && (double) npc.velocity.Y > -1.0)
                npc.velocity.Y = -1f;
        }
    }  

    npc.TargetClosest(true); // Gets a valid player to target.
    //The 'true' means that we want the NPC to look at the player.

    // The following is plucked right from the 'Demon Eye' AI, so you may want to take a look, but you might not understand it all:

    float num1 = 4f;
    float num2 = 1.5f;
    float num3 = num1 * (float) (1.0 + (1.0 - (double) npc.scale));
    float num4 = num2 * (float) (1.0 + (1.0 - (double) npc.scale));
    if (npc.direction == -1 && (double) npc.velocity.X > -(double) num3)
    {
        npc.velocity.X = npc.velocity.X - 0.1f;
        if ((double) npc.velocity.X > (double) num3)
            npc.velocity.X = npc.velocity.X - 0.1f;
        else if ((double) npc.velocity.X > 0.0)
            npc.velocity.X = npc.velocity.X + 0.05f;
        if ((double) npc.velocity.X < -(double) num3)
         n    pc.velocity.X = -num3;
    }
    else if (npc.direction == 1 && (double) npc.velocity.X < (double) num3)
    {
        npc.velocity.X = npc.velocity.X + 0.1f;
        if ((double) npc.velocity.X < -(double) num3)
            npc.velocity.X = npc.velocity.X + 0.1f;
        else if ((double) npc.velocity.X < 0.0)
            npc.velocity.X = npc.velocity.X - 0.05f;
        if ((double) npc.velocity.X > (double) num3)
            npc.velocity.X = num3;
    }
    if (npc.directionY == -1 && (double) npc.velocity.Y > -(double) num4)
    {
        npc.velocity.Y = npc.velocity.Y - 0.04f;
        if ((double) npc.velocity.Y > (double) num4)
            npc.velocity.Y = npc.velocity.Y - 0.05f;
        else if ((double) npc.velocity.Y > 0.0)
            npc.velocity.Y = npc.velocity.Y + 0.03f;
        if ((double) npc.velocity.Y < -(double) num4)
            npc.velocity.Y = -num4;
    }
    else if (npc.directionY == 1 && (double) npc.velocity.Y < (double) num4)
    {
        npc.velocity.Y = npc.velocity.Y + 0.04f;
        if ((double) npc.velocity.Y < -(double) num4)
            npc.velocity.Y = npc.velocity.Y + 0.05f;
        else if ((double) npc.velocity.Y < 0.0)
            npc.velocity.Y = npc.velocity.Y - 0.03f;
        if ((double) npc.velocity.Y > (double) num4)
            npc.velocity.Y = num4;
    }

    if(!npc.wet)
        return false;

    if ((double) npc.velocity.Y > 0.0)
        npc.velocity.Y = npc.velocity.Y * 0.95f;
    npc.velocity.Y = npc.velocity.Y - 0.5f;
    if ((double) npc.velocity.Y < -4.0)
        npc.velocity.Y = -4f;
    npc.TargetClosest(true);

    return false;
}

Fonte (Tem mais informações que podem ser úteis sobre este código na página)