segunda-feira, 5 de abril de 2021

EnemyProjectile: Criando um projétil teleguiado

Neste artigo vamos criar uma classe base C++ para representar os projéteis teleguiados que são disparados pelos canhões inimigos.

No Content Browser, acesse a pasta TutoPart3 que está dentro da pasta C++ Classes. Clique com o botão direito em um espaço livre e escolha a opção New C++ Class...:


Na tela seguinte, escolha a classe Actor como classe pai e clique no botão Next.


No campo Name coloque EnemyProjectile. No campo Path, mantenha a pasta padrão do projeto. Clique no botão Create Class.

A classe EnemyProjectile usará quatro tipos de componentes:

  • USphereComponent: É usado como componente Root e para o teste de colisão.
  • UStaticMeshComponent: Contém o Static Mesh que representará visualmente o projétil.
  • UParticleSystemComponent: Componente com um emissor de partículas que será usado para simular um efeito de fogo no projétil.
  • UProjectileMovementComponent: Componente usado para movimentar o projétil. Será configurado para seguir o jogador.

 

Adicione a declaração dos componentes no arquivo EnemyProjectile.h que ficará assim:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "EnemyProjectile.generated.h"

UCLASS()
class TUTOPART3_API AEnemyProjectile : public AActor
{
  GENERATED_BODY()
	
public:	
  // Sets default values for this actor's properties
  AEnemyProjectile();

protected:
  // Called when the game starts or when spawned
  virtual void BeginPlay() override;

public:	
  // Called every frame
  virtual void Tick(float DeltaTime) override;
	
  UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
  UStaticMeshComponent* StaticMesh;
	
  UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
  class USphereComponent* CollisionComponent;
	
  UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
  class UParticleSystemComponent* Particles;

  UPROPERTY(VisibleAnywhere, BlueprintReadOnly)	
  class UProjectileMovementComponent* ProjectileMovement;
	
};

No arquivo EnemyProjectile.cpp, temos a inicialização dos componentes feita no construtor. Não esqueça de adicionar as linhas #include dos componentes.

#include "EnemyProjectile.h"
#include "Engine/CollisionProfile.h"
#include "Components/SphereComponent.h"
#include "Particles/ParticleSystemComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Kismet/GameplayStatics.h"


// Sets default values
AEnemyProjectile::AEnemyProjectile()
{
  PrimaryActorTick.bCanEverTick = true;

  InitialLifeSpan = 10.f;
	
  CollisionComponent = CreateDefaultSubobject<USphereComponent>(
                                             TEXT("CollisionComponent"));
  RootComponent = CollisionComponent;
  CollisionComponent->InitSphereRadius(25.f);
  CollisionComponent->SetCollisionProfileName(
                              UCollisionProfile::BlockAllDynamic_ProfileName);

  StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
  StaticMesh->SetupAttachment(CollisionComponent);
	
  Particles = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("Particles"));
  Particles->SetupAttachment(StaticMesh);
	
  ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(
                                             TEXT("ProjectileMovement"));
  ProjectileMovement->InitialSpeed = 300.f;
  ProjectileMovement->MaxSpeed = 300.f;
  ProjectileMovement->bRotationFollowsVelocity = true;
  ProjectileMovement->bIsHomingProjectile = true;
  ProjectileMovement->HomingAccelerationMagnitude = 300.f;
  ProjectileMovement->ProjectileGravityScale = 0.f;
}

// Called when the game starts or when spawned
void AEnemyProjectile::BeginPlay()
{
  Super::BeginPlay();
	
  APawn* PlayerPawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
	
  if(PlayerPawn)
  {
    ProjectileMovement->HomingTargetComponent = PlayerPawn->GetRootComponent();
  }
}

// Called every frame
void AEnemyProjectile::Tick(float DeltaTime)
{
  Super::Tick(DeltaTime);
}

Fiz os seguintes passos para configurar o UProjectileMovementComponent como um projétil teleguiado:

  • Atribuí true à variável bRotationFollowsVelocity para que o projétil rotacione quando mudar de direção.
  • Atribuí true à variável bIsHomingProjectile para indicar que este é um projétil teleguiado.
  • Atribuí um valor para a variável HomingAccelerationMagnitude que indica a aceleração que o projétil se moverá em direção ao alvo. Utilizei o mesmo valor da velocidade do projétil.
  • Removi a força de gravidade do projétil atribuindo o valor 0 à variável ProjectileGravityScale.
  • O último passo é atribuir um USceneComponent à variável  HomingTargetComponent que será usado como alvo. Isto é feito na função BeginPlay(). O alvo é o RootComponent do jogador.   


Compile o código C++. Os Assets de Static Mesh e de Particle System serão selecionadas nos Blueprint filhos. Além disso, os valores iniciais atribuídos aos componentes podem ser modificados em Blueprints filhos.  


Sumário C++