Vamos criar uma função em C++ com o nome StartGame(). O nome de uma função é sempre seguida de parênteses. Uma função possui um ou mais comandos que serão executados quando a função for chamada.
A função StartGame() faz parte da classe TutoProjectGameMode e é responsável por atribuir os valores iniciais das variáveis de estado do jogo que foram criadas no artigo anterior. Esta função é chamada no início do jogo e após o fim do jogo, se o jogador quiser jogar de novo.
Uma declaração de função informa ao compilador o nome da função, os parâmetros que ela recebe e o tipo do valor de retorno. A declaração de função é feita no arquivo de cabeçalho (.h).
Uma definição de função fornece o corpo da função contendo os comandos. A definição de função é feita no arquivo de implementação (.cpp).
A função StartGame() será public porque ela também será usada pela classe C++ que representa o jogador quando ele quiser reiniciar o jogo. Vamos colocar a declaração desta função no arquivo TutoProjectGameMode.h depois da declaração do construtor ATutoProjectGameMode(), conforme o código abaixo. Observe que existe também a declaração da função BeginPlay(). Vamos comentar sobre BeginPlay() no fim deste artigo.
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "TutoProjectGameMode.generated.h"
UCLASS(minimalapi)
class ATutoProjectGameMode : public AGameModeBase
{
GENERATED_BODY()
public:
ATutoProjectGameMode();
void StartGame();
protected:
int32 PlayerLevel;
int32 Score;
int32 ItemCount;
int32 Time;
bool bGameOver;
virtual void BeginPlay() override;
};
A palavra chave void que está antes do nome da função StartGame() significa que esta função não retorna um valor. Os parênteses vazio significa que a função não possui parâmetros. Os parâmetros são usados para passar valores no momento da execução da função. Como exemplo, se quiséssemos que a função StartGame() recebesse um valor inteiro indicando o nível de dificuldade, a declaração da função ficaria assim:
void StartGame(int32 DifficultyLevel);
O parâmetro DifficultyLevel funciona como uma variável que pode ser usado dentro da função StartGame(). Isto foi apenas um exemplo de parâmetro, não faça esta mudança no código do nosso jogo.
O corpo da função StartGame() contendo os comandos deve ser colocado no arquivo TutoProjectGameMode.cpp. Este arquivo já possui o corpo do construtor ATutoProjectGameMode() que foi criado pelo modelo do projeto Third Person.
O arquivo TutoProjectGameMode.cpp fica assim:
// Copyright Epic Games, Inc. All Rights Reserved.
#include "TutoProjectGameMode.h"
#include "TutoProjectCharacter.h"
#include "UObject/ConstructorHelpers.h"
ATutoProjectGameMode::ATutoProjectGameMode()
{
// set default pawn class to our Blueprinted character
static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(
TEXT("/Game/ThirdPersonCPP/Blueprints/ThirdPersonCharacter"));
if (PlayerPawnBPClass.Class != NULL)
{
DefaultPawnClass = PlayerPawnBPClass.Class;
}
}
void ATutoProjectGameMode::StartGame()
{
Score = 0;
PlayerLevel = 1;
ItemCount = 0;
Time = 30;
bGameOver = false;
}
void ATutoProjectGameMode::BeginPlay()
{
Super::BeginPlay();
StartGame();
}
Observe que todos os nomes das funções estão precedidos por ATutoProjectGameMode::. Os caracteres :: em C++ é o operador de resolução de escopo. Neste exemplo ele está sendo usado para indicar que as funções pertencem à classe C++ ATutoProjectGameMode.
ATutoProjectGameMode() é o construtor da classe. Esta função é executada no momento que uma instância da classe ATutoProjectGameMode é criada na memória. Observe que um construtor não possui uma palavra chave definindo o tipo de retorno.
Neste exemplo, o construtor está buscando a classe que representa o jogador para definir como o DefaultPawnClass deste Game Mode. Em um artigo futuro vamos examinar em detalhes estes comandos.
A nossa função StartGame() é simples, ela apenas atribui valores iniciais para as variáveis. O caractere = é chamado de operador de atribuição em C++. Em uma operação de atribuição, o valor que está à direita do operador = é colocado na variável à esquerda do operador. No exemplo abaixo, o valor 0 é colocado na variável Score. Se a variável Score possuía um valor anteriormente, ele será perdido.
Score = 0;
Agora vamos falar sobre a função BeginPlay(). Se você já programou em Blueprints deve estar familiarizado com o Evento BeginPlay que é acionado quando o jogo começa para um Actor.
Os eventos na Unreal Engine são implementados em C++ usando funções que não retornam valor, ou seja o tipo de retorno é void. Esta foi a forma que declaramos a função BeginPlay():
virtual void BeginPlay() override;
A palavra chave virtual indica funções que podem ser sobrescritas em classes filhas. A função BeginPlay() foi declarada na classe C++ AActor da Unreal Engine, sendo assim qualquer classe que pertence à hierarquia de AActor pode sobrescrever BeginPlay().
A palavra override é opcional, mas é muito útil. Ela é usada para garantir que o programador realmente está sobrescrevendo uma função da classe pai. O programador pode confundir o número ou tipo de parâmetros ao sobrescrever uma função. Usando override o compilador irá gerar um erro caso não seja encontrada uma função na classe pai que seja equivalente.
Em nosso exemplo, a função BeginPlay() só possui dois comandos. O primeiro comando é Super::BeginPlay(); que é usado para chamar a função BeginPlay() que foi definida na classe pai, que em nosso exemplo é a classe C++ AGameModeBase. A Unreal Engine definiu um identificador chamado Super para referenciar a classe pai, que também é conhecida por superclasse. As classes filhas também são chamadas de subclasses.
O segundo comando é o StartGame(); que é a chamada para a função que criamos para inicializar as variáveis.