Featured

Steampunk Corridor

Unity In-Engine Screenshot

A Steampunk Corridor Vertical Slice Game Demo Project using Unity and C#.

Implementations:

  • C# Unity Scripting
  • Player Animation Controls/Input
  • Cameras and Cutscenes
  • Modular 3D Environment Modelling/Texturing/Animation in Maya & Substance
  • Rigging
  • Physics/Lighting/VFX

* Player character model/textures were provided by Unity. Player character animation provided by Mixamo.

Walkthrough: https://youtu.be/TOga_uwfP0o

Tools and Shaders – Projection

In-Game Scene

For our Games Engine Architecture module project, we had to create tools with supporting documentation in relation to the concept of Projection in Unreal Engine and Unity.

Implementations:

  • Unreal Engine Blueprints
  • Unity C# Scripting
  • Shaders
  • Procedural Spline Tool
  • Lights
  • Render Targets
  • Custom Depth Buffer/Stencil
  • Post Processing

Angry Birds (Replica Project)

Angry Birds Replica Gameplay Screen

A recreation of Angry Birds in C++ with the SFML library.

Implementations:

  • Vector Math
  • Effective use of classes and Inheritence
  • Class Polymorphism
  • Scoring System & Lives
  • Collision Management
  • Sprite sheet Implementation
  • Special Abilities
  • Startup Menu
  • Audio System

Link to Github: https://github.com/TRDP90/Angry-Birds-Replica.git

*Assets by Kenney.

Space Invaders (Replica)

Space Invaders Gameplay Screen

A recreation of Space Invaders in C++ with the SFML library.

Implementations:

  • Vector Math
  • Movement Along a Quadratic Equation Line
  • Effective use of classes and Inheritence
  • Class Polymorphism
  • Scoring System
  • Collision Management
  • Startup Menu
  • Keyboard Input Controls

*Assets by Kenney.

Link to Github: https://github.com/TRDP90/Space-Invaders-Replica.git

Dungeon Escape

The gargoyle is taken off it’s pedestal.

The dungeon escape game is a tech demonstration of creating a Grabber Component for the Pawn/Player. It also demonstrates the use of Unreal’s “Mass” to activate Trigger Events such as rotating, opening and closing doors using Unreal Engine’s C++ Components. In order to escape the dungeon, the player has to place the required objects in the trigger volume to open the door in order for the player to exit the level.

void UGrabber::SetupInputComponent()
{
	InputComponent = GetOwner()->FindComponentByClass<UInputComponent>();

	if (InputComponent)
	{
		InputComponent->BindAction("Grab", IE_Pressed, this, &UGrabber::Grab);
		InputComponent->BindAction("Grab", IE_Released, this, &UGrabber::Release);
	}
}

The grab key is binded to the right-mouse button.

FVector UGrabber::GetPlayersReach() const
{
	FVector PlayerViewpointLocation;
	FRotator PlayerViewpointRotation;

	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(OUT PlayerViewpointLocation, OUT PlayerViewpointRotation);

	return PlayerViewpointLocation + (PlayerViewpointRotation.Vector() * Reach);
}
FHitResult UGrabber::GetFirstPhysicsBodyInReach() const
{
	FHitResult Hit;
	//Ray cast out to a certain distance (Reach)
	FCollisionQueryParams TraceParams(FName(TEXT("")), false, GetOwner());
	
	GetWorld()->LineTraceSingleByObjectType
	(
		OUT Hit,
		GetPlayersWorldPos(),
		GetPlayersReach(),
		FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
		TraceParams
	);
	return Hit;
}

Line Trace from the player to the first physics body.

void UGrabber::Grab()
{
	UE_LOG(LogTemp, Warning, TEXT("Grabber pressed"));
	
	FHitResult HitResult = GetFirstPhysicsBodyInReach();
	UPrimitiveComponent* ComponentToGrab = HitResult.GetComponent(); 
	AActor* ActorHit = HitResult.GetActor();
	
	//If we hit something then attach the physics handle.
	if (ActorHit)
	{	if (!PhysicsHandle){return;}
	
		PhysicsHandle->GrabComponentAtLocation
		(	ComponentToGrab,
			NAME_None,
			GetPlayersReach()
		);
	}
}

Grab function by attaching a physics handle.

float UOpenDoor::TotalMassOfActors() const
{
	float TotalMass = 0.f;

	//Find All Overlapping Actors.
	TArray<AActor*> OverlappingActors;
	if (!PressurePlate) {return TotalMass;}
	PressurePlate->GetOverlappingActors(OUT OverlappingActors);

	//Add Up Their Masses.
	for (AActor* Actor : OverlappingActors)
	{
		TotalMass+= Actor->FindComponentByClass<UPrimitiveComponent>()->GetMass();
	}
	return TotalMass;
}

Finding Total Mass of Actors in Trigger Volume.

void UOpenDoor::OpenDoor(float DeltaTime)
{
	CurrentYaw = FMath::FInterpTo(CurrentYaw, OpenAngle, DeltaTime, DoorOpenSpeed);
	FRotator DoorRotation = GetOwner()->GetActorRotation();
	DoorRotation.Yaw = CurrentYaw;
	GetOwner()->SetActorRotation(DoorRotation);

	CloseDoorSound = false;
	if (!AudioComponent) {return;}
	if (!OpenDoorSound)
	{
		AudioComponent->Play();
		OpenDoorSound = true;
	}
}

The door opens when the trigger volume’s mass parameters are met and closes/remains shut when they are not met.

Bulls & Cows

UE4 In-Game Screenshot

Bulls and Cows is a Terminal Game built in Unreal Engine 4 as part of the Udemy Unreal Engine C++ Developer Course by Gamedev.tv. This course taught me the basics of C++ in Unreal Engine.

The game’s objective is to guess the Hidden Word. The player wins if you guess the exact Hidden Word. If the player guesses incorrectly, the player loses a life. Once the number of lives run out, the player loses.

void UBullCowCartridge::BeginPlay() // When the game starts
{
    Super::BeginPlay();
    Isograms= GetValidWords(Words);
    SetupGame();
}

void UBullCowCartridge::OnInput(const FString& PlayerInput) // When the player hits enter
{
    if (bGameOver)
    {
        ClearScreen();
        SetupGame();
    }

    else //check PlayerGuess
    {
        ProcessGuess(PlayerInput);
    }       
}

void UBullCowCartridge::EndGame()
{
    bGameOver = true;
 
    PrintLine (TEXT("\nPress Enter to Play Again"));
}

Once the player wins or loses, the game ends and the game is restarted.

The Bulls are characters, ‘E’ and ‘A’. The Cows are characters ‘M’ and ‘T’.

The number of bulls is determined by the number of matching characters seated at the exact spot of the hidden word.

The number of cows is determined by the number of remaining matching characters regardless of where the character is seated in the word.

void UBullCowCartridge::ProcessGuess(const FString& Guess)
{
 if (Guess == HiddenWord)
        {
            PrintLine (TEXT("You Win!"));
            EndGame();
            return;
        }

    if (Guess.Len() != HiddenWord.Len())
    {
        PrintLine(TEXT("The hidden word is %i letters long."), HiddenWord.Len());
        PrintLine(TEXT("Sorry, try guessing again!\nYou have %i lives remaining"), Lives);
        return;
    }
    
    // Check if Isogram
    if (!IsIsogram(Guess))
    {
        PrintLine(TEXT("No repeating letters, guess again!"));
        return;
    }
    
    // Remove Life 
     PrintLine(TEXT("You lost a life!"));
     --Lives;  
     if (Lives <= 0)
             {
                ClearScreen();
                PrintLine(TEXT("You have no lives left!"));
                PrintLine(TEXT("The hidden word was: %s"), *HiddenWord);
                EndGame();
                return;
             }
    
    //Show players bulls and cows
    FBullCowCount Score = GetBullCows(Guess);

    PrintLine(TEXT("You have %i Bulls and %i Cows."), Score.Bulls, Score.Cows);
    PrintLine(TEXT("Guess again, you have %i lives left"), Lives);
}

Every Hidden Word is an isogram. The number of lives is determined by the number of characters in the Hidden Word.

bool UBullCowCartridge :: IsIsogram(const FString& Word) const
{
    for (int32 Index = 0; Index < Word.Len(); Index++)
    {
        for (int32 Comparison = Index + 1; Comparison < Word.Len(); Comparison++)
        {
            if (Word[Index] == Word[Comparison])
            {
                return false;
            }
        }
    }
    return true;
}

The Hidden Word is selected by random off an array in a header file I had set up.

void UBullCowCartridge::SetupGame()
{
   //Welcoming the player
    PrintLine (TEXT("Hello, Welcome to BullCows!"));
       
    HiddenWord = Isograms[FMath::RandRange(0, Isograms.Num() -1)];
    Lives = HiddenWord.Len();
    bGameOver = false;
   
    PrintLine (TEXT("Guess the %i letter word!"), HiddenWord.Len());
    PrintLine(TEXT("The Hidden Word is %s.") , *HiddenWord); //Debug Line
    PrintLine (TEXT("You have %i lives.") , Lives);
    PrintLine (TEXT("Type in your guess and\nPress Enter to Continue..."));//Prompt Player for Guess
}

The Player’s input is compared character by character with the Hidden Word and validated. The number of bulls and cows are checked and calculated.

TArray<FString> UBullCowCartridge :: GetValidWords(const TArray<FString>& WordList)const
{
TArray<FString> ValidWords ;

for (FString Word : WordList)
{
    if (Word.Len() >= 4 && Word.Len() <= 8)
    {
        if (IsIsogram(Word))
        {
            ValidWords.Emplace(Word);
        }
    }   
}
return ValidWords;
}

FBullCowCount UBullCowCartridge :: GetBullCows(const FString& Guess) const
{
    FBullCowCount Count;

    for (int32 GuessIndex = 0; GuessIndex < Guess.Len(); GuessIndex++)
    {
        if (Guess[GuessIndex] == HiddenWord[GuessIndex])
        {
            Count.Bulls++;
            continue;
        }

        for (int32 HiddenIndex = 0; HiddenIndex < HiddenWord.Len(); HiddenIndex++)
        {
            if (Guess[GuessIndex] == HiddenWord[HiddenIndex])
            {
               Count.Cows++;
               break;
            }
        } 
    } 
   return Count;   
}

Triple X

Visual Studio Code Terminal Snippet

A Triple X C++ Terminal Project as part of the Udemy Unreal Engine C++ Developer Course by Gamedev.tv.

The objective of the game is to guess the correct 3 numbers.

2 hints are given, the addition and product of all the 3 numbers.

Introduction is printed.

void PrintIntroduction(int Difficulty)
{
//Print welcome messages to the terminal
 
    std::cout << "\n\nChoose the correct passcodes at level..." << Difficulty << "\n";
    std::cout << "Start guessing till its right...\n";
}

3 numbers are selected at random. Randomization is set to be based off of the time of day. The numbers increase with difficulty. A max level difficulty is set at 10. The game is looped until all the levels are completed.

bool PlayGame(int Difficulty)
{
    PrintIntroduction(Difficulty);
    //Declare 3 number code
    const int CodeA = rand() % Difficulty + Difficulty;
    const int CodeB = rand() % Difficulty + Difficulty;
    const int CodeC = rand() % Difficulty + Difficulty;

    const int CodeSum = CodeA + CodeB + CodeC;
    const int CodeProduct = CodeA * CodeB * CodeC;
    
    //Print CodeSum and CodeProduct to the terminal
    std::cout <<"\n- There are 3 numbers in the code";
    std::cout << "\n- The codes add up to: " << CodeSum ;
    std::cout << "\n- The codes multiply to give: " << CodeProduct <<"\n";

    //Store player guesses
    int GuessA, GuessB, GuessC;
    std::cin >> GuessA >> GuessB >> GuessC;

    int GuessSum = GuessA + GuessB + GuessC;
    int GuessProduct = GuessA * GuessB * GuessC;

//Check if the player's guess is correct
    if(GuessSum == CodeSum && GuessProduct == CodeProduct)
{
    std::cout << "\nGo Next!";
    return true;
}
 else
{
    std::cout << "\nRetry!";
    return false;

}

}


int  main()
{   
    srand(time(NULL)); // create new random sequence based on time of day
    int LevelDifficulty = 1;
    const int MaxDifficulty = 10;
    
    while(LevelDifficulty<=MaxDifficulty)// Loop game until all levels completed
    {
    
        bool bLevelComplete = PlayGame(LevelDifficulty);
        std::cin.clear(); //Clears any errors
        std::cin.ignore(); // Discards the buffers

        if (bLevelComplete)
        //increase level difficulty
        {
            ++LevelDifficulty;
        }
        
    }
   
   std::cout << "\nEnd Game~Well done!";
    return 0;
}
Design a site like this with WordPress.com
Get started