C++ School Assignment
Project Type: Solo Project
Role: Solo Developer
Engine: Unreal Engine 5
Project Duration: December 2 - December 6 2024
Description
This prototype was made as an assignment for our C# & C++ Course at Futuregames.
For the C++ part of the course, we were tasked with creating a small game in Unreal Engine 5 using C++ for the majority of the game logic.
I ultimately created a game where the player must keep collecting pickups to extend the game timer. The game periodically spawns NPCs that try to snatch the pickups before the player, which does not add to the timer. Once time runs out, it’s Game Over.
The objective of the game is simple: Survive for as long as possible by collecting time pickups. Once the time is up, it’s Game Over. There is no win condition.
As time passes, the game spawns in more and more NPCs that also try to grab the pickups. After a while, it’ll be impossible to keep going.
Since the game is not intended to be played for more than a minute or two, the timer is capped at 20 seconds to maintain pressure and avoid unnecessarily extending playtime.
NPC and pickup spawning is handled using spawners. Because of the number of pickups that get spawned and destroyed, I decided to implement the Object Pool pattern to increase performance, even though it’s a small project.
Overview
Game Logic
The timer logic runs in the player character’s Tick function, which, in hindsight, would have been better located in the game’s GameMode class.
First, the game checks whether the GameMode enum is set to Game, indicating that the game isn’t paused or in Game Over. If that is not the case, it returns early.
After that, every frame it decrements RemainingTime by DeltaTime and checks if RemainingTime <= 0. If true, sets the Game Mode to GameOver.
The SetGameMode function simply sets CurrentGameMode to the EGameMode passed in the function parameter. It then broadcasts the change to notify subscribers. In the case of Game Over, the “Game Over” screen is enabled, and all relevant tick functions return early, preventing logic from running. It’s essentially a super-simple game state machine.
Pickups & Spawning
The pickup spawning is also based on a timer, but I wanted a bit of randomness. Every time a pickup spawns, it picks a random value from a range that I store in a 2D Vector. The spawn location also features randomness
Because a large number of pickups could be spawned and destroyed, I opted to implement a simple object pool to improve performance.
It first checks if there are any inactive pickups. If true, it retrieves the pickup at index 0, sets its location to the spawn location, and moves it from the InactivePickups array to the ActivePickups array.
Otherwise it spawns a new one and adds it to the ActivePickupsArray.
Once the pickup gets picked up (by overlapping with an ACharacter), the spawner moves the pickup from ActivePickups back to InactivePickups and sets its location to somewhere far off the map.
Writing AI code was slightly out of scope for this small project, but I implemented this BehaviorTree task in C++.
The NPC gets all objects of type AMyPickupActor and adds them to an array. If there are any present, it picks a random index of the array, gets the location of the object, and sets it as the target location, then returns with success. Otherwise, the task fails. One important thing I learned from this is that a task must always return; otherwise, your AI gets stuck.
Upon finding a target, the NPC will move to the location of the pickup, causing them to overlap, which removes the pickup from the map as seen in the spawner code above. The NPC then waits 1 second before trying to find its next target.
NPC Behavior
Game Timer
Even though this was a short project whose main purpose was to write C++ code that compiled and ran without crashing, I gained a much better understanding of concepts such as pointers and references, generics, and design patterns.
C++ seems much less intimidating than it used to, and I’ll definitely be utilizing it in the future.
As for the game I made, I could have implemented a win condition or point system for collecting pickups and save the points as a score, but I wanted to make something that couldn’t be won, only finished. I’m sure there’s probably a metaphor for life buried in there somewhere, if one were to think about it for long enough.