Posted March 07, 2024 by Byte Arcane
Weekly updates time! There's an eclectix mix of changes: porting, visual, audio, bugs ... well, the usual culprits I guess.
Save slots
Without a doubt, saving and loading game state is incredibly useful for testing. I mean, I can't imagine people not doing that, as it sounds like "game programming: the roguelike approach". So, years ago, I decided to implement quicksave/quickload, I made it performant enough so that I save my sanity, and that was that.
I think I saw on twitter recently some fellow developer posting their support for multiple save slots in their admittedly far more polished and near-finished game, so it got me thinking: "why shouldn't I have it?". Well, no reason at all! So, with a little bit of work and bit of ImGui magic, I got the feature working in a very convenient way I might say (for development at least). The video above demonstrates this a bit. Basically we have a number of slots, with one marked as "active" (using radiobuttons). There's an easy way to create a new save and add it to the list, and there's an easy way to delete saves: delete files from hard drive and click a "refresh" button in the gui. That's it! So, now I can save before I enter a level, then go in a level, perform a few actions, save again, and backtrack to any point I like.
So, after having saves for about 5 years, I managed to add support for this clearly ultra-challenging feature. The future is now, folks!
ImGui input capture
I've had developer GUI for years now (foreshadowing). One of the problems that I had was that if I had a slider for example and moved the slider using click-and-drag, the camera would also start moving. Oops. And being the type "perfect is the enemy of good" for apparently very low values of both "perfect" and "good", I let that ... slide (the puns write themselves). "It's just me' nobody else will complain" I kept telling myself. So, 5 years in Unity, I didn't bother fixing that.
Now with Godot and ImGui, same problem, same attidude. Until last week where I added some InputText widget for the save slots, and starting typing a savegame name, and halfway through typing something like "at world", I would get a stutter when I hit "r". After connecting the admittedly very obvious dots, I realised that I was triggering a shader reload every time I typed "r". Ok, that was the straw that broke the camel's back.
So, I put my engineering hat on, googled for 10', tried 3-4 different things for 10' more, and lo and behold, found a solution and this issue is now fixed forever. The solution is twofold: first, there are a couple of ImGui flags that tell you if keyboard and mouse was used in ImGui, e.g. if you're hovering over a window, mouse gets used. The second part is that everywhere in my code where I check for key/mouse presses, I check an additional boolean which says "can we handle input" which is true when neither mouse or keyboard are captured.
Sounds and surfaces
I thought I'd play around with sound a bit this week, as I wanted to try out the new sound packs that I got. And I quickly realised that my audio infrastructure could be much much better. In particular, I implemented support for surfaces specifying sounds for stepping on with boots or bare feet. This means that I can specify different sounds when creatures walk with or without boots on different biomes, and even make splash sounds when walking through water. Nice! I think the sounds that I use, and the mixing, could be astronomically improved, but I like building systems and the system works. I Just Need Good Data. On a similar note, I also implemented support for a multitude of creature sounds, including flying, screaming, dying, etc, but I haven't hooked up actual sounds for these yet, neither the code hooks to trigger them. I guess that's a very long-winded way of saying "I made some enums".
Because in my sound packs I had different sounds for walking over rugs, I changed how I represent rugs in the game to support that, which was a good idea as the previous code was a bit hacky. Also: now when creatures walk over rug, you get a different sound!
Water, transparency and autotiles
Water is tricky because I want something better than a two-frame tile animation and sprites haphazardly mixed with it. In the Unity code, I had some complicated solution that required similar code over several shaders, and the code is like shadertoy code if you know: lots of magic values, that does some magic and out come visual effects. I was not keen on porting all the hacks from Unity, and that's one reason the Godot port takes as long as it does.
So, after a bit of tinkering, that included adding support for saving named rendertargets from various stages during rendering, I got the water working nicely again, with underwater distortion and haziness included. On top of that, now there's a little bit of wave at the separation between water and sprite. Great!
One more problem though. I'm using auto-tiling masks where water is "recessive": a tile that is water and is surrounded by land will contain water in the center and the tile's borders will be land. When the character is partially underwater in such a water border tile, the problem is that the character looks like is under ... land. So, I had two options. I either write some very complicated code to handle this (no idea how) or I make the water tiles "dominant". This means that a single water tile with all land neighbours, will be entirely water, and all the neighbouring land tiles will contain the water border. After a day of dealing with my complex autotiling system I managed to make it work, so ... phew.
Misc
That's mostly it for this week! A number of things remain for the port: