Multiple quicksave support

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, submersion and distortion

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

  • Fixed some bugs associated with saving/loading, which led to fixing some more bugs, so graphics are almost ported actually!
  • Because I support arbitrary zoom in/out, at zoom-out some effects become noisy (e.g. waves) or look plain weird (heat haze). So I added "global" shader support for passing the camera distance, and the shaders can modify the effect's intensity based on the distance. There are possibly some good mathematical approaches to do this properly, but nobody's got time for that in the DI-all-Y indie space.

That's mostly it for this week! A number of things remain for the port:

  • Handling inputs and contextual actions
  • Restore partially the developer-game-gui so that I can handle inventories and execute actions
  • Test everything: abilities, more dungeons, bots, ai etc