Hi fellow UE4 developers! We are Blazing Badger, a small studio from Frankfurt, Germany, and we’ve developed a game called ‘Guardians’ for the Epic MegaJam. The game has won the Eye Candy and an Allegorithmic Award, for which we are very grateful. Michael Allar, who played through all the game jam entries in a truly epic stream-a-thon, suggested we write something like a “Making Of” blog post, so here it is!
Kick Off
Since Blazing Badger’s foundation in April 2014, we’ve worked on AIPD, our debut project. With its development finally wrapped up, we were happy when the Epic Mega Jam came along – a great opportunity to fill up the creative batteries.
The first day was filled with lots of brainstorming about how to incorporate the theme – “Standing on the shoulders of giants”. In the end we settled for two approaches in parallel: We’d introduce two characters, one small submarine and one a giant whale, entwined in a symbiotic relationship (two giants right there, both in their own way). Also we’d heavily lean into a classic game, metaphorically standing on its shoulders.
We finally settled on an underwater game that closely resembles “Tempest” (originally by Dave Theurer). It is simple enough to be done within a week, and there’s plenty of screen space available for a giant creature!
Technical Foundation
Even for a short-lived game jam project we wanted to have a solid foundation that would enable us to structure our gameflow and add things like credits, results screen etc. later on.
The game is broken down into a handful of Game States that are tied together using a simple State Machine. The two initial states were “Menu” and “In game” so we could get working on the core gameplay experience right away. Later we added a results screen as well as the credits screen.
Since there are clear transitions between the different states, those could easily initialize and clean up whatever data and actors would be needed for that specific state. In doing so we were early-on able to play a few rounds without the need to restart the game. And that is what “customers” would expect from a “finished” game.
We also set up a Session Data structure as well as a Persistent Data structure along with some service functions. Session Data holds “per in-game session” information such as the current score. Persistent Data holds “lifetime” information such as high scores.
Our Game Designers could use those data structures to add more session data or persistent data which would then be automatically cleared for every round or serialized into a save game, respectively.
Level Generator
Our levels are based on a procedurally generated track that forms an imaginary tube. All gameplay actors move along the surface of that tube. The environment geometry is placed outside of that tube.
As with most aspects of the game, we did not know in the beginning how many iterations and how much polishing we could apply to our procedural level generator. This meant we had to put something in place that we could leave in if needed but that was also easily expandable. We also had to make sure that the Game Designers could start working on enemy behaviour really early, so some basic form of level generation had to be implemented really quickly.
The important part here was to define a coordinate system that would not change even if the track layout changed. We came up with a system that represents the actor positions based on the distance travelled along the level track as well as the angle and the radius of the tube. This enabled the Game Designers to implement enemy behaviour logic using simple and consistent coordinates regardless of the final track layout. There is a function to convert those coordinates into an actor transform which is done at the end of every actor tick.
The first version of the level generator just output a straight line, and if we had run out of time we could have just left it that way. After some experimentation we ended up with a simple circle having a huge radius that is modulated by a few smaller sine waves with different wavelengths. In other words the tube very softly turns right globally and goes “randomly” up, down, left, or right locally.
In order to place the environment geometry, the track is divided into segments of different length. Every segment is assigned a primary environment geometry such as “wall” that dominates the segment. The other environment geometry types are used to fill up the segment. We ran out of time to add more environment types, however the system worked well enough with the assets given.
Player Controls
The player controls started out very simple and direct as did a lot of features of Guardians. As player controls are so important for the perceived feeling of a game, we added a few bells and whistles here: There is some short acceleration and deceleration of the player’s ship. The ship also turns and banks but only as a visual effect to keep the controls tight and direct. The camera also tilts a bit if the player’s ship rotates around the giant whale to make everything look and feel more dynamic. We also have a “screen shake fanatic” on our team, who added screen shakes all over the place to make everything feel impactful.
Since we didn’t want to include a manual, we simply mapped all gamepad buttons to “fire” and all directional axes to “movement”. So whatever you try intuitively will work. The same is true for keyboard controls, where we also mapped multiple keys to “fire” and “movement”.
Due to time constraints we decided to stick with a single control scheme that is used for gamepad and keyboard alike. However when watching people play the game for the first time, we realized they often tended to push the gamepad thumb stick to the upper-left because they want the player’s ship to be on the upper-left part of the tube. We feared this might happen, and we should have spent some more time coming up with an additional control scheme for gamepads.
Camera
One of our goals with the camera was to have the in-game action in the centre of the screen. We also wanted to show the giant size difference between the player ship and his giant whale companion, without obscuring the parts of the screen where the enemies are.
We built a little “tool” which enabled us to tweak the camera settings in-game to find the sweet spot between art and design requirements.
When we settled with a nice camera setup, there was one issue. The camera was “perfect” when the player was next to the whale (at + or - 90 degrees) but if he flew at 0 or 180 degrees, the player ship was not in vision of the camera. To fix this we interpolate between a CameraMinimumPositionOffset and a CameraMaximumPositionOffset, dependent of the player angle.
The final camera movement looked something like this:
The Blueprint for this part looked like this (FishAngle is the PlayerAngle):
In order to visualize different states the player could be in we had to go with something fairly simple due to time constraints.
The slow motion effect was achieved by blending between the regular scene texture and a distorted one. Due to the way we toggled our post process by using blend values that aren’t either 0 or 1, you automatically get that double vision effect.
The other post processes work in a similar fashion - fading to grey on death and a linear interpolation between very faint hue shift values when the player progresses along the track to imply a gradual change in the environment the player is in. We would have loved to do more in that regard and would probably allocate more resources to that area next time.
User Interface
For the UI we wanted to create something very simple but elegant. Something that looks slick and polished but was quick to produce.
One of the most important aspects for this was to decide which font we wanted to use, because a good font speaks for itself and can stand alone. We went with a font called “Geo Sans Light” which combined everything we were looking for.
In total we had three screens. A main menu, a mission results screen and a credits screen. The elegant font and the minimalistic approach of showing information worked very well, even without a background, but we wanted Guardians to make a good impression from the very first second you played the game, so we dressed a small menu level for this.
After the first playtesting, we quickly realized that it’s really hard to aim in Guardians, especially when the track is not just a straight line. One of the things we did to get rid of this issue was to give every enemy a widget component which would become visible when the player and the enemy are at the same tube angle (+/- angle tolerance).
Efficient Enemy Design
We decided to have three types of enemies. All enemies share a common parent enemy Blueprint, which deals with hitpoints/death, movement and registering/unregistering with the Blueprint that takes care of the spawning. This enabled us to have very slim actual enemy implementations.
The basic ‘drone’ enemy serves as the cannon fodder necessary for engaging second-to-second gameplay in a ‘Tempest’ style shooter. It slowly drifts sideways along the tunnel walls.
The ‘dodger’ can take more hits and frequently executes a barrel role on damage taken. It requires the player to deal with it at least twice and forces her to reposition herself.
Finally there’s the ‘splitter’, who splits in two after a few seconds. The children then split in two as well, providing the player with up to four targets if ignored.
Also we decided that as the player progresses in the game, the enemies should not only become more numerous, but also more aggressive in some way. The intended outcome was to limit the player’s ability to progress score wise. We implemented one parameter of each enemy to be affected by the game’s progress. The drone’s maximum drift speed increases. The dodger rolls even farther. The splitter splits up within an even shorter time frame.
Simplified AI Director
Now that we had enemies to fight against, we had to make sure they appeared in a proper manner. Our goals were threefold: Spawn positions should be perceived as ‘sufficiently random, but not chaotic’. The enemy type distribution should change over time, as new enemies are introduced and then ramped up in number. Finally the raw amount of enemies should slowly overwhelm the player.
The spawn position requirement we solved by not completely randomizing the spawn angle for each single enemy, but rather deciding on a new ‘general spawn direction angle’ every few seconds, then slightly offsetting enemy spawns from that general angle. This leads to a nice clustering effect, which allows the player to focus on one area at a time at the beginning of the game, while still forcing him to be all over the place towards the end game due to raw enemy amounts.
The spawn timer was implemented using a very basic formula which calculates the ‘time to next enemy’ depending on the amount of time that has passed since the game started. Using a few constants, the spawn time was tweaked to progress from ‘one enemy every few seconds’ to ‘several enemies a second’ over the course of a game session.
Last but not least, the enemy distribution was handled simply by filling an ‘enemy class’ array repeatedly with different enemy distributions over the course of the game, with new enemies being added over time. Each time an enemy was to be spawned, it would be shuffled and an entry selected at random.
The design of such “enemy directing” systems is a specialty of our Game Designers. They talked several times about this topic at various local conferences. If you like to know more about this, you can check out one of their presentations at slideshare.net.
Music & Sound Effects
It was not clear in the beginning if there would be time to compose some music for the game. This led to the decision that at least we would need a high quality background ambience. For Guardians the deep sea ambience is put together using five different sound effect loops, each occupying a different part of the frequency spectrum. The mixing of these different loops is also adjusted procedurally over time so the mood of the background ambience never stays exactly the same. Adding to that there are also a handful of one-shot sound effects being triggered about twice a minute to make the ambience even less repetitive.
The rest of the Guardians’ sound effects are mostly taken off commercial sound libraries and cut and mixed to make them fit. We were lucky to find some really good samples to make the giant whale come alive. We always wanted to implement something like the iconic horn sound from the movie “Inception”, therefore we tried cinematic horn sounds which worked really well for “epic whale giant monster sounds”.
We also composed our own in-game music, which is a simple uptempo electronica song based on a chord progression that is played as a riff. All sounds except the bass drum are softer than in a typical dance track to leave more room for the sound effects and the background ambience. We did not have the time to compose a title / menu track but that turned out to be a good thing as it exaggerates the contrast between the intense in-game action and the relaxing atmosphere throughout the menu screens.
Environment Art
The first step was to create a mood board regarding the colour palette and visual style of the game. In order to build as many assets as possible in such a short time, we wanted to keep the game simple and stylized.
Our environment concepts were painted above an engine screenshot of the planned camera angle and show potential assets, effects and colour schemes. We wanted the whole environment to change during the level without losing some constants like fish swarms and seaweed. In this way, we’d just need a few assets to create plenty of different environments. Sadly, we couldn’t produce as many assets as planned so in the end, we went with rocks, algae, seaweed and awesome light rays.
For animation purposes the vines were UVed in such a way that we could animate them with a sine wave along their height. The same UV gradient was used to mask the animation towards the bottom, so the vines would move less at their base. The direction and strength of the waving motion is controlled with a collection parameter to make tweaking the values easier. All in all, a very simple and fairly self-explanatory setup.
In order to make the movement a bit less uniform, a texture based offset that’s pans across the world was added. On top of that, random animation strength variation based on “PerInstanceRandom” was added, since we are using instanced static meshes when generating the level – why not use what EPIC so generously provides :)
Giant Whale
The giant is supposed to be a huge and ancient whale-like sea creature, having travelled through the ocean since the dawn of time. The water is filled with vicious creatures attacking the whale, so mankind sent a unit to protect what seems to be the last of the giants.
To illustrate the lore of an ancient creature, glowing veins float all over the body of the giant. Because the player circles the head of the whale, this part includes various shapes and materials to keep it interesting. First (but discarded) ideas also involved opening the giant’s mouth (AoE attack) and having its glowing eyes as a health bar.
This was our reference mood board for the whale:
Final concept:
Due to the very large size and the resulting amount of screen space the whale could potentially occupy we opted to build a simple rig for animation purposes instead of using vertex animation like we did for most of the other things.
Player Ship
The ship is based on the shape of a manta ray to fit into the underwater world and to provide it with character. Also manta rays are awesome. After elaborating the concept, a rough block out was made to test it in-game as soon as possible.
Enemies – Evil Jellyfish Cyborgs!
The main purpose of the enemy design was to ‘pop out’ of the surroundings. This was accomplished by intensive colours and effects. The environment was kept in blue and cyan while the enemies were given contrasting tones from yellow to red, so we didn’t have too many colours in one screen. We also went with jellyfish cyborgs, because it allowed us to provide them with different vertex shader animation approaches depending on the type of desired motion.
Conclusion
Guardians was a very fun project to work on. We are happy with the result because it almost feels like a complete game. If you’ve read through all of this and played Guardians, thank you very much! We certainly can’t enter every game jam from now on, but we’ll be back for the Epic Mega Jam 2016 :)
If you have further questions, reach out to us on twitter @blabadger or fb.com/BlazingBadger
Cheers,
The Blazing Badger Team