Friedrich Hanisch's Dev Log
DONE
- Finally, the post-jam version 1.0 of sustAIn is up on itch. Unfortunately Matthias didn't show up again since then, but LaraKaa wrote the additional dialogs and quests, and together we made a fully playable adventure game. Quite a feat, I think. My biggest regret is the lack of an artist, so the game looks... not so great. But at least the story is original and uplifting, which is why I added the game to my projects list after all. I guess I could try to improve my pixel art capabilities and replace some of the graphics, but I think I'd rather reuse the Bitsy-like system that I created with this jam entry for something new.
Oh, and there were some annoying performance problems with the web build of the game, so we removed that one from itch. A bummer, really, but I don't have the time to investigate this further for now.
- The little one pager website for Mops & Mobs is online now, even though the presskit assets are missing. It's at least ready for the Lange Nacht der Computerspiele in Leipzig and the A MAZE in Berlin, where we will showcase the game for a few hours. I like the slightly rotated elements of the page. Somehow I wish we could add music without looking totally out of touch.
SEEN
- Unity 6.1 was released and I just find it remarkable how it did not interest me in the slightest. Seems like I'm converting to Godot harder than I thought. I ported my almost abandoned side project to the new Unity version and it became corrupted. I'm not even in the mood to investigate.
- Saw a short and interesting video about Godot's Canvas Groups.
- I also watched a tutorial video about Gimp, mostly to understand the differences to other graphics programs. (And also because I still want to switch to Linux some day.) It's not that awful, but yeah, it's definitely missing some QoL things from Photoshop or Affinity Photo.
DONE
- While teaching GDScript to my students there was the urge to use an FSM at some point, so I updated my Simple FSM script. It now supports omitting the parameters of each method, and also having several target nodes instead of just one.
- It's not online yet, but we soon have a simple one pager website for Mops & Mobs. It was designed by Jana, and we wanted it to be responsive. I noticed how absolutely out of date my CSS knowledge is, so that was an opportunity to learn about flex boxes and stuff. As a result I want to remove the
w3.css
dependency of my own website too, but there are more important things to do currently.
- I wanted to improve the extensibility of our combat cards in Mops & Mobs by adding a traits system based on Resources, like I did with the Dummies. After a lot of thinking and planning it just didn't come together. It's not really a complexity problem, but the cards are just too different in their behaviour in order to streamline it. For now I accepted my fate, and will just try to to improve the readability overall, I guess.
DONE
- I reworked the NPC system of Mops & Mobs a bit, as it became apparent that certain features were missing and not easy to implement. Instead of my strange and overcomplex system based on proxies, the game now just assumes an NPC exists only once and places them at the correct position if necessary. It's still possible to have several characters with the same appearance, or even several characters sharing one memory (blackboard). There is still no real NPC manager, as everything is controlled by the story progress anyway. I would love having NPC schedules, but I think in such a game it would actually be annoying if it's not clear at all times where a character can be found. On the other hand, by abusing the scripting language I could probably create simple logic that would randomly move an NPC around in the room or even the current dungeon level. In any case, the rework of the NPCs mostly took so long because changing dungeon levels (which removes the previous level) was wonky and fell apart, so I had to repair that system too.
SEEN
- I use a lot of custom resources for Mops & Mobs, for data containers like card types or NPCs. The amount of files is increasing slowly, and I finally reached the point where I'd really like some kind of table overview of all the data. And thankfully there already is a solution for this - aptly named "Edit Resources as Table", by Don Tnowe. Integrating it in our project worked without problems so far.
DONE
- Another update for my dialog editor connected, so it's now version 0.9.7. This is another small update that mostly fixes the incorrect file sorting in the 'Welcome Screen' (it was sorted by last access instead of last changed). I also added the option to change the created JSON files' extension from
.json
to whatever. These two changes were once again motivated by Godot's strange behaviour of resaving JSON files seemingly at random times, and also reformatting them in the process. Especially the latter is very annoying, as Godot now (since v4.4) displays every float value with ".0" added when they're integer. This change isn't bad per se, but it adds a lot of unnecessary extra data to my JSON files. I even submitted an issue on the Godot repository, but it seems the problem is already known. Doesn't look like there is much incentive to fix it though. And I still didn't get an answer why Godot does the reformatting at all, as I don't see any reason why it's necessary.
DONE
- Finally I took the time to add an RSS feed to this dev log. Not sure if anybody is actually interested in this, but at least it's there now.
DONE
- I wanted to make the mouse over hovering in Mops & Mobs' combat a bit more robust, by using
PhysicsDirectSpaceState2D.intersect_point()
instead of the usual mouse_entered
signals. Turns out there is a bug (at least I think so) where intersect_point()
does not recognise any Area2D
s or other physics objects when they're children (direct or indirect) of a CanvasLayer
node. I don't know why that is, but I am sure it's a bug because 2D raycasts work. So I filed an issue.
SEEN
- This video about Surface-Stable Fractal Dithering was a nice watch. I'm primed by Ultima Underworld II, so I love dithering in games. I'm not sure I particularly like the technique shown in the video, but it was interesting nonetheless of course, as most explanations that go in-depth into shaders.
- Today I learned that Godot can just "forget" writing
print()
messages and errors into the Output tab; this seems to happen always when the game closes to quickly. As I had a crash bug that would instantly shut down the game whenever it happened this is a very annoying behaviour, as I couldn't see any result of printstack()
. The solution was to start Godot with the console, as that one doesn't care about the game window being too quick.
DONE
- The randomness of Mops & Mobs' battles was a bit too random, as there were situations that would be unwinnable sometimes and then become quite easy after trying again. Overall I think I want most fights to be non-random, but I still put some work into distributing the cards, based on their "dangerousness", a bit more evenly in the deck. I'm not entirely sure I succeeded, but so far most tests were promising. I'm basically sorting the cards by their danger factor, split them into two stacks (above average danger and below average danger), and then create packs that have around the same amount of "dangerous" and "harmless" cards in them. These packs are shuffled and then moved into the final deck.
SEEN
- I read this blog post about hash generation for Unity's
Vector2Int
. While the post was an insightful read, somehow I always suspected it isn't the best implementation, and long before they even had the Vector*Int
structures, I had to create my own Position*
stuff for integer based vectors. I don't know if my hash methods are better though (they were copied from somewhere else).
DONE
- I continued the Godot course from last week, mostly showing my students how to use GDScript. As usual, I live-coded the little puzzle game where the player has to follow a pre-generated path, but this time it was done in 2D. It's on the already mentioned GitHub repository, but it's also directly playable oon itch.io.
SEEN
- I read an article about SpaceX. I didn't really follow what SpaceX was doing, the things I heard mostly were in the region of "at least SpaceX is a cool company even if Musk is a a vile moron", but now I'm sure even that is not true. (The part about Musk is still valid though.) In any case, there is this quote in the article that pretty much sums up what Rat King is doing wrong all the time:
"You never achieve iterative design with a full-scale prototype. It is incredibly wasteful and can lead you down several problematic and dead-end solutions."
DONE
- Before we can work full-time on Mops & Mobs again, I'm doing small stuff from time to time. It would be great if we could concentrate on the content (story, levels, characters) when we get back to game development, but that's of course quite unrealistic. In any case I did some work on the card combat, improving some animations and adding a few sounds. Also it's now possible to flee from a fight. Another thing that might be worth mentioning is the removal of the slot for the card deck of the dungeon ("the enemy"), as we might go back to Mondar's Dungeon's way where all the cards are already placed in the dungeon stacks.
- I still hope we might get a "finished" version of sustAIn some day, and for that I created an outro. It consists of simple, hard-coded camera movements over the characters.
- COOLFRIENDS has a new project, a small NES game, and for that one I created a very minimalistic level editor in Godot. It mostly consists of two
ItemList
s and a grid for the tiles. It's nice that Godot has a built-in method for a native file dialog, so even saving/loading the level was easy to implement. The editor itself is nothing to brag about, but I still like creating tools, and I think Godot might become my to-go framework for that.
- I gave another Godot course last week, the created scenes and scripts are in this GitHub repository. It took another day to add extensive (German) comments to the code. As usual giving lessons is a mixed bag, especially when the range of knowledge and interest among the students is very wide. It can't be helped, I guess.
DONE
- I couldn't do much game dev the last few days, but I still managed to add a small feature to Mops & Mobs, at least rudimentarily. By adding a new
DummyTrait
that lets the level designer define a map point. This map point displays a text, usually a room's name, inside the backend map - depending on the mode by just walking into it or by calling discover_map_point()
in a script. This is a little QoL change I wanted to add for a long time. Of course, I should concentrate on the combat cards instead ... The plan is to have a version with three or four fights ready that can be tested at a local game festival (Lange Nacht der Computerspiele) in a few weeks.
DONE
- Gompl has the keyword
interrupt
now for stopping the script's execution and also allows defining a maximum amount of instructions being called. After the interruption, the script can be continued by providing a "state" Dictionary
. This way it's easy to make some kind of fantasy console, I hope. I also added a register_func()
method that allows registering Callable
s, as an alternative or extension to providing Gompl with a Godot object target. As the latter's methods are called directly, they would behave badly when the user calls a function in the wrong way, with no way for me to catch the error unfortunately. So with registering methods the responsibility lies with the programmer, not the scripter, to define the methods correctly. A small video on BlueSky.
DONE
- Godot 4.4 is out and I virtually instantly ported Mops & Mobs. Almost no changes were necessary, which is great. And the new typed dictionaries already improved the code, although less so than I hoped - as you can't nest types (so something like
var d: Dictionary[String, Array[int]]
is not possible).
- One of my goals with Gompl is to make it almost as usable as the SmallBasic interpreter for Unity, and one of the major things missing (at least for me) was being able to interrupt the execution of Gompl code. Because otherwise a user of a hypothetical coding game could just create an endless loop and freeze the game. So I finally, after quite some think work, I took the direct evaluation code out that would be called on the nested
Expr
nodes of the AST, and instead let them create a simple array of instructions, basically "compiling" the script. This array can then be used in the new run()
method of Gompl. This is the first step, the second step is of course adding logic to stop the execution after, for example, 1000 steps and afterwards let the user continue for another 1000 steps, rinse and repeat. Gompl on GitHub.
DONE
- I changed the icons on the homepage of this website from Font Awesome to some pixelart. Not sure I like them, it was hard enough to think of some symbols, but it's better to have less dependencies anyway.
DONE
- I updated Gimpl, renaming it to Gompl (I really don't care about the name, which might be obvious by the latter choice, but someone told me not to use "gimp"). Before I had a parser based on combinators, as learned in the tutorial by Jay Conrod, but I now replaced it with a parser using recursive descent parsing. This is described in Crafting Interpreters, and only now, after doing the first version of Gompl, I could understand it well enough to apply the knowledge. I also read the material from the TinyCompiler, but it didn't really help. In any case, Gompl ditches the
;
for separating expression lists, which I like a lot. There might be (severe) bugs, so using it in Mops & Mobs further will be a good test.
- I improved the gamepad handling in Mops & Mobs a bit and also gave the combat cards a shader that would give them a shadow and an outline. For that I just took TabMK's shadow shader and extended it with things I needed. I never thought of just increasing the size of the
Sprite2D
by scaling the vertices in the vertex shader, allowing the shadows to be much bigger this way. Somehow I find it genius, even if it's a bit crude. It's increasing overdraw, but I don't think that will be a problem for us, at least not in this case.
- I'm still working on sustAIn now and then together with LaraKaa, not necessarily because I think it's a great game, but mostly because it's fun to work on it. Somehow Godot makes it a joy to extend a jam game even after a while.
DONE
- Connected received a very small update, which adds the option to save the dialog JSON files with tabs instead of spaces. It was increasingly annoying to me that Godot would resave JSON files inside a project and change all spaces to tabs, as this sometimes resulted in very large commits for the Github repo. So this problem is solved. I also had to remove the BOM bytes in front and add a newline to the end of the JSONs.
- And Gimpl now understands negative numbers. Kind of awkward that it couldn't do a simple
x = -5
before, but now it works. There are two things I'd like to change - removing the ; separators and fixing bools, so things like true == true
work as expected - but somehow I think I should change the whole code for the parser to a hand-written one. For now Gimpl does everything I want for Mops & Mobs, so changes will have to wait.
DONE
- I added support for strings and function calls (not functions, though) to Gimpl, and also changed everything to expressions. Even though error handling (among other things) is sorely missing, I think Gimpl is now kind of usable in Mops & Mobs; and indeed I already implemented it.
DONE
- I finished following a tutorial for an interpreter in Python. I used GDScript instead, because I actually wanted to have a simple scripting language that I can use in our own Godot game projects (for Unity I'm quite content with SmallBasic, or just Rosalyn). I didn't find anything yet that suited my needs, so creating "my own" apparently was the way to go. Although I read stuff about interpreters before, I never did quite grok the whole thing, but the tutorial by Jay Conrod helped to finally just do it, and that approach was the most helpful so far. I tried reading "Crafting Interpreters" by Robert Nystrom, and while it's extremely complete, following is a bit of a chore, because the author adds too much fluff to the text, in my opinion. I think the lack of verbosity of Jay Conrod helped me much more with concentrating and understanding. On the other hand, IMP is very simplistic, and before I can actually use it for our projects I have to try adding some features, especially functions. Nonetheless I uploaded Gimpl to Github.
SEEN
DONE
- I did some more stuff for sustAIn, small QOL changes only, but there's still no release of the full version in sight. I guess creating a story-based adventure game, even with no additional gameplay, is always harder to make than first anticipated.
- The same with Mops & Mobs. I worked on small things that felt necessary, like a sanity check for the decoration mode (so that the player doesn't spawn into a barrel) and feedback messages when placing decorations, bug fixes for the savegames, moving the controls to the settings screen, adding titles and descriptions to quest lines... But without significant progress on the story I don't feel like uploading a new demo version. The differences are just too small, even if they're numerous.
DONE
- I participated in this year's game jam of the bpb, and as always it was great! This time I didn't work together with Jana, as it's pretty much impossible for now that we both attend such an event at the same time (because of the baby, of course). Instead I did the programming for Lara Keilbart's game idea: you're feeding a blank AI the knowledge of a small community so it will actually be a useful tool in the end. Cozy AI was the working title, but most people somehow incorporated "AI" into the title we also went with sustAIn. I provided the setting - the community are actually survivors of a generation spaceship that crash-landed on an alien planet - and of course my 'vast' Godot knowledge. Matthias Bunzel, the third team member, mostly worked on the dialogs, and for that he had to write formatted text files for the system that I created for the jam. In hindsight it probably would have been faster to use an existing dialog editor for Godot, but somehow I was interested in parsing textfiles that allow if-then logic. It was a bit more involved than I anticipated, so it took a big chunk of the time to create this, but I'm glad I tried it out. In any case the game isn't finished, we barely could make the first scene, but the systems are there and can be extended easly, if Lara and Matthias are willing. I also did some additional work already by adding the possibility to have both English and German in the game. Oh, and all the other entries were awesome too.
SEEN
- Funny that the first stealth video game was about stealing things too. The gameplay is a bit too simplistic for my taste, but the animations are great.
DONE
- Mops & Mobs feels more complete again, as I added an option to change the language of the game. Of course, for now it's only German as second language. Apart from the dialogs, where the translation will take a bit longer, there's also the job description at the beginning of the first level, which is a texture and not localized yet. Jana hopefully will change it to something using Godot's UI system, so that it will be easier to translate it via the CSVs.
DONE
- The new inventory UI in Mops & Mobs for the combat cards proved to be useful for preparing the combat too, and also the removal of exceeding cards from the backpack afterwards. This didn't need much additional code, which makes me happy, but of course it just means I missed some detail that will increase the complexity anyway. But for now, the combat system feels complete, and we can finally work on some "real" fights, as real as a card game can be, in the near future.
PLAN
- In light of the current events (Twixxer's boss Musk more and more open about being a nazi), I'll have to remove/replace all the links to Twitter on this dev log some day.
DONE
- I added an inventory UI screen for the combat cards in Mops & Mobs. After much thinking about the approach, we decided that a single overview of all cards in the player's backpack in a grid would be enough. The first cards, marked with an outline, are inside the deck, which is used for the next fight. Clicking on a card moves it to the first slot, so it will definitely be part of the combat deck too (and the last one gets removed). We hope the minimalism of this approach is appreciated, but it might be that some people want more control. Overall we try to not overengineer the combat in Mops & Mobs just so it doesn't get more important than the rest of the game mechanics. Wish us luck.
SEEN
- Some gameplay of Behind Stars and Under Hills can be seen in the series "Deutscher" on the German broadcast ZDF (3rd episode, 25:02)! I totally forgot about this - back in 2019 a TV production company asked us if they could use a video of one of our games. Screenshot on Mastodon.
SEEN
- I just learned that Mark Sibly, creator of several easy to use game development languages/tools, has passed away last month. I really enjoyed Blitz3D back in the day and even bought Monkey and tried to make some small games with it. It was always cool to be able to use BASIC in combination with versatile graphics engines. In any case it's nice to read so many testimonials of Sibly's influence on game developers' careers.
DONE
- My brother released the intro video that I made for his art exhibition.
- It was a bit more complicated than I anticipated, but now a dialog can branch differently in Mops & Mobs depending on the outcome of a fight. The problem was, of course, that there was no result until the player did the fight, but the dialog nodes would advance until the next "stopping node" (Text or Choice). So any Condition node would be evaluated too early. I added a "pause" functionality that is called as soon as a Script node notices that the current game state isn't the dialog mode anymore. This works well enough, but in the future I might create a dedicated Combat node for dialogs in order to combine the Script and the Condition.
DONE
- While the player is walking through the dungeons of Mops & Mobs they're triggering different actions with each step, like a dialog starts or music changes. This happens via
Dummy
nodes. If the game were more physics-based I'd use Area3D
s, but I found it more logical to just use points at distinct positions; might be a decision born out of overthinking, but it's what we use now. Over the months the Dummy
script received more and more functionality - not only do the dummies start dialogs or change music, they can also change the whole ambience, teleport the player to another dummy or level, and so on. But while the code doesn't have to be beautiful, I still thought having so many optional parameters makes the dummies unneccessary bulky, and creating different types of Dummy
scripts that handle each case individually isn't as easy as in Unity with its MonoBehaviour
component system. After some thinking I decided to use Godot's resource system. Each dummy now has an array of "traits", and every trait is inheriting a DummyTrait
which is a Resource
script. This means seldom used dummy functionalities like is_player_start
don't pollute all dummies, which I like. I also added the posibility to create custom scripts, like they're used in dialogs already. I don't really use a scripting language currently for the game, but if the need arises it should be easy to parse some simple if-then-else
constructs.
SEEN
- A tool to paint on 3D objects in Blender. It's free!
- A short video about three types of optimizations in Godot - pre-compiling GPU particles, freeing everything that isn't visible, and setting the
Monitoring
and Monitorable
flags of Area2D
nodes (plus the layer masks).
- The minimal theme for Godot got updated.
DONE
- Currently I'm not really working on anything worth mentioning (unfortunately), but I'm preparing a video for my brother's art exhibition. The exhibition is called BACKROOM, so of course it's just a fly-through in a labyrinthine backroom, with the typical wallpaper and carpet floor. I use bloed to create the level along a simple path. Dreamteck's spline tool is a bit overpowered for the camera path, but at least I don't have to make my own bezier curves. Annoyingly there was a bug that would only appear in the standalone build and not in the editor (the position change of the spline during
Start()
wouldn't be recognized by the path follower anymore).