A week off for complex life-stuff and self-care, and we’re back.
It’s tricky to regain momentum on a project, once that momentum is broken, but it’s still quite possible to do. Just keep plugging away at it, because momentum tends to build slowly. Ironically, it’s that slow build-up that makes it last.
So, not much work this week, as I get back into things, but nevertheless, I feel it was some solid stuff.
Building on week 35’s widget customisations, I realised that there were widget elements that you probably didn’t want to touch when modifying an existing widget (control IDs, for example), so I altered the parsing a little to allow you to specify a field to remain untouched.
One thing led to another, and I decided to start the framework for adjusting the z-stacking-order of widgets. Z-order is important, as it determines which widgets are drawn in front of which other widgets.
Previously, widgets were referred to by a widget-handle, and that handle internally was nothing more than the index of a widget in a container. Widgets that were created later had higher indexes, and were drawn later than (that is, in front of) widgets with a lower index.
If I was going to allow changes to z-ordering, I had to decouple handles from indexes. So I did.
Handles still start out as widget list indices (because they have to be something), but they’re indirect, and the actual index of the widget can now be changed. A widget can be moved up or down in the Z-stacking-order (changing its index) without the handle of the widget changing.
This allows me (or the story author, once I’ve got some more code done) to introduce arbitrary widgets (I’m expecting images/sprites) at any level of the interface, and adjust their Z-stacking-order at will. Want to blot the whole screen out with an image? That’ll be possible.
Early days, though. The underlying support now exists, and I can build up that framework later.
Under Windows, you can toggle on the Windows Assistive Voice, and Argus will try to use that to read the story to you. It isn’t perfect yet, as it doesn’t read out choices yet, or modal confirmation dialogues, but we’re getting there.
There are some TTS (text-to-speech) options on other platforms, but I hadn’t gotten any further than using the one provided in Windows, so the code was a little sparse and unfocused. That’s all been modularised now, so it should be easy to initialise/use/deinitialise TTS output systems on different platforms. Or, at least, easy to drop the code in for them, when I get around to it.
Another part of assistive tech is keyboard use. You shouldn’t need the mouse to play the game. Modal dialogues are now keyboard driven, and so are choices (you can use the number keys to select an option, though that isn’t obvious).
I’m not yet sure how I’m going to integrate controller support with that yet. Maybe a movable cursor on choices? Maybe map some controller buttons? Reply hazy. Have to think on that some more.
There are some sections of the interface that don’t fully support keyboard/game-controller controls as well. The character-selection interface has limited support, and the preferences/load/save screens have no support at all. Most of the options you really have to have as an impaired user can be activated via function keys, though. Again, some more thought is required.
If you’re vision-impaired, or have motor-problems that shouldn’t limit your enjoyment of the game. I just need to work on that some more.
Pretty much all errors fall into two categories. Either, the author of the story bungled something that the story-compiler didn’t catch, and it causes Argus to go wrong, or Argus is missing critical files.
Mostly, when this sort of thing happened, I called abort(), which threw me to the debugger, but isn’t exactly a friendly thing to do to a user, who at least wants some clues about what is going on.
In both of these categories we have both fatal and non-fatal errors. Non-fatal errors generate an on-screen notice (at the top), just letting you know that they’ve happened. More detail goes into the log-file, and Argus tries to carry on anyway.
Fatal errors are things that stop the Argus from continuing at all. There’s a new screen for that, which handles pretty much every kind of bungle you can imagine, reporting it, before allowing the user to exit.
The only kind it really can’t handle is the possibility that it lacks even the resources to produce that screen. In which case, there’s a fallback error dialogue for that too.
It’s still possible to crash and burn without generating a proper error report to the user, but I’m closing in on those cases, and I’m confident that they’ll be caught soon enough.
Anywhere I handle time in the code, I have refit to use C++-11/14’s chrono library, with only a very few exceptions.
It makes dealing with time-quantities a great deal simpler and provides distinct types for doing it. It’s just a little thing, really, but it makes the code easier to read and easier to understand, and that’s good for me.
And that’s it, actually. Just four hours this week, which isn’t much, but I’m satisfied with the amount that I got done.