Postmortem - Dungeon Crawler Example
This dungeon crawler prototype was a fun little project and I think overall it was a success. I decided to make this project to learn more about GB Studio and pixel art as I am a software developer by trade, the arts is not really my cup of tea lol.
While I’m not artist, I did learn a lot about the art of pixel art and animations. This is a craft that I do hope to improve upon over time as I get more experience with it.
At the same time, I wanted to create a little 2d game as those are normally my fav compared to 3d. Don’t get me wrong, I do enjoy a nice 3d game but I think it stems from growing up playing Atari, NES and Super nintendo as a kid that I just fell in love with the 2d pixel art style.
Why a gameboy game?
The Gameboy and Gameboy Colour were also a huge part of my childhood and I decided to take on the challenge of using a very limited palette to create a game.
At first I was looking at using the Godot game engine as I have had some experience with it in the past. Nothing too crazy but a small platformer that never saw the light of day and was only one level. As I was browsing through Itch’s assets for pixel art assets (this was before I thought of trying to make mine from inspiration) I came across a few games built using this “gb studio” software.
After a few searches I ended up coming to the GB Studio site, downloaded it and started playing with the sample projects. Fast forward a day, I join up the GB Studio discord (so many talented people there!) and was able to learn even faster by picking up a lot of tips and tricks from other devs. Sadly, I only just got into GBVM scripting (https://www.gbstudio.dev/docs/scripting/gbvm/) for one little thing near the end of development but it’s something I am going to look into leveraging a whole lot more for my next(?)/a real game!
Now with that all out of the way, it’s time to jump into the good stuff.
Handling “quests”
While the game doesn’t display any quests to the player, there are actually 3 in the game:
- Exit your house
- Talk to the Inn keeper to “activate” the portal
- Kill the boss.
These are all handled with their own global variables that hold a true/false value if it has been completed or not. Looking back though, I should have leveraged using Flags. Oh well, lesson learned!
The first quest to “Exit your house” was added near the end of development actually as a way to get around the overlay (text pop up) showing if you entered your house again after leaving it. Since I already had a custom QuestHandler script created, it was faster to call that script instead of setting another global variable and adding if checks in the scene to see if you have been there or not. There is probably cleaner ways to handle this though…
The third quest: “Kill the boss” was the first one put in the game when I built my QuestHandler script. It’s very simple actually. Once the boss is slain, set a global variable indicating the boss was slain then on a trigger at the end of the room, allow the player to pass. If the player tries to enter that trigger before then they are turned around and told to kill the boss.
As for the second quest, this was a simple yet fun one to implement. If the player tries to interact with the portal before they talk to the inn keeper, they are shown a bunch of random symbols. Otherwise, the portal will teleport the player to a random dungeon scene.
Dungeons
Speaking of dungeons, how did I handle it?
Well this was the first big challenge I came across using GB Studio. How do I make this dungeon crawler feel “random”? I knew I couldn’t really do any type of procedural generation without really tapping into GBVM scripting and potentially doing some funky things with background tile scripting. That and I honestly had no idea how I would set colliders using that method to keep the player or other actors (enemies) from going off screen.
My solution? I built out a bunch of “dungeon” scenes and when you complete one it will change scene to another dungeon scene using a randomly number that gets generated when you touch the end of scene trigger. Simple and got the job done. I took it a step further and added more randomness in though. Instead of hard coding 5 rooms before the boss, I implemented another random number generator that gets called at the start of the game. This number determines how many dungeons the player needs to complete before being sent to the boss scene.
The Boss
The boss you fight is actually made up of 6 sprites (Actors). This was another fun challenge to get them syncing up and moving around randomly together.
I created a script that takes in 6 params (the actors) and runs a number generator to determine what direction the boss should move in. This is call On Update. Then I simply moved each actor (piece of the boss) in the same direction.
The boss also has more health than regular monsters. As such, I needed to sync up when the boss got hit anywhere to his health. This was fairly easy to do in GB studio as I had a global variable holding the boss’ health in it and just ran checks against it. Once the boss was dead, I set the global variable BossIsSlain to true.
But why did I do this?
Well, I built my player and the inn keeper as a 16x16 sprite. A “metasprite” as it’s called vs a 8x8 or even 8x16. This was way before I could really know what to do with GB Studio. I eventually created an enemy that is 8x8 just to test what it would look like. But I wanted the boss to be bigger. One method I saw people doing more so in side scrollers was using an overlay and some GBVM magic to have a full screen boss move across the screen. Wouldn’t really work in my case though.
Given that I only had 1 actor out of a total of 12 you can have in a scene, I decided to create my boss out of multiple sprites and take the approach as mentioned above.
Not making the cut
I actually had several weapons made up that didn’t make it into the final build. There were swords, axes and daggers. The idea was going to be that the player could pick up coins from dropped monsters and go back to town to visit the Shop (Built out but I replaced it with a generic house) to buy new weapons.
I also planned out and started building a “diablo like” loot system where I would use Flag variables to indicate if the weapon had different abilities. So your weapon wouldn’t just hit the enemy and kill them, they could do bonus damage, or attack faster, etc.
There was also a working inventory screen of sorts that you could open with SELECT. This would show your health, coins and your weapon stats on it. This was cut though just due to scope creep for what I wanted with this project and would have taken a lot longer to work out kinks and clean up.
A lot of art work never made it into the game either due to time constraints. Same goes with sounds. I didn’t end up implementing the sounds when you took damage or swinging your dagger for example. Ultimately for these I had to make the decision to cut off development there since the goal of this project was to learn more about GB Studio and not so much about sound and art.