Main Contributions

Revolver Star was a project that was created in our own custom C++ engine.  I worked on a team with 3 other Programmers, 2 Designers, and 1 Artist at DigiPen.  I was a Co-Producer where I organized / led Meetings, tracked work / milestones, and kept the team on track with the TCR’s.  As a developer my main contributions were the Audio Engine, Sound Effects, Editor, and Gameplay.  Detailed information for the systems I worked on are provided below.

FMODLogo.jpg

Soundemitters using FMOD

Using FMOD I created a custom SoundEmitter component that referenced instances of Sound objects with an interface used for development on my team.

SoundEmitterEditor.jpg

Editor using imgui

Inside of the Archetype Editor, SoundEmitters had special display options for selecting the Music / SFX, with the ability to sample sounds in editor.

GAM250_RevolverStar_3_hires.jpg

Gameplay & sfx

When I created all of the SFX, I would typically start off with a sound sample, edit the sound in Magix Music Maker and sometimes by coding effects in engine.

My largest contribution to gameplay is all of the bullet patterns and the first boss after wave 2 .



Notes About Our Custom Engine

In the following code snippets I'm using as examples, there are bits of custom code for our engine.  We used macros to make the component creation process a lot simpler.  These macros helped automatically register components for Reflection and Serialization, as well as provided a clean interface for everyone using our engine.  With my current syntax highlighting, macros appear purple, so you know that these were custom functionality to our engine.

SoundEmitter.PNG

SoundEmitters

When designing the SoundEmitters for our engine, I modeled the user functionality based on engines that already had them, such as Unity's AudioSource and DigiPen's Proprietary Zero Engine's SoundEmitters.  I knew that I was going to design them as a component that you can place on an object to play sounds from that object, and that it should be very simple for anyone to play a sound.

The image above shows a snippet from my resulting SoundEmitter Component interface.  It knows the sound it is supposed to play, and hold all of the properties the user could want to change.  However, I didn't start with the SoundEmitter interface; I started with the Sound Object itself, which would serve as a wrapper to the FMOD API so my team wouldn't have to touch it.

I knew that I would need the basics: Play, Pause, Stop, Restart, and some checking such as if the sound is currently playing.  Now this isn't meant to be a tutorial, so I won't go into details on the FMOD implementation, but for anyone who has used FMOD, you can imagine how these functions would be using the API.

So I had a good idea of how I could start creating the Sound class and what it would do, but at first I didn't know anything about FMOD.  I decided that I would go abut learning the FMOD API by creating an audio-visualizer as a fun project.  It is currently displayed on my home page.

My main resource for learning FMOD was just simply the documentation provided in the CHM.  I went through all of the introduction / setup code to make sure it was initialized, and it took off from there.  What was great about making an audio-visualizer was not only that it was a fun project, but it was low enough scope to be great practice, but it also gave me familiarity with the FMOD API without having to think about the structure of my wrapper / components in our engine.  I purposefully wanted to separate the two thought processes, and make sure I knew enough about FMOD before I started creating the interface that would be used in our engine.

Once I felt familiar enough, and created a Sound interface that I felt worked well, I started creating the Audio Manager that the engine would use to do anything with audio.  I wanted the Sound Objects to be something that was only managed by the Audio Manager and nothing else.  I didn't want my team to have to worry about individual Sound Objects; only to have the Audio Manager do what they want for them.

To the left is a small snippet of the large Audio Manager.  You can see that it stores all of the needed data such as type specific channels, volume, and I had also implemented cross-fade functionality which you can see that data is stored here as well. Some examples of what the Manager was used for are: setting master / music / sfx volume, setting sound states such as play / pause / stop, as well handling the subscription of the SoundEmitter components.  The Audio Manager was a core system in our engine, where it has it's own Initialize and Update during the gameloop.

The Manager on initialize would load the needed audio assets, each of which were stored as an enum of SFX or Music depending on what the asset was for.  The reason I chose to have the interface use enums instead of strings to reference sounds was because I wanted to eliminate the possibility of user-error.  Maintaining the list of SFX and Music we had would have been a pain, so I created a batch file would search our Music / SFX directories and generate a header file and paste the name of the files as the enums.

Once I had the Manager working as I intended, it was time to create the SoundEmitter components that my team would be able to use.  This component would serve as an easy way to play sounds through game logic on other components.  The SoundEmitter was essentially a wrapper around the Sound Object.  Each SoundEmitter stored a pointer to the Sound Object specified by the user, and would invoke the functions of the Sound Object with it's own channels for FMOD.

This was great, although I wanted it to be an even easier experience for my team.  Instead of setting all of the information of the SoundEmitter in code, it would be way better to have an editor interface to just select all of the properties, and it would take care of itself based on how the user set it up.

In our editor once you added a SoundEmitter component, this is the interface that would be shown to the user.  There is an SFX / Music toggle, a SoundObject drop-down select including the ability to play the sound so you know what you are selecting.  It also had the expected features such as: loop until stopped, start playing the sound once the object is created, volume, and the speed scale of the sound.  The properties regarding the samples were specifically used for the FFT Frequency Spectrum that you could receive from FMOD to allow some audio-interactions.


GAM250_RevolverStar_1_hires.jpg

Gameplay

When it came to creating gameplay and systems to be used for gameplay, I made sure to focus on the areas I knew there wasn't much time for it to be left alone.  We all wanted classic boss fights as well as fun bullet patterns all over the game.  There came a point where I found enough free time to stop working on Audio and Editor and was able to put time into implementing gameplay features that would benefit our game.

When I started working on on the boss, I realized that we didn't have any special types of bullet patterns for it to shoot.  I decided that it would be worth the time to create a Projectile System to allow my team to select from multiple patterns for the bullets to then handle their behavior accordingly.  I brainstormed some patterns, some I knew were cool from other bullet hells, and others I felt would be great for our game.

There were specific patterns that I knew I wanted to have for only the boss, so I just got to making as much as I could think of at the time.  We didn't have too much time at this point, so to make a full event system for projectiles was out of the question.  I made sure to functionalize each pattern so it was at least organized inside it's self-contained system.

The approach I took in in creating the patterns was to just make them all based on time and simple math functions. Variations based on those two things alone gave us a good variety.  In addition, these were just the patterns I was creating.  When creating the actual weapons, you could specify the timing per shot, the amount of shot, and even if it's an angled spread-shot or just straight.  Altogether we
were able to come up with many more weapons.

This is an example of the Target Ring pattern that was designed for only the boss.  In the above code snippet, you can see it had about 4 distinct states. When the shot was first spawned, it created the sub bullets for the pattern at the correct angles.  Each sub bullet would move out to create a stationary circle around the boss and wait about a second before they all targeted and shot towards the player.  As you can see, this is just using cosine / sine to spawn the bullets, and multiple intervals of time to separate the states.  It's essentially just a makeshift state-machine, but it's this way since we had very little time to be adding content.

Once I had enough bullet patterns to work with for the boss, but also added a lot of variety for my teammates to be able to diversify the enemies in each level, it was time to work on the boss.  I put a lot more time into designing the boss fight, and made sure it was actually setup like a state-machine.  Before I started coding any of the boss logic, I created a list of what the cycles would be, and what would happen during each cycle.

I functionalized each mode for each cycle so all of the logic was well-organized.  I knew from the beginning that I wanted three cycles for the boss to switch through based on it's current health.

The boss took a lot of playtesting for it to feel the way we wanted to.  Originally it had way too much health and the sections were too long.  After adjusting, it became too easy, and sections were beaten too fast.  We left it at a happy medium where it was just enough challenging for players good at bullet hells, and wasn't too challenging for the average player.  The result was three main cycles each with three subsegments.  Each cycle lasted the same amount of boss health lost, and also made sure to have a minion spawning segment to make sure the player was able to keep replenishing their ammunition.

BossStateFunctions.PNG

SFX

The other ares of the game I contributed a lot too was the actual audio content.  I created all of the SFX in the game, most of which started from sound samples which I then edited to fit the effect used for the game. One of the sounds I am particularly proud of is one that I first edited in a DAW, but then implemented it to be parameterized based on game state.

This sound was used for feedback when the player is attempting to grab an enemy to use in their revolver.  We had a nice lightning effect visually, and I wanted to make sure it not only matched the visual feedback, but also audibly told the player whether or not they had almost successfully grabbed the enemy.

There was a set duration the player need to hold onto the enemy before they grabbed it.  Knowing this, I wanted the sound to over time change up until the enemy was grabbed.

While the player was holding onto the enemy to grab it, I increased the speed and pitch of the sound which gave the effect that it was charging up.  It turned out to be very satisfying, and it was an SFX I knew I wouldn't have been able to make a static one-shot to achieve.