Combate
O combate é menos um sistema discreto e mais abstrato - É a interação complexa de vários sistemas diferentes trabalhando juntos, e a complexidade da implementação depende muito da complexidade do design.
No nosso jogo, o escopo do design é muito simples. O jogador tem um meio de ataque - pular em cima de um inimigo. Os inimigos têm duas maneiras diferentes de atacar o jogador - corpo a corpo e contato, dependendo do tipo de inimigo.
Para o ataque do jogador e o ataque corpo a corpo do inimigo, os fundamentos são quase exatamente os mesmos. Temos uma ou mais hitboxes colocadas na malha do esqueleto do personagem com base em como ele pode atacar corpo a corpo, junto com uma ou mais áreas de impacto para aproximar a área que queremos que seja passível de teste de acerto.
Para o ataque de contato com o inimigo, usamos o colisor de cápsulas do inimigo para verificar se o jogador entrou em contato com ele e realizar as mesmas ações de acerto que fazemos para o combate corpo a corpo. Você pode ver a implementação do que ocorre quando um personagem é atingido em nossa classe base de personagem, encontrada aqui: Parrot\Source\Parrot\Public\Character\ParrotCharacterBase.h. A lógica funcional está contida aqui e nas subclasses ParrotPlayerCharacter.h e ParrotEnemyCharacterBase.h.
O personagem do jogador.
A configuração para o jogador é única na forma como ele funciona ao atacar um inimigo. Quando o jogador se sobrepõe à área de dano de um inimigo, o inimigo retransmite essa informação ao jogador para perguntar se o ataque foi válido. Nesse caso, ele verifica se o jogador está acima do topo da área de impacto para garantir que ele esteja caindo em cima e não batendo pelas laterais ou por baixo. Se o ataque for válido, o inimigo sinaliza ao jogador para executar um salto. Se o jogador ainda estiver segurando o botão de pular quando fizer contato com a área de impacto, ele pulará mais alto. Soltar antes de fazer contato com a área de impacto resultará em um salto mais baixo.
O personagem inimigo.
A configuração para o inimigo é um pouco mais complicada por alguns motivos. Queremos que os ataques corpo a corpo pareçam realistas, então as áreas de dano dos inimigos são colocadas na borda de suas armas. A configuração das caixas de acerto, áreas de impacto e colisor de cápsulas podem ser vistas na janela de visualização do projeto de um personagem inimigo, como o encontrado aqui: Blueprints, Enemy, Skeleton, BP_EnemyCharacter_Skeleton.
Neste exemplo, você pode ver a caixa de impacto na cabeça, a caixa de acerto na arma e o colisor de cápsulas. Cada um desses gatilhos direciona seus eventos de sobreposição para funções pai na classe base do personagem.
Além disso, as animações de ataque enviam eventos de notificação que habilitam apenas as caixas de acerto da arma durante a parte da animação em que a arma está sendo brandida. Desta forma, parece que o jogador está realmente sendo atingido pela arma, e não apenas entrando em contato com um inimigo e sofrendo danos em um momento aleatório. Essas animações de notificação são inseridas na animação do ataque em pontos específicos para ativar a caixa de dano, que é habilitada e depois desabilitada. É possível visualizar as notificações da animação em Blueprints, Enemy/EnemyBase, BP_AnimNotify_EnemyAttackBegin e Blueprints, Enemy, EnemyBase, BP_AnimNotify_EnemyAttackEnd com a configuração na animação de ataque de um personagem inimigo específico, como Assets, Quaternius, PirateKit, Characters, Headless_Skeleton, Animations, Characters_Skeleton_Headless_Anim_CharacterArmature_Sword.
O personagem inimigo é aquele que verifica se há sobreposições e aciona eventos. Isso significa que o inimigo aciona tanto sua própria função HitCharacter() quanto a função HitCharacter() do jogador quando são detectadas sobreposições apropriadas.
É possível visualizar o código que atua nas sobreposições de caixas de acerto e caixas de dano aqui: Parrot\Source\Parrot\Public\Character\ParrotEnemyCharacterBase.h nas funções HitBeginOverlap() e HurtBeginOverlap().
Combate contra o chefe
Para a batalha contra o chefe, há uma funcionalidade adicional quando o chefe é atingido pelo jogador, a fim de reproduzir uma sequência de "fúria". É possível visualizar o código do projeto que aciona uma resposta do chefe aqui: Blueprints, Enemy, BossShark, BP_EnemyCharacter_BossShark.
A sequência de "fúria" é uma sequência simples cronometrada que reproduz uma animação telegrafada de "sacudir a cabeça" antes de aumentar a velocidade de caminhada do chefe e habilitar um componente de chama verde do Niagara para efeitos visuais. Durante essa sequência, ela também desabilita a área de dano, tornando o chefe invencível.