quarta-feira, 31 de março de 2021

PlayerCharacter: Array de PlayerProjectile

O PlayerCharacter pode mudar o tipo de PlayerProjectile que está sendo usado durante o jogo. As classes que representam os diversos tipos de PlayerProjectile serão adicionadas em um TArray na classe C++ PlayerCharacter.

Cada elemento do TArray é do tipo TSubclassOf<APlayerProjectile>. O uso do TSubclassOf permite que sejam armazenadas referências para a classe APlayerProjectile ou para qualquer uma de suas classes filhas (subclasses).

O código abaixo é a nova versão do arquivo PlayerCharacter.h contendo as variáveis e função necessárias para fazer a troca de projéteis. O conteúdo novo está em negrito. Observe que antes da macro UCLASS() foi feita uma forward declaration da classe APlayerProjectile. Dessa forma só precisamos adicionar o #include "PlayerProjectile.h" no arquivo cpp.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "PlayerCharacter.generated.h"

class APlayerProjectile;

UCLASS()
class TUTOPART3_API APlayerCharacter : public ACharacter
{
  GENERATED_BODY()

public:
  // Sets default values for this character's properties
  APlayerCharacter();

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

public:	
  // Called every frame
  virtual void Tick(float DeltaTime) override;

  // Called to bind functionality to input
  virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) 
                                                                            override;

  UFUNCTION(BlueprintCallable, Category = Movement)
  void MoveForward(float Value);
	
  UFUNCTION(BlueprintCallable, Category = Movement)
  void MoveRight(float Value);
	
  UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Projectile)
  TSubclassOf<APlayerProjectile> CurrentProjectileClass;
	
  UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Projectile)
  TArray< TSubclassOf<APlayerProjectile> > ProjectileClasses;
	
  UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Projectile)
  int32 IndexProjectileClass;
	
  UFUNCTION(BlueprintCallable, Category = Projectile)
  void ChangeProjectile();
};

Vamos analisar cada uma das novas declarações:

  • TSubclassOf<APlayerProjectile> CurrentProjectileClass: Esta variável armazena a referência da classe do tipo APlayerProjectile que representa o projétil selecionado pelo jogador.
  • TArray< TSubclassOf<APlayerProjectile> > ProjectileClasses: Array que armazena todas as referências de classe do tipo APlayerProjectile que podem ser selecionadas pelo jogador. 
  • int32 IndexProjectileClass: Armazena o índice com a posição no Array do APlayerProjectile selecionado. 
  • void ChangeProjectile(): Função que muda para o próximo projétil e atualiza as variáveis. Ao chegar no final do Array, retorna para o início.

No arquivo PlayerCharacter.cpp temos a definição da função ChangeProjectile(). Além disso, na função BeginPlay(), a variável CurrentProjectileClass é inicializada com o primeiro elemento do Array, que é o elemento com índice 0. A nova versão do arquivo ficou assim:  

#include "PlayerCharacter.h"
#include "PlayerProjectile.h"

// Sets default values
APlayerCharacter::APlayerCharacter()
{
  // Set this character to call Tick() every frame.
  PrimaryActorTick.bCanEverTick = true;
}

// Called when the game starts or when spawned
void APlayerCharacter::BeginPlay()
{
  Super::BeginPlay();

  if(CurrentProjectileClass == nullptr && ProjectileClasses.Num() > 0)
  {
    CurrentProjectileClass = ProjectileClasses[0];
  }	
}

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

// Called to bind functionality to input
void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
  Super::SetupPlayerInputComponent(PlayerInputComponent);
}

void APlayerCharacter::MoveForward(float Value)
{
  AddMovementInput(GetActorForwardVector(), Value);
}

void APlayerCharacter::MoveRight(float Value)
{
  AddMovementInput(GetActorRightVector(), Value);
}

void APlayerCharacter::ChangeProjectile()
{
  IndexProjectileClass++;
	
  if(IndexProjectileClass == ProjectileClasses.Num()) 
  {
    IndexProjectileClass = 0;
  }
	
  CurrentProjectileClass = ProjectileClasses[IndexProjectileClass];
}


No próximo artigo vamos fazer os ajustes necessário no Blueprint BP_PlayerCharacter e adicionar os elementos do Array de PlayerProjectile.


Sumário C++