Broughlikes intro part 5 - The retrospect

dev-log game-dev

After I've wrapped up the project about a week ago, finishing up to setup the proper itch page and everything, I've been thinking a lot about summarizing the lessons I've learned during this six months period working on it. I figured I should at least look back from the bird's eye view once, and sort of brain dump of the things I'd want to avoid, or the nice things to carry onto the next one.

But, I'm a little torn on how to approach this to be honest. It's easy to do a retrospective at the end of regular web app development or whatever. I'm quite used to it. But it's kinda hard to do it for game dev projects specifically. Because one, I've never done postmortems properly for game devs before. (I usually try to do it for jam games. But they've never been complex enough, even for week long jams, in order to gain any meaningful insights.) And two, I feel like a lot of disciplines are intertwined so closely together when making games, it's a little bit hard to give out a meaningful statement without separating or meshing up multiple disciplines in a nice, cohesive way, if that's ever gonna make sense at all.

I make my own art. It sort of stands out on its own, but it's no where close to give credit for. And sound effects are generated by BFXR, so there's nothing to talk about at all. So, I'll try to lean as much as I can into design and technical aspects.

So, here goes.

1) Simplicity of the spells -- Good

This is possibly the best outcome I'd like to carry on to the other projects, even non-roguelike games. I feel like their effects are at least easier to observe without having to supply huge tooltip texts or whatever. One thing I would like to do (maybe the next time) is to have more interactions between multiple spells. I love the idea of curses in Imbroglio, and drawing inspiration from the traditional role-playing games, buffing and debuffing effects might be one way to do it. But is it the only way to do it; I don't really know. So many games have done it for years, it might be hard to break out of the norm. We'll see.

I did have an idea about equippable items that will act like modifiers to the unlocked spells. For instance, higher bonus damage from Cannibalize, more healing power from Heal, Nova will chain across multiple enemies, that sort of things. But I feel like that's a cheap design decision that AAA RPGs usually do with skill trees. You're just doing the same thing, but more. It'll probably make sense for games of bigger scale, but definitely not here.

The point is; complexity doesn't necessarily mean creativity. I've never properly understood those words before, even after working professionally as a software developer for almost a decade. But now, I do. Often times when I thought of interesting ideas for spells, or even enemies, (sometimes even got down to implement them), I usually revert back to a more simpler approach. People might find that they're too simple in some occasions when playing the game. But I do believe that those kinds of lessons are far more valuable for me as a designer in the long run than the game itself.

2) Trivial scoring mechanism -- Bad

I'm not sure how to explain this, other than the fact the final scoring system feels really... lazy. In other words, this is one of the bad things I don't really know how to fix right now. I mean, I could easily say that, the aim of the player is to dive as deep as possible, while collecting as much treasures as possible. But, you can question it as, if the treasures/gems are so valuable, why do you have to spend them to cast the spells.

High score screen, double-serving as the main menu

In short, the score system has really became an afterthought, instead of the main driving force to let the player come back to the game, at least thematically, or overarching plot, or something like that. But it wasn't. They were just arbitrary numbers saved onto the drive in order to get displayed on the menu. Maybe I could add some sort of meta game, where the player can unlock a perk before the start of the run; initial health boost, a random spell unlock, etc. And the perks will gradually be available depending on the highest scores you can manage.

I'll probably try it out later on.

3) Lack of polish -- Bad

Even from glancing at the gameplay gifs, it's obvious that the game totally lacks the shininess you'd expect from a modern video game. I was constantly fooling myself with the reason that I was more focused on the design than actually making this game presentable or whatever. And there are also commercial games out there which don't have any kinds of polish at all. But the thing about those commercial games is, they have an extremely good design foundation. My game here doesn't. So, it's totally a lame excuse.

I should've, and could've, spent ten hours or so, adding simple particles and make some of the UI interactions better.

4) Very little control over the randomization -- Good and bad, mostly bad

This is one of the things that you might start to notice after playing the game for a few runs, especially when it comes to generating the levels. The level layouts are simply just too erratic. Other than making sure that it doesn't spawn island tiles, (basically, a free passable tile that's surrounded by walls so that it becomes inaccessible by conventional means) the map generation code has no intelligence at all. Sometimes the enemies would spawn clustered around the player, sometimes the player will be spawned next to the exit stairway.

Another thing is a bit more on the technical side. The way I programmed the map generation code doesn't allow me to utilize seeds in order to re-generate the same series of levels altogether. The code is simple that it works for prototyping a single idea, but it's bad that there's very little control over it, thus doesn't leave any room for adding meaningful layers on top of map generation.

In other words, the levels are just generated in a pure random fashion, not procedurally. If I have to pick at least one thing to improve the map generation in the game, I might say the spawning locations for the player, the enemies and the exit should be spread out across the level more organically, so that the player would at least have a better reason to spend more time in a level.

5) Terrible handling of event queues

This is also another technical aspects that I wasn't really satisfied with. I'm not really sure the event queue is the right term for referring to this. Basically what I mean by that is, in a typical turn-based games (be it roguelike or whatever) you'll have sequence of events that happen every turn. Player inputs will be accepted, enemies will take their actions, passive buffs and debuffs on the actors will take effect, timers and cooldowns will be ticked down, et cetra, et cetra. All of these have to happen in a nice liner fashion, and more importantly, in a predictable and sensible way within the game world.

Let's use a simple example from our game itself; the Spikes spell. The player casts the spell to lay the spiky trap on the floor, the trap activates and deactivates every other turn. When an enemy or the player walks onto the tile with the trap when it activates, they need to get hurt. Such a simple concept so the implementation should be pretty straightforward, right? The turn advances when the player takes action. So, you might be thinking, when the player did something, the spike should change its state so that an enemy walking onto the tile with the spike can get hurt. Well, yes, you're thinking it right. But remember, the player can also get hurt when walking onto the spikes too. Soooooo.... if the world advances only when the player moves, when should the state of the spikes be changed, so that the player can get hurt when they're walking onto the spikes that were deactivated in the previous turn.

spikes

Be weary of your own traps

I hope you're starting to see my point here. Even a simple interaction like this can get pretty weird when you actually start to dig deeper into the problem. And I haven't even touched the subject of syncing the animations with those entity states. The way I solved the problem in the game was... ok. Just about ok. I mean, it works, but it was a pain in the butt to understand what's happening what and where. Strangely, I haven't really seen this problem addressed properly even in tutorials that focus on roguelikes. I do have an idea about a proper system in mind that I'd like to implement in the next project. So, I'll probably write more about it when I get there.

6) Engine capabilities and features, or rather, abundance there of -- Bad, maybe?

Yeah, you've heard that right. I was getting too much engine features. I used Unity to build this game. Before I spark another age-old "whether Unity is the best engine for every possible game genre out there?" or "Unity vs. GameMaker vs. Godot warfare on the 2D battlefield" or "if you're a man, build your own engine" arguments, let me just say outright that I like working in Unity. I don't love it, but I like it and I enjoy using it enough that I've got several results came out of game jams over the past few years. Their qualities are vary but that depend entirely on the efforts we've put into those jams, not the engine.

So, before I explain anything further, let's look at this code below.

If you understood the code correctly, it displays a maximum of 8 health pips nicely laid out in two rows above each entity's head. That's it. Pretty straightforward logic. The actual meat of the code is in fact UpdateHealthPipsDraw() method, which is only 9 lines of code including the braces. The rest is essentially boilerplates that blows into this 50 or so lines of code. I can still combine the UpdateHealthPipsDraw() together with InitHealthPips() method, but that could potentially make things a little less efficient. If you've ever worked in Unity just for a minute before, you'll understand why straightaway. Unity just doesn't possess simple mechanism to draw multiple 2D sprites in a single batch. A single Game Object in Unity cannot have more than one Sprite Renderer component attached to it. So if you want to draw the same sprite eight times, you'll just have to create eight different Game Objects. It's just not in Unity's DNA to get around this.

It's not like I'm only getting an epiphany recently or anything like that. I've always known this fact and have to deal with it every time I work in Unity. I'm only using this as the simplest example to get to this point; Unity can get in your way, A LOT. Unity is an extremely powerful engine, there's no doubt about that. But I just don't need that power 90% of the time for this particular type of game. Even if it comes to simple rendering frameworks, (MonoGame, Love2D, HaxeFlixel, you name it) I could've done this health pip display logic in less than 10 lines of code. Sure, those frameworks don't have fancy stuffs like physics engines or animation tools or whatever. But like I said, I just don't need them for this type of game.

There was no rigid bodies or colliders used. Every single entity in the game world is data driven. Inheritance is a common answer in OOP for sharing the same functionality across multiple types, but inheriting MonoBehaviours can get weird sometimes (not to mention the quirkiness of the Unity editor trying to serialize those child object's properties into the Inspector.) Unity's Animator is a powerful tool, but try using that alongside inherited components. More often that not, you'll end up with component logics being dictated by the animation state machines, which is really not a good thing to have in a simple 2D game.

I know it's a lot of rant, and some of them might sound like nitpicking. I just want to say that a good portion of my time working on the game was fighting the opinionated rules of the engine which can often pose themselves as flexible features. I don't want anyone asking the question "What's the best engine to make video games?" take this as an answer. It definitely isn't. Ultimately, Unity is just an engine. A tool. And the right tool needs to be used to reach the best possible solution. Even the hammer won't be fitting to hit every possible nail under the sun. Smaller nails might need smaller hammers. My point is, Unity is definitely not the best hammer to hit this particular type of game.

Onwards...

Whatever the case, I did have a lot of fun working on this project. There were both ups and downs, encouraging and depressing moments alike. Overall quality of the game is still garbage. But in the end, I finished it, relatively better than most of the projects I've worked on in the past few years. And more importantly, learned a lot of lessons.

I already have a rough plan for the next project of course, and have been doing a lot of research on some aspects over the last couple of weeks. I might start throwing out dev logs as soon as the next project starts to show a solid gameplay loop. But for now, jump onto the itch.io project page and check out the game, which is creatively titled; the "Dungeon Brawler". I'd love to hear your thoughts.