
As the Principal UI Programmer for Something Mighty, I did client work on Contraband, a project by Avalanche Studios. Working for this client, I was chiefly responsible for implementing the in-game map screen and HUD minimap widget. Contraband uses the Coherent Gameface package for their user interface.
My first task was to generate the textures for the in-game map screen procedurally. Previously, all open-world games by Avalanche Studios featured hand-drawn maps, but my client realized this approach would not scale for their latest title. I built them a custom tool in Qt/C++ that reads the height map data and sea level for the world and applies a simple lighting equation to create the base terrain textures. I then used the same height map data to generate height lines and applied a pre-rendered road texture on top. Finally, I generated the textures at five levels of detail (LOD) for a combined total resolution of 32,768 x 32,768px.
It was critical to my client that the application ran on the CPU only since it needed to work on build machines that often lacked a dedicated GPU. Using a multi-threaded approach that divides the work into jobs, I generated all textures with shading programs that manipulated pixels directly without uploading them to the graphics card first. On an eight-core machine, generating all 1351 textures took less than 90 seconds, whereas it previously took a human artist a day and a half to create the same textures at only one LOD. This meant we could run the process on the build machines every time the world was modified, which was a huge boon for the level designers on the project.
The in-game map screen was one of the most resource-intensive screens in the game. It needed to stream in the high-quality map textures when zoomed in and show lower-resolution versions when zoomed out. Simultaneously, it needed to support dynamic icons, GPS paths, and tooltips. Players could also seamlessly transition between playing with a gamepad or mouse and keyboard. I imported the widget framework I built for one of my projects to achieve the necessary real-time performance on this screen. These widgets use an invalidation pattern to ensure they are updated when their data has changed, and the tech batched all widget updates on the next frame. This pattern worked so well that we used my widget tech everywhere in Contraband's UI screens, and the icons shown on the in-game map screen ran the same code as those on the minimap widget in the HUD.
Gameface uses the MVVM paradigm, where the view model code separates the gameplay code and the UI. Unfortunately, coders must set up bindings to Gameface to transfer data back and forth. To avoid human errors when setting up these bindings, I introduced code generation using my open-source Panini framework for C++ code generation. I then set up JSON documents as the source of truth for view models to generate the C++ bindings and eventually simultaneously generate Typescript code. Compared to other code generation solutions, the significant advantage of this C++-centered approach is the ease of maintenance; whenever there was an issue with the code generation, we could attach the Visual Studio debugger to the application and step through its execution line-by-line.
A common issue facing online games is that all player data must be downloaded from a server somewhere, but the UI needs to be updated every frame. This often means that UI developers must write multiple layers of callbacks to get the required data, which they repeat multiple times throughout the codebase. An elegant solution for Contraband was "data sources," which handled all the communication to the various gameplay and backend systems. Data sources were also responsible for caching data on the client, ensuring that view models could poll them every frame without tanking performance or hitting rate limits on the backend. We commonly shared data sources between view models, and they could depend on each other. For example, a vehicle data source might use the inventory data source to check which vehicles are currently assigned to a player.