top of page
HALITE
DESCRIPTION
Game project #5 at The Game Assembly
MY CONTRIBUTIONS
-
2D collision system
- Adaptive audio with FMOD Studio
- Gameplay features
- Particle emitter editor
TIMEFRAME
8 weeks (20h/week)
GENRE
Role-playing game
TEAM
5 programmers, 5 artists, 3 level designers
ENGINE
The Game Assembly's in-house 3D engine

"Long ago, alien fungi caused the collapse of civilization. Today, humanity has learned to live in symbiosis with some of their invaders; venture through the wilderness and find the means to stay alive."
Our 5th project, an RPG, meant a leap in complexity for us programmers as expectations were high to include as many features typical of the genre as possible, such as NPC:s, quests, dialogue, scripted events, powerups, different zones, etc. In other words, an excellent learning experience!
Since we could reuse an import/export pipeline of mine from a previous project, my first contribution was to use my knowledge of this pipeline to quickly create the game's 2D collision system. This being the first project for which we could collaborate with audio designers, I also helped ours integrate adaptive audio events into the game, learning the FMOD Studio API for C++ in the process.
Having worked mostly as a backend programmer thus far - and as a fan of the genre - I took the opportunity to practice some gameplay programming by implementing the player character and its features. Finally, I took my particle emitter system from a previous project and further developed it by adding an editor, which helped to decrease design iteration times for the game's VFX.
Since we could reuse an import/export pipeline of mine from a previous project, my first contribution was to use my knowledge of this pipeline to quickly create the game's 2D collision system. This being the first project for which we could collaborate with audio designers, I also helped ours integrate adaptive audio events into the game, learning the FMOD Studio API for C++ in the process.
Having worked mostly as a backend programmer thus far - and as a fan of the genre - I took the opportunity to practice some gameplay programming by implementing the player character and its features. Finally, I took my particle emitter system from a previous project and further developed it by adding an editor, which helped to decrease design iteration times for the game's VFX.
2D COLLISION SYSTEM

IMPLEMENTATION
I designed the system with support for two shapes: AABBs and circles. Both collider types inherited from a common interface ICollider, which allowed me to use double dispatch to check if two IColliders were overlapping. When creating a collider, client code had to use one of the factory methods in a manager class, as it kept track of all existing colliders and was responsible for the collision checking itself. I chose to only use layer-based collision culling as this had been more than sufficient in previous projects.
For collision handling I used the Subscriber pattern, meaning collision handlers derived from an interface and passed themselves to the manager when creating a collider. They would then be notified by the manager upon a collision event involving one of its associated colliders.
On collision, I made sure to compute the minimum translation vector between the two bodies and pass it to the handlers; this is because I predicted that since the player (and enemies) can walk anywhere and touch anything, there would be a high chance of clipping and/or jittering unless a mathematically robust method was used to resolve collisions. By using the minimum translation vector, these problems were almost completely avoided.
I encountered the classical problem of what to do when a subscriber needs to unsubscribe as part of its message handling, or as in my case when it needed to remove one of its colliders. For this I exposed an extra method that would allow for deferred removal by buffering and executing the request later.
If given the chance to redesign this system with the knowledge I have today, I would probably remove the abstract base class ICollider, make the concrete AABB and circle classes pure structs without methods, use an std::variant for storage, and use std::visit for the collision checking as I believe its double dispatching capabilities would be a perfect fit for this scenario.
For collision handling I used the Subscriber pattern, meaning collision handlers derived from an interface and passed themselves to the manager when creating a collider. They would then be notified by the manager upon a collision event involving one of its associated colliders.
On collision, I made sure to compute the minimum translation vector between the two bodies and pass it to the handlers; this is because I predicted that since the player (and enemies) can walk anywhere and touch anything, there would be a high chance of clipping and/or jittering unless a mathematically robust method was used to resolve collisions. By using the minimum translation vector, these problems were almost completely avoided.
I encountered the classical problem of what to do when a subscriber needs to unsubscribe as part of its message handling, or as in my case when it needed to remove one of its colliders. For this I exposed an extra method that would allow for deferred removal by buffering and executing the request later.
If given the chance to redesign this system with the knowledge I have today, I would probably remove the abstract base class ICollider, make the concrete AABB and circle classes pure structs without methods, use an std::variant for storage, and use std::visit for the collision checking as I believe its double dispatching capabilities would be a perfect fit for this scenario.
RESULT
My collision system was used in nearly every interaction: for keeping the player and enemies out of walls and other obstructions, for making the player take damage from enemies, for the player's melee and projectile attacks, for interacting with NPCs, for portals, pits, slopes, destructible objects, pickups, audio triggers, and more.
In addition to the collision system itself, I made it simple to debug by adding an option to render color-coded sprites over each collider with its color determined by its collision layer. I also made a user interface from which one could see the number of existing colliders of different types and the number of collision checks that was currently taking place. Moreover, for level testing purposes I made it so that the user could toggle on and off collision between different layers at will - useful for noclipping or just to avoid taking damage from enemies.
In addition to the collision system itself, I made it simple to debug by adding an option to render color-coded sprites over each collider with its color determined by its collision layer. I also made a user interface from which one could see the number of existing colliders of different types and the number of collision checks that was currently taking place. Moreover, for level testing purposes I made it so that the user could toggle on and off collision between different layers at will - useful for noclipping or just to avoid taking damage from enemies.

ADAPTIVE AUDIO WITH FMOD STUDIO

BACKGROUND
During this project we had the pleasure of working together with a new discipline - audio designers. With two people joining our team from Östra Grevie Folkhögskola's programme in Virtual Composing and Sound Design, the stage was set to take our game's audio to the next level.
For example, several sound effects was to be upgraded to 3D and have different randomized variations for each playback, while music and ambience should smoothly transition between different intensities depending not only on the player's location in the level but also on her health state. Also, the game's NPCs should have unique talk sounds interspersed in their dialogue.
As part of the audio taskforce, it was therefore my job to help our audio designers achieve their creative vision for our game.
For example, several sound effects was to be upgraded to 3D and have different randomized variations for each playback, while music and ambience should smoothly transition between different intensities depending not only on the player's location in the level but also on her health state. Also, the game's NPCs should have unique talk sounds interspersed in their dialogue.
As part of the audio taskforce, it was therefore my job to help our audio designers achieve their creative vision for our game.
IMPLEMENTATION
While part of the challenge was to learn to work in the FMOD Studio application itself and the features it supports, another part was to familiarize myself with the FMOD Studio API for C++ and to integrate it into our codebase. Since the API is very user friendly, setting it up was fortunately not too hard. In the process, I learned how FMOD packs its audio assets into banks and how to load them during runtime, how to create audio events using either string paths or a generated C++ header with GUIDs, how to position events in 3D and set their parameters in order to alter their instruments and playback behavior, just to name a few.
As a concrete example, in order to make our settings menu affect the in-game audio, I had to learn about FMOD Studio's implementation of audio buses and how to fetch and manipulate them during runtime.
Another issue I had to solve was that some game objects would create an audio event but forget to release it and then lose the pointer to it, resulting in not only a memory leak but also a perpetual sound. To foolproof the system, I made a RAII-style smart pointer class to wrap one of the API:s native classes, ensuring that the event is properly released on destruction.
As a concrete example, in order to make our settings menu affect the in-game audio, I had to learn about FMOD Studio's implementation of audio buses and how to fetch and manipulate them during runtime.
Another issue I had to solve was that some game objects would create an audio event but forget to release it and then lose the pointer to it, resulting in not only a memory leak but also a perpetual sound. To foolproof the system, I made a RAII-style smart pointer class to wrap one of the API:s native classes, ensuring that the event is properly released on destruction.


APPLICATION: PARAMETER TRIGGER
The "FMOD for Unity" library provides game components for triggering events when, say, a collision occurs between two game objects, and our audio designers were familiar with this workflow. Naturally, they expected a similar functionality in our game and requested the ability for our level designers to place "trigger boxes" in the level, which were supposed to change the appearance of the level's music and ambience once the player stepped into the box.
Although we were only using Unity as a convenient level editor while TGA's engine was used to actually run the game, I could emulate this workflow by creating a custom component in Unity to fill in the role of a parameter trigger and implement the desired functionality directly in our codebase.
Although we were only using Unity as a convenient level editor while TGA's engine was used to actually run the game, I could emulate this workflow by creating a custom component in Unity to fill in the role of a parameter trigger and implement the desired functionality directly in our codebase.
APPLICATION: NPC TALK SOUNDS
The player's tribe was a close-knit group of characters with variations in gender, role, and personality. To make this come across when speaking with them as NPCs, our audio designers created different "talk sounds" for each, depending on both the NPCs name and mood.
I was responsible for implementing the NPCs and their dialogue, and having already created a system in which one or more components in Unity stored the NPCs' lines of dialogue, I extended this system to support these talk sounds. To do this, I decided that as the line gradually appeared on screen, tokens of the form "<mood>" would be accepted and trigger a corresponding talk sound. This made it simple for one of our level designers (who was also in charge of writing the dialogue) to add the appropriate sounds.
I was responsible for implementing the NPCs and their dialogue, and having already created a system in which one or more components in Unity stored the NPCs' lines of dialogue, I extended this system to support these talk sounds. To do this, I decided that as the line gradually appeared on screen, tokens of the form "<mood>" would be accepted and trigger a corresponding talk sound. This made it simple for one of our level designers (who was also in charge of writing the dialogue) to add the appropriate sounds.

GAMEPLAY FEATURES

RAMPS AND PITS
Our level designers wanted to build levels that varied in height, with features such as slopes and cliffs. Though my collision system was 2D-based, I met their request by implementing a special "slope" collider that would push the player model up or down while crossing it so as to give the illusion of changing height. I also created pits by making a collider which on entering would make the player go into her "fall" state, give damage, and then respawn her close to the pit.

PORTALS
Unlike our previous project in which levels were designed to be played sequentially, we now wanted the player to be able to go to and from different zones, including a hub. To enable this, I created portals which could transport the player between different scenes. I also made it so that a portal could be disabled until some requirements were met, such as until the player had collected enough vehicle parts.

NPCs
We wanted to include NPCs, both so that they could provide narrative and also give quests, and as part of the narrative taskforce it fell on me to implement them. As an application, the game loop consisted of leaving the hub in search of the next vehicle part and returning it to a special NPC in the hub, which would use it for repairs and advance the game state.

KNOCKBACK AND INVINCIBILITY FRAMES
One had to be careful when walking on narrow paths surrounded by cliffs, as an enemy could easily catch up and knock you straight into a pit!

MELEE AND PROJECTILES
I made the melee attack by simply having the player temporarily spawn a collider in front of her. I also made projectiles by spawning in an object with a collier that used the same collision layer as the melee attack and letting it shoot out in the player's forward direction.