Completing the Bounty Dash game loop!

With our HUD in place, we can now implement the functionality to finish the Bounty Dash game loop. We need to be able to end the game when the player reaches the same kill point that destroys the objects that are moving down the game field. Upon reaching this kill point, we should pause the game and present the player with game over text. Upon game over, the player should also be able to press R to reset the game. To achieve this, we are going to have to make edits to the ABountyDashGameMode class to support game over and pause functionality, to the ABountyDashCharacter class to support restarting, and to the ABountyDashHUD class so that we can draw the game over text.

The beginning of the end and pausing the game

Instead of having the game suddenly pause when the player reaches the kill point, it would be more user-friendly to have the character fall for a short while before we pause the game and report that the game is over. To do this, we are going to have to set up a timer within the ABountyDashGameMode class and a few Boolean flags we can use to represent the different game over states. Navigate to BountyDashGameMode.h and add the following public functions to the class definition now:

UFUNCTION()
bool GetGameOver();

UFUNCTION()
void GameOver();
UFUNCTION()
void SetGamePaused(bool gamePaused);

The first will be used to query whether the game is in fact over, and the second will be called when the character detects that it has reached the kill point. This will start the game over timer. Once the timer has reached a specified time, we will set a game over flag to true. The last one will be used to pause the game once the game over timer has run its course. We now need to add a few protected members to the class definition:

UPROPERTY()
bool bGameOver;

UPROPERTY()
bool startGameOverCount;

UPROPERTY()
float timeTillGameOver;

UPROPERTY()
float gameOverTimer;

The first is a Boolean flag that represents if the game is in fact over. The next Boolean flag is used to gauge when to start the game over timer. The next two floating point values are used for the timer itself. The first will be used to hold how long it will take between the character reaching the KillPoint and the game over screen being shown. The second is the accumulated time since startGameOverCount was set to true.

Navigate to BountyDashGameMode.cpp now. We need to add some default values for the new protected members we just created; let's do that now by adding the following code to the constructor:

RunTime = 0.0f;
bGameOver = false;
startGameOverCount = false;
timeTillGameOver = 2.0f;
gameOverTimer = 0.0f;

The game over timer will run for two seconds before we pause the game. We have also added some safe defaults for the Boolean flags and the RunTime counter we made earlier.

Next, we need to adjust the tick function so that it includes the new game over timer. Modify ABountyDashGameMode::Tick() so that it appears as follows:

if (!startGameOverCount)
{
    RunTime += DeltaSeconds;
}
else
    {
    gameOverTimer += DeltaSeconds;

    if (gameOverTimer >= timeTillGameOver)
    
            bGameOver = true;
        }
    }

Here, we are checking whether we have begun the game over timer. If not, we need to increment the runtime as the game is still in progress. Otherwise, we need to increment the game over timer until it is greater than or equal to timeTillGameOver. If so, we will change the bGameOver flag to true. Next, we need to add the following simple functions to the .cpp:

bool ABountyDashGameMode::GetGameOver()
{
    return bGameOver;
}

void ABountyDashGameMode::GameOver()
{
    startGameOverCount = true;
}

The first simply returns the bGameOver flag and the second is used to start the game over timer.

Pausing the Game

Now we can write our pause function. Pausing a game from C++ is very easy; all we need is a handle to a player controller. In our case, this will be the first player controller. We can then call SetPause on this controller to pause the game. Define the ABountyDashGameMode::SetGamePaused method as follows:

void ABountyDashGameMode::SetGamePaused(bool gamePaused)
{
    APlayerController* myPlayer = GetWorld()->GetFirstPlayerController();

    if (myPlayer != nullptr)
    {
        myPlayer->SetPause(gamePaused);
    }
}

Here, we are simply getting the first player controller from the world context, ensuring the controller is valid, and then calling SetPause on the controller.

Restarting the game

We now need to allow the player to restart the game somehow while the game is paused. We can do this by binding another input action to the ABountyDashCharacter. We are then going to inform that action to be allowed to execute even when the game is paused. The first thing we need to do is create a new action mapping in the editor. Do this now. Navigate to Edit->ProjectSettings->Engine->Input and add the following action mapping:

Restarting the game

We need to bind this mapping to a new function in ABountyDashCharacter. Navigate to BountyDashCharacter.h and add the following protected method to the class definition:

UFUNCTION()
void Reset();

This function will be bound to the input event and defined so that the game level is reset. Navigate to ABountyDashCharacter::SetupPlayerInputComponent() in BountyDashCharacter.cpp. We need to add one more binding to the definition of this function. Add the following line of code:

InputComponent->BindAction("Reset", IE_Pressed, this, &ABountyDashCharacter::Reset).bExecuteWhenPaused = true;

What we are doing here is binding the Reset() method we just created to the Reset input action mapping pressed state. The BindAction function returns a reference to a newly created FInputActionBinding. We are then setting the bExecutWhenPaused member of this new binding to true. Whenever you want an input action to be carried out, even when a game state is paused, you must set this flag appropriately.

Now we can define the Reset() method. Add the following code to the .cpp now:

void ABountyDashCharacter::Reset()
{
    UGameplayStatics::OpenLevel(GetWorld(), TEXT("BountyDashMap"));
}

This code utilizes the UGameplayStatistics namespace function OpenLevel. This function will open the level specified, given a game world context. Reloading this level will perform the same action as resetting the level.

We need to do one last thing before we are done editing ABountyDashCharacter. We need to add some code to the Tick function so that when the player reaches the killPoint of the floor object, the game mode will be informed to start the game over counter.

First, we need to retrieve and save the kill point somewhere. Add the following protected member to the ABountyDashCharacter class definition:

// Kill Point
float Killpoint;

Now modify ABountyDashCharacter::BeginPlay in BountyDashCharacter.cpp to include the following code:
for (TActorIterator<AFloor> TargetIter(GetWorld()); TargetIter; ++TargetIter)
{
    Killpoint = TargetIter->GetKillPoint();
    }    

This code will retrieve the floor actor in the level and save the killPoint into the value we just declared. As we just reference AFloor in this .cpp, ensure to add the appropriate include to the include list. Finally, we can add the following code to ABountyDashCharacter::Tick():

if (GetActorLocation().X < Killpoint)
{
    GetCustomGameMode<ABountyDashGameMode>(GetWorld())->
    GameOver();
}

Simply, if the character reaches the killPoint, we need to inform the game to start the game over counter.

Drawing the game over text

We are nearly done! All we need to do now is draw the game over text within the HUD when ABountyDashGameMode::bGameOver has been set to true. Navigate to ABountyDashHUD::DrawHUD() in BountyDashHUD.cpp and add the following code:

if (DashGameMode->GetGameOver())
{
    FVector2D GameOverSize;
    GetTextSize(TEXT("GAME OVER!!! Press R to Restart!"), GameOverSize.X, GameOverSize.Y, HUDFont);

    DrawText(TEXT("GAME OVER!!! Press R to Restart!"), FColor::Yellow, (ScreenDimensions.X - GameOverSize.X) / 2.0f, 
    (ScreenDimensions.Y - GameOverSize.Y) / 2.0f, HUDFont);

    DashGameMode->SetGamePaused(true);
}

This section of code is checking whether the game is over. If so, we need to draw GAME OVER!!! Press R to Restart! in the middle of the screen. We can do this by using the same draw text function we created earlier; however, this time, instead of parsing hard-coded values (such as 50), we are simply calculating the position of the text. We have used the GetTextSize() method to retrieve how much space the previous sentence will take up in screen space when using the font we made earlier. We are then using these text size dimensions to place the game over text in the middle of the screen. We do this by subtracting the appropriate text dimension from the corresponding screen dimension, then dividing the resulting value by 2.0f. This will place the text in the middle of the screen while compensating for screen text size. Then, finally, we have set the game to pause!

Great! We are now done with the Bounty Dash game loop! Compile, build, and run the code. Let the player be pushed off the back of the floor object, wait two seconds and you should be presented with this:

Drawing the game over text

Now when you press R, the game will restart and you can try beating your previous score!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.184.239