Join the Madness DevBlog, November 2021 – Carnifex

One of the biggest outstanding tasks on my list, from the moment I started this project thinking it was a one-month game jam project, has been that of the first boss. It has come to stand in my mind as one of the biggest obstacles to completing this initial vertical slice of the game, and there’s a few reasons for that: First, I’d never made a boss fight before, and I wasn’t sure what-all would be involved. Second, this character was one of the first concepts I had for the game, and one of the reasons I decided to invest real time into finishing it, so I really wanted this fight to turn out well and to do the character justice. Initially, I just imagined some sort of vampire boss, something notably larger than the player character but not a titanic full-room boss, something relatively mobile and acutely and immediately dangerous-feeling – as I now realize, this probably makes it one of the trickiest bosses to actually make. While the concept of the character started as a vampire, she quickly became something a little more absurd, funny, bestial, and monstrous: Duchess Carnifex – sort of like if Lady Dimetrescu from Resident Evil 8 was a Muppet Hannibal Lecter.

I started November with the resolution that it was finally time to start tackling this problem for real and to make this boss. It turned out that all of my concerns were highly justified – this boss fight alone took me most of the month, and I think it would be fair to say that it is currently more complex than all of the standard enemy types put together.

I started with a brainstorm of what her capabilities would be and how they would interact with each other – certain moves she could only do from certain stances, certain moves only happened after other moves or always transitioned into other moves, and so forth. Once I had all this sketched out, I started trying to program it the same way I’d developed other enemy behaviors – with a big switch statement. However, I quickly found that I was having a difficult time sorting out my thoughts and plans and that it was tricky, and only going to become trickier, to try to develop the battle experience this way. Fortunately, the enemies for Join the Madness as they stand now are not my only experience with developing basic opponent AI. While I had avoided getting into the engineering weeds for these relatively simple enemy types, it seemed it was now time to create the go-to solution for creature behaviors, a state machine.

A state machine is a relatively simple design pattern conceptually: The machine (in this case the boss’s AI controller) can be in one of a set of states, and that state controls the behavior. Each state can then pass off control to other states as necessary, and each state can perform special one-time tasks whenever you exit or enter them. There’s a bunch of different ways to tackle this, but in this case I created a generic EnemyAction behavior which could be loaded into any enemy to control them. Of course, for this boss I created unique behaviors which are unlikely to be reused, but I made the system flexible enough that if I wanted to, say, re-code the dog enemy type’s pursuit behavior as an EnemyAction it could then be reused as often as I need to. Actually, with this system I could probably start creating new enemy types entirely out of reused behaviors, with no unique code at all – and so I may, someday, but in the short term it mostly made it so I could really focus on each one of the boss’s abilities in turn while leaving each ability’s parameters clearly exposed and categorized in the inspector.

Figuring all this out took me a week or so up-front, but I was finally ready to start actually making the boss fight. I started with her movement abilities: I now realize this might be somewhat odd, but I actually ended up giving this boss as many movement abilities as actual attacks. I considered enumerating all of her movement and attack abilities here, but instead I’ll just include a short video demonstrating them.

The basic movement abilities and attacks were fairly straightforward to develop, taking maybe a day at most for each. The teleportation ability was slightly tricky, since it had to keep the character inside the bounds of the level while still allowing movement during teleportation (at least, that’s how I imagined it), and required a bit of fixing up. The two more complex attacks, however – the portal arm attack and the falling blocks attack – took a significant amount of work, with the portal attack in particular representing almost a solid week of development.

In addition to working on boss behaviors, I took a diversion for a few days to rework how the dithered light shader worked. The way I had the shader working before, I had a number of issues with pixels erroneously getting lit with the color of the light source – so, for instance, a puddle of blood might look white right next to a white light. This is a behavior that actually makes some sense – in a normal shader, one expects those sorts of highlights – but is almost never what I actually wanted, and particularly created issues with objects which I wanted to block the background while still receiving light, since even the black pixels meant to block whatever was behind were getting shown as white. This became a real problem with the Carnifex boss design, since her dress and hair, the majority of her form, were black – and with this lighting method that simply wasn’t working. I reworked the light mode to only light the pixel up to its normal diffuse color – so red turns to black if it’s far away from a light source, but even if it’s right next to it only turns red instead of white. Another issue with the shader that came up was that, while the pattern of lit pixels was stable relative to the screen, objects moving across the screen kept flickering as their bright pixels happened to intersect the lighting pattern. This became really noticeable with Carnifex, since it was mostly just her outline and details that were visible and these kept flickering in and out of view – so I reworked the shader to base the dithering patterns off of the sprite’s local coordinates rather than their screen coordinates, giving moving objects much more consistent lighting.

I feel generally fine about the amount of time I spent on the boss – I can see where the effort went, and it’s on a part of the game I genuinely care about and want to do well on. All that said, I’m definitely starting to feel fatigued and burnt out, particularly on the lack of progress outside of this one room of the game. Now that everything is, as far as I can tell, more or less functional in this fight (though I expect to spend more time polishing and tweaking it somewhere down the line), I’m going to be going back and finishing up rooms, placing items and enemies, and writing more dialogue and music. The music part isn’t even necessary for the vertical slice, I’ve just been missing writing music and want to figure out what some of the later areas sound like – as well as, perhaps, make some improvements to the music I have done so far.

If you’d like to help support this project or my writing, please consider supporting me on Patreon. Support at any level lets you read new posts one week early and adds your name to the list of supporters on the sidebar.

Leave a Reply

Your email address will not be published. Required fields are marked *