SPITE:

Bleeding Skies

In a temple city once rules by cruel Sky Gods, a false prophet rises, demanding blood to prevent a foretold eclipse. As fear spreads and cults grow, the Earth Gods send their champion to stop the madness. Wield divine power, crush the eclipse cult, and decide the fate of a world on the brink.

Genre

Action RPG

Reference game

Diablo III

Production time

Preprod: 5 weeks | Production: 10 weeks

Games produced as part of studies at The Game Assembly are based on a reference game. This is to give students a starting point for their projects, and to speed up the inital stages of production. Genre and metrics (camera angle, character size, movement speed etc.) should adhere to the reference game. Deviations are allowed, but must be well motivated.

itch.io page here, with a downloadable version of the game.

My contributions

This was my fifth game project at TGA, and the first created with our custom-built engine, bean (yes, all lowercase). As such, all systems had to be created from scratch. During pre-production, my responsibilities were to set up a basic asset management system, and to adapt my audio wrapper (which I had originally built for TunnelVision) to our new engine. Once we entered the production phase, I worked on player navigation and created a UI manager.

UI system

For Spite, our UI system only needed to handle four things: enemy health bars, the player's skill bar, and game menus.

The overarching system was handled by a UI Manager. Upon loading a scene (a level or menu screen), the UI manager would read a json file with data for all 2D sprites required for the scen, then initialize them. This way, sprites would already be available, and simply kept hidden (not rendered) until needed.

This UI layout json contained all information required for each sprite (size, position, rotation, texture, texture rect), as well as its type (button, slider bar, visual only, etc.) While each type had its own designated depth layer by default - e.g. anything interactable would be rendered in front of anything purely visual - these could be overridden by assigning a different one in the layout file.

Functions could also be added in the layout, to be assigned to a button or slider on load-in. Each button could store up to five different functions and sound effects - one per state (neutral, hovered, clicked, held, released).

Health bars were kept fairly simple: appear when an enemy is injured, fade after not taking damage for a few seconds. At the top of the screen, a larger health bar displays the name of whichever foe happens to be hovered by the cursor.

For the player's skill bar, we opted for Diablo style health/mana orbs (with shaders supplied by our tech artitsts). Data such as skill cooldown time and remaining mana is passed to a game info buffer, and thus accessible by the shaders.

In addition to the above, the same 2D rendering system was used for loading screens between levels, and the in-game vignette overlay.

Audio manager & FMOD wrapper

The audio system for Spite consisted of two layers: the interface for our sound programmers, and the wrapper for FMOD.

Built by former students and teachers at TGA and referred to as the SoundEngine, the wrapper provides a minimal, general interface for interaction with FMOD. As it lacked some basic functionality - such as one-shots for 3D sound and memory deallocation for single event sources - I had to expand it slightly to suit our needs.

The Audio Manager, by contrast, was created for a specific game - TunnelVision. My task became to clean up my old work, adapt it to our new engine, and add anything new that Spite might require. Our audio programmer, Bam Alberto, had built a similar system for his previous team, from which we decided to pilfer a few useful functions that my audio manager lacked.

Since our engine is component-oriented, I also created a SoundComponent. This could be attached to any game object and access functions in the Audio Manager, or bypass the wrapper entirely in those cases direct interaction with the SoundEngine itself was more sensible.

Once we had tested the new system to satisfaction, I could hand it over to Bam, who then worked on implementation of SFX and music provided to us by our audio designers and composers.

Player navigation (navmesh)

Establishing well-working navigation in Spite proved to be the toughest challenge of this project. We were limited both in terms of how we generated it (using Unreal, then exporting) and by the fact that we were planning on using a single navmesh for each level. This restricted us to one layer - no bridges over navigable terrain, no buildings with multiple floors. However, these constraints also meant fewer challenges needed to be solved.

Initial tests were made with using a completely flat - essentially 2D - navmesh, which was achieved by simply ignoring the height coordinate of the mesh. Once we added elevation (ramps, stairs, etc.), the player's and enemies' movement became, predictably, strange. The simple solution was to do a temporary conversion from 3D to 2D, and once a position in the XZ plane had been attained, project it up ontothat navmesh triangle to find the Y value.

Once one of our programmers, Erik, had implemented debug drawing, our level designers could easily spot problematic areas of the mesh, and adjust or exclude them in Unreal before re-exporting.

The team: Water Leaks Studio

Water Leaks consists of 20 students at The Game Assembly, Malmö. Spite is the first of three games we will be making together during our second year at TGA. For this project, we were joined by three students from Östra Grevie Folkhögskola, who provided audio for the game.

Programmers
Scroll to Top