Post image
AcademicGames

Call of the Void

Sophomore game project created with a team of 6 people at DigiPen Institute of Technology.

NOTE: This project is not publicly available (source code or built version).

THIS WRITE-UP WAS WRITTEN AND PUBLISHED ON 9/2/2023.
THIS PROJECT WAS COMPLETED IN APRIL OF 2022.

BEFORE WE BEGIN…

Before we start, I’d like to preface this project with some important information:

Please note that I am by no means a master of writing. This was a large project that was worked on for several months and this write-up is decently long. There may be gaps, or it might be a little janky in terms of flow. Sorry about that.

This project was developed alongside five other people (six person team, including me) in my cohort at DigiPen Institute of Technology, located at Redmond, WA. Unfortunately, I cannot disclose source code or a playable build of this project. This write-up was written significantly after the project was “completed” (context later), as such, details may be blurry but the main points will still be correct. Please keep in mind that the structure of how DigiPen operates projects like these are subject to change and this is a retelling of how it worked when I was taking the class.

This write-up will also mainly feature my contributions to the project. I will still be describing the general path of the project from all of its initial ideas to what we landed on.

With that out of the way, let’s get started.

TEAMING UP

DigiPen is a bit unique in that they have Game classes where you form or join a team and work together to make a game. This project started in the Fall semester of 2021, at our sophomore year (GAM 200). Each student in the class had to join or create their own team. And each team will create a game from scratch. Some conditions apply as every team will have a unique makeup of members, but that’s the general idea.

For GAM 200, this is (usually) the first time that students from all disciplines are combined together. This meant that the class was made up of not only programmers, but artists, sound designers and game designers too. For programmers specifically, we have been divided into specializations, so there were graphics programmers as well. The goal for GAM 200 is to simulate an actual team that would exist in the real world, with the academic safety net of professors and TAs.

To help facilitate the “hiring” process, the class held a physical event where teams would reserve spaces in a large lab and other students looking for teams to join could tour around and ask questions or get to know different teams.

WHERE I WENT

In my case specifically, I went the route of forming my own team with someone else (we had worked together previously on a different game project), and that’s how our team began, with only 2 people. Down the line, we managed to take along two others during the hiring events. They were also programmers. We weren’t able to snag any artists, as they were in pretty high demand (there was definitely a higher programmer to artist ratio in the cohort).

A CLASSIC CASE OF OVERSCOPING

With our team built, it was time to come up with a concept for our game. It’s a well known curse in this line of work to horribly overscope your projects. As enthusiastic students ourselves, we fell into that trap with this game project, not knowing how much effort it would take to build something substantial.

We had an idea for an endless arcade-style game going for high scores. It sort of developed into this idea of the player defending a cargo train by building turrets on top of it. It further then developed to making different damage types. We were in the pre-planning phase for our engine & game and we already went so far overboard. Somehow, we were confident we could get a good version of this game by the end of its course.

Here’s a list of things we wanted:

At this point, we piled on ideas without thinking on the design at this point. So questions like: “how does the train take damage?” went unanswered.

We were set on these ideas for a while, but we ultimately decided to scrap the entire concept for something else after the 1st semester (which was half of our alloted time). But first things first: the engine.

THE BIRTH OF OUR ENGINE

I was the technical lead for the project, so I was responsible for hosting technical meetings, making sure all of us were on board and that no one got left behind. We managed to get a working product out and that in itself is an accomplishment, I think.

But it mainly began with our graphics programmer beginning the usual process…

As any engine goes, getting something on the screen for the first time was a big hurdle to cross (surely that dies down after working on stuff like this for a while). I worked on the application architecture while our graphics programmer did the rendering pipeline with my suggestions and how it should fit into the overall architecture.

Shortly after this point, I managed to implement a very rough ECS system and one of our programmers also got in some physics stuff and we were now able to crank out more than just one box.

And with ECS & physics, the limitations start to unravel. We then turned the boxes into projectiles.

NOVEMBER

So, at this point in time, we’re in early November. Winter Break is next month. We have turrets that can shoot, but no reactions to overlapping objects. So the next task at hand… Collision.

Another one of our programmers was willing to do some physics & collision code and got some of it going (sphere and box). With that out of the way, I then tried working in some basic enemy behaviors, while two other programmers tagged together to get a health system for all “units” up and running.

It was quite a jump from the last visually documented engine to this one. I spent some time polishing up the editor UI and theming it (we used ImGui).

You may also notice that the “enemy” we have has a texture on it. For placeholder purposes, that is our team logo, designed by yours truly.

We’re at the tail end of November now. And one of the professors mentioned that particle systems were a great way to introduce lots of visual flair when you don’t have artists. So, I tackled that system next. I wanted a real quick, rough and dirty version of it running so that something was there by the end of the semester (which was graded and our “check-in” point). Here is a look at the first version of the editor:

It was very barebones and was tied to the game (separate empty scene that spawns the ImGui windows). I had planned to elevate it to the next level later and I am really happy with how it came out given my skills at that point in time.

WINTER

It’s December now. Everything was looking well. I don’t have much to show here, unfortunately, we put together a small “gameplay demo” that served as a tutorial. It had enemy spawns, the train, the turrets, switching and firing. So technically, it was a game. All teams at this point, before the end of the semester, were to submit the current state of their projects.

A lot of the submission process involved archiving everything, from sound assets, to art assets, and some technical documents that I wrote up as well. It’s a chore to do manually all the time when we change something, so I designed a system using Makefiles to archive it all automatically by running a batch script.

We were then ready to submit.

We had an excellent rating and feedback was incredibly positive at how well the engine was put together, especially with “it has what it needs and not much more than that”, which could be a very dangerous rabbit hole to go down. I was feeling off about the concept of the game though, and we had the Spring semester left to “fix” it.

SPRING

At this point in time, our engine is in a really solid shape to do our needs. Our focus shifts to gameplay. We started thinking about refining it, its pacing, and several questions that have thus far gone unanswered.

It was apparent that the ideas we wanted to cobble together wasn’t going to go very far. So I created a new branch of the game, went all the way to the other end and trashed the entire gameplay concept with something new. And I aptly called the new branch: “GameplayRedux”. And this was the start of a completely new game.

This new concept revolved around the player utilizing a slingshot to maneuver around.

In short, you control a little cube in the world that can shoot. Your movement is solely controlled by slingshotting yourself within the screen. Hold right click to enter, drag to control power, release to send yourself flying.

This came about because I felt that the “train” was just slow, clunky, and sluggish to work with. So I gravitated to something that could feel a little more snappier. Faster. Initially you could control yourself with the WASD keys as well, but that got switched off in our final versions.

You can see me fiddling with this new idea a bit. I also did a little bit of under-the-hood refactoring and consolidation of code which made our lives easier for creating a “Unit”, that is, an entity with health, has the capacity to do damage (or not), and has collision. Pure obstacles (Units that don’t fire, but can kill when collided with), the Player, and enemy shooters go with this.

Slingshot starts getting used 7 seconds in. Was just testing collision into obstacle.

Our team was sold on the idea of the Slingshot. So we heavily invested into it as it was now in scope (with all the extra bits from the prior concept thrown away) and our engine was obviously capable of doing it. In our commitment, we then moved on to additional enemy behaviors (particularly with movement).

This was supposed to be enemies circling around you, but as you can see it does it with a quirk.

SOME IDEAS

We continued exploring avenues of making the gameplay more intricate with more enemy behaviors. But what we hadn’t explored yet was fire patterns for enemies. And that kinda got the ball rolling for this little guy (who sadly, got scrapped).

And on that front, I also really wanted some sort of boss enemy. We weren’t artists by any stretch of the imagination, so I tried using some geometrical shapes. Not sure why I did this.

This idea also got scrapped. No boss. But I think we would’ve refined it if we had more time!

We had a scheduled presentation coming up. And for it, we managed to get a new demo showcase working. At this point we really wanted to solidify on our name (it didn’t really have one before now), and it ended up being “Call of the Void”.

I couldn’t tell you exactly why we settled on Call of the Void. I think we funneled down to something related to Void because the background that I had made for the game looked like the spacey void-ish kinda deal.

THE NEW PATH

Armed with our new player mechanic, we simply turned ourselves into an arcade-style bullet hell where you dodge enemy attacks and try and stay alive as long as possible. With that, we were confident going forward for our presentation.

This presentation was particularly exciting because we got to show off our entirely new game concept (to which, we received praise for being able to switch so seamlessly), and we had a prospective “hire” watching as well. They were a designer, so unlike the rest of us, they could point our sort-of aimless concept into a more cohesive direction, and we were happy to welcome a non-programmer onto our team.

AUTOMATING

Here’s a really cool thing I was happy to work on: I wanted to simplify the process of getting playtesting builds out and about. Especially since we were bringing on a designer, fast iteration and updating might be paramount. Coupled with the fact that, back then, Discord had like 5MB file upload limits, it was tedious to upload a version of the game for testing and sharing a link to it.

SO. I ended up moving our work to Microsoft’s Azure DevOps service, which was free for small teams and permitted by our instructors. For most of us, this change was seamless and smooth, it’s just changing where the remote is and where our repository will live. But, a lot of extra tools became available for us.

BUILD AUTOMATION

Firstly, I was able to schedule automatic builds on certain events, which is similar to GitHub Actions. All builds made were archived with debug symbols as well. We settled on having weekly builds (end of Friday, as that was our big lab work day), but we mostly manually triggered it when major additions or fixes were integrated. The game gets built and we can just pull the version off of the DevOps service which is really handy.

UPDATING

This then ties really well together to the next thing: I built a launcher tool for us to distribute instead of specific game versions that were hand-built by us.

The launcher was built by reusing the game engine, as it already integrates ImGui for an easy UI library, and it’s lightweight when you don’t bundle it with a bunch of assets.

Once a new build was completed, it gets deployed on my own personal webserver. The launcher would then retrieve it and extract the files.

It also supports “Patch Notes” cause I kinda wanted to be extra.

The launcher also helped serve as a process watchdog. In the event of a crash, the game itself spits a crash report, but then the watchdog compiles everything we need to investigate the error. It collects the crash dump, all logs, and a copy of the game executable into one neat little archive and then uploads it to our server. We can then retrieve it and debug it with its specific symbols from DevOps, as the launcher installs builds created there. Debugging the crash dump was then neatly handled by Visual Studio. It was really, really nice to have. And I’m proud of being able to integrate it to our workflow. And as a nice little notification, it sends a Discord message webhook as well.

Gameplay reports are compilations of gameplay log data from our playtesting sessions which are very handy.

The launcher also solved the problem of distributing the game. It was small enough to distribute over Discord to new playtesters. And if we wanted to conduct another playtest with someone who had already had a chance to try it, they could simply just open the launcher and update the game. It also allows us to patch the game really fast if they encounter a bug and we wanted to continue playtesting with a patched version (provided a programmer was able to fix it, or the conductor was a programmer themselves).

All of this work culminated into a really good experience for our designer. At this point, my main goal was to get their issues fixed promptly. I also worked on any of their feature requests to tools and the game.

They made an incredible remark of how I was like a “designer in the tech space”, and it seems that it really unlocked a road to pursuing tools development at some point. I haven’t decided yet (at the time of writing), but working on these tools and getting the workflow ultra-smooth was fun and rewarding to me.

OTHER SCREENSHOTS

THE FINAL BITS

There’s not much left to cover. The game just sort of took off from there, now that we had a designer to point us in the right direction with what we need. The rest of the process is not significant to write home about.

There is one last thing that I’d like to touch up on, however. A revamped particle system.

PARTIKLE

Similar to the launcher, our Particle Editor, called “Partikle”, is built using the game engine as a separate build target in our project solution.

C++ does not natively support reflection. And building an editor that is a little introspective and can see what particle components it can support would be a little challenging on our own. Thankfully, our solution involves a nice little library called RTTR. It handles the hard reflection part for us. We do have to put a lot of preprocessor macros to expose the details but it was well worth it, as additions to our particle system just work in the editor, as we integrate them. It does look a little unruly, but I find it’s no different than working with Unreal’s own reflection system. And it still ultimately helped us in the long run.

We use RTTR to expose metadata, functions, and data for the editor to modify, see, and play with. The revamped particle system also makes use of instancing to improve performance with large amounts of particles.

This is the general look of the editor.

On the top is a toolbar for creating new particle systems. To the left is the particle component list, split into 4 subsections. Next to it is the property window to edit the active component (or the system itself if you open the base properties). To the right is the engine display, with controls to start/stop the system. And on the bottom left is an asset browser capable of looking at textures and existing particle systems. To the bottom right is the entity inspector to adjust the emitter’s transform if needed.

There’s also some neat quality of life things the editor provides, like keyboard shortcuts, dragging and dropping textures, etc.

Now let’s talk about the architecture itself. You might recognize the structure from other solutions.

ARCHITECTURE

A particle system is composed of 4 types of components:

  1. Emitters
  2. Initializers
  3. Operators
  4. Children

EMITTERS

Emitters are, well, emitters. They are responsible for spawning individual particles. Examples of component types of emitters can be:

Spawn particles are then fed to the system’s Initializers.

INITIALIZERS

Initializers take every particle and INITIALIZES them with some default values (or random values, depending on the Initializer). They are responsible for setting the initial state of each particle. Examples can be:

Once particles are initialized, they are then passed to the system’s Operators.

OPERATORS

Operators carry out functions that are performed on each existing particle. Examples include:

That is then the entire lifecycle of a singular particle, up until its lifetime reaches zero and is cleaned up.

CHILDREN

Particle systems in a hierarchy structure so that multiple systems can be bundled together to create one mega effect.

SERIALIZATION

Particle systems are serialized as JSON files, like our asset system.

OTHER MEDIA

SOME CLOSING THOUGHTS

I’m not entirely sure what to wrap this up with. The whole thing was a great experience and I had a great time as well. It was really fun to put together something of this scale. Especially since it lends itself so well to real teamwork and collaboration. It’s as real as it gets, with the safety net of academia.

Would I totally do something like this again? Absolutely. Working in a team that meshes well together is such a blast, and you’re not working in a void all to yourself to keep secrets. You’re building something with many different people of different backgrounds and everyone provides their own perspective and a great idea solo, or even a mid tier idea solo, could become a great idea when thrown into a brainstorming session with your peers.

I ended up leading and doing a lot of work (and some of it not even being necessary, let’s be honest), and thinking about it again, it’s kind of scary. Were this not an academic project, the whole scope and prospect of leading a team can be really daunting. Looking back through this actually helped to re-inspire my confidence and, regardless of whether or not it was put together “badly”, we got something done together.

This experience, however, has shown me that I had a lot of fun working on DevOps and tools development. And those are some paths that I would like to explore in the future.

We ended up not having time left to put finishing details and polish on it (or as much as we wanted), but it still came out pretty solid.

I definitely think I’ve missed a detail here and there and that this write-up is sort of all over the place. But truth be told, I’ve been putting this off for so long just because of how large of a project it was. I knew I’d be writing a lot, and yet, there’s probably still more I could write about.

But I’m cutting it off and putting a stopper on this. It was nice to look back on this, seeing how far I’ve come in games. And now it’s time to look towards the future. And I hope, for those reading all the way down here, this provides a good look into how I talk, how I interact, how I get things done, and how I do it (even though I’m not sure how I’ve made it this far sometimes).

If you’d personally like to know more that I haven’t covered, feel free to directly contact me using the form. If I can recall it, I’ll be happy to share anything you’re interested in.

WHERE AM I NOW?

Unfortunately, past my sophomore year, my mental health had been declining severely. I figured that, by the time summer break was done, I would have felt better, but unfortunately, that was not the case. It kept spiraling down and eventually feeding itself into a massive bout of depression. On top of that, I was already anxious a lot of time (both socially and just about anywhere else), and I felt stuck. I wanted to keep going but I knew I couldn’t get anything done when I was in that state. Because of that, I made the decision to request a hardship withdrawal from the institute, which was granted.

At the time of writing, it’s nearly been a full year since I left. And now I’m feeling that itch again. To learn and do something cool. Revisiting this has done a lot more for me than I thought it would initially. I do intend to return to the institute at some point in the future. It’s unfortunate that it is financially very costly. But I do want to go back and complete my studies. Until then, I will try and look for cool opportunities elsewhere.

Even though my academic career isn’t going as planned, it doesn’t stop me from knowing that I made something awesome with a cool bunch of people. And it was really fun. Now I hope I can continue going out there and making more awesome things.