quarta-feira, 31 de março de 2021

PlayerCharacter: Array of PlayerProjectile

The PlayerCharacter can change the type of PlayerProjectile that is being used during the game. The classes that represent the different types of PlayerProjectile will be added to a TArray in the PlayerCharacter C++ class.

Each element of TArray is of type TSubclassOf<APlayerProjectile>. The use of TSubclassOf allows the storage of references to the APlayerProjectile class or to any of its child classes (subclasses).

The code below is the new version of the PlayerCharacter.h file containing the variables and function needed for the change of projectiles. The new content is in bold. Note that before the UCLASS() macro, a forward declaration of the APlayerProjectile class was made. That way we just need to add the #include "PlayerProjectile.h" to the cpp file.

#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();
};

Let's look at each of the new declarations:

  • TSubclassOf<APlayerProjectile> CurrentProjectileClass: This variable stores the reference of the class of type APlayerProjectile that represents the projectile selected by the player.
  • TArray< TSubclassOf<APlayerProjectile> > ProjectileClassesArray that stores all class references of type APlayerProjectile that can be selected by the player. 
  • int32 IndexProjectileClassStores the index with the position in the Array of the selected APlayerProjectile
  • void ChangeProjectile(): Function that changes to the next projectile and updates the variables. When it reaches the end of the Array, it returns to the beginning.

In the PlayerCharacter.cpp file we have the ChangeProjectile() function definition. In addition, in the BeginPlay() function, the CurrentProjectileClass variable is initialized with the first element of the Array, which is the element with index 0. The new version of the file looks like this:  

#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];
}


In the next article we will make the necessary adjustments to the Blueprint BP_PlayerCharacter and add the elements of the PlayerProjectile Array.


Table of Contents C++