Vertebrave is our 5th game project at The Game Assembly, made by Tombstone Interactive. It is a fun and quirky top-down adventure game inspired by The Legend of Zelda: A Link to the Past. You play as misunderstood skeleton Skelly who only wants to become friends and play with the humans in the village. In order to prove that Skelly has a good heart, you have to help Skelly defeat the fellow skeletons and the army headed to the village.
For this project, I wanted to try something new (yet again), and I realised that I was yet to work with a large game-play area. I have previously worked on the systems underlying the game-play loop, such as scene handling and menus, and only slightly touched upon game-play via pickups and player systems. So, for this game, I was determined to work on a more significant game-play area and I ended up with the exciting task of working on the enemies and the boss.
The programmers decided to use an old project's game object and component system. This would allow us to manage all game objects very generally, with the ability to store them in the same vectors and having the benefit of following a standard of how to create components. This way we would easily understand each others' work. I started the project off by making a simple melee enemy with a sword while trying to keep in mind that I want to expand this system, hence keeping the components very generalized would be to my benefit.
I created an EnemyComponent
that would hold the most general data and
behaviour, such as collision data, health and orientation in the world. I then wrote an
EnemyPatrolComponent
that would add the ability to patrol an area to the
basic enemy . I thought this might be a good idea because I knew that I wanted two
other enemies (one ranged with bow and arrow and one melee enemy with a ball and chain)
that also needed to patrol. The patrol paths were either a default squares or it was
derived from a list of points that the level designers placed in the world. This made
the enemies' patrolling more versatile and less repetative.
I then created an EnemyMeleeComponent
that
would be useful for both the melee enemy with the sword and the one with the ball and
chain. I continued this approach for the ranged enemy with an EnemyShootingComponent
which was accompanied by ArrowComponent
for the arrows. This would not only cover
all the three main enemies, but also the minibosses, which were stronger versions
of the original enemy.
The boss fight is made up of three phases and involved three different attacks. The first phase would be an introduction for the player to realise that you need to parry the boss's bolts and avoid lightning strikes. The other phases would cause the boss to spawn more and harder enemies onto the battleground. All of this would require for a larger system than the ones mentioned before.
I decided to create a main component that would take care of the phases and timing. This class
was to be called the FinalBossComponent
and this would accompany the EnemyComponent
like the rest of the enemies. I then added components for the specific attacks: shoot bolts,
lightning strike and spawn enemies. These were then activated depending on the state of the
FinalBossComponent
.
The bossfight required a lot of tweaking for it to work like expected. I had been working and staring at this boss fight for a few weeks and knew I was not the right person to tweak it. The programmers were all very persistent on allowing the rest of the group to adjust variables of anything in the game, so naturally I exposed the timing, spawn rate, damage and other variables concerning the boss fight to a json-file where the rest of the group could try things out. The group used the nlohmann library in this project.
I feel like I ran into quite a few problems during this project and some I fixed; however, I would say that quite a few made their way into the game. I would say that I went into this project quite naive about the scale of things that I would take on. It turned out to be a challenge at times and perhaps a lesson would be that I should not be afraid to ask for help.
One main problem that you will see in the game is the "shaking" of the enemies when colliding with each other or with environment. We did not use any pathfinding in this game, and I had yet to learn about state machines and behaviour trees, so I kind of winged it. The shaking was a result of me trying to desperately push the enemy away from an object once it had collided with it. When pushing an enemy away, I added a velocity in the opposite direction of the current one, making the animation change. By the animation changing so drastically, the solution turned into a very visual bug. If I were to solve this now, I would try to use my newly found knowledge within grouping behaviour and pathfinding to try to avoid the collisions all together. I would also try to avoid making games where the animations only work for four directions, making shaking a massive eye sore.