Game thing progress #7, the long awaited second release and whatever has happened inbetween

Well, well, well.. Been a while, hasn't it? About four month to be exact. Sorry! To be fair, I mostly was not slacking off, you can look at the git history!

I have, I think, finished the story for day 3, which means the release should be coming very soon (upd: it's out). There is also some optional content that hopefully isn't too hard to find. Many things have happened, especially code-wise, next follow some interesting techincal highlights.

To implement a certain feature for the walking part of the game, there was a need to draw things over the shader-processed stuff the rest of the game has (that is, the darkness and the lights). For this, I have implemented a "layer" system, of which there is only one now (not counting the unnamed default layer). The overlay layer ensures that the object is drawn after everything else is drawn and without the room's shaders, which are now specified per-room and can have all kinds of parameters, there can even be multiple shaders! So anyway, the overlayed objects are drawn afterwards so they're not affected by shaders, and they still have the usual z level logic which allows to put them on top of each other on the overlay layer.

For some sprite related things, I have discovered (thanks to my dayjob, actually) the concept of slices in aseprite. Slices are basically rectangles on the picture that are saved in its json metadata file. I used this feature for that very same thing mentioned before. I mapped out two areas for putting text into them and then in code made text conform to these areas. Hopefully since the code is quite generic I will be able to use them for something else, too.

The code structure changed quite a bit, since there was need for dynamic entity instantiation. So, now it's easy to make new entities and the code that existed before takes advantage of the entity creation functions too. Overlall, the code moved quite a bit into modules.

The callback system was reworked a lot and I used that same concept in other places too: that is, callbacks now specify the module and the name of the function they want to call, instead of some hard-coded name. This makes things a lot easier to separate and is very good for modding.

This same concept was used for custom story lines: the lines which are too rarely used to have them built into the parser. These lines basically specify "it's a custom line, here's the module and the class, and here's the data to pass to it", and the parser does so. When implementing custom lines I came up with an idea to mark places where line names are referenced in their data with YAML type tags. Many people don't know they even exist but there were very useful in my case, since custom lines aren't directly processed by the parser it had no way to know which things to parse if the custom line wanted to jump somewhere in a different file. So when using a custom line if one wants to reference a line in it, it has to be written as !line-name name/goes/here. This makes the parser aware that this is indeed a line and it can pre-load the file and validate all the things at startup. Very useful and a lot better than what I initially did, which was just loading lines from lua at runtime. Needless to say, it didn't work very well and it didn't scale. An example custom line looks like this:

    class: { module: "terminal.select_line", class: "SelectLine" }
    - condition: |-
          return TerminalModule.state_variables.know_about_stuff
      next: !line-name know-about-stuff
    - next: !line-name dont-know

The few custom lines implemented and used currently are:

  • SelectLine, which selects from a set of possible ways to branch from some conditions and has a default condition to select if nothing matches. Sort of like switch~/~case
  • SaveLine and ReturnLine, these work together. The first one saves its "returnto" property and then jumps to "next". Afterwards, when one wants to go back, ReturnLine is used by specifying next_was to the value that was used in SaveLine and after loading the return line name from it it jump back to that line. Effectively, that means one can have, for example, a dialogue which can be started from anywhere with a SaveLine and then after it's finished execution is returned back to where the dialogue was called from, even though it doesn't not exactly where that happened. I used this to implement dialogues that will, most likely, be available throughout several points in the story.

Another custom line that exists is a special one-off menu, which I will not be discussing here because it's kind of spoiler-y, but it's not that interesting anyway.

The tags for the walking system objects were reworked a bit: now they created components automatically based on their name. Before, the tags where dispatched from hard-coded values to components created beforehand. In this context, a tag is a component (in ECS terms) which doesn't have any actual data but it used to mark an entity as something special.

A new puzzle was implemented for day 3's walking section, hopefully it's not too hard, since this time it's actually somewhat of a puzzle and I thing it can't really be just brute forced. It requires just a tiny bit of thinking, so to speak.

A testing system was implemented, for both C++ and lua's ECS. As of this moment, the coverage says about 50% but that's not really true. Not much is tested but the foundation is there. I have also moved back from moonscript to lua, because one can't really count coverage from moonscript, as no coverage tool exists for it. The only thing where moonscript still exists are the tests, because it's a lot more convenient to use there.

A full-blown templating engine was introduced in the terminal part, so answers could be easily changed depending on certain choices the player makes. Day 3 uses this functionality heavily, I hope it creates more choice for the player to enjoy, making this whole thing more of a game.

The walking mode also has received a debug menu, like the one used in terminal mode. For now it just shows state variables for the walking mode, but hopefully I'll add more useful features to it. Showing the whole ECS world structure would be cool to have.

Interaction system for the walking mode was changed a bit too, now interactables can overlap and if they do, the player will have a choice of which one they want to use: first pressing E to show the list and then the number of the thing they want to use.

A character parameter of font size was added, as it is used in the special custom menu line mentioned before. This menu has a header that writes text that's bigger than usual.

For the past month or so I didn't actually have to touch the code most of the time, as most of it was already written I just had to write the rest of the story. I tell you, it wasn't easy!

I also implemented an accurate way of counting words in the story, currently it shows 11789!

The past few weeks have been hard for me, due to an uneasy situtation in my country. I wasn't really able to concenrate on anything. After a bit I did actually start doing things again, even though the uneasy situation is far from over. Nevertheless, I think I can work on things now, so that's good.

The environment images sadly are still not really available. I didn't draw new ones, as it takes me a lot of time. I'm hardly an artist, and drawing even such small pictures takes a long time. I recenly tried to ask a certain person who in the past said I may commision him some art for the game when I'm ready for it, but it turned out after he published his game he left the industry as it was too much for him. That means, of course, I couldn't commision art from him. The search continues (though I'm not exactly trying really hard).

I also received a PinePhone recently. Let me tell you, it's not a good "phone" in the traditional sense as the software is very rough, young and made by the community, but it's a full-fledged computer, whic is great. It's so easy to cross-compile for: you just compile it with the usual desktop compiler for AArch64 and copy it to the phone, and that's it. Everything works. I spent the last few days tinkering with it before actually coming back to finish the story :)

Update from 06.09.2020: After writing this post I stumbled upon an interesting bug that took me a bit to solve, so I thought I'd write about it here too. When OutputLine is skipped too fast, the next line would be created too soon, before script_after is executed, that is, right after the interaction is processed (and scripts are executed afterwards in another function, which draws the lines). So, now the OutputLine explicitly says to wait until its script is executed before proceeding. This problem didn't seem to concern the other lines because they have more requirements than just "all text is output".

I have also implemented a way to scale a window down and up to half/double the size for smaller and bigger screens. It's not ideal, but it allows people to play even if their screen has a very small or high resolution.

I think that's most of the things.. Hopefully we shall meet again soon. And thank you for reading my blog post :)