top of page
Top of Page
ScreenshotAfterburn.PNG

Afterburn

  • Engine: Personal Engine

  • Development Time: 3 Months

  • Tools and Languages:

    • C++

    • Visual Studios

    • HLSL

    • DirectX11

  • Skills:

    • 3D Mathematics

    • 3D Lighting

    • 3D Models

    • VFX

    • Gameplay Programming

Overview

Afterburn is a space flight-sim that places the player in a space-faring fighter. The player controls a ship that can yaw, pitch, roll, and thrust in a 3D arena. Asteroids will drift into the arena along with AI controlled ships, both of which the player can shoot. The player can destroy both targets to send them scattering in a shower of debris, all while ticking their score up. Once the player has lost all of their lives, the game ends. Afterburn also supports two player split screen if two Xbox Controllers are connected.

This game is an independent study that I took on to further explore 3D game design in my personal game engine. It was an environment I used to explore 3D graphics, including lighting, 3D Models (read in from a .obj file), and 3D effects. One of the features I am the most proud of is the "debris" mechanic which is discussed in further detail below. To further understand the game, I've provided a short video of the gameplay. Please keep in mind that I did not create the 3D models or the music and sounds used in this game. 

Mesh Debris

One of the goals of this project was to explore adding more "juice" into my games. At this point in my career, I'd only made one game in "3D" space and it was Doomenstein, a project I always felt was more of a tech demo than a game. In Afterburn, I immediately drew similarities to another game I made called Starship. In Starship, we also had debris, and I remembered how much that simple mechanic added to the game. It made me think, "What would that look like in 3D?" 

​

The code shown below wasn't the first implementation. I originally had an actor spawn a different "Debris" instance for every face of their 3D model. This was similar to the Starship implementation, which I knew would get results on the screen early. Each Debris instance had its own local verts and draw call. It worked like a charm! At first. But as you can imagine, 3D models, especially ones that are smoother like the asteroids in my game, have a lot of faces. This meant a LOT of draw calls. My frame rate quickly tanked, and I had to explore new ideas. My next idea is what made it into the final product, and is shown below.

​

AfterburnDebris.gif

At a high level, each Actor spawns a new DebrisMesh when it dies. The DebrisMesh would copy over the verts of the original mesh and would then translate and rotate them each frame. This new method batched every face of the original mesh into one class, and therefore, a single Draw call for the whole mesh was feasible. Admittedly, I still have to do some slower operations to make this work, primarily copying the vector of vertices every Render call so I could translate each face independently. However, I started out understanding that this sequence of actions doesn't happen often, so it shouldn't be slow enough to be an issue. In the end, I was right. 

Post Mortem

"Code Fast, Refactor Faster"

What Went Well: Code fast! Coding the thing I knew would get results on the screen fastest was easily the best takeaway from this project. Self-motivation can sometimes be extremely difficult, but I've found that I can mitigate the issue by giving my brain visual queues that I'm succeeding as often as possible. When approaching a problem, I always ask myself, "What is the least amount of work I can do to see something happen on screen?" This is what helped me in the early development of my DebrisMesh.

​

What Went Wrong: The first solution you code isn't always going to be the last solution you implement. In fact, in my experience, it hardly ever is. Does that mean you should take your time getting things on the screen? I don't think so. It's easy to get analysis paralysis by wanting to design the perfect system the first time.
You spend hours and days just thinking about the solution, trying to make sure nothing could go wrong, but you'll never catch every scenario. 

​

However, this is a double edged sword. By "Coding Fast," you almost inevitably set yourself up for failure when your first solution crumbles under the weight of your future development. But I've found this is actually perfectly fine, as long as you're prepared to be honest with yourself when changes need to be made. This brings me to my next point. 

​

Even Better If: Refactor faster! Be ready for your first solution to fail. Invite it, even! And when it does, be ready to examine its weak points and devise a new solution. Thanks to the "Code Fast" mentality, you'll have actual use cases for what works and what doesn't. There won't be any guess-work as to what needs to be designed. Then rinse and repeat for when your solution fails again!

bottom of page