It has been a long time since the last update.
Somehow it was predictable. In the last post (almost 4 years ago!) I wrote about some fixes and new features I wanted to implement for version 1.0.2 of the game. I wrote about the fisheye rendering correction, which was already implemented by then, and I also wrote that I wanted to implement controller support - and this was were the feature creep began...
Controller Support
At a first glance, it sounded easy to implement controller support. SDL2, the framework that is the basis for my engine, has built-in controller support and detecting a button press on the controller shouldn't be harder to detect than a key press on the keyboard, right?
Well, there are some special things on the controller that are different than with mouse and keyboard. First, there are axes. Modern standard controllers have two analog sticks, wich are used for movement and camera orientation. This is a little bit different to mouse look and keyboard movement, since they have a wider range of values compared to a button (which has basically only the two states "pressed" or "not pressed"). Further, the current operating systems allow only one mouse to be present (regardless of how many of them are connected). On the other hand side, you can connect multiple controllers to one machine and it will handle them independently (which is important for local multiplayer games).
This being said, adding controller support for the ingame movement and interaction was indeed not too hard. However, all the menus (the main menu, the load and save menu, the options menu, the inventory and the NPC dialogs) were designed for mouse interaction. What I had to do was adding a pointer that could jump between the existing UI hotspots using the analog stick when a controller is connected. Further, the game will always only use the first controller that is connected to the machine.
Another problem for controller support is the vast variety of different controller models. How should I define a meaningful default setup when every user had a different gamepad or joystick model? Fortunately, this problem is a solved one. There is a GitHub project called the SDL_GameControllerDB. Basically, this is just a text file with tons of controller models mapped to the layout of an XBox-controller. This can be loaded into SDL and then be used to work with any supported controller as if it was an XBox controller. There have been some problems in practice with buttons that were recognized as axes and vice versa (namely the trigger buttons, which are axes on some controllers and buttons on other ones), but I'll spare you the dirty details...
Rendering Corrections
The fisheye-effect that my renderer used to produce due to my naive implementation was already fixed, but when I tried to increase the field of view (FOV) from 60 degrees to 90 degrees in order to get rid of the claustrophobic feeling, I noticed that the positioning of ingame sprites was imprecise. When I moved the camera, the sprites moved as well. With a FOV of 60° this was barely notable, but with a higher FOV, this was unacceptable.
I wondered how this could have stayed unnoticed, but it turned out that I used a very imprecise approximation for the screen position of world sprites instead of calculating this correctly. After fixing this, and with the increased FOV and fisheye correction, I think that the game will be more easily consumable without causing any headache or motion-sickness.
Localization
The feature creep was starting to grow and I wanted to support more than just one language. Thus, I used the gettext libary and tools for extracting every string from my game's Python code and inserting it into a translation file. Then I started to translate the contents to German, which is my native language.
One problem with german words and sentences is that they tend to be longer than their english equivalents. This leads to the fact that I had to adapt some of the UI in order to fit the German versions of the texts.
It was relatively easy to extract the strings from the code using gettext, but I am not sure whether using the library itself is really a benefit, since the localization flies have to be compiled before they can be used. Currently I am thinking about using simple yaml or JSON files for more flexibility and the ability to add new language support without even touching the game itself, just by adding new translation files to the asset directory.
Voice acting
Multiple languages in text were not enough. I also wanted to have spoken words, because in my opinion, this creates another layer of immersion. I started to record voice lines for Randuras, Flanduras and the gargolyes. However, my voice is not suited for recording female characters, so I reached out to a community of audiobook makers and I finally found a voice for Aurelia. I am excited about this, but the lines are not yet integrated into the game, this is why I'm not sharing more information here.
However, I uploaded a short demo video of my voice for Randuras and some of the gargoyles on YouTube:
Improved Sprites and Textures
When playtesting the new features, I noticed some things I wanted to improve. First, the potion sprites looked a bit blunt - not as glossy as a glass bottle should look like. I experimented with a rendered version of the potions in Blender in order to later scale it down and pixelate the end result, but this didn't look good. Instead, I decided to put a little bit more work in the original spites:
Another thing I did not like was the bookshelf texture in Randuras' house. I made the original version in a very low resolution with strongly saturated colors. This did not really fit to the rest of the game. This is why I decided to draw a new version and to add some more variety to the shelves:
More Combat Feedback and Destructible Environments
I already implemented some hit feedback that pushes enemies a little bit when they are hit by the player's sword. However, some feedback suggested that this was not enough, so I added small hit animations when an item is hit by a sword: Rats lose blood, wood and bones lose strands and hard surfaces have a more generic impact animation:
Further, I decided that the green skull banners should be destructable, just like the amphoras already are (but obviously, the banners don't spawn any loot, since they cannot contain anything).
Making Doors and Keys More Readable
One thing I noticed when watching people play the game was that most of them had orientation problems in the upper dungeon area and problems to figure out which key belongs to which door.
I thought about adding more unique textures to this area, but this would not have solved the problem with the doors. Instead, I decided to give each locked door a texture that indicates the color of the needed key: The rusty lock needs a rusty key, the silver lock needs a silver key and the golden lock needs a golden key. Further, I changed the name of these doors from just "Door" to "Door with a golden lock".
This should make the upper dungeon more accessible without destroying the fun or making it too easy for the players.
Release of v1.0.2
Slowly, I feel like I managed to contain the feature creep and focus on the delivery of an actual version. The best features are worthless, if they can't be played by anyone.
I plan to change one or two more minor things, integrate the voice lines for Aurelia and then release the new version in late spring or early summer of 2024.
Thank you for reading, keep safe and stay tuned,
Carsten