Akuma is our Celeste inspired platformer game. It was the product of 6 Levels Deep during poject 4 at The Game Assembly. You play as a geisha who has been possessed by a magical mask, giving them extra powers, such as the ability to dash and double jump. In exchange, you try to return the mask to its rightful home. On the way you flee through the tombs of a temple, forests and underground caves.

  • Side scrolling platform game
  • 8 weeks half time
  • The Game Assembly's in-house game engine TGA2D
  • Written in C++

I started off the project by code mining and integrating some of my former projects' menu-button systems and a classmate's animation system so that it would work with our new code structure.

When delegating areas of the project, I went for some old familiar responsibilities, such as UI and menu- systems, but I also took on some new challenges: scene handling and the audio system. I also chose to implement the scripted event, but more on that later.

Internal State Stack Structure

After code mining and landing in a new project, I proceeded with the creation of a system that can handle the scenes (or states as we called it in this project) in the game. This involved creating a smooth and seamless system to handle transitions between e.g. menus and in-game and back. Following what we learned in our course Design Patterns for Game Development, I implemented a state stack system for the handling of such scenes.

The system allowed for multiple states to be stored in stacks and allowed for states to be rendered behind others when desired. I believe the end result made the process of adding new states to the game simple and fast.

The basic idea of the state stack is that it is made up of a vector of vectors. This allows there to be a structure of main states upon which mini states can be placed. Every time a main state is entered, a new vector, with the main state as its first element, is pushed into the already existing base vector (myStateStack). In Akuma (and the other games made by my groups following this project), the main menu is a main state and states such as settings and credits are mini states. The in-game state is also a main state, therefore, one does not need to pop the main menu state when entering the game. Instead, one simply pops the in-game state to return to the main menu again.

The state stack is located at the very bottom of the game play structure and we often use the function GetStackSize() to controll whether to close the program or not. If the stack size is zero, then the game is shut down.

Here, you can see the parent class state from which the states in the game will inherit their functionality. The update function returns either if the state will be popped (either mini or main state) in the next frame or if it should continue. The statestack also allows for states to be manually popped.

The let-through member variables let the state stack know whether the underlying states in the main stack will be rendered or even updated.

The OnEnter() and OnLeave() functions allows the developer to reset the states or notify the systems in the state that the state is either closing or being entered. This has been a very nice feature for controlling music, timers, hiding the cursor or resetting levels between state changes.

Audio System

There are systems implemented in the TGA2D-engine for audio, however, we needed an interface that would allow us to quickly and easily play music from anywhere in the game and have a ready set of sounds available to us after starting the program. The AudioManager class allowed for this. The interface is very basic and only consists of an init- and update-function and some getters for the volume that were needed for the menus.

So, what did you have to do as a developer to be able to play a sound at any location in the project? Well, we had already implemented an observer system using a so-called postmaster, such that the audio manager would listen for messages concerning SFX and music and act acordingly. You can see here that the audio manager class is a subscriber and has a receive-function in which different actions were taken depending on if the message told it to, e.g., stop playing music or play a specific SFX.

What I then did was to place messages in a queue to be handled in order. If I remember correctly, I wanted to do this because I wanted to be able to not start playing SFX and music while fading out already playing music. In hindsight, I realise that handling calls for effects like this is problematic. This can potentially set delays on SFX that need to be satisfying for the entire game experience. I have developed systems for particle effects in later projects with this lession in mind.

Our Scripted Event

I was given the responsibility to program the scripted event for Akuma. The event involved the character walking on a brige which would break beneath her, sending her down into the underground. I implemented this by removing the player when entering the event area and simulating the player losing control over the character by rendering a new sprite which I could then completely control said sprite and by using linear interpolation, make it perform the movements required by the event. I will admit that this was very roughly done using many magic numbers, however, the final result turned out cute anyway.

UI and Menus

The UI and menus was the one big part where I got to collaborate the most with other disciplines during this project. I was working closely with the UI-dedicated graphics designer making sure that the menus looked the way as they were intended.

We also animated the main menu background which makes it more dynamic and turned out to look really cool, in my opinion.